| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -45,8 +45,11 @@ There are four fundamental stream types within Node.js: | |||
| 45 | 45 | is written and read (for example, [`zlib.createDeflate()`][]). | |
| 46 | 46 | ||
| 47 | 47 | Additionally, this module includes the utility functions | |
| 48 | - [`stream.pipeline()`][], [`stream.finished()`][], [`stream.Readable.from()`][] | ||
| 49 | - and [`stream.addAbortSignal()`][]. | ||
| 48 | + [`stream.duplexPair()`][], | ||
| 49 | + [`stream.pipeline()`][], | ||
| 50 | + [`stream.finished()`][] | ||
| 51 | + [`stream.Readable.from()`][], and | ||
| 52 | + [`stream.addAbortSignal()`][]. | ||
| 50 | 53 | ||
| 51 | 54 | ### Streams Promises API | |
| 52 | 55 | ||
@@ -2700,6 +2703,30 @@ unless `emitClose` is set in false. | |||
| 2700 | 2703 | Once `destroy()` has been called, any further calls will be a no-op and no | |
| 2701 | 2704 | further errors except from `_destroy()` may be emitted as `'error'`. | |
| 2702 | 2705 | ||
| 2706 | + #### `stream.duplexPair([options])` | ||
| 2707 | + | ||
| 2708 | + <!-- YAML | ||
| 2709 | + added: REPLACEME | ||
| 2710 | + --> | ||
| 2711 | + | ||
| 2712 | + * `options` {Object} A value to pass to both [`Duplex`][] constructors, | ||
| 2713 | + to set options such as buffering. | ||
| 2714 | + * Returns: {Array} of two [`Duplex`][] instances. | ||
| 2715 | + | ||
| 2716 | + The utility function `duplexPair` returns an Array with two items, | ||
| 2717 | + each being a `Duplex` stream connected to the other side: | ||
| 2718 | + | ||
| 2719 | + ```js | ||
| 2720 | + const [ sideA, sideB ] = duplexPair(); | ||
| 2721 | + ``` | ||
| 2722 | + | ||
| 2723 | + Whatever is written to one stream is made readable on the other. It provides | ||
| 2724 | + behavior analogous to a network connection, where the data written by the client | ||
| 2725 | + becomes readable by the server, and vice-versa. | ||
| 2726 | + | ||
| 2727 | + The Duplex streams are symmetrical; one or the other may be used without any | ||
| 2728 | + difference in behavior. | ||
| 2729 | + | ||
| 2703 | 2730 | ### `stream.finished(stream[, options], callback)` | |
| 2704 | 2731 | ||
| 2705 | 2732 | <!-- YAML | |
@@ -4872,6 +4899,7 @@ contain multi-byte characters. | |||
| 4872 | 4899 | [`stream.addAbortSignal()`]: #streamaddabortsignalsignal-stream | |
| 4873 | 4900 | [`stream.compose`]: #streamcomposestreams | |
| 4874 | 4901 | [`stream.cork()`]: #writablecork | |
| 4902 | + [`stream.duplexPair()`]: #streamduplexpairoptions | ||
| 4875 | 4903 | [`stream.finished()`]: #streamfinishedstream-options-callback | |
| 4876 | 4904 | [`stream.pipe()`]: #readablepipedestination-options | |
| 4877 | 4905 | [`stream.pipeline()`]: #streampipelinesource-transforms-destination-callback | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,62 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const { | ||
| 3 | + Symbol, | ||
| 4 | + } = primordials; | ||
| 5 | + | ||
| 6 | + const { Duplex } = require('stream'); | ||
| 7 | + const assert = require('internal/assert'); | ||
| 8 | + | ||
| 9 | + const kCallback = Symbol('Callback'); | ||
| 10 | + const kInitOtherSide = Symbol('InitOtherSide'); | ||
| 11 | + | ||
| 12 | + class DuplexSide extends Duplex { | ||
| 13 | + #otherSide = null; | ||
| 14 | + | ||
| 15 | + constructor(options) { | ||
| 16 | + super(options); | ||
| 17 | + this[kCallback] = null; | ||
| 18 | + this.#otherSide = null; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + [kInitOtherSide](otherSide) { | ||
| 22 | + // Ensure this can only be set once, to enforce encapsulation. | ||
| 23 | + if (this.#otherSide === null) { | ||
| 24 | + this.#otherSide = otherSide; | ||
| 25 | + } else { | ||
| 26 | + assert(this.#otherSide === null); | ||
| 27 | + } | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + _read() { | ||
| 31 | + const callback = this[kCallback]; | ||
| 32 | + if (callback) { | ||
| 33 | + this[kCallback] = null; | ||
| 34 | + callback(); | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + _write(chunk, encoding, callback) { | ||
| 39 | + assert(this.#otherSide !== null); | ||
| 40 | + assert(this.#otherSide[kCallback] === null); | ||
| 41 | + if (chunk.length === 0) { | ||
| 42 | + process.nextTick(callback); | ||
| 43 | + } else { | ||
| 44 | + this.#otherSide.push(chunk); | ||
| 45 | + this.#otherSide[kCallback] = callback; | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + _final(callback) { | ||
| 50 | + this.#otherSide.on('end', callback); | ||
| 51 | + this.#otherSide.push(null); | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + function duplexPair(options) { | ||
| 56 | + const side0 = new DuplexSide(options); | ||
| 57 | + const side1 = new DuplexSide(options); | ||
| 58 | + side0[kInitOtherSide](side1); | ||
| 59 | + side1[kInitOtherSide](side0); | ||
| 60 | + return [ side0, side1 ]; | ||
| 61 | + } | ||
| 62 | + module.exports = duplexPair; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -101,6 +101,7 @@ Stream.Writable = require('internal/streams/writable'); | |||
| 101 | 101 | Stream.Duplex = require('internal/streams/duplex'); | |
| 102 | 102 | Stream.Transform = require('internal/streams/transform'); | |
| 103 | 103 | Stream.PassThrough = require('internal/streams/passthrough'); | |
| 104 | + Stream.duplexPair = require('internal/streams/duplexpair'); | ||
| 104 | 105 | Stream.pipeline = pipeline; | |
| 105 | 106 | const { addAbortSignal } = require('internal/streams/add-abort-signal'); | |
| 106 | 107 | Stream.addAbortSignal = addAbortSignal; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,7 +12,6 @@ This directory contains modules used to test the Node.js implementation. | |||
| 12 | 12 | * [CPU Profiler module](#cpu-profiler-module) | |
| 13 | 13 | * [Debugger module](#debugger-module) | |
| 14 | 14 | * [DNS module](#dns-module) | |
| 15 | - * [Duplex pair helper](#duplex-pair-helper) | ||
| 16 | 15 | * [Environment variables](#environment-variables) | |
| 17 | 16 | * [Fixtures module](#fixtures-module) | |
| 18 | 17 | * [Heap dump checker module](#heap-dump-checker-module) | |
@@ -669,14 +668,6 @@ Reads a Domain String and returns a Buffer containing the domain. | |||
| 669 | 668 | Takes in a parsed Object and writes its fields to a DNS packet as a Buffer | |
| 670 | 669 | object. | |
| 671 | 670 | ||
| 672 | - ## Duplex pair helper | ||
| 673 | - | ||
| 674 | - The `common/duplexpair` module exports a single function `makeDuplexPair`, | ||
| 675 | - which returns an object `{ clientSide, serverSide }` where each side is a | ||
| 676 | - `Duplex` stream connected to the other side. | ||
| 677 | - | ||
| 678 | - There is no difference between client or server side beyond their names. | ||
| 679 | - | ||
| 680 | 671 | ## Environment variables | |
| 681 | 672 | ||
| 682 | 673 | The behavior of the Node.js test suite can be altered using the following | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -126,6 +126,7 @@ if (common.isMainThread) { | |||
| 126 | 126 | 'NativeModule internal/streams/compose', | |
| 127 | 127 | 'NativeModule internal/streams/destroy', | |
| 128 | 128 | 'NativeModule internal/streams/duplex', | |
| 129 | + 'NativeModule internal/streams/duplexpair', | ||
| 129 | 130 | 'NativeModule internal/streams/end-of-stream', | |
| 130 | 131 | 'NativeModule internal/streams/from', | |
| 131 | 132 | 'NativeModule internal/streams/legacy', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,7 +8,7 @@ const common = require('../common'); | |||
| 8 | 8 | if (!common.hasCrypto) | |
| 9 | 9 | common.skip('missing crypto'); | |
| 10 | 10 | ||
| 11 | - const makeDuplexPair = require('../common/duplexpair'); | ||
| 11 | + const { duplexPair } = require('stream'); | ||
| 12 | 12 | const onGC = require('../common/ongc'); | |
| 13 | 13 | const assert = require('assert'); | |
| 14 | 14 | const tls = require('tls'); | |
@@ -37,7 +37,7 @@ function connect() { | |||
| 37 | 37 | return; | |
| 38 | 38 | } | |
| 39 | 39 | ||
| 40 | - const { clientSide, serverSide } = makeDuplexPair(); | ||
| 40 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 41 | 41 | ||
| 42 | 42 | const tlsSocket = tls.connect({ socket: clientSide }); | |
| 43 | 43 | tlsSocket.on('error', common.mustCall(connect)); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,7 +3,7 @@ | |||
| 3 | 3 | const common = require('../common'); | |
| 4 | 4 | const http = require('http'); | |
| 5 | 5 | const async_hooks = require('async_hooks'); | |
| 6 | - const makeDuplexPair = require('../common/duplexpair'); | ||
| 6 | + const { duplexPair } = require('stream'); | ||
| 7 | 7 | ||
| 8 | 8 | // Regression test for https://github.com/nodejs/node/issues/30122 | |
| 9 | 9 | // When a domain is attached to an http Agent’s ReusedHandle object, that | |
@@ -36,7 +36,7 @@ async_hooks.createHook({ | |||
| 36 | 36 | // attached to too many objects that use strong references (timers, the network | |
| 37 | 37 | // socket handle, etc.) and wrap the client side in a JSStreamSocket so we don’t | |
| 38 | 38 | // have to implement the whole _handle API ourselves. | |
| 39 | - const { serverSide, clientSide } = makeDuplexPair(); | ||
| 39 | + const [ serverSide, clientSide ] = duplexPair(); | ||
| 40 | 40 | const JSStreamSocket = require('internal/js_stream_socket'); | |
| 41 | 41 | const wrappedClientSide = new JSStreamSocket(clientSide); | |
| 42 | 42 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,7 @@ | |||
| 2 | 2 | const common = require('../common'); | |
| 3 | 3 | const assert = require('assert'); | |
| 4 | 4 | const http = require('http'); | |
| 5 | - const MakeDuplexPair = require('../common/duplexpair'); | ||
| 5 | + const { duplexPair } = require('stream'); | ||
| 6 | 6 | ||
| 7 | 7 | // Test 1: Simple HTTP test, no keep-alive. | |
| 8 | 8 | { | |
@@ -13,7 +13,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 13 | 13 | res.end(testData); | |
| 14 | 14 | })); | |
| 15 | 15 | ||
| 16 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 16 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 17 | 17 | server.emit('connection', serverSide); | |
| 18 | 18 | ||
| 19 | 19 | const req = http.request({ | |
@@ -37,7 +37,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 37 | 37 | res.end(testData); | |
| 38 | 38 | }, 2)); | |
| 39 | 39 | ||
| 40 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 40 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 41 | 41 | server.emit('connection', serverSide); | |
| 42 | 42 | ||
| 43 | 43 | function doRequest(cb) { | |
@@ -77,7 +77,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 77 | 77 | }); | |
| 78 | 78 | })); | |
| 79 | 79 | ||
| 80 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 80 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 81 | 81 | server.emit('connection', serverSide); | |
| 82 | 82 | clientSide.on('end', common.mustCall()); | |
| 83 | 83 | serverSide.on('end', common.mustCall()); | |
@@ -117,7 +117,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 117 | 117 | ||
| 118 | 118 | })); | |
| 119 | 119 | ||
| 120 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 120 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 121 | 121 | server.emit('connection', serverSide); | |
| 122 | 122 | clientSide.on('end', common.mustCall()); | |
| 123 | 123 | serverSide.on('end', common.mustCall()); | |
@@ -143,7 +143,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 143 | 143 | { | |
| 144 | 144 | const server = http.createServer(common.mustNotCall()); | |
| 145 | 145 | ||
| 146 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 146 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 147 | 147 | server.emit('connection', serverSide); | |
| 148 | 148 | ||
| 149 | 149 | server.on('clientError', common.mustCall()); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,13 +2,13 @@ | |||
| 2 | 2 | const common = require('../common'); | |
| 3 | 3 | const assert = require('assert'); | |
| 4 | 4 | const http = require('http'); | |
| 5 | - const MakeDuplexPair = require('../common/duplexpair'); | ||
| 5 | + const { duplexPair } = require('stream'); | ||
| 6 | 6 | ||
| 7 | 7 | // Test that setting the `maxHeaderSize` option works on a per-stream-basis. | |
| 8 | 8 | ||
| 9 | 9 | // Test 1: The server sends an invalid header. | |
| 10 | 10 | { | |
| 11 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 11 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 12 | 12 | ||
| 13 | 13 | const req = http.request({ | |
| 14 | 14 | createConnection: common.mustCall(() => clientSide), | |
@@ -30,7 +30,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 30 | 30 | ||
| 31 | 31 | // Test 2: The same as Test 1 except without the option, to make sure it fails. | |
| 32 | 32 | { | |
| 33 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 33 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 34 | 34 | ||
| 35 | 35 | const req = http.request({ | |
| 36 | 36 | createConnection: common.mustCall(() => clientSide) | |
@@ -59,7 +59,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 59 | 59 | ||
| 60 | 60 | server.on('clientError', common.mustNotCall()); | |
| 61 | 61 | ||
| 62 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 62 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 63 | 63 | serverSide.server = server; | |
| 64 | 64 | server.emit('connection', serverSide); | |
| 65 | 65 | ||
@@ -75,7 +75,7 @@ const MakeDuplexPair = require('../common/duplexpair'); | |||
| 75 | 75 | ||
| 76 | 76 | server.on('clientError', common.mustCall()); | |
| 77 | 77 | ||
| 78 | - const { clientSide, serverSide } = MakeDuplexPair(); | ||
| 78 | + const [ clientSide, serverSide ] = duplexPair(); | ||
| 79 | 79 | serverSide.server = server; | |
| 80 | 80 | server.emit('connection', serverSide); | |
| 81 | 81 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments