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