Tampermonkey: Calling lots of time to setTimeout and clearTimeout gives an error

Created on 8 May 2019  路  4Comments  路  Source: Tampermonkey/tampermonkey

Expected Behavior

Run the script that calls lots of time to setTimeout and clearTimeout as a throttler for an external event without issues

Actual Behavior

The script logs 2 times "timer triggered" and on the third I get an exception:
TypeError: Cannot convert undefined or null to object

Specifications

  • Chrome: 74.0.3729.131 (Build oficial) (64 bits)
  • TM: (i.e. 4.5.5648)
  • OS: Windows 10

Script

(Please give an example of the script if applicable.)

// ==UserScript==
// @id           setTimeoutTest
// @name         setTimeoutTest
// @version      0.1
// @description  test
// @author       Alfonso M.
// @match        *://*/*
// @grant        none
// ==/UserScript==

var timer;

function someHandler() {
    if (timer) {
        clearTimeout(timer);
    }
    timer = setTimeout(function () {
        timer = null;
        console.log('timer triggered');
    }, 1000);
}

function runIt() {
    for (var i = 0; i < 3000; i++) {
        someHandler();
    }
}

runIt();
setInterval(runIt, 5000);
bug external

Most helpful comment

In the meantime, you can circumvent the errors by making sure your calls to setInterval, setTimeout, clearTimeout, etc, are bound to the window object;

// ==UserScript==
// @id           setTimeoutTest
// @name         setTimeoutTest
// @version      0.1
// @description  test
// @author       Alfonso M.
// @match        *://*/*
// @grant        none
// ==/UserScript==

window.clearTimeout = window.clearTimeout.bind(window);
window.clearInterval = window.clearInterval.bind(window);
window.setTimeout = window.setTimeout.bind(window);
window.setInterval = window.setInterval.bind(window);
// ...
setInterval(runIt, 5000);

All 4 comments

Of course, I guess that this is a bug in Chrome itself not TamperMonkey, but I'm unable to recreate bug outside of a userscript.

In the meantime, you can circumvent the errors by making sure your calls to setInterval, setTimeout, clearTimeout, etc, are bound to the window object;

// ==UserScript==
// @id           setTimeoutTest
// @name         setTimeoutTest
// @version      0.1
// @description  test
// @author       Alfonso M.
// @match        *://*/*
// @grant        none
// ==/UserScript==

window.clearTimeout = window.clearTimeout.bind(window);
window.clearInterval = window.clearInterval.bind(window);
window.setTimeout = window.setTimeout.bind(window);
window.setInterval = window.setInterval.bind(window);
// ...
setInterval(runIt, 5000);

I had the same problem, I thought it was my scripts fault until I saw this.
Thank god it's not my script issue
I used the code above and it worked

Was this page helpful?
0 / 5 - 0 ratings