| // Flags: --expose-gc |
| 'use strict'; |
| |
| const common = require('../common'); |
| const { aborted } = require('util'); |
| const assert = require('assert'); |
| const { getEventListeners } = require('events'); |
| const { inspect } = require('util'); |
| |
| const { |
| test, |
| } = require('node:test'); |
| |
| test('Aborted works when provided a resource', async () => { |
| const ac = new AbortController(); |
| const promise = aborted(ac.signal, {}); |
| ac.abort(); |
| await promise; |
| assert.strictEqual(ac.signal.aborted, true); |
| assert.strictEqual(getEventListeners(ac.signal, 'abort').length, 0); |
| }); |
| |
| test('Aborted with gc cleanup', async () => { |
| // Test aborted with gc cleanup |
| const ac = new AbortController(); |
| |
| const abortedPromise = aborted(ac.signal, {}); |
| const { promise, resolve } = Promise.withResolvers(); |
| |
| setImmediate(common.mustCall(() => { |
| globalThis.gc(); |
| ac.abort(); |
| assert.strictEqual(ac.signal.aborted, true); |
| assert.strictEqual(getEventListeners(ac.signal, 'abort').length, 0); |
| resolve(); |
| })); |
| |
| await promise; |
| |
| // Ensure that the promise is still pending |
| assert.match(inspect(abortedPromise), /<pending>/); |
| }); |
| |
| test('Fails with error if not provided AbortSignal', async () => { |
| await Promise.all([{}, null, undefined, Symbol(), [], 1, 0, 1n, true, false, 'a', () => {}].map((sig) => |
| assert.rejects(aborted(sig, {}), { |
| code: 'ERR_INVALID_ARG_TYPE', |
| }) |
| )); |
| }); |
| |
| test('Fails if not provided a resource', async () => { |
| // Fails if not provided a resource |
| const ac = new AbortController(); |
| await Promise.all([null, undefined, 0, 1, 0n, 1n, Symbol(), '', 'a'].map((resource) => |
| assert.rejects(aborted(ac.signal, resource), { |
| code: 'ERR_INVALID_ARG_TYPE', |
| }) |
| )); |
| }); |
| |
| // To allow this case to be more flexibly tested on runtimes that do not have |
| // child_process.spawn, we lazily require it and skip the test if it is not |
| // present. |
| |
| let spawn; |
| function lazySpawn() { |
| if (spawn === undefined) { |
| try { |
| spawn = require('child_process').spawn; |
| } catch { |
| // Ignore if spawn does not exist. |
| } |
| } |
| return spawn; |
| } |
| |
| test('Does not hang forever', { skip: !lazySpawn() }, async () => { |
| const { promise, resolve } = Promise.withResolvers(); |
| const childProcess = spawn(process.execPath, ['--input-type=module']); |
| childProcess.on('exit', common.mustCall((code) => { |
| assert.strictEqual(code, 13); |
| resolve(); |
| })); |
| childProcess.stdin.end(` |
| import { aborted } from 'node:util'; |
| await aborted(new AbortController().signal, {}); |
| `); |
| await promise; |
| }); |