Timers in the Window context prevent Node.js process from exit and window object from GC clean-up
See original GitHub issueIf FetchExternalResources
and ProcessExternalResources
contain 'script'
and page scripts set timers, Node.js process does not exit.
Test code 1 (page scripts with some possible timers are under user’s control):
const jsdom = require('jsdom');
jsdom.env({
html: `
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
window.document.title = 'Scripted Title';
window.setInterval(() => {}, 1000);
</script>
</body>
</html>
`,
done: (err, window) => {
console.log(window.document.title);
},
features: {
FetchExternalResources: ['script'],
ProcessExternalResources: ['script']
},
});
After logged output the script just freezes. However, if all timers are cleaned up, the script exits properly:
const jsdom = require('jsdom');
jsdom.env({
html: `
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
window.document.title = 'Scripted Title';
window.setInterval(() => {}, 1000);
</script>
</body>
</html>
`,
done: (err, window) => {
console.log(window.document.title);
let id = window.setTimeout(() => {}, 0);
console.log(id);
while (id) {
window.clearTimeout(id);
id--;
}
id = window.setInterval(() => {}, 0);
console.log(id);
while (id) {
window.clearInterval(id);
id--;
}
},
features: {
FetchExternalResources: ['script'],
ProcessExternalResources: ['script']
},
});
Test code 2 (page scripts with many timers are beyond easy user’s control):
const jsdom = require('jsdom');
jsdom.env({
url: 'http://www.nytimes.com/',
done: (err, window) => {
console.log(window.document.title);
},
features: {
FetchExternalResources: ['script'],
ProcessExternalResources: ['script']
},
});
After logged output the script just freezes as well. And if all timers are cleaned up, the script exits properly too:
const jsdom = require('jsdom');
jsdom.env({
url: 'http://www.nytimes.com/',
done: (err, window) => {
console.log(window.document.title);
let id = window.setTimeout(() => {}, 0);
console.log(id);
while (id) {
window.clearTimeout(id);
id--;
}
id = window.setInterval(() => {}, 0);
console.log(id);
while (id) {
window.clearInterval(id);
id--;
}
},
features: {
FetchExternalResources: ['script'],
ProcessExternalResources: ['script']
},
});
Issue Analytics
- State:
- Created 7 years ago
- Comments:5 (5 by maintainers)
Top Results From Across the Web
Timers in Node.js
The Timers module in Node.js contains functions that execute code after a set period ... This function is similar to window. ... The...
Read more >Timers | Node.js v19.3.0 Documentation
This object is created internally and is returned from setTimeout() and setInterval() . It can be passed to either clearTimeout() or clearInterval() in...
Read more >Node.js v19.3.0 Documentation
Creates a new CallTracker object which can be used to track if functions were called a specific number of times. The tracker.verify() must...
Read more >The Node.js Event Loop, Timers, and process.nextTick()
timers : this phase executes callbacks scheduled by setTimeout() and setInterval() . · pending callbacks: executes I/O callbacks deferred to the next loop ......
Read more >Process | Node.js v19.3.0 Documentation
The 'beforeExit' event is emitted when Node.js empties its event loop and has no additional work to schedule. Normally, the Node.js process will...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
There’s no way to execute code in the future without keeping the process in which that code will execute alive. So documenting seems like the way to go here.
Well, I am not a native English speaker and my English is bad, so maybe I should not suggest a large amount of the text. However, something like that (with your additions and corrections) may be helpful:
It should be taken into consideration, that timers in the page scripts (set by
window.setImmediate()
,window.setInterval()
andwindow.setTimeout()
) could preventwindow
object from being GC-ed and thereby could cause memory leaks. These timers also could interfere with main process eventloop and prevent the script from natural exit after eventloop drain. To mitigate these risks,window.close()
should be called after each document processing completion if page scripts execution is activated.