Reputation: 298226
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?
Upvotes: 3
Views: 1253
Reputation: 298226
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';
};
Upvotes: 1
Reputation: 16609
It's not nice, but all I can think to do is to load the script via ajax instead of putting it in a <script>
tag, manipulate the result string to call your own version of the function (or "rename" bad_function
so it doesn't override your version), then put that in a <script>
tag and append it to your page:
An example using jQuery for simplicity:
function good_function() {
alert("I am good");
}
$.ajax({
url: '/echo/html/',
type: 'POST',
data: {
html: "function bad_function() { alert('hahaha'); } bad_function();",
delay: 0
},
success: function(data) {
console.log(data);
// comment this line to see the original
data = data.replace('bad_function();', 'good_function();')
var newScript = $('<script type="text/javascript" />').text(data);
$('body').append(newScript);
}
});
Upvotes: 0