summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/timers.js6
-rw-r--r--test/async-hooks/test-timers.setTimeout.js61
2 files changed, 64 insertions, 3 deletions
diff --git a/lib/timers.js b/lib/timers.js
index 4d41b5dc8a..954c73f602 100644
--- a/lib/timers.js
+++ b/lib/timers.js
@@ -289,7 +289,7 @@ TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) {
// An optimization so that the try/finally only de-optimizes (since at least v8
// 4.7) what is in this smaller function.
-function tryOnTimeout(timer) {
+function tryOnTimeout(timer, start) {
timer._called = true;
const timerAsyncId = (typeof timer[async_id_symbol] === 'number') ?
timer[async_id_symbol] : null;
@@ -297,7 +297,7 @@ function tryOnTimeout(timer) {
if (timerAsyncId !== null)
emitBefore(timerAsyncId, timer[trigger_async_id_symbol]);
try {
- ontimeout(timer);
+ ontimeout(timer, start);
threw = false;
} finally {
if (timerAsyncId !== null) {
@@ -520,7 +520,7 @@ function unrefdHandle(now) {
try {
// Don't attempt to call the callback if it is not a function.
if (typeof this.owner._onTimeout === 'function') {
- ontimeout(this.owner, now);
+ tryOnTimeout(this.owner, now);
}
} finally {
// Make sure we clean up if the callback is no longer a function
diff --git a/test/async-hooks/test-timers.setTimeout.js b/test/async-hooks/test-timers.setTimeout.js
new file mode 100644
index 0000000000..8f1d3222dd
--- /dev/null
+++ b/test/async-hooks/test-timers.setTimeout.js
@@ -0,0 +1,61 @@
+'use strict';
+
+const common = require('../common');
+const assert = require('assert');
+const tick = require('./tick');
+const initHooks = require('./init-hooks');
+const { checkInvocations } = require('./hook-checks');
+const TIMEOUT = common.platformTimeout(100);
+
+const hooks = initHooks();
+hooks.enable();
+
+// install first timeout
+setTimeout(common.mustCall(ontimeout), TIMEOUT);
+const as = hooks.activitiesOfTypes('Timeout');
+assert.strictEqual(as.length, 1);
+const t1 = as[0];
+assert.strictEqual(t1.type, 'Timeout');
+assert.strictEqual(typeof t1.uid, 'number');
+assert.strictEqual(typeof t1.triggerAsyncId, 'number');
+checkInvocations(t1, { init: 1 }, 't1: when first timer installed');
+
+let timer;
+let t2;
+function ontimeout() {
+ checkInvocations(t1, { init: 1, before: 1 }, 't1: when first timer fired');
+
+ setTimeout(onSecondTimeout, TIMEOUT).unref();
+ const as = hooks.activitiesOfTypes('Timeout');
+ t2 = as[1];
+ assert.strictEqual(as.length, 2);
+ checkInvocations(t1, { init: 1, before: 1 },
+ 't1: when second timer installed');
+ checkInvocations(t2, { init: 1 },
+ 't2: when second timer installed');
+
+ timer = setTimeout(common.mustNotCall(), 2 ** 31 - 1);
+}
+
+function onSecondTimeout() {
+ const as = hooks.activitiesOfTypes('Timeout');
+ assert.strictEqual(as.length, 3);
+ checkInvocations(t1, { init: 1, before: 1, after: 1 },
+ 't1: when second timer fired');
+ checkInvocations(t2, { init: 1, before: 1 },
+ 't2: when second timer fired');
+ clearTimeout(timer);
+ tick(2);
+}
+
+process.on('exit', onexit);
+
+function onexit() {
+ hooks.disable();
+ hooks.sanityCheck('Timeout');
+
+ checkInvocations(t1, { init: 1, before: 1, after: 1, destroy: 1 },
+ 't1: when process exits');
+ checkInvocations(t2, { init: 1, before: 1, after: 1, destroy: 1 },
+ 't2: when process exits');
+}