Skip to content

Commit 1e05ddf

Browse files
mscdexMylesBorins
authored andcommitted
stream: improve writable.write() performance
Backport-PR-URL: #32169 PR-URL: #31624 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]>
1 parent 90a4d43 commit 1e05ddf

File tree

1 file changed

+27
-48
lines changed

1 file changed

+27
-48
lines changed

lib/_stream_writable.js

+27-48
Original file line numberDiff line numberDiff line change
@@ -268,35 +268,8 @@ Writable.prototype.pipe = function() {
268268
};
269269

270270

271-
function writeAfterEnd(stream, cb) {
272-
const er = new ERR_STREAM_WRITE_AFTER_END();
273-
// TODO: defer error events consistently everywhere, not just the cb
274-
errorOrDestroy(stream, er);
275-
process.nextTick(cb, er);
276-
}
277-
278-
// Checks that a user-supplied chunk is valid, especially for the particular
279-
// mode the stream is in. Currently this means that `null` is never accepted
280-
// and undefined/non-string values are only allowed in object mode.
281-
function validChunk(stream, state, chunk, cb) {
282-
var er;
283-
284-
if (chunk === null) {
285-
er = new ERR_STREAM_NULL_VALUES();
286-
} else if (typeof chunk !== 'string' && !state.objectMode) {
287-
er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk);
288-
}
289-
if (er) {
290-
errorOrDestroy(stream, er);
291-
process.nextTick(cb, er);
292-
return false;
293-
}
294-
return true;
295-
}
296-
297271
Writable.prototype.write = function(chunk, encoding, cb) {
298272
const state = this._writableState;
299-
var ret = false;
300273
const isBuf = !state.objectMode && Stream._isUint8Array(chunk);
301274

302275
// Do not use Object.getPrototypeOf as it is slower since V8 7.3.
@@ -306,29 +279,42 @@ Writable.prototype.write = function(chunk, encoding, cb) {
306279

307280
if (typeof encoding === 'function') {
308281
cb = encoding;
309-
encoding = null;
282+
encoding = state.defaultEncoding;
283+
} else {
284+
if (!encoding)
285+
encoding = state.defaultEncoding;
286+
if (typeof cb !== 'function')
287+
cb = nop;
310288
}
311289

312290
if (isBuf)
313291
encoding = 'buffer';
314-
else if (!encoding)
315-
encoding = state.defaultEncoding;
316-
317-
if (typeof cb !== 'function')
318-
cb = nop;
319292

293+
let err;
320294
if (state.ending) {
321-
writeAfterEnd(this, cb);
295+
err = new ERR_STREAM_WRITE_AFTER_END();
322296
} else if (state.destroyed) {
323-
const err = new ERR_STREAM_DESTROYED('write');
324-
process.nextTick(cb, err);
325-
errorOrDestroy(this, err);
326-
} else if (isBuf || validChunk(this, state, chunk, cb)) {
327-
state.pendingcb++;
328-
ret = writeOrBuffer(this, state, chunk, encoding, cb);
297+
err = new ERR_STREAM_DESTROYED('write');
298+
} else if (chunk === null) {
299+
err = new ERR_STREAM_NULL_VALUES();
300+
} else {
301+
if (!isBuf && !state.objectMode) {
302+
if (typeof chunk !== 'string') {
303+
err = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk);
304+
} else if (encoding !== 'buffer' && state.decodeStrings !== false) {
305+
chunk = Buffer.from(chunk, encoding);
306+
encoding = 'buffer';
307+
}
308+
}
309+
if (err === undefined) {
310+
state.pendingcb++;
311+
return writeOrBuffer(this, state, chunk, encoding, cb);
312+
}
329313
}
330314

331-
return ret;
315+
process.nextTick(cb, err);
316+
errorOrDestroy(this, err, true);
317+
return false;
332318
};
333319

334320
Writable.prototype.cork = function() {
@@ -363,13 +349,6 @@ Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
363349
// in the queue, and wait our turn. Otherwise, call _write
364350
// If we return false, then we need a drain event, so set that flag.
365351
function writeOrBuffer(stream, state, chunk, encoding, cb) {
366-
if (!state.objectMode &&
367-
state.decodeStrings !== false &&
368-
encoding !== 'buffer' &&
369-
typeof chunk === 'string') {
370-
chunk = Buffer.from(chunk, encoding);
371-
encoding = 'buffer';
372-
}
373352
const len = state.objectMode ? 1 : chunk.length;
374353

375354
state.length += len;

0 commit comments

Comments
 (0)