How to override a site's variable with Tampermonkey?

Viewed 789

I am trying to override a function set up by a website (window.jsl.dh). This is the declaration:

window.jsl = window.jsl || {};
window.jsl.dh = window.jsl.dh || function(i, c, d) { blabla }

I want to assign dh to a dud function, but after banging my head for a while, I don't know what's real anymore. I've tried creating a bogus dh() and Object.freeze(window.jsl), using a Proxy, adding setters, cheering up my laptop... no luck. Whatever I do, that piece of code seems to run unimpeded, and the dh() function always gets assigned and running without an issue.

This is the code:

  window.jsl = window.jsl || {};
  window.jsl.dh = function () {
    console.log('Called the dud');
  };
  Object.freeze(window.jsl);

If I set a breakpoint after the TM script run, but before the site's declaration and manually enter the same code in the console, it works.

Thinking this may be a sandboxing issue, I've messed with every @grant and script injection method under the sun —also different timings with @run-at.

Can't see why it's not working on its own, and I run out of ideas.

2 Answers

I can't replicate the problem...

The website contains:

window.jsl = window.jsl || {};
window.jsl.dh = window.jsl.dh || function(i, c, d) { console.log("Master version!"); }

window.jsl.dh();

// I've added a timeout just in case there was a race timing issue with tampermonkey script
setTimeout(function(){ window.jsl.dh(); }, 1000);

My tampermonkey script...

// ==UserScript==
// @name           Stackoverflow script
// @copyright      Author
// @version        1.0.0
// @namespace      https://xxxxxxxxxx/users/999999
// @homepageURL    https://xxxxxxxxxx/scripts/999999
// @description    stackoverflow sample
// @match          *
// @include        /^https?://
// @grant          none
// @author         author
// @license        (CC) by-nc-sa 3.0
// @run-at         document-start
// ==/UserScript==

window.jsl = window.jsl || {};
window.jsl.dh = function () {
     console.log('Called the dud');
};

//Object.freeze(window.jsl);

I had to comment out Object.freeze() because it throws an error at any attempt to modify window.jsl which would cause the site not to function as expected.

The console outputs "Called the dud" twice.

If you set // @grant none like John did, then there is no "sandbox" and it should work fine.

If you set @grant to something else like // @grant GM.getValue, there will be a "sandbox" and you cannot access the window of the page. But you can escape the sandbox by adding // @grant unsafeWindow and then access the page's window like this: unsafeWindow.jsl.dh = ...

Related