I'm getting into user scripting with tampermonkey and can't get through this error, any help would be appreciated.
I detect keys fine, space key triggers this function who will repeat itself as long as the key remains in the down position. The console writes the output normally for 30 seconds more or less and then there's a TypeError.
As per reputation-restriction, here's a screenshot:
User-Script:
// ==UserScript==
// @name TEST STUFF--------------------
// @namespace /
// @version 0.1
// @description try to take over the world!
// @author You
// @run-at document-start
// @include http://*
// @include https://*
// @grant none
// ==/UserScript==
( function()
{
'use strict';
window.addEventListener ( "keydown", CaptureKeyPress );
window.addEventListener ( "keyup", CaptureKeyPress );
var Hotkeys =
{
perform: 32
};
var HotkeyToggle = false;
function CaptureKeyPress ( a )
{
if ( a.keyCode == Hotkeys.perform )
{
a.preventDefault();
a.stopPropagation();
a.cancelBubble = true;
a.stopImmediatePropagation();
if ( a.type == "keydown" && !HotkeyToggle )
{
console.clear();
HotkeyToggle = true;
perform();
}
if ( a.type == "keyup" && HotkeyToggle )
{
HotkeyToggle = false;
}
}
}
function perform()
{
if(HotkeyToggle == false) // exit
{
return 0
}
//do stuff...
console.info("working...");
if(HotkeyToggle == true) // continue after everything pletes
{
setTimeout(() => {
perform()
}, 280);
return 0
}
return 1
}
} ) ();
I'm getting into user scripting with tampermonkey and can't get through this error, any help would be appreciated.
I detect keys fine, space key triggers this function who will repeat itself as long as the key remains in the down position. The console writes the output normally for 30 seconds more or less and then there's a TypeError.
As per reputation-restriction, here's a screenshot:
User-Script:
// ==UserScript==
// @name TEST STUFF--------------------
// @namespace http://tampermonkey/
// @version 0.1
// @description try to take over the world!
// @author You
// @run-at document-start
// @include http://*
// @include https://*
// @grant none
// ==/UserScript==
( function()
{
'use strict';
window.addEventListener ( "keydown", CaptureKeyPress );
window.addEventListener ( "keyup", CaptureKeyPress );
var Hotkeys =
{
perform: 32
};
var HotkeyToggle = false;
function CaptureKeyPress ( a )
{
if ( a.keyCode == Hotkeys.perform )
{
a.preventDefault();
a.stopPropagation();
a.cancelBubble = true;
a.stopImmediatePropagation();
if ( a.type == "keydown" && !HotkeyToggle )
{
console.clear();
HotkeyToggle = true;
perform();
}
if ( a.type == "keyup" && HotkeyToggle )
{
HotkeyToggle = false;
}
}
}
function perform()
{
if(HotkeyToggle == false) // exit
{
return 0
}
//do stuff...
console.info("working...");
if(HotkeyToggle == true) // continue after everything pletes
{
setTimeout(() => {
perform()
}, 280);
return 0
}
return 1
}
} ) ();
HotkeyToggle
is null when the perform()
is called from the setTimeout()
function.
– Bagus Tesa
Commented
Mar 24, 2019 at 23:51
SetTimeouts
. It seems the closure on window
can be lost if during certain types of recursion, for instance I was redefining the function that called SetTimeout()
several times, sometimes recursively and it seems like a memory management problem because I receive an error indicating SetTimeout
is null like this, but only seemingly randomly.
– Motomotes
Commented
Jun 6, 2019 at 18:27
This is either a TamperMonkey-specific issue, or a new security policy/bug in Chrome itself - I've ran into the same thing and caught it in the debugger, and none of the arguments are null/undefined; setTimeout is not overriden.
Edit: A shared trait between the userscript in question and the one that I was debugging is the "recursive" use of setTimeout. I changed it to be a setInterval
instead, and that seems to have fixed it in my case.
This is a confirmed bug in Chrome:
Reported on TM github
Reported on bugs.chromium
Another solution which looks to work is to .bind
the functions to window
, eg:
window.clearTimeout = window.clearTimeout.bind(window);
window.clearInterval = window.clearInterval.bind(window);
window.setTimeout = window.setTimeout.bind(window);
window.setInterval = window.setInterval.bind(window);
The bug should be fixed in Chrome 75.
I had the same issue using Tampermonkey and Google Chrome. What worked for me was using window.setTimeout
instead of setTimeout
.