var domain = timer.domain;
var msecs = timer._idleTimeout;
+ L.remove(timer);
+
// Timer has been unenrolled by another timer that fired at the same time,
// so don't make it timeout.
- if (!msecs || msecs < 0)
+ if (msecs <= 0)
return;
if (!timer._onTimeout)
return;
- if (domain && domain._disposed)
- return;
+ if (domain) {
+ if (domain._disposed)
+ return;
- try {
- var threw = true;
+ domain.enter();
+ }
- if (domain) domain.enter();
+ debug('unreftimer firing timeout');
+ timer._called = true;
+ _runOnTimeout(timer);
- debug('unreftimer firing timeout');
- L.remove(timer);
- timer._called = true;
- timer._onTimeout();
+ if (domain)
+ domain.exit();
+}
+function _runOnTimeout(timer) {
+ var threw = true;
+ try {
+ timer._onTimeout();
threw = false;
-
- if (domain)
- domain.exit();
} finally {
if (threw) process.nextTick(unrefTimeout);
}
var timeSinceLastActive;
var nextTimeoutTime;
var nextTimeoutDuration;
- var minNextTimeoutTime;
+ var minNextTimeoutTime = TIMEOUT_MAX;
var timersToTimeout = [];
// The actual timer fired and has not yet been rearmed,
// and rearm the actual timer if the next timeout to expire
// will expire before the current actual timer.
var cur = unrefList._idlePrev;
- while (cur != unrefList) {
+ while (cur !== unrefList) {
timeSinceLastActive = now - cur._idleStart;
if (timeSinceLastActive < cur._idleTimeout) {
nextTimeoutDuration = cur._idleTimeout - timeSinceLastActive;
nextTimeoutTime = now + nextTimeoutDuration;
- if (minNextTimeoutTime == null ||
+ if (minNextTimeoutTime === TIMEOUT_MAX ||
(nextTimeoutTime < minNextTimeoutTime)) {
// We found a timeout that will expire earlier,
// store its next timeout time now so that we
// Rearm the actual timer with the timeout delay
// of the earliest timeout found.
- if (minNextTimeoutTime != null) {
+ if (minNextTimeoutTime !== TIMEOUT_MAX) {
unrefTimer.start(minNextTimeoutTime - now, 0);
unrefTimer.when = minNextTimeoutTime;
debug('unrefTimer rescheduled');
--- /dev/null
+'use strict';
+
+// https://github.com/nodejs/node/pull/2540/files#r38231197
+
+const common = require('../common');
+const timers = require('timers');
+const assert = require('assert');
+const domain = require('domain');
+
+// Crazy stuff to keep the process open,
+// then close it when we are actually done.
+const TEST_DURATION = common.platformTimeout(100);
+const keepOpen = setTimeout(function() {
+ throw new Error('Test timed out. keepOpen was not canceled.');
+}, TEST_DURATION);
+
+const endTest = makeTimer(2);
+
+const someTimer = makeTimer(1);
+someTimer.domain = domain.create();
+someTimer.domain.dispose();
+someTimer._onTimeout = function() {
+ throw new Error('someTimer was not supposed to fire!');
+};
+
+endTest._onTimeout = common.mustCall(function() {
+ assert.strictEqual(someTimer._idlePrev, null);
+ assert.strictEqual(someTimer._idleNext, null);
+ clearTimeout(keepOpen);
+});
+
+const cancelsTimer = makeTimer(1);
+cancelsTimer._onTimeout = common.mustCall(function() {
+ someTimer._idleTimeout = 0;
+});
+
+timers._unrefActive(cancelsTimer);
+timers._unrefActive(someTimer);
+timers._unrefActive(endTest);
+
+function makeTimer(msecs) {
+ const timer = {};
+ timers.unenroll(timer);
+ timers.enroll(timer, msecs);
+ return timer;
+}