• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const {
4  SymbolDispose,
5} = primordials;
6
7const {
8  AbortError,
9  codes,
10} = require('internal/errors');
11
12const {
13  isNodeStream,
14  isWebStream,
15  kControllerErrorFunction,
16} = require('internal/streams/utils');
17
18const eos = require('internal/streams/end-of-stream');
19const { ERR_INVALID_ARG_TYPE } = codes;
20let addAbortListener;
21
22// This method is inlined here for readable-stream
23// It also does not allow for signal to not exist on the stream
24// https://github.com/nodejs/node/pull/36061#discussion_r533718029
25const validateAbortSignal = (signal, name) => {
26  if (typeof signal !== 'object' ||
27       !('aborted' in signal)) {
28    throw new ERR_INVALID_ARG_TYPE(name, 'AbortSignal', signal);
29  }
30};
31
32module.exports.addAbortSignal = function addAbortSignal(signal, stream) {
33  validateAbortSignal(signal, 'signal');
34  if (!isNodeStream(stream) && !isWebStream(stream)) {
35    throw new ERR_INVALID_ARG_TYPE('stream', ['ReadableStream', 'WritableStream', 'Stream'], stream);
36  }
37  return module.exports.addAbortSignalNoValidate(signal, stream);
38};
39
40module.exports.addAbortSignalNoValidate = function(signal, stream) {
41  if (typeof signal !== 'object' || !('aborted' in signal)) {
42    return stream;
43  }
44  const onAbort = isNodeStream(stream) ?
45    () => {
46      stream.destroy(new AbortError(undefined, { cause: signal.reason }));
47    } :
48    () => {
49      stream[kControllerErrorFunction](new AbortError(undefined, { cause: signal.reason }));
50    };
51  if (signal.aborted) {
52    onAbort();
53  } else {
54    addAbortListener ??= require('events').addAbortListener;
55    const disposable = addAbortListener(signal, onAbort);
56    eos(stream, disposable[SymbolDispose]);
57  }
58  return stream;
59};
60