I'm working on a project that requires my user script be run on pages as they are rendered without executing any of the page's JavaScript. That is to say, we need to browse with JavaScript disabled.
I've encountered a problem though when I try to delay execution of a function within my script. Whenever I make a call to window.setTimeout
, the function I pass in never gets executed.
I think maybe this function is actually getting called on unsafeWindow
instead of window. Is there any workaround for this?
I should mention that calls to setTimeout
work fine when JavaScript is enabled and everything else in my script is working fine without enabling JavaScript.
Thanks for your help!
Explanation: setTimeout() is non-blocking which means it will run when the statements outside of it have executed and then after one second it will execute. All other statements that are not part of setTimeout() are blocking which means no other statement will execute before the current statement finishes.
While famously known as “JavaScript Timers”, functions like setTimeout and setInterval are not part of the ECMAScript specs or any JavaScript engine implementations. Timer functions are implemented by browsers and their implementations will be different among different browsers.
The setInterval method has the same syntax as setTimeout : let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...) All arguments have the same meaning. But unlike setTimeout it runs the function not only once, but regularly after the given interval of time.
We all know that passing a string to setTimeout (or setInterval ) is evil, because it is run in the global scope, has performance issues, is potentially insecure if you're injecting any parameters, etc. So doing this is definitely deprecated: setTimeout('doSomething(someVar)', 10000);
Even though Greasemonkey JavaScript runs with elevated privileges, as Pointy said, setTimeout
functions are appended to the page's JavaScript space -- wrapped in a closure as needed. (In normal operation, the Greasemonkey instance is often gone by the time any timers, it has set, fire.)
So, if the page's main JavaScript is disabled, the timer will never run.
Possible workarounds:
Use GM_xmlhttpRequest
as a crude delay. You can setup a page that deliberately draws out its response. So code like:
GM_xmlhttpRequest
(
{
method: "GET",
url: "http://YourTestServer.com/DelayService.php?Seconds=2",
onload: function (response) {YourDelayedFunctionHere (); }
}
);
Would call a utility page that you set up to do the delay for you.
Use NoScript to disable all of the page's JavaScript except for the main page. For example, for page, YourSite.com/testpage.htm, which includes scripts from, say, *SpamGenerator.net... Allow scripts from YourSite.com but block them from SpamGenerator.net.
The window
reference is still the page's window
, just wrapped in the sandbox wrapper thing. When you call setTimeout
on it you're still setting up something to be run by the page. I suppose that it must be the case that the browser won't fire those timeout events at all (or will just ignore the events) when Javascript is disabled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With