• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const common = require('../common');
4const { ok, strictEqual } = require('assert');
5const { setImmediate: pause } = require('timers/promises');
6const {
7  transferableAbortSignal,
8  transferableAbortController,
9} = require('util');
10
11
12function deferred() {
13  let res;
14  const promise = new Promise((resolve) => res = resolve);
15  return { res, promise };
16}
17
18(async () => {
19  const ac = transferableAbortController();
20  const mc = new MessageChannel();
21
22  const deferred1 = deferred();
23  const deferred2 = deferred();
24  const resolvers = [deferred1, deferred2];
25
26  mc.port1.onmessage = common.mustCall(({ data }) => {
27    data.addEventListener('abort', common.mustCall(() => {
28      strictEqual(data.reason, 'boom');
29    }));
30    resolvers.shift().res();
31  }, 2);
32
33  mc.port2.postMessage(ac.signal, [ac.signal]);
34
35  // Can be cloned/transferd multiple times and they all still work
36  mc.port2.postMessage(ac.signal, [ac.signal]);
37
38  mc.port2.close();
39
40  // Although we're using transfer semantics, the local AbortSignal
41  // is still usable locally.
42  ac.signal.addEventListener('abort', common.mustCall(() => {
43    strictEqual(ac.signal.reason, 'boom');
44  }));
45
46  await Promise.all([ deferred1.promise, deferred2.promise ]);
47
48  ac.abort('boom');
49
50  // Because the postMessage used by the underlying AbortSignal
51  // takes at least one turn of the event loop to be processed,
52  // and because it is unref'd, it won't, by itself, keep the
53  // event loop open long enough for the test to complete, so
54  // we schedule two back to back turns of the event to ensure
55  // the loop runs long enough for the test to complete.
56  await pause();
57  await pause();
58
59})().then(common.mustCall());
60
61{
62  const signal = transferableAbortSignal(AbortSignal.abort('boom'));
63  ok(signal.aborted);
64  strictEqual(signal.reason, 'boom');
65  const mc = new MessageChannel();
66  mc.port1.onmessage = common.mustCall(({ data }) => {
67    ok(data instanceof AbortSignal);
68    ok(data.aborted);
69    strictEqual(data.reason, 'boom');
70    mc.port1.close();
71  });
72  mc.port2.postMessage(signal, [signal]);
73}
74
75{
76  // The cloned AbortSignal does not keep the event loop open
77  // waiting for the abort to be triggered.
78  const ac = transferableAbortController();
79  const mc = new MessageChannel();
80  mc.port1.onmessage = common.mustCall();
81  mc.port2.postMessage(ac.signal, [ac.signal]);
82  mc.port2.close();
83}
84