Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
stream: optimize creation
  • Loading branch information
ronag committed Sep 13, 2019
commit 35ca570c96dece066cf8b61c89c20d9601799700
42 changes: 21 additions & 21 deletions lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ const { Buffer } = require('buffer');
const debug = require('internal/util/debuglog').debuglog('stream');
const BufferList = require('internal/streams/buffer_list');
const destroyImpl = require('internal/streams/destroy');
const { getHighWaterMark } = require('internal/streams/state');
const {
getHighWaterMark,
getDefaultHighWaterMark
} = require('internal/streams/state');
const {
ERR_INVALID_ARG_TYPE,
ERR_STREAM_PUSH_AFTER_EOF,
Expand Down Expand Up @@ -69,28 +72,20 @@ function prependListener(emitter, event, fn) {
emitter._events[event] = [fn, emitter._events[event]];
}

function ReadableState(options, stream, isDuplex) {
options = options || {};

// Duplex streams are both readable and writable, but share
// the same options object.
// However, some cases require setting options to different
// values for the readable and the writable sides of the duplex stream.
// These options can be provided separately as readableXXX and writableXXX.
if (typeof isDuplex !== 'boolean')
isDuplex = stream instanceof Stream.Duplex;
Comment thread
ronag marked this conversation as resolved.
Outdated

function ReadableState(options, isDuplex) {
// Object stream flag. Used to make read(n) ignore n and to
// make all the buffer merging and length checks go away
this.objectMode = !!options.objectMode;
this.objectMode = !!(options && options.objectMode);

if (isDuplex)
this.objectMode = this.objectMode || !!options.readableObjectMode;
this.objectMode = this.objectMode ||
!!(options && options.readableObjectMode);

// The point at which it stops calling _read() to fill the buffer
// Note: 0 is a valid value, means "don't call _read preemptively ever"
this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark',
isDuplex);
this.highWaterMark = options ?
getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex) :
getDefaultHighWaterMark(false);

// A linked list is used to store data chunks instead of an array because the
// linked list can remove elements from the beginning faster than
Expand Down Expand Up @@ -121,18 +116,18 @@ function ReadableState(options, stream, isDuplex) {
this.errorEmitted = false;

// Should close be emitted on destroy. Defaults to true.
this.emitClose = options.emitClose !== false;
this.emitClose = !options || options.emitClose !== false;

// Should .destroy() be called after 'end' (and potentially 'finish')
this.autoDestroy = !!options.autoDestroy;
this.autoDestroy = !!(options && options.autoDestroy);

// Has it been destroyed
this.destroyed = false;

// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
this.defaultEncoding = (options && options.defaultEncoding) || 'utf8';

// Ref the piped dest which we need a drain event on it
// type: null | Writable | Set<Writable>
Expand All @@ -144,7 +139,7 @@ function ReadableState(options, stream, isDuplex) {

this.decoder = null;
this.encoding = null;
if (options.encoding) {
if (options && options.encoding) {
if (!StringDecoder)
StringDecoder = require('string_decoder').StringDecoder;
this.decoder = new StringDecoder(options.encoding);
Expand All @@ -163,11 +158,16 @@ function Readable(options) {
if (!(this instanceof Readable))
return new Readable(options);

// Duplex streams are both readable and writable, but share
// the same options object.
// However, some cases require setting options to different
// values for the readable and the writable sides of the duplex stream.
// These options can be provided separately as readableXXX and writableXXX.
// Checking for a Stream.Duplex instance is faster here instead of inside
// the ReadableState constructor, at least with V8 6.5
const isDuplex = this instanceof Stream.Duplex;

this._readableState = new ReadableState(options, this, isDuplex);
this._readableState = new ReadableState(options, isDuplex);

// legacy
this.readable = true;
Expand Down
39 changes: 20 additions & 19 deletions lib/_stream_writable.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ const internalUtil = require('internal/util');
const Stream = require('stream');
const { Buffer } = require('buffer');
const destroyImpl = require('internal/streams/destroy');
const { getHighWaterMark } = require('internal/streams/state');
const {
getHighWaterMark,
getDefaultHighWaterMark
} = require('internal/streams/state');
const {
ERR_INVALID_ARG_TYPE,
ERR_METHOD_NOT_IMPLEMENTED,
Expand All @@ -55,28 +58,20 @@ Object.setPrototypeOf(Writable, Stream);
function nop() {}

function WritableState(options, stream, isDuplex) {
options = options || {};

// Duplex streams are both readable and writable, but share
// the same options object.
// However, some cases require setting options to different
// values for the readable and the writable sides of the duplex stream,
// e.g. options.readableObjectMode vs. options.writableObjectMode, etc.
if (typeof isDuplex !== 'boolean')
isDuplex = stream instanceof Stream.Duplex;

// Object stream flag to indicate whether or not this stream
// contains buffers or objects.
this.objectMode = !!options.objectMode;
this.objectMode = !!(options && options.objectMode);

if (isDuplex)
this.objectMode = this.objectMode || !!options.writableObjectMode;
this.objectMode = this.objectMode ||
!!(options && options.writableObjectMode);

// The point at which write() starts returning false
// Note: 0 is a valid value, means that we always return false if
// the entire buffer is not flushed immediately on write()
this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark',
isDuplex);
this.highWaterMark = options ?
getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex) :
getDefaultHighWaterMark(false);

// if _final has been called
this.finalCalled = false;
Expand All @@ -96,13 +91,13 @@ function WritableState(options, stream, isDuplex) {
// Should we decode strings into buffers before passing to _write?
// this is here so that some node-core streams can optimize string
// handling at a lower level.
const noDecode = options.decodeStrings === false;
const noDecode = !!(options && options.decodeStrings === false);
this.decodeStrings = !noDecode;

// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
this.defaultEncoding = (options && options.defaultEncoding) || 'utf8';

// Not an actual buffer we keep track of, but a measurement
// of how much we're waiting to get pushed to some underlying
Expand Down Expand Up @@ -150,10 +145,10 @@ function WritableState(options, stream, isDuplex) {
this.errorEmitted = false;

// Should close be emitted on destroy. Defaults to true.
this.emitClose = options.emitClose !== false;
this.emitClose = !options || options.emitClose !== false;

// Should .destroy() be called after 'finish' (and potentially 'end')
this.autoDestroy = !!options.autoDestroy;
this.autoDestroy = !!(options && options.autoDestroy);

// Count buffered requests
this.bufferedRequestCount = 0;
Expand Down Expand Up @@ -212,6 +207,12 @@ function Writable(options) {
// Node.js LazyTransform implementation, which has a non-trivial getter for
// `_writableState` that would lead to infinite recursion.


// Duplex streams are both readable and writable, but share
// the same options object.
// However, some cases require setting options to different
// values for the readable and the writable sides of the duplex stream,
// e.g. options.readableObjectMode vs. options.writableObjectMode, etc.
// Checking for a Stream.Duplex instance is faster here instead of inside
// the WritableState constructor, at least with V8 6.5
const isDuplex = (this instanceof Stream.Duplex);
Expand Down