Skip to content

Instantly share code, notes, and snippets.

@BrockA
Created May 6, 2012 06:11
Show Gist options
  • Save BrockA/2620135 to your computer and use it in GitHub Desktop.
Save BrockA/2620135 to your computer and use it in GitHub Desktop.
This is a utility function, meant to be used inside a Greasemonkey script that has the "@run-at document-start" directive set. It Checks for and deletes or replaces specific <script> tags.
/*--- checkForBadJavascripts()
This is a utility function, meant to be used inside a Greasemonkey script that
has the "@run-at document-start" directive set.
It Checks for and deletes or replaces specific <script> tags.
*/
function checkForBadJavascripts (controlArray) {
/*--- Note that this is a self-initializing function. The controlArray
parameter is only active for the FIRST call. After that, it is an
event listener.
The control array row is defines like so:
[bSearchSrcAttr, identifyingRegex, callbackFunction]
Where:
bSearchSrcAttr True to search the SRC attribute of a script tag
false to search the TEXT content of a script tag.
identifyingRegex A valid regular expression that should be unique
to that particular script tag.
callbackFunction An optional function to execute when the script is
found. Use null if not needed.
Usage example:
checkForBadJavascripts ( [
[false, /old, evil init()/, function () {addJS_Node (init);} ],
[true, /evilExternalJS/i, null ]
] );
*/
if ( ! controlArray.length) return null;
checkForBadJavascripts = function (zEvent) {
for (var J = controlArray.length - 1; J >= 0; --J) {
var bSearchSrcAttr = controlArray[J][0];
var identifyingRegex = controlArray[J][1];
if (bSearchSrcAttr) {
if (identifyingRegex.test (zEvent.target.src) ) {
stopBadJavascript (J);
return false;
}
}
else {
if (identifyingRegex.test (zEvent.target.textContent) ) {
stopBadJavascript (J);
return false;
}
}
}
function stopBadJavascript (controlIndex) {
zEvent.stopPropagation ();
zEvent.preventDefault ();
var callbackFunction = controlArray[J][2];
if (typeof callbackFunction == "function")
callbackFunction (zEvent.target);
//--- Remove the node just to clear clutter from Firebug inspection.
zEvent.target.parentNode.removeChild (zEvent.target);
//--- Script is intercepted, remove it from the list.
controlArray.splice (J, 1);
if ( ! controlArray.length) {
//--- All done, remove the listener.
window.removeEventListener (
'beforescriptexecute', checkForBadJavascripts, true
);
}
}
}
/*--- Use the "beforescriptexecute" event to monitor scipts as they are loaded.
See https://developer.mozilla.org/en/DOM/element.onbeforescriptexecute
Note seems to work on acripts that are dynamically created, despite what
the spec says.
*/
window.addEventListener ('beforescriptexecute', checkForBadJavascripts, true);
return checkForBadJavascripts;
}
function addJS_Node (text, s_URL, funcToRun) {
var D = document;
var scriptNode = D.createElement ('script');
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
//--- Don't error check here. if DOM not available, should throw error.
targ.appendChild (scriptNode);
}
@wabiloo
Copy link

wabiloo commented Jul 24, 2014

This does not seem to work in Chrome with TamperMonkey. It looks like the beforescriptexecute event never fires...

Brock responds:
Correct. Chrome never did implement beforescriptexecute. There is/was a bug report for that that was opne for years.

Reference:

@gcosta87
Copy link

gcosta87 commented Feb 9, 2015

This script is great and very helpful. I'll use in small GreaseMonkey scripts.
It would be great if GM implement this type of solution, to make it available natively and also expand the current API. Maybe you can propose your solution to developers GM ;).

@mikhoul
Copy link

mikhoul commented Jul 5, 2016

After all those years does somebody found a way to make it work in Chromium browser with Tampermonkey ?

Or any workaround to edit/stop inline script in Chromium browser.

Regards.

@calraith
Copy link

calraith commented May 21, 2018

@mikhoul See https://stackoverflow.com/a/46188137/1683264

I got that polyfill working in Chrome + Tampermonkey. I had to do something like this:

// ==UserScript==
// ... headers ...
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==

(function(w) {
    // ... polyfill here with all instances of "window" replaced with "w"

    w.onbeforescriptexecute = (e) => {
        if (e.script.textContent.includes("crap I don't want")) {
            e.replacePayload([
                "string-ish js code",
                "more string-ish js code"
            ].join("\n"));
        }
    };
})(unsafeWindow);

I think you might alternatively be able to replace all instances of the window object with document and forego the need for unsafeWindow, but I haven't thoroughly tested it. The MDN says the onbeforescriptexecute event belongs to document anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment