Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save maple3142/c6593f0aff180bc0e4be5d549259da2c to your computer and use it in GitHub Desktop.
Save maple3142/c6593f0aff180bc0e4be5d549259da2c to your computer and use it in GitHub Desktop.
polyfill of 'beforescriptexecute' event
// 'beforescriptexecute' event [es5]
// original version: https://gist.github.com/jspenguin2017/cd568a50128c71e515738413cd09a890
;(function() {
;('use strict')
function Event(script, target) {
this.script = script
this.target = target
this._cancel = false
this._replace = null
this._stop = false
}
Event.prototype.preventDefault = function() {
this._cancel = true
}
Event.prototype.stopPropagation = function() {
this._stop = true
}
Event.prototype.replacePayload = function(payload) {
this._replace = payload
}
var callbacks = []
var addBeforeScriptExecuteListener = function(f) {
if (!f instanceof Function) {
throw new Error('Event handler must be a function.')
}
callbacks.push(f)
}
var removeBeforeScriptExecuteListener = function(f) {
var i = callbacks.length
while (i--) {
if (callbacks[i] === f) {
callbacks.splice(i, 1)
}
}
}
var addev = window.addEventListener.bind(window)
var rmev = window.removeEventListener.bind(window)
window.addEventListener = function() {
if (arguments[0].toLowerCase() === 'beforescriptexecute') addBeforeScriptExecuteListener(arguments[1])
else addev.apply(null, arguments)
}
window.removeEventListener = function() {
if (arguments[0].toLowerCase() === 'beforescriptexecute') removeBeforeScriptExecuteListener(arguments[1])
else rmev.apply(null, arguments)
}
var dispatch = function(script, target) {
var e = new Event(script, target)
if (window.onbeforescriptexecute instanceof Function) {
try {
window.onbeforescriptexecute(e)
} catch (err) {
console.error(err)
}
}
for (var i = 0; i < callbacks.length; i++) {
if (e._stop) {
break
}
try {
callbacks[i](e)
} catch (err) {
console.error(err)
}
}
return e
}
var observer = new MutationObserver(mutations => {
for (var i = 0; i < mutations.length; i++) {
for (var j = 0; j < mutations[i].addedNodes.length; j++) {
var el = mutations[i].addedNodes[j]
if (el.tagName !== 'SCRIPT') continue
var e = dispatch(el, mutations[i].target)
if (e._cancel) {
el.remove()
} else if (typeof e._replace === 'string') {
el.textContent = e._replace
}
}
}
})
observer.observe(document, {
childList: true,
subtree: true
})
})()
!function(){function e(e,t){this.script=e,this.target=t,this._cancel=!1,this._replace=null,this._stop=!1}e.prototype.preventDefault=function(){this._cancel=!0},e.prototype.stopPropagation=function(){this._stop=!0},e.prototype.replacePayload=function(e){this._replace=e};var t=[],n=window.addEventListener.bind(window),o=window.removeEventListener.bind(window);window.addEventListener=function(){"beforescriptexecute"===arguments[0].toLowerCase()?function(e){if(!e instanceof Function)throw new Error("Event handler must be a function.");t.push(e)}(arguments[1]):n.apply(null,arguments)},window.removeEventListener=function(){"beforescriptexecute"===arguments[0].toLowerCase()?function(e){for(var n=t.length;n--;)t[n]===e&&t.splice(n,1)}(arguments[1]):o.apply(null,arguments)};var r=function(n,o){var r=new e(n,o);if(window.onbeforescriptexecute instanceof Function)try{window.onbeforescriptexecute(r)}catch(e){console.error(e)}for(var i=0;i<t.length&&!r._stop;i++)try{t[i](r)}catch(e){console.error(e)}return r};new MutationObserver(e=>{for(var t=0;t<e.length;t++)for(var n=0;n<e[t].addedNodes.length;n++){var o=e[t].addedNodes[n];if("SCRIPT"===o.tagName){var i=r(o,e[t].target);i._cancel?o.remove():"string"==typeof i._replace&&(o.textContent=i._replace)}}}).observe(document,{childList:!0,subtree:!0})}();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="onbeforescriptexecute.js"></script>
<script>
window.addEventListener('beforescriptexecute',e => {
if (e.script.textContent.includes('alert')) {
e.preventDefault()
}
else if (e.script.innerHTML.includes('hello')) {
e.replacePayload(e.script.innerHTML.replace(/hello/g, 'world'))
}
else if (e.script.src.includes('xxx')) {
e.preventDefault()
}
})
</script>
<script>
// won't execute
alert('hello')
</script>
<script>
// will execute, but 'hello' will be convert to 'world'
console.log('hello')
</script>
<!-- won't execute -->
<script src="xxx.js"></script>
</body>
</html>
alert('C8763')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment