-
Notifications
You must be signed in to change notification settings - Fork 408
fix double patched timers in older node versions #744
Conversation
@manuelschneider , I think the purpose of the original logic is
So I think we should still need to patch global.setTimeout if global.setTimeout not using timer.js, to confirm that, I think we should not compare the reference, but we have to check the result which returned from setTimeout. something like this
And we should add test cases to simulate that global don't use timers' setTimeout/immediate/Interval case. |
@JiaLiPassion what do you think we should do with this PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should check whether global setTimeout using timers setTimeout
@JiaLiPassion I don't think we should rely on the zone-patched return object to decide if the method needs patching, as it seems undocumented to me, and therefore may change in the future. This is why I went with the above solution. My quick research revealed that the mentioned ones are the only variants in 'vanilla' node. If something else patches the timers, the assumption behind the zone-patched return objects also turns out Only supporting vanilla node leaves us in my view with two options:
I'd still stick to the latter, but maybe I'm not seeing a third solution here. |
@manuelschneider var timer = require('timers');
console.log('global.setTimeout', global.setTimeout.toString());
console.log('timer.setTimeout', timer.setTimeout.toString());
console.log('equal', global.setTimeout === timer.setTimeout); So my previous comment means we should check global.setTimeout use timers.setTimeout or not , not only check And you are right #440 fix #437, thank you for the info. But it seems the fix have been reverted. |
That is correct. If the reference is equal it means we have to wrap both entrypoints. If it's not equal, there's no way to know if the two functions call each other. We can assume it by either
|
That's why I think we should use detect code like this const timer = require('timer');
const originSetTimeout = timer.setTimeout;
let globalUseTimeoutFromTimer = false;
timer.setTimeout = function() {
globalUseTimeoutFromTimer = true;
return originSetTimeout.apply(this, arguments);
}
const detectTimeout = global.setTimeout(noop, 100);
clearTimeout(detectTimeout);
timer.setTimeout = originSetTimeout;
patchTimer(timer);
if (!globalUseTimeoutFromTimer) {
patchTimer(global);
} |
That looks like a third solution :) |
@manuelschneider , thanks for confirm, and I would like to consider to fix this one with #437, because the #440 seems to be gone. |
…e, fix nodejs v0.10.x timer issue
…e, fix nodejs v0.10.x timer issue
Maybe due to this, after updating from 0.8.9 to 0.8.10, I get this error:
Using Electron and |
@MitchTalmadge , thanks for posting the issue, I will make a PR to fix it |
* fix(patch): fix #744, add namespace to load patch name * in electron, we only patch timers.setTimeout * refactor browser/node module load structure
Differences between the node versions with regards to patching timers are:
timers
-module and executing the appropriete function.global.clearImmediate = timers.clearImmediate;
This means:
Because the tests aren't compatible to v0.10, I have no testcase for this. But getting exact stacktraces is simple:
Problem is:
shouldPatchGlobalTimers
is alwaystrue
, because the method in old node, which does the lazy loading is not equal to the patched method from timers.If this was the reason behind
shouldPatchGlobalTimers
, the linked commit should do the trick:At least the stacktraces look great after the change: