1// Flags: --no-warnings --expose-internals
2'use strict';
3const common = require('../common');
4const assert = require('assert');
5const timers = require('timers');
6const { promisify } = require('util');
7const child_process = require('child_process');
8
9const { getEventListeners } = require('events');
10const { NodeEventTarget } = require('internal/event_target');
11
12const timerPromises = require('timers/promises');
13
14const setPromiseImmediate = promisify(timers.setImmediate);
15const exec = promisify(child_process.exec);
16
17assert.strictEqual(setPromiseImmediate, timerPromises.setImmediate);
18
19process.on('multipleResolves', common.mustNotCall());
20
21{
22  const promise = setPromiseImmediate();
23  promise.then(common.mustCall((value) => {
24    assert.strictEqual(value, undefined);
25  }));
26}
27
28{
29  const promise = setPromiseImmediate('foobar');
30  promise.then(common.mustCall((value) => {
31    assert.strictEqual(value, 'foobar');
32  }));
33}
34
35{
36  const ac = new AbortController();
37  const signal = ac.signal;
38  assert.rejects(setPromiseImmediate(10, { signal }), /AbortError/)
39    .then(common.mustCall());
40  ac.abort();
41}
42
43{
44  const signal = AbortSignal.abort(); // Abort in advance
45  assert.rejects(setPromiseImmediate(10, { signal }), /AbortError/)
46    .then(common.mustCall());
47}
48
49{
50  // Check that aborting after resolve will not reject.
51  const ac = new AbortController();
52  const signal = ac.signal;
53  setPromiseImmediate(10, { signal })
54    .then(common.mustCall(() => { ac.abort(); }))
55    .then(common.mustCall());
56}
57
58{
59  // Check that timer adding signals does not leak handlers
60  const signal = new NodeEventTarget();
61  signal.aborted = false;
62  setPromiseImmediate(0, { signal }).finally(common.mustCall(() => {
63    assert.strictEqual(getEventListeners(signal, 'abort').length, 0);
64  }));
65}
66
67{
68  Promise.all(
69    [1, '', false, Infinity].map(
70      (i) => assert.rejects(setPromiseImmediate(10, i), {
71        code: 'ERR_INVALID_ARG_TYPE'
72      })
73    )
74  ).then(common.mustCall());
75
76  Promise.all(
77    [1, '', false, Infinity, null, {}].map(
78      (signal) => assert.rejects(setPromiseImmediate(10, { signal }), {
79        code: 'ERR_INVALID_ARG_TYPE'
80      })
81    )
82  ).then(common.mustCall());
83
84  Promise.all(
85    [1, '', Infinity, null, {}].map(
86      (ref) => assert.rejects(setPromiseImmediate(10, { ref }), {
87        code: 'ERR_INVALID_ARG_TYPE'
88      })
89    )
90  ).then(common.mustCall());
91}
92
93{
94  exec(`${process.execPath} -pe "const assert = require('assert');` +
95    'require(\'timers/promises\').setImmediate(null, { ref: false }).' +
96    'then(assert.fail)"').then(common.mustCall(({ stderr }) => {
97    assert.strictEqual(stderr, '');
98  }));
99}
100
101(async () => {
102  const signal = AbortSignal.abort('boom');
103  await assert.rejects(timerPromises.setImmediate(undefined, { signal }), {
104    cause: 'boom',
105  });
106})().then(common.mustCall());
107