Skip to content
File

Blob: src/node/internal/streams_legacy.js

javascript112 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4//
5// Copyright Joyent, Inc. and other Node contributors.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a
8// copy of this software and associated documentation files (the
9// "Software"), to deal in the Software without restriction, including
10// without limitation the rights to use, copy, modify, merge, publish,
11// distribute, sublicense, and/or sell copies of the Software, and to permit
12// persons to whom the Software is furnished to do so, subject to the
13// following conditions:
14//
15// The above copyright notice and this permission notice shall be included
16// in all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
21// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24// USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26import { EventEmitter } from 'node-internal:events';
27 
28import { Buffer } from 'node-internal:internal_buffer';
29 
30export function Stream(opts) {
31 EventEmitter.call(this, opts || {});
32}
33 
34Object.setPrototypeOf(Stream.prototype, EventEmitter.prototype);
35Object.setPrototypeOf(Stream, EventEmitter);
36 
37Stream.prototype.pipe = function (dest, options) {
38 const source = this; // eslint-disable-line @typescript-eslint/no-this-alias
39 function ondata(chunk) {
40 if (dest.writable && dest.write(chunk) === false && source.pause) {
41 source.pause();
42 }
43 }
44 source.on('data', ondata);
45 function ondrain() {
46 if (source.readable && source.resume) {
47 source.resume();
48 }
49 }
50 dest.on('drain', ondrain);
51 
52 // If the 'end' option is not supplied, dest.end() will be called when
53 // source gets the 'end' or 'close' events. Only dest.end() once.
54 if (!dest._isStdio && (!options || options.end !== false)) {
55 source.on('end', onend);
56 source.on('close', onclose);
57 }
58 let didOnEnd = false;
59 function onend() {
60 if (didOnEnd) return;
61 didOnEnd = true;
62 dest.end();
63 }
64 function onclose() {
65 if (didOnEnd) return;
66 didOnEnd = true;
67 if (typeof dest.destroy === 'function') dest.destroy();
68 }
69 
70 // Don't leave dangling pipes when there are errors.
71 function onerror(er) {
72 cleanup();
73 if (EventEmitter.listenerCount(this, 'error') === 0) {
74 this.emit('error', er);
75 }
76 }
77 source.prependListener('error', onerror);
78 dest.prependListener('error', onerror);
79 
80 // Remove all the event listeners that were added.
81 function cleanup() {
82 source.removeListener('data', ondata);
83 dest.removeListener('drain', ondrain);
84 source.removeListener('end', onend);
85 source.removeListener('close', onclose);
86 source.removeListener('error', onerror);
87 dest.removeListener('error', onerror);
88 source.removeListener('end', cleanup);
89 source.removeListener('close', cleanup);
90 dest.removeListener('close', cleanup);
91 }
92 source.on('end', cleanup);
93 source.on('close', cleanup);
94 dest.on('close', cleanup);
95 dest.emit('pipe', source);
96 
97 // Allow for unix-like usage: A.pipe(B).pipe(C)
98 return dest;
99};
100 
101// Backwards-compat with node 0.4.x
102Stream.Stream = Stream;
103Stream._isUint8Array = function isUint8Array(value) {
104 return value instanceof Uint8Array;
105};
106Stream._isArrayBufferView = function isArrayBufferView(value) {
107 return ArrayBuffer.isView(value);
108};
109Stream._uint8ArrayToBuffer = function _uint8ArrayToBuffer(chunk) {
110 return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
111};