Skip to content

Commit 206ef41

Browse files
committed
Fix circular dependency
At the time `require('inherits')(Duplex, Readable)` is called, Readable is hoisted but not yet defined due to a circular dependency. Because the only uses of Duplex by the base classes are checking for if they themselves are a Duplex, we can replace typeof with a boolean. This boolean actually already exists in Writeable, so it makes sense to use it elsewhere to solve the circular dependency.
1 parent bcbe5e0 commit 206ef41

File tree

3 files changed

+13
-26
lines changed

3 files changed

+13
-26
lines changed

lib/_stream_duplex.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ require('inherits')(Duplex, Readable);
5757

5858
function Duplex(options) {
5959
if (!(this instanceof Duplex)) return new Duplex(options);
60-
Readable.call(this, options);
61-
Writable.call(this, options);
60+
Readable.call(this, options, true);
61+
Writable.call(this, options, true);
6262
this.allowHalfOpen = true;
6363

6464
if (options) {

lib/_stream_readable.js

+5-11
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
'use strict';
2222

2323
module.exports = Readable;
24-
/*<replacement>*/
25-
26-
var Duplex;
27-
/*</replacement>*/
2824

2925
Readable.ReadableState = ReadableState;
3026
/*<replacement>*/
@@ -72,6 +68,7 @@ if (debugUtil && debugUtil.debuglog) {
7268
var BufferList = require('./internal/streams/buffer_list');
7369

7470
var destroyImpl = require('./internal/streams/destroy');
71+
const { exception } = require('console');
7572

7673
var _require = require('./internal/streams/state'),
7774
getHighWaterMark = _require.getHighWaterMark;
@@ -104,16 +101,12 @@ function prependListener(emitter, event, fn) {
104101
}
105102

106103
function ReadableState(options, stream, isDuplex) {
107-
Duplex = Duplex || require('./_stream_duplex');
108104
options = options || {}; // Duplex streams are both readable and writable, but share
109105
// the same options object.
110106
// However, some cases require setting options to different
111107
// values for the readable and the writable sides of the duplex stream.
112108
// These options can be provided separately as readableXXX and writableXXX.
113109

114-
if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag. Used to make read(n) ignore n and to
115-
// make all the buffer merging and length checks go away
116-
117110
this.objectMode = !!options.objectMode;
118111
if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; // the point at which it stops calling _read() to fill the buffer
119112
// Note: 0 is a valid value, means "don't call _read preemptively ever"
@@ -166,12 +159,13 @@ function ReadableState(options, stream, isDuplex) {
166159
}
167160
}
168161

169-
function Readable(options) {
170-
Duplex = Duplex || require('./_stream_duplex');
162+
function Readable(options, isDuplex) {
171163
if (!(this instanceof Readable)) return new Readable(options); // Checking for a Stream.Duplex instance is faster here instead of inside
172164
// the ReadableState constructor, at least with V8 6.5
173165

174-
var isDuplex = this instanceof Duplex;
166+
if (typeof isDuplex !== 'boolean') isDuplex = false; // object stream flag. Used to make read(n) ignore n and to
167+
// make all the buffer merging and length checks go away
168+
175169
this._readableState = new ReadableState(options, this, isDuplex); // legacy
176170

177171
this.readable = true;

lib/_stream_writable.js

+6-13
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ function CorkedRequest(state) {
4747
}
4848
/* </replacement> */
4949

50-
/*<replacement>*/
51-
52-
53-
var Duplex;
54-
/*</replacement>*/
55-
5650
Writable.WritableState = WritableState;
5751
/*<replacement>*/
5852

@@ -80,6 +74,7 @@ function _isUint8Array(obj) {
8074
}
8175

8276
var destroyImpl = require('./internal/streams/destroy');
77+
const { exception } = require('console');
8378

8479
var _require = require('./internal/streams/state'),
8580
getHighWaterMark = _require.getHighWaterMark;
@@ -101,16 +96,12 @@ require('inherits')(Writable, Stream);
10196
function nop() {}
10297

10398
function WritableState(options, stream, isDuplex) {
104-
Duplex = Duplex || require('./_stream_duplex');
10599
options = options || {}; // Duplex streams are both readable and writable, but share
106100
// the same options object.
107101
// However, some cases require setting options to different
108102
// values for the readable and the writable sides of the duplex stream,
109103
// e.g. options.readableObjectMode vs. options.writableObjectMode, etc.
110104

111-
if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag to indicate whether or not this stream
112-
// contains buffers or objects.
113-
114105
this.objectMode = !!options.objectMode;
115106
if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false
116107
// Note: 0 is a valid value, means that we always return false if
@@ -226,8 +217,8 @@ if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.protot
226217
};
227218
}
228219

229-
function Writable(options) {
230-
Duplex = Duplex || require('./_stream_duplex'); // Writable ctor is applied to Duplexes, too.
220+
function Writable(options, isDuplex) {
221+
// Writable ctor is applied to Duplexes, too.
231222
// `realHasInstance` is necessary because using plain `instanceof`
232223
// would return false, as no `_writableState` property is attached.
233224
// Trying to use the custom `instanceof` for Writable here will also break the
@@ -236,7 +227,9 @@ function Writable(options) {
236227
// Checking for a Stream.Duplex instance is faster here instead of inside
237228
// the WritableState constructor, at least with V8 6.5
238229

239-
var isDuplex = this instanceof Duplex;
230+
if (typeof isDuplex !== 'boolean') isDuplex = false; // object stream flag to indicate whether or not this stream
231+
// contains buffers or objects.
232+
240233
if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options);
241234
this._writableState = new WritableState(options, this, isDuplex); // legacy.
242235

0 commit comments

Comments
 (0)