Skip to content

Commit

Permalink
doc: remove all references to internal AbortError
Browse files Browse the repository at this point in the history
This is done to prepare user code for signal.reason, which will allow
custom errors to be thrown on aborts. Custom errors means that it
will not be possible to conclusively determine if an error is from an
`ac.abort()`, just by looking at it. By not declaring what error is
thrown, node is also free to change it to
`new DOMException(message, 'AbortError')` in a future release. This
also avoids the possible addition of a public `AbortError` to node.

The thrown errors will remain instances of the internal `AbortError`
for now, to avoid effecting existing user code.

While signal.aborted can be used to detect aborted errors in most
cases, it does fully not work for the stream pipeline API, where
individual streams are destroyed with
`stream.destroy(new AbortError())`. Here the stream can no longer
fully detect aborts. However, I don't think this is ever relevant, as
streams should always perform the same cleanup logic, regardless of
what error is passed. If it doesn't support a signal option, it does
not make sense to include logic to handle signal aborts.

Refs: nodejs#40692
Refs: nodejs#38361
Refs: whatwg/dom#1027
  • Loading branch information
kanongil committed Nov 19, 2021
1 parent 7518743 commit 937a17c
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 33 deletions.
24 changes: 12 additions & 12 deletions doc/api/child_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,15 @@ lsExample();
```

If the `signal` option is enabled, calling `.abort()` on the corresponding
`AbortController` is similar to calling `.kill()` on the child process except
the error passed to the callback will be an `AbortError`:
`AbortController` is similar to calling `.kill()` on the child process except a
different error is passed:

```js
const { exec } = require('child_process');
const controller = new AbortController();
const { signal } = controller;
const child = exec('grep ssh', { signal }, (error) => {
console.log(error); // an AbortError
console.log('aborted', signal.aborted); // true
});
controller.abort();
```
Expand Down Expand Up @@ -373,15 +373,15 @@ function. Any input containing shell metacharacters may be used to trigger
arbitrary command execution.**

If the `signal` option is enabled, calling `.abort()` on the corresponding
`AbortController` is similar to calling `.kill()` on the child process except
the error passed to the callback will be an `AbortError`:
`AbortController` is similar to calling `.kill()` on the child process except a
different error is passed:

```js
const { execFile } = require('child_process');
const controller = new AbortController();
const { signal } = controller;
const child = execFile('node', ['--version'], { signal }, (error) => {
console.log(error); // an AbortError
console.log('aborted', signal.aborted); // true
});
controller.abort();
```
Expand Down Expand Up @@ -488,8 +488,8 @@ The `shell` option available in [`child_process.spawn()`][] is not supported by
`child_process.fork()` and will be ignored if set.

If the `signal` option is enabled, calling `.abort()` on the corresponding
`AbortController` is similar to calling `.kill()` on the child process except
the error passed to the callback will be an `AbortError`:
`AbortController` is similar to calling `.kill()` on the child process except a
different error is passed:

```js
if (process.argv[2] === 'child') {
Expand All @@ -502,7 +502,7 @@ if (process.argv[2] === 'child') {
const { signal } = controller;
const child = fork(__filename, ['child'], { signal });
child.on('error', (err) => {
// This will be called with err being an AbortError if the controller aborts
// This will be called with true signal.aborted if the controller aborts
});
controller.abort(); // Stops the child process
}
Expand Down Expand Up @@ -689,16 +689,16 @@ parameter passed to `spawn` from the parent, retrieve it with the
`process.argv0` property instead.

If the `signal` option is enabled, calling `.abort()` on the corresponding
`AbortController` is similar to calling `.kill()` on the child process except
the error passed to the callback will be an `AbortError`:
`AbortController` is similar to calling `.kill()` on the child process except a
different error is passed:

```js
const { spawn } = require('child_process');
const controller = new AbortController();
const { signal } = controller;
const grep = spawn('grep', ['ssh'], { signal });
grep.on('error', (err) => {
// This will be called with err being an AbortError if the controller aborts
// This will be called with true signal.aborted if the controller aborts
});
controller.abort(); // Stops the child process
```
Expand Down
14 changes: 7 additions & 7 deletions doc/api/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ with an error. On FreeBSD, a representation of the directory's contents will be
returned.
It is possible to abort an ongoing `readFile` using an {AbortSignal}. If a
request is aborted the promise returned is rejected with an `AbortError`:
request is aborted the promise will be rejected:
```mjs
import { readFile } from 'fs/promises';
Expand All @@ -1209,8 +1209,8 @@ try {
await promise;
} catch (err) {
// When a request is aborted - err is an AbortError
console.error(err);
// When a request is aborted - signal.aborted is true
console.error('aborted', signal.aborted);
}
```
Expand Down Expand Up @@ -1572,8 +1572,8 @@ try {
await promise;
} catch (err) {
// When a request is aborted - err is an AbortError
console.error(err);
// When a request is aborted - signal.aborted is true
console.error('aborted', signal.aborted);
}
```
Expand Down Expand Up @@ -3253,7 +3253,7 @@ readFile('<directory>', (err, data) => {
```
It is possible to abort an ongoing request using an `AbortSignal`. If a
request is aborted the callback is called with an `AbortError`:
request is aborted the callback is called with an `Error`:
```mjs
import { readFile } from 'fs';
Expand Down Expand Up @@ -4361,7 +4361,7 @@ const controller = new AbortController();
const { signal } = controller;
const data = new Uint8Array(Buffer.from('Hello Node.js'));
writeFile('message.txt', data, { signal }, (err) => {
// When a request is aborted - the callback is called with an AbortError
// When a request is aborted - signal.aborted is true
});
// When the request should be aborted
controller.abort();
Expand Down
2 changes: 1 addition & 1 deletion doc/api/http2.md
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ close when the final `DATA` frame is transmitted. User code must call either

When `options.signal` is set with an `AbortSignal` and then `abort` on the
corresponding `AbortController` is called, the request will emit an `'error'`
event with an `AbortError` error.
event. Use `signal.aborted` to check if the error was from an abort.

The `:method` and `:path` pseudo-headers are not specified within `headers`,
they respectively default to:
Expand Down
6 changes: 4 additions & 2 deletions doc/api/readline.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,8 @@ setTimeout(() => ac.abort(), 10000);

If this method is invoked as it's util.promisify()ed version, it returns a
Promise that fulfills with the answer. If the question is canceled using
an `AbortController` it will reject with an `AbortError`.
an `AbortController` it will reject. Use `signal.aborted` to test if the
passed error is from an abort.

```js
const util = require('util');
Expand Down Expand Up @@ -901,7 +902,8 @@ setTimeout(() => ac.abort(), 10000);

If this method is invoked as it's util.promisify()ed version, it returns a
Promise that fulfills with the answer. If the question is canceled using
an `AbortController` it will reject with an `AbortError`.
an `AbortController` it will reject. Use `signal.aborted` to test if the
passed error is from an abort.

```js
const util = require('util');
Expand Down
21 changes: 11 additions & 10 deletions doc/api/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -1853,8 +1853,9 @@ changes:
**Default:** `true`.
* `signal` {AbortSignal} allows aborting the wait for the stream finish. The
underlying stream will _not_ be aborted if the signal is aborted. The
callback will get called with an `AbortError`. All registered
listeners added by this function will also be removed.
callback will get called with an `Error`. Use `signal.aborted` to test if
the error is from an abort. All registered listeners added by this
function will also be removed.
* `callback` {Function} A callback function that takes an optional error
argument.
* Returns: {Function} A cleanup function which removes all registered
Expand Down Expand Up @@ -1976,7 +1977,7 @@ The `pipeline` API provides a promise version, which can also
receive an options argument as the last parameter with a
`signal` {AbortSignal} property. When the signal is aborted,
`destroy` will be called on the underlying pipeline, with an
`AbortError`.
`Error`.

```js
const { pipeline } = require('stream/promises');
Expand Down Expand Up @@ -2012,7 +2013,7 @@ async function run() {
);
}

run().catch(console.error); // AbortError
run().catch((err) => console.log('aborted', signal.aborted)); // true
```

The `pipeline` API also supports async generators:
Expand Down Expand Up @@ -2338,8 +2339,8 @@ Attaches an AbortSignal to a readable or writeable stream. This lets code
control stream destruction using an `AbortController`.

Calling `abort` on the `AbortController` corresponding to the passed
`AbortSignal` will behave the same way as calling `.destroy(new AbortError())`
on the stream.
`AbortSignal` will behave the same way as calling `.destroy(new Error())` on
the stream.

```js
const fs = require('fs');
Expand Down Expand Up @@ -2564,8 +2565,8 @@ const myWritable = new Writable({
```

Calling `abort` on the `AbortController` corresponding to the passed
`AbortSignal` will behave the same way as calling `.destroy(new AbortError())`
on the writeable stream.
`AbortSignal` will behave the same way as calling `.destroy(new Error())` on
the writeable stream.

```js
const { Writable } = require('stream');
Expand Down Expand Up @@ -2918,8 +2919,8 @@ const myReadable = new Readable({
```

Calling `abort` on the `AbortController` corresponding to the passed
`AbortSignal` will behave the same way as calling `.destroy(new AbortError())`
on the readable created.
`AbortSignal` will behave the same way as calling `.destroy(new Error())` on
the readable created.

```js
const { Readable } = require('stream');
Expand Down
2 changes: 1 addition & 1 deletion doc/api/timers.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ cancel the timer and prevent it from triggering.

For the promisified variants of [`setImmediate()`][] and [`setTimeout()`][],
an [`AbortController`][] may be used to cancel the timer. When canceled, the
returned Promises will be rejected with an `'AbortError'`.
returned Promises will be rejected.

For `setImmediate()`:

Expand Down

0 comments on commit 937a17c

Please sign in to comment.