Search code examples
javascriptmonkeypatching

Monkey-patching a named function that's called immediately


A script I'm loading is misbehaving. It's got a structure like this:

function bad_function() {
    ...
}

/* randomly generated stuff */

bad_function();

How do I modify the behavior of bad_function if it's called immediately at the end of the script? I thought of creating a silently read-only property on window before loading the script, but this throws a TypeError: Identifier 'bad_function' has already been declared exception when the above script is executed:

Object.defineProperty(window, 'bad_function', {
    value: function() {
        /* my monkey-patched code */
    }
});

How do I monkey-patch this function?


Solution

  • While this isn't an answer to my question in general, I was able to monkey patch my specific function by patching a global function like encodeURIComponent that was called inside of my function, performing the necessary changes, and throwing an exception to prevent the rest of the original function from running.

    var old_encodeURIComponent = window.encodeURIComponent;
    
    window.encodeURIComponent = function() {
        // If this function is used in multiple places, look for variables in
        // the current scope to determine if this is the right spot to start 
        // monkey patching.
        if (typeof a === 'undefined' || typeof b === 'undefined') {
            return old_encodeURIComponent.apply(this, arguments);
        }
    
        // You now have access to the variables in the scope of your target 
        // function. If your monkey patching is just a simple tweak, you're all set
    
        // Otherwise, do what you need to do and throw an exception to stop the
        // rest of the code from running
    
        throw 'goodbye';
    };