tools: add lint rule for aborted AbortController · nodejs/node@5755712 · GitHub
Skip to content

Commit 5755712

Browse files
trivikraduh95
andcommitted
tools: add lint rule for aborted AbortController
Refs: #63489 Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com> Assisted-by: openai:gpt-5.5 PR-URL: #63541 Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent f32b412 commit 5755712

5 files changed

Lines changed: 277 additions & 3 deletions

File tree

test/eslint.config_partial.mjs

Lines changed: 1 addition & 0 deletions

test/parallel/test-abortcontroller.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ test('AbortController inspection depth 1 or null works', () => {
161161

162162
test('AbortSignal reason is set correctly', () => {
163163
// Test AbortSignal.reason
164+
// eslint-disable-next-line node-core/prefer-abort-signal-abort
164165
const ac = new AbortController();
165166
ac.abort('reason');
166167
assert.strictEqual(ac.signal.reason, 'reason');
@@ -235,6 +236,7 @@ test('AbortSignal.reason should default', () => {
235236
assert.ok(signal.reason instanceof DOMException);
236237
assert.strictEqual(signal.reason.code, 20);
237238

239+
// eslint-disable-next-line node-core/prefer-abort-signal-abort
238240
const ac = new AbortController();
239241
ac.abort();
240242
assert.ok(ac.signal.reason instanceof DOMException);
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if ((!common.hasCrypto) || (!common.hasIntl)) {
5+
common.skip('ESLint tests require crypto and Intl');
6+
}
7+
8+
common.skipIfEslintMissing();
9+
10+
const RuleTester = require('../../tools/eslint/node_modules/eslint').RuleTester;
11+
const rule = require('../../tools/eslint-rules/prefer-abort-signal-abort');
12+
13+
const message = 'Use AbortSignal.abort() instead of creating and aborting an AbortController.';
14+
15+
new RuleTester().run('prefer-abort-signal-abort', rule, {
16+
valid: [
17+
'const signal = AbortSignal.abort();',
18+
`
19+
const controller = new AbortController();
20+
controller.abort();
21+
controller.abort();
22+
fn(controller.signal);
23+
`,
24+
`
25+
const controller = new AbortController();
26+
controller.abort();
27+
console.log(controller);
28+
fn(controller.signal);
29+
`,
30+
`
31+
const controller = new AbortController();
32+
// This comment should not be removed.
33+
controller.abort();
34+
fn(controller.signal);
35+
`,
36+
`
37+
const controller = new AbortController();
38+
setImmediate(() => controller.abort());
39+
fn(controller.signal);
40+
`,
41+
`
42+
const controller = new AbortController();
43+
controller.abort('reason', 'extra');
44+
fn(controller.signal);
45+
`,
46+
],
47+
invalid: [
48+
{
49+
code: `
50+
const controller = new AbortController();
51+
controller.abort();
52+
fn(controller.signal);
53+
`,
54+
errors: [{ message }],
55+
output: `
56+
fn(AbortSignal.abort());
57+
`,
58+
},
59+
{
60+
code: `
61+
const abortController = new AbortController();
62+
abortController.abort(new Error('aborted'));
63+
fn({ signal: abortController.signal });
64+
`,
65+
errors: [{ message }],
66+
output: `
67+
fn({ signal: AbortSignal.abort(new Error('aborted')) });
68+
`,
69+
},
70+
{
71+
code: `
72+
{
73+
const ac = new AbortController();
74+
ac.abort();
75+
await wait({ signal: ac.signal });
76+
}
77+
`,
78+
errors: [{ message }],
79+
output: `
80+
{
81+
await wait({ signal: AbortSignal.abort() });
82+
}
83+
`,
84+
},
85+
{
86+
code: `
87+
{
88+
const controller = new AbortController();
89+
controller.abort();
90+
fn(controller.signal, controller.signal);
91+
}
92+
`,
93+
errors: [{ message }],
94+
output: `
95+
{
96+
const controller = AbortSignal.abort();
97+
fn(controller, controller);
98+
}
99+
`,
100+
},
101+
{
102+
code: `
103+
{
104+
const controller = new AbortController();
105+
controller.abort("reason");
106+
fn(controller.signal, controller.signal);
107+
}
108+
`,
109+
errors: [{ message }],
110+
output: `
111+
{
112+
const controller = AbortSignal.abort("reason");
113+
fn(controller, controller);
114+
}
115+
`,
116+
},
117+
]
118+
});

test/parallel/test-quic-writer-abort-signal.mjs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,11 @@ const stream = await clientSession.createBidirectionalStream();
3333
const w = stream.writer;
3434

3535
// Create an already-aborted signal.
36-
const ac = new AbortController();
37-
ac.abort(new Error('already aborted'));
36+
const signal = AbortSignal.abort(new Error('already aborted'));
3837

3938
// write() with an already-aborted signal should reject immediately.
4039
await rejects(
41-
w.write(encoder.encode('data'), { signal: ac.signal }),
40+
w.write(encoder.encode('data'), { signal }),
4241
{ message: 'already aborted' },
4342
);
4443

Lines changed: 154 additions & 0 deletions

0 commit comments

Comments
 (0)