1import * as common from '../common/index.mjs'; 2import { describe, it } from 'node:test'; 3import { once } from 'node:events'; 4import assert from 'node:assert'; 5 6describe('AbortSignal.any()', { concurrency: true }, () => { 7 it('should throw when not receiving an array', () => { 8 const expectedError = { code: 'ERR_INVALID_ARG_TYPE' }; 9 assert.throws(() => AbortSignal.any(), expectedError); 10 assert.throws(() => AbortSignal.any(null), expectedError); 11 assert.throws(() => AbortSignal.any(undefined), expectedError); 12 }); 13 14 it('should throw when input contains non-signal values', () => { 15 assert.throws( 16 () => AbortSignal.any([AbortSignal.abort(), undefined]), 17 { 18 code: 'ERR_INVALID_ARG_TYPE', 19 message: 'The "signals[1]" argument must be an instance of AbortSignal. Received undefined' 20 }, 21 ); 22 }); 23 24 it('creates a non-aborted signal for an empty input', () => { 25 const signal = AbortSignal.any([]); 26 assert.strictEqual(signal.aborted, false); 27 signal.addEventListener('abort', common.mustNotCall()); 28 }); 29 30 it('returns a new signal', () => { 31 const originalSignal = new AbortController().signal; 32 const signalAny = AbortSignal.any([originalSignal]); 33 assert.notStrictEqual(originalSignal, signalAny); 34 }); 35 36 it('returns an aborted signal if input has an aborted signal', () => { 37 const signal = AbortSignal.any([AbortSignal.abort('some reason')]); 38 assert.strictEqual(signal.aborted, true); 39 assert.strictEqual(signal.reason, 'some reason'); 40 signal.addEventListener('abort', common.mustNotCall()); 41 }); 42 43 it('returns an aborted signal with the reason of first aborted signal input', () => { 44 const signal = AbortSignal.any([AbortSignal.abort('some reason'), AbortSignal.abort('another reason')]); 45 assert.strictEqual(signal.aborted, true); 46 assert.strictEqual(signal.reason, 'some reason'); 47 signal.addEventListener('abort', common.mustNotCall()); 48 }); 49 50 it('returns the correct signal in the event target', async () => { 51 const signal = AbortSignal.any([AbortSignal.timeout(5)]); 52 const interval = setInterval(() => {}, 100000); // Keep event loop alive 53 const [{ target }] = await once(signal, 'abort'); 54 clearInterval(interval); 55 assert.strictEqual(target, signal); 56 assert.ok(signal.aborted); 57 assert.strictEqual(signal.reason.name, 'TimeoutError'); 58 }); 59 60 it('aborts with reason of first aborted signal', () => { 61 const controllers = Array.from({ length: 3 }, () => new AbortController()); 62 const combinedSignal = AbortSignal.any(controllers.map((c) => c.signal)); 63 controllers[1].abort(1); 64 controllers[2].abort(2); 65 assert.ok(combinedSignal.aborted); 66 assert.strictEqual(combinedSignal.reason, 1); 67 }); 68 69 it('can accept the same signal more than once', () => { 70 const controller = new AbortController(); 71 const signal = AbortSignal.any([controller.signal, controller.signal]); 72 assert.strictEqual(signal.aborted, false); 73 controller.abort('reason'); 74 assert.ok(signal.aborted); 75 assert.strictEqual(signal.reason, 'reason'); 76 }); 77 78 it('handles deeply aborted signals', async () => { 79 const controllers = Array.from({ length: 2 }, () => new AbortController()); 80 const composedSignal1 = AbortSignal.any([controllers[0].signal]); 81 const composedSignal2 = AbortSignal.any([composedSignal1, controllers[1].signal]); 82 83 composedSignal2.onabort = common.mustCall(); 84 controllers[0].abort(); 85 assert.ok(composedSignal2.aborted); 86 assert.ok(composedSignal2.reason instanceof DOMException); 87 assert.strictEqual(composedSignal2.reason.name, 'AbortError'); 88 }); 89 90 it('executes abort handlers in correct order', () => { 91 const controller = new AbortController(); 92 const signals = []; 93 signals.push(controller.signal); 94 signals.push(AbortSignal.any([controller.signal])); 95 signals.push(AbortSignal.any([controller.signal])); 96 signals.push(AbortSignal.any([signals[0]])); 97 signals.push(AbortSignal.any([signals[1]])); 98 99 let result = ''; 100 signals.forEach((signal, i) => signal.addEventListener('abort', () => result += i)); 101 controller.abort(); 102 assert.strictEqual(result, '01234'); 103 }); 104}); 105