Stop execution of Javascript function (client side

2018-12-31 17:00发布

问题:

I want to stop the execution of one single line from a site, so that the whole page is read by the browser except that single line. Or the browser may simply skip the execution of that javascript function.

OR

Is there way i can tweak the javascript somehow so that the random number generating function in javascript do not generate random number, but the numbers i want...

I dont have access to the site on which the script is hosted so all this needs to be done client side.

回答1:

Firefox currently supports the beforescriptexecute event (as of Version 4, released on March 22, 2011).

With that event and the // @run-at document-start directive, Firefox and Greasemonkey now seem to do a good job intercepting specific <script> tags.

This is still not possible for Chrome+Tampermonkey. For anything but Firefox+Greasemonkey, you will need to use techniques as shown in the other answers, below, of write a full browser extension.

The checkForBadJavascripts function encapsulates this. For example, suppose the page had a <script> tag like so:

<script>
    alert (\"Sorry, Sucka!  You\'ve got no money left.\");
</script>

You could use checkForBadJavascripts like so:

checkForBadJavascripts ( [
    [   false, 
        /Sorry, Sucka/, 
        function () {
            addJS_Node (\'alert (\"Hooray, you\\\'re a millionaire.\");\');
        } 
    ]
] );

to get a much nicer message. (^_^)
See the inline documentation, in checkForBadJavascripts, for more.


To see a demonstration in a complete script, first visit this page at jsBin. You will see 3 lines of text, two of them added by JS.

Now, install this script (View source; it\'s also below.) and revisit the page. You will see that the GM-script deleted one bad tag and replaced another with our \"good\" JS.


Note that only Firefox supports the beforescriptexecute event. And it was removed from the HTML5 spec with no equivalent capability specified.



Complete GM script example (The same as the one at GitHub and jsBin):

Given this HTML:

<body onload=\"init()\">
<script type=\"text/javascript\" src=\"http://jsbin.com/evilExternalJS/js\"></script>
<script type=\"text/javascript\" language=\"javascript\">
    function init () {
        var newParagraph            = document.createElement (\'p\');
        newParagraph.textContent    = \"I was added by the old, evil init() function!\";
        document.body.appendChild (newParagraph);
    }
</script>
<p>I\'m some initial text.</p>
</body>


Use this Greasemonkey script:

// ==UserScript==
// @name        _Replace evil Javascript
// @include     http://jsbin.com/ogudon*
// @run-at      document-start
// ==/UserScript==

/****** New \"init\" function that we will use
    instead of the old, bad \"init\" function.
*/
function init () {
    var newParagraph            = document.createElement (\'p\');
    newParagraph.textContent    = \"I was added by the new, good init() function!\";
    document.body.appendChild (newParagraph);
}

/*--- Check for bad scripts to intercept and specify any actions to take.
*/
checkForBadJavascripts ( [
    [false, /old, evil init()/, function () {addJS_Node (init);} ],
    [true,  /evilExternalJS/i,  null ]
] );

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.
    */
    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 ();

            //--- 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 that it does not work on acripts that are dynamically created.
    */
    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);
}


回答2:

The answer depends on details which were not provided (The exact page and line of code would be best), but here\'s how you do it in general:

  1. If the offending JS code does not fire right away (Fires after DOMContentLoaded), then you can use Greasemonkey to replace the offending code.   EG:

    var scriptNode          = document.createElement (\"script\");
    scriptNode.textContent  = \"Your JS code here\";
    document.head.appendChild (scriptNode);
    

    Done.

  2. If the JS code fires immediately, then it gets more complicated.
    First, grab a copy of the script and make the desired change to it. Save this locally.

  3. Is the offending script in a file or is it in the main page HTML (<script src=\"Some File> versus <script>Mess O\' Code</script>)?

  4. If the script is in a file, install Adblock Plus and use it to block loading of that script. Then use Greasemonkey to add your modified code to the page. EG:

    var scriptNode          = document.createElement (\"script\");
    scriptNode.setAttribute (\"src\", \"Point to your modified JS file here.\");
    document.head.appendChild (scriptNode);
    
  5. If the script is in the main HTML page, then install either NoScript (best) or YesScript and use it to block JavaScript from that site.
    This means that you will then need to use Greasemonkey to replace all scripts, from that site, that you do want to run.



回答3:

Using TamperMonkey? All you need to add below your // @grant in the TamperMonkey header is // @require http://urlofyoursite.com/myfile.js. For example, here is the very top of my TamperMonkey thingie:

// ==UserScript==
// @name         Project
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://docs.google.com/presentation/*
// @grant        none
// @require http://cdnjs.cloudflare.com/ajax/libs/annyang/2.1.0/annyang.min.js
// ==/UserScript==


回答4:

You can use what is called a bookmarklet.

Build the js file you want to run on the other site: your.js

Make an HTML page with the following code:

<html>
<body>
  <a href=\"javascript:(function(){var s=document.createElement(\'SCRIPT\');s.src=\'/url/to/your.js?\'+(Math.random());document.getElementsByTagName(\'head\')[0].appendChild(s);})()\">
    Drag\'n Drop this to your bookmarks
  </a>
</body>
</html>

Replace /url/to/your.js with the path of your js file.

Load that small page in your browser and drag\'n drop the link to your bookmark bar.

Go to the web site you want to hack, and click the bookmark you just created.
This will load your.js in the page and run the code.

Note: the ?\'+(Math.random()) part is to avoid your js being cached, this is not mandatory but it is helpful when you develop your.js