mirror of
https://github.com/nodejs/node.git
synced 2025-05-01 08:42:45 +00:00

Co-authored-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/44048 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
84 lines
2.3 KiB
JavaScript
84 lines
2.3 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const { ok, strictEqual } = require('assert');
|
|
const { setImmediate: pause } = require('timers/promises');
|
|
const {
|
|
transferableAbortSignal,
|
|
transferableAbortController,
|
|
} = require('util');
|
|
|
|
|
|
function deferred() {
|
|
let res;
|
|
const promise = new Promise((resolve) => res = resolve);
|
|
return { res, promise };
|
|
}
|
|
|
|
(async () => {
|
|
const ac = transferableAbortController();
|
|
const mc = new MessageChannel();
|
|
|
|
const deferred1 = deferred();
|
|
const deferred2 = deferred();
|
|
const resolvers = [deferred1, deferred2];
|
|
|
|
mc.port1.onmessage = common.mustCall(({ data }) => {
|
|
data.addEventListener('abort', common.mustCall(() => {
|
|
strictEqual(data.reason, 'boom');
|
|
}));
|
|
resolvers.shift().res();
|
|
}, 2);
|
|
|
|
mc.port2.postMessage(ac.signal, [ac.signal]);
|
|
|
|
// Can be cloned/transferd multiple times and they all still work
|
|
mc.port2.postMessage(ac.signal, [ac.signal]);
|
|
|
|
mc.port2.close();
|
|
|
|
// Although we're using transfer semantics, the local AbortSignal
|
|
// is still usable locally.
|
|
ac.signal.addEventListener('abort', common.mustCall(() => {
|
|
strictEqual(ac.signal.reason, 'boom');
|
|
}));
|
|
|
|
await Promise.all([ deferred1.promise, deferred2.promise ]);
|
|
|
|
ac.abort('boom');
|
|
|
|
// Because the postMessage used by the underlying AbortSignal
|
|
// takes at least one turn of the event loop to be processed,
|
|
// and because it is unref'd, it won't, by itself, keep the
|
|
// event loop open long enough for the test to complete, so
|
|
// we schedule two back to back turns of the event to ensure
|
|
// the loop runs long enough for the test to complete.
|
|
await pause();
|
|
await pause();
|
|
|
|
})().then(common.mustCall());
|
|
|
|
{
|
|
const signal = transferableAbortSignal(AbortSignal.abort('boom'));
|
|
ok(signal.aborted);
|
|
strictEqual(signal.reason, 'boom');
|
|
const mc = new MessageChannel();
|
|
mc.port1.onmessage = common.mustCall(({ data }) => {
|
|
ok(data instanceof AbortSignal);
|
|
ok(data.aborted);
|
|
strictEqual(data.reason, 'boom');
|
|
mc.port1.close();
|
|
});
|
|
mc.port2.postMessage(signal, [signal]);
|
|
}
|
|
|
|
{
|
|
// The cloned AbortSignal does not keep the event loop open
|
|
// waiting for the abort to be triggered.
|
|
const ac = transferableAbortController();
|
|
const mc = new MessageChannel();
|
|
mc.port1.onmessage = common.mustCall();
|
|
mc.port2.postMessage(ac.signal, [ac.signal]);
|
|
mc.port2.close();
|
|
}
|