Skip to content

Commit 40e9fcd

Browse files
ErickWendelUlisesGascon
authored andcommitted
test_runner: add support for setImmediate
PR-URL: #49397 Reviewed-By: Chemi Atlow <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]>
1 parent 23216f1 commit 40e9fcd

File tree

3 files changed

+312
-10
lines changed

3 files changed

+312
-10
lines changed

doc/api/test.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -1594,9 +1594,10 @@ added:
15941594
Enables timer mocking for the specified timers.
15951595

15961596
* `timers` {Array} An optional array containing the timers to mock.
1597-
The currently supported timer values are `'setInterval'` and `'setTimeout'`.
1598-
If no array is provided, all timers (`'setInterval'`, `'clearInterval'`, `'setTimeout'`,
1599-
and `'clearTimeout'`) will be mocked by default.
1597+
The currently supported timer values are `'setInterval'`, `'setTimeout'`,
1598+
and `'setImmediate'`. If no value is provided, all timers (`'setInterval'`,
1599+
`'clearInterval'`, `'setTimeout'`, `'clearTimeout'`, `'setImmediate'`,
1600+
and `'clearImmediate'`) will be mocked by default.
16001601

16011602
**Note:** When you enable mocking for a specific timer, its associated
16021603
clear function will also be implicitly mocked.

lib/internal/test_runner/mock/mock_timers.js

+72-5
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,19 @@ function abortIt(signal) {
4848
return new AbortError(undefined, { __proto__: null, cause: signal.reason });
4949
}
5050

51-
const SUPPORTED_TIMERS = ['setTimeout', 'setInterval'];
51+
const SUPPORTED_TIMERS = ['setTimeout', 'setInterval', 'setImmediate'];
52+
const TIMERS_DEFAULT_INTERVAL = {
53+
__proto__: null,
54+
setImmediate: -1,
55+
};
5256

5357
class MockTimers {
5458
#realSetTimeout;
5559
#realClearTimeout;
5660
#realSetInterval;
5761
#realClearInterval;
62+
#realSetImmediate;
63+
#realClearImmediate;
5864

5965
#realPromisifiedSetTimeout;
6066
#realPromisifiedSetInterval;
@@ -63,6 +69,9 @@ class MockTimers {
6369
#realTimersClearTimeout;
6470
#realTimersSetInterval;
6571
#realTimersClearInterval;
72+
#realTimersSetImmediate;
73+
#realTimersClearImmediate;
74+
#realPromisifiedSetImmediate;
6675

6776
#timersInContext = [];
6877
#isEnabled = false;
@@ -76,6 +85,16 @@ class MockTimers {
7685
#setInterval = FunctionPrototypeBind(this.#createTimer, this, true);
7786
#clearInterval = FunctionPrototypeBind(this.#clearTimer, this);
7887

88+
#setImmediate = (callback, ...args) => {
89+
return this.#createTimer(
90+
false,
91+
callback,
92+
TIMERS_DEFAULT_INTERVAL.setImmediate,
93+
...args,
94+
);
95+
};
96+
97+
#clearImmediate = FunctionPrototypeBind(this.#clearTimer, this);
7998
constructor() {
8099
emitExperimentalWarning('The MockTimers API');
81100
}
@@ -158,7 +177,7 @@ class MockTimers {
158177
yield* iterator;
159178
}
160179

161-
#setTimeoutPromisified(ms, result, options) {
180+
#promisifyTimer({ timerFn, clearFn, ms, result, options }) {
162181
return new Promise((resolve, reject) => {
163182
if (options?.signal) {
164183
try {
@@ -173,12 +192,12 @@ class MockTimers {
173192
}
174193

175194
const onabort = () => {
176-
this.#clearTimeout(id);
195+
clearFn(id);
177196
return reject(abortIt(options.signal));
178197
};
179198

180-
const id = this.#setTimeout(() => {
181-
return resolve(result || id);
199+
const id = timerFn(() => {
200+
return resolve(result);
182201
}, ms);
183202

184203
if (options?.signal) {
@@ -192,6 +211,28 @@ class MockTimers {
192211
});
193212
}
194213

214+
#setImmediatePromisified(result, options) {
215+
return this.#promisifyTimer({
216+
__proto__: null,
217+
timerFn: FunctionPrototypeBind(this.#setImmediate, this),
218+
clearFn: FunctionPrototypeBind(this.#clearImmediate, this),
219+
ms: TIMERS_DEFAULT_INTERVAL.setImmediate,
220+
result,
221+
options,
222+
});
223+
}
224+
225+
#setTimeoutPromisified(ms, result, options) {
226+
return this.#promisifyTimer({
227+
__proto__: null,
228+
timerFn: FunctionPrototypeBind(this.#setTimeout, this),
229+
clearFn: FunctionPrototypeBind(this.#clearTimeout, this),
230+
ms,
231+
result,
232+
options,
233+
});
234+
}
235+
195236
#toggleEnableTimers(activate) {
196237
const options = {
197238
__proto__: null,
@@ -233,6 +274,23 @@ class MockTimers {
233274
this,
234275
);
235276
},
277+
setImmediate: () => {
278+
this.#realSetImmediate = globalThis.setImmediate;
279+
this.#realClearImmediate = globalThis.clearImmediate;
280+
this.#realTimersSetImmediate = nodeTimers.setImmediate;
281+
this.#realTimersClearImmediate = nodeTimers.clearImmediate;
282+
283+
globalThis.setImmediate = this.#setImmediate;
284+
globalThis.clearImmediate = this.#clearImmediate;
285+
286+
nodeTimers.setImmediate = this.#setImmediate;
287+
nodeTimers.clearImmediate = this.#clearImmediate;
288+
289+
nodeTimersPromises.setImmediate = FunctionPrototypeBind(
290+
this.#setImmediatePromisified,
291+
this,
292+
);
293+
},
236294
},
237295
toReal: {
238296
__proto__: null,
@@ -254,6 +312,15 @@ class MockTimers {
254312

255313
nodeTimersPromises.setInterval = this.#realPromisifiedSetInterval;
256314
},
315+
setImmediate: () => {
316+
globalThis.setImmediate = this.#realSetImmediate;
317+
globalThis.clearImmediate = this.#realClearImmediate;
318+
319+
nodeTimers.setImmediate = this.#realTimersSetImmediate;
320+
nodeTimers.clearImmediate = this.#realTimersClearImmediate;
321+
322+
nodeTimersPromises.setImmediate = this.#realPromisifiedSetImmediate;
323+
},
257324
},
258325
};
259326

0 commit comments

Comments
 (0)