Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 74ca960

Browse filesBrowse files
committed
lib: initial experimental AbortController implementation
AbortController impl based very closely on: https://github.com/mysticatea/abort-controller Marked experimental. Not currently used by any of the existing promise apis. Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: #33527 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 3e2a300 commit 74ca960
Copy full SHA for 74ca960

File tree

Expand file treeCollapse file tree

14 files changed

+260
-0
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

14 files changed

+260
-0
lines changed
Open diff view settings
Collapse file

‎.eslintrc.js‎

Copy file name to clipboardExpand all lines: .eslintrc.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ module.exports = {
280280
'node-core/no-duplicate-requires': 'error',
281281
},
282282
globals: {
283+
AbortController: 'readable',
283284
Atomics: 'readable',
284285
BigInt: 'readable',
285286
BigInt64Array: 'readable',
Collapse file

‎doc/api/cli.md‎

Copy file name to clipboardExpand all lines: doc/api/cli.md
+8Lines changed: 8 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ Enable experimental Source Map V3 support for stack traces.
167167
Currently, overriding `Error.prepareStackTrace` is ignored when the
168168
`--enable-source-maps` flag is set.
169169

170+
### `--experimental-abortcontroller`
171+
<!-- YAML
172+
added: REPLACEME
173+
-->
174+
175+
Enable experimental `AbortController` and `AbortSignal` support.
176+
170177
### `--experimental-import-meta-resolve`
171178
<!-- YAML
172179
added:
@@ -1209,6 +1216,7 @@ Node.js options that are allowed are:
12091216
* `--disable-proto`
12101217
* `--enable-fips`
12111218
* `--enable-source-maps`
1219+
* `--experimental-abortcontroller`
12121220
* `--experimental-import-meta-resolve`
12131221
* `--experimental-json-modules`
12141222
* `--experimental-loader`
Collapse file

‎doc/api/globals.md‎

Copy file name to clipboardExpand all lines: doc/api/globals.md
+96Lines changed: 96 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,101 @@ The objects listed here are specific to Node.js. There are [built-in objects][]
1717
that are part of the JavaScript language itself, which are also globally
1818
accessible.
1919

20+
## Class: `AbortController`
21+
<!--YAML
22+
added: REPLACEME
23+
-->
24+
25+
> Stability: 1 - Experimental
26+
27+
<!-- type=global -->
28+
29+
A utility class used to signal cancelation in selected `Promise`-based APIs.
30+
The API is based on the Web API [`AbortController`][].
31+
32+
To use, launch Node.js using the `--experimental-abortcontroller` flag.
33+
34+
```js
35+
const ac = new AbortController();
36+
37+
ac.signal.addEventListener('abort', () => console.log('Aborted!'),
38+
{ once: true });
39+
40+
ac.abort();
41+
42+
console.log(ac.signal.aborted); // Prints True
43+
```
44+
45+
### `abortController.abort()`
46+
<!-- YAML
47+
added: REPLACEME
48+
-->
49+
50+
Triggers the abort signal, causing the `abortController.signal` to emit
51+
the `'abort'` event.
52+
53+
### `abortController.signal`
54+
<!-- YAML
55+
added: REPLACEME
56+
-->
57+
58+
* Type: {AbortSignal}
59+
60+
### Class: `AbortSignal extends EventTarget`
61+
<!-- YAML
62+
added: REPLACEME
63+
-->
64+
65+
The `AbortSignal` is used to notify observers when the
66+
`abortController.abort()` method is called.
67+
68+
#### Event: `'abort'`
69+
<!-- YAML
70+
added: REPLACEME
71+
-->
72+
73+
The `'abort'` event is emitted when the `abortController.abort()` method
74+
is called. The callback is invoked with a single object argument with a
75+
single `type` propety set to `'abort'`:
76+
77+
```js
78+
const ac = new AbortController();
79+
80+
// Use either the onabort property...
81+
ac.signal.onabort = () => console.log('aborted!');
82+
83+
// Or the EventTarget API...
84+
ac.signal.addEventListener('abort', (event) => {
85+
console.log(event.type); // Prints 'abort'
86+
}, { once: true });
87+
88+
ac.abort();
89+
```
90+
91+
The `AbortController` with which the `AbortSignal` is associated will only
92+
ever trigger the `'abort'` event once. Any event listeners attached to the
93+
`AbortSignal` *should* use the `{ once: true }` option (or, if using the
94+
`EventEmitter` APIs to attach a listener, use the `once()` method) to ensure
95+
that the event listener is removed as soon as the `'abort'` event is handled.
96+
Failure to do so may result in memory leaks.
97+
98+
#### `abortSignal.aborted`
99+
<!-- YAML
100+
added: REPLACEME
101+
-->
102+
103+
* Type: {boolean} True after the `AbortController` has been aborted.
104+
105+
#### `abortSignal.onabort`
106+
<!-- YAML
107+
added: REPLACEME
108+
-->
109+
110+
* Type: {Function}
111+
112+
An optional callback function that may be set by user code to be notified
113+
when the `abortController.abort()` function has been called.
114+
20115
## Class: `Buffer`
21116
<!-- YAML
22117
added: v0.1.103
@@ -226,6 +321,7 @@ The object that acts as the namespace for all W3C
226321
[WebAssembly][webassembly-org] related functionality. See the
227322
[Mozilla Developer Network][webassembly-mdn] for usage and compatibility.
228323

324+
[`AbortController`]: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
229325
[`TextDecoder`]: util.html#util_class_util_textdecoder
230326
[`TextEncoder`]: util.html#util_class_util_textencoder
231327
[`URLSearchParams`]: url.html#url_class_urlsearchparams
Collapse file

‎doc/node.1‎

Copy file name to clipboardExpand all lines: doc/node.1
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ Enable FIPS-compliant crypto at startup.
118118
Requires Node.js to be built with
119119
.Sy ./configure --openssl-fips .
120120
.
121+
.It Fl -experimental-abortcontroller
122+
Enable experimental AbortController and AbortSignal support.
123+
.
121124
.It Fl -enable-source-maps
122125
Enable experimental Source Map V3 support for stack traces.
123126
.
Collapse file

‎lib/internal/abort_controller.js‎

Copy file name to clipboard
+83Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
'use strict';
2+
3+
// Modeled very closely on the AbortController implementation
4+
// in https://github.com/mysticatea/abort-controller (MIT license)
5+
6+
const {
7+
Object,
8+
Symbol,
9+
} = primordials;
10+
11+
const {
12+
EventTarget,
13+
Event
14+
} = require('internal/event_target');
15+
const {
16+
customInspectSymbol,
17+
emitExperimentalWarning
18+
} = require('internal/util');
19+
const { inspect } = require('internal/util/inspect');
20+
21+
const kAborted = Symbol('kAborted');
22+
23+
function customInspect(self, obj, depth, options) {
24+
if (depth < 0)
25+
return self;
26+
27+
const opts = Object.assign({}, options, {
28+
depth: options.depth === null ? null : options.depth - 1
29+
});
30+
31+
return `${self.constructor.name} ${inspect(obj, opts)}`;
32+
}
33+
34+
class AbortSignal extends EventTarget {
35+
get aborted() { return !!this[kAborted]; }
36+
37+
[customInspectSymbol](depth, options) {
38+
return customInspect(this, {
39+
aborted: this.aborted
40+
}, depth, options);
41+
}
42+
}
43+
44+
Object.defineProperties(AbortSignal.prototype, {
45+
aborted: { enumerable: true }
46+
});
47+
48+
function abortSignal(signal) {
49+
if (signal[kAborted]) return;
50+
signal[kAborted] = true;
51+
const event = new Event('abort');
52+
if (typeof signal.onabort === 'function') {
53+
signal.onabort(event);
54+
}
55+
signal.dispatchEvent(event);
56+
}
57+
58+
class AbortController {
59+
#signal = new AbortSignal();
60+
61+
constructor() {
62+
emitExperimentalWarning('AbortController');
63+
}
64+
65+
get signal() { return this.#signal; }
66+
abort() { abortSignal(this.#signal); }
67+
68+
[customInspectSymbol](depth, options) {
69+
return customInspect(this, {
70+
signal: this.signal
71+
}, depth, options);
72+
}
73+
}
74+
75+
Object.defineProperties(AbortController.prototype, {
76+
signal: { enumerable: true },
77+
abort: { enumerable: true }
78+
});
79+
80+
module.exports = {
81+
AbortController,
82+
AbortSignal,
83+
};
Collapse file

‎lib/internal/bootstrap/pre_execution.js‎

Copy file name to clipboardExpand all lines: lib/internal/bootstrap/pre_execution.js
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const {
44
Map,
55
ObjectDefineProperty,
6+
ObjectDefineProperties,
67
SafeWeakMap,
78
} = primordials;
89

@@ -53,6 +54,7 @@ function prepareMainThreadExecution(expandArgv1 = false) {
5354
// (including preload modules).
5455
initializeClusterIPC();
5556

57+
initializeAbortController();
5658
initializeDeprecations();
5759
initializeWASI();
5860
initializeCJSLoader();
@@ -304,6 +306,30 @@ function initializeDeprecations() {
304306
});
305307
}
306308

309+
function initializeAbortController() {
310+
const abortController = getOptionValue('--experimental-abortcontroller');
311+
if (abortController) {
312+
const {
313+
AbortController,
314+
AbortSignal
315+
} = require('internal/abort_controller');
316+
ObjectDefineProperties(global, {
317+
AbortController: {
318+
writable: true,
319+
enumerable: false,
320+
configurable: true,
321+
value: AbortController
322+
},
323+
AbortSignal: {
324+
writable: true,
325+
enumerable: false,
326+
configurable: true,
327+
value: AbortSignal
328+
}
329+
});
330+
}
331+
}
332+
307333
function setupChildProcessIpcChannel() {
308334
if (process.env.NODE_CHANNEL_FD) {
309335
const assert = require('internal/assert');
@@ -438,6 +464,7 @@ module.exports = {
438464
setupWarningHandler,
439465
setupDebugEnv,
440466
prepareMainThreadExecution,
467+
initializeAbortController,
441468
initializeDeprecations,
442469
initializeESMLoader,
443470
initializeFrozenIntrinsics,
Collapse file

‎lib/internal/main/worker_thread.js‎

Copy file name to clipboardExpand all lines: lib/internal/main/worker_thread.js
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const {
1313
setupInspectorHooks,
1414
setupWarningHandler,
1515
setupDebugEnv,
16+
initializeAbortController,
1617
initializeDeprecations,
1718
initializeWASI,
1819
initializeCJSLoader,
@@ -112,6 +113,7 @@ port.on('message', (message) => {
112113
if (manifestSrc) {
113114
require('internal/process/policy').setup(manifestSrc, manifestURL);
114115
}
116+
initializeAbortController();
115117
initializeDeprecations();
116118
initializeWASI();
117119
initializeCJSLoader();
Collapse file

‎node.gyp‎

Copy file name to clipboardExpand all lines: node.gyp
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
'lib/wasi.js',
9696
'lib/worker_threads.js',
9797
'lib/zlib.js',
98+
'lib/internal/abort_controller.js',
9899
'lib/internal/assert.js',
99100
'lib/internal/assert/assertion_error.js',
100101
'lib/internal/assert/calltracker.js',
Collapse file

‎src/node_options.cc‎

Copy file name to clipboardExpand all lines: src/node_options.cc
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
274274
"experimental Source Map V3 support",
275275
&EnvironmentOptions::enable_source_maps,
276276
kAllowedInEnvironment);
277+
AddOption("--experimental-abortcontroller",
278+
"experimental AbortController support",
279+
&EnvironmentOptions::experimental_abortcontroller,
280+
kAllowedInEnvironment);
277281
AddOption("--experimental-json-modules",
278282
"experimental JSON interop support for the ES Module loader",
279283
&EnvironmentOptions::experimental_json_modules,
Collapse file

‎src/node_options.h‎

Copy file name to clipboardExpand all lines: src/node_options.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class EnvironmentOptions : public Options {
101101
public:
102102
bool abort_on_uncaught_exception = false;
103103
bool enable_source_maps = false;
104+
bool experimental_abortcontroller = false;
104105
bool experimental_json_modules = false;
105106
bool experimental_modules = false;
106107
std::string experimental_specifier_resolution;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.