lib: revert primordials in a hot path

Evidence has shown that use of primordials have sometimes an impact of
performance. This commit reverts the changes who are most likely to be
responsible for performance regression in the HTTP response path.

PR-URL: https://github.com/nodejs/node/pull/38248
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Antoine du Hamel authored and Matteo Collina committed 2021-04-19 10:23:01 +02:00
1 parent 4e9212bb7b
commit ee9e2a2eb6
20 files changed
+182 -222

No files matched your search

+2 -4
View File
@@ -22,11 +22,9 @@
'use strict';
const {
ArrayPrototypePushApply,
MathMin,
Symbol,
RegExpPrototypeTest,
TypedArrayPrototypeSlice,
} = primordials;
const { setImmediate } = require('timers');
@@ -66,7 +64,7 @@ function parserOnHeaders(headers, url) {
// Once we exceeded headers limit - stop collecting them
if (this.maxHeaderPairs <= 0 ||
this._headers.length < this.maxHeaderPairs) {
ArrayPrototypePushApply(this._headers, headers);
this._headers.push(...headers);
}
this._url += url;
}
@@ -138,7 +136,7 @@ function parserOnBody(b, start, len) {
// Pretend this was the result of a stream._read call.
if (len > 0 && !stream._dumped) {
const slice = TypedArrayPrototypeSlice(b, start, start + len);
const slice = b.slice(start, start + len);
const ret = stream.push(slice);
if (!ret)
readStop(this.socket);
+2 -4
View File
@@ -22,8 +22,6 @@
'use strict';
const {
ArrayPrototypePush,
FunctionPrototypeCall,
ObjectDefineProperty,
ObjectSetPrototypeOf,
StringPrototypeCharCodeAt,
@@ -59,7 +57,7 @@ function IncomingMessage(socket) {
};
}
FunctionPrototypeCall(Readable, this, streamOptions);
Readable.call(this, streamOptions);
this._readableState.readingMore = true;
@@ -350,7 +348,7 @@ function _addHeaderLine(field, value, dest) {
} else if (flag === 1) {
// Array header -- only Set-Cookie at the moment
if (dest['set-cookie'] !== undefined) {
ArrayPrototypePush(dest['set-cookie'], value);
dest['set-cookie'].push(value);
} else {
dest['set-cookie'] = [value];
}
+9 -14
View File
@@ -24,13 +24,7 @@
const {
Array,
ArrayIsArray,
ArrayPrototypeForEach,
ArrayPrototypeJoin,
ArrayPrototypePush,
ArrayPrototypeUnshift,
FunctionPrototype,
FunctionPrototypeBind,
FunctionPrototypeCall,
MathFloor,
NumberPrototypeToString,
ObjectCreate,
@@ -88,7 +82,7 @@ const { CRLF } = common;
const kCorked = Symbol('corked');
const nop = FunctionPrototype;
const nop = () => {};
const RE_CONN_CLOSE = /(?:^|\W)close(?:$|\W)/i;
const RE_TE_CHUNKED = common.chunkExpression;
@@ -101,7 +95,7 @@ function isCookieField(s) {
}
function OutgoingMessage() {
FunctionPrototypeCall(Stream, this);
Stream.call(this);
// Queue that holds all currently pending data, until the response will be
// assigned to the socket (until it will its turn in the HTTP pipeline).
@@ -331,7 +325,7 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback) {
data = this._header + data;
} else {
const header = this._header;
ArrayPrototypeUnshift(this.outputData, {
this.outputData.unshift({
data: header,
encoding: 'latin1',
callback: null
@@ -368,7 +362,7 @@ function _writeRaw(data, encoding, callback) {
return conn.write(data, encoding, callback);
}
// Buffer, as long as we're not destroyed.
ArrayPrototypePush(this.outputData, { data, encoding, callback });
this.outputData.push({ data, encoding, callback });
this.outputSize += data.length;
this._onPendingData(data.length);
return this.outputSize < HIGH_WATER_MARK;
@@ -397,9 +391,10 @@ function _storeHeader(firstLine, headers) {
}
} else if (ArrayIsArray(headers)) {
if (headers.length && ArrayIsArray(headers[0])) {
ArrayPrototypeForEach(headers, (entry) =>
processHeader(this, state, entry[0], entry[1], true)
);
for (let i = 0; i < headers.length; i++) {
const entry = headers[i];
processHeader(this, state, entry[0], entry[1], true);
}
} else {
if (headers.length % 2 !== 0) {
throw new ERR_INVALID_ARG_VALUE('headers', headers);
@@ -877,7 +872,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
if (typeof callback === 'function')
this.once('finish', callback);
const finish = FunctionPrototypeBind(onFinish, undefined, this);
const finish = onFinish.bind(undefined, this);
if (this._hasBody && this.chunkedEncoding) {
this._send('0\r\n' + this._trailer + '\r\n', 'latin1', finish);
+41 -47
View File
@@ -23,20 +23,12 @@
const {
ArrayIsArray,
ArrayPrototypeForEach,
ArrayPrototypePush,
ArrayPrototypeShift,
Error,
FunctionPrototype,
FunctionPrototypeBind,
FunctionPrototypeCall,
ObjectKeys,
ObjectSetPrototypeOf,
ReflectApply,
RegExpPrototypeTest,
Symbol,
SymbolFor,
TypedArrayPrototypeSlice,
} = primordials;
const net = require('net');
@@ -185,7 +177,7 @@ class HTTPServerAsyncResource {
}
function ServerResponse(req) {
FunctionPrototypeCall(OutgoingMessage, this);
OutgoingMessage.call(this);
if (req.method === 'HEAD') this._hasBody = false;
@@ -212,7 +204,7 @@ ObjectSetPrototypeOf(ServerResponse, OutgoingMessage);
ServerResponse.prototype._finish = function _finish() {
DTRACE_HTTP_SERVER_RESPONSE(this.socket);
emitStatistics(this[kServerResponseStatistics]);
FunctionPrototypeCall(OutgoingMessage.prototype._finish, this);
OutgoingMessage.prototype._finish.call(this);
};
@@ -386,7 +378,7 @@ function Server(options, requestListener) {
validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser');
this.insecureHTTPParser = insecureHTTPParser;
FunctionPrototypeCall(net.Server, this, { allowHalfOpen: true });
net.Server.call(this, { allowHalfOpen: true });
if (requestListener) {
this.on('request', requestListener);
@@ -422,8 +414,10 @@ Server.prototype[EE.captureRejectionSymbol] = function(err, event, ...args) {
const { 1: res } = args;
if (!res.headersSent && !res.writableEnded) {
// Don't leak headers.
ArrayPrototypeForEach(res.getHeaderNames(),
(name) => res.removeHeader(name));
const names = res.getHeaderNames();
for (let i = 0; i < names.length; i++) {
res.removeHeader(names[i]);
}
res.statusCode = 500;
res.end(STATUS_CODES[500]);
} else {
@@ -431,8 +425,8 @@ Server.prototype[EE.captureRejectionSymbol] = function(err, event, ...args) {
}
break;
default:
ReflectApply(net.Server.prototype[SymbolFor('nodejs.rejection')],
this, arguments);
net.Server.prototype[SymbolFor('nodejs.rejection')]
.apply(this, arguments);
}
};
@@ -493,20 +487,20 @@ function connectionListenerInternal(server, socket) {
outgoingData: 0,
keepAliveTimeoutSet: false
};
state.onData = FunctionPrototypeBind(socketOnData, undefined,
server, socket, parser, state);
state.onEnd = FunctionPrototypeBind(socketOnEnd, undefined,
server, socket, parser, state);
state.onClose = FunctionPrototypeBind(socketOnClose, undefined,
socket, state);
state.onDrain = FunctionPrototypeBind(socketOnDrain, undefined,
socket, state);
state.onData = socketOnData.bind(undefined,
server, socket, parser, state);
state.onEnd = socketOnEnd.bind(undefined,
server, socket, parser, state);
state.onClose = socketOnClose.bind(undefined,
socket, state);
state.onDrain = socketOnDrain.bind(undefined,
socket, state);
socket.on('data', state.onData);
socket.on('error', socketOnError);
socket.on('end', state.onEnd);
socket.on('close', state.onClose);
socket.on('drain', state.onDrain);
parser.onIncoming = FunctionPrototypeBind(parserOnIncoming, undefined,
parser.onIncoming = parserOnIncoming.bind(undefined,
server, socket, state);
// We are consuming socket, so it won't get any actual data
@@ -527,18 +521,18 @@ function connectionListenerInternal(server, socket) {
parser.consume(socket._handle);
}
parser[kOnExecute] =
FunctionPrototypeBind(onParserExecute, undefined,
server, socket, parser, state);
onParserExecute.bind(undefined,
server, socket, parser, state);
parser[kOnTimeout] =
FunctionPrototypeBind(onParserTimeout, undefined,
server, socket);
onParserTimeout.bind(undefined,
server, socket);
// When receiving new requests on the same socket (pipelining or keep alive)
// make sure the requestTimeout is active.
parser[kOnMessageBegin] =
FunctionPrototypeBind(setRequestTimeout, undefined,
server, socket);
setRequestTimeout.bind(undefined,
server, socket);
// This protects from DOS attack where an attacker establish the connection
// without sending any data on applications where server.timeout is left to
@@ -594,7 +588,7 @@ function socketOnClose(socket, state) {
function abortIncoming(incoming) {
while (incoming.length) {
const req = ArrayPrototypeShift(incoming);
const req = incoming.shift();
req.destroy(connResetException('aborted'));
}
// Abort socket._httpMessage ?
@@ -606,7 +600,7 @@ function socketOnEnd(server, socket, parser, state) {
if (ret instanceof Error) {
debug('parse error');
// socketOnError has additional logic and will call socket.destroy(err).
FunctionPrototypeCall(socketOnError, socket, ret);
socketOnError.call(socket, ret);
} else if (!server.httpAllowHalfOpen) {
socket.end();
} else if (state.outgoing.length) {
@@ -629,7 +623,7 @@ function socketOnData(server, socket, parser, state, d) {
function onRequestTimeout(socket) {
socket[kRequestTimeout] = undefined;
// socketOnError has additional logic and will call socket.destroy(err).
ReflectApply(socketOnError, socket, [new ERR_HTTP_REQUEST_TIMEOUT()]);
socketOnError.call(socket, new ERR_HTTP_REQUEST_TIMEOUT());
}
function onParserExecute(server, socket, parser, state, ret) {
@@ -649,7 +643,7 @@ function onParserTimeout(server, socket) {
socket.destroy();
}
const noop = FunctionPrototype;
const noop = () => {};
const badRequestResponse = Buffer.from(
`HTTP/1.1 400 ${STATUS_CODES[400]}${CRLF}` +
`Connection: close${CRLF}${CRLF}`, 'ascii'
@@ -696,7 +690,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
prepareError(ret, parser, d);
ret.rawPacket = d || parser.getCurrentBuffer();
debug('parse error', ret);
FunctionPrototypeCall(socketOnError, socket, ret);
socketOnError.call(socket, ret);
} else if (parser.incoming && parser.incoming.upgrade) {
// Upgrade or CONNECT
const req = parser.incoming;
@@ -719,7 +713,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
if (eventName === 'upgrade' || server.listenerCount(eventName) > 0) {
debug('SERVER have listener for %s', eventName);
const bodyHead = TypedArrayPrototypeSlice(d, ret, d.length);
const bodyHead = d.slice(ret, d.length);
socket.readableFlowing = null;
@@ -738,7 +732,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
// When receiving new requests on the same socket (pipelining or keep alive)
// make sure the requestTimeout is active.
parser[kOnMessageBegin] =
FunctionPrototypeBind(setRequestTimeout, undefined, server, socket);
setRequestTimeout.bind(undefined, server, socket);
}
if (socket._paused && socket.parser) {
@@ -802,7 +796,7 @@ function resOnFinish(req, res, socket, state, server) {
// array will be empty.
assert(state.incoming.length === 0 || state.incoming[0] === req);
ArrayPrototypeShift(state.incoming);
state.incoming.shift();
// If the user never called req.read(), and didn't pipe() or
// .resume() or .on('data'), then we call req._dump() so that the
@@ -835,7 +829,7 @@ function resOnFinish(req, res, socket, state, server) {
}
} else {
// Start sending the next message
const m = ArrayPrototypeShift(state.outgoing);
const m = state.outgoing.shift();
if (m) {
m.assignSocket(socket);
}
@@ -861,7 +855,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
return 2;
}
ArrayPrototypePush(state.incoming, req);
state.incoming.push(req);
// If the writable end isn't consuming, then stop reading
// so that we don't become overwhelmed by a flood of
@@ -879,8 +873,8 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
const res = new server[kServerResponse](req);
res._keepAliveTimeout = server.keepAliveTimeout;
res._onPendingData = FunctionPrototypeBind(updateOutgoingData, undefined,
socket, state);
res._onPendingData = updateOutgoingData.bind(undefined,
socket, state);
res.shouldKeepAlive = keepAlive;
DTRACE_HTTP_SERVER_REQUEST(req, socket);
@@ -896,7 +890,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
if (socket._httpMessage) {
// There are already pending outgoing res, append.
ArrayPrototypePush(state.outgoing, res);
state.outgoing.push(res);
} else {
res.assignSocket(socket);
}
@@ -904,8 +898,8 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
// When we're finished writing the response, check if this is the last
// response, if so destroy the socket.
res.on('finish',
FunctionPrototypeBind(resOnFinish, undefined,
req, res, socket, state, server));
resOnFinish.bind(undefined,
req, res, socket, state, server));
if (req.headers.expect !== undefined &&
(req.httpVersionMajor === 1 && req.httpVersionMinor === 1)) {
@@ -977,8 +971,8 @@ function unconsume(parser, socket) {
function generateSocketListenerWrapper(originalFnName) {
return function socketListenerWrap(ev, fn) {
const res = ReflectApply(net.Socket.prototype[originalFnName], this,
[ev, fn]);
const res = net.Socket.prototype[originalFnName].call(this,
ev, fn);
if (!this.parser) {
this.on = net.Socket.prototype.on;
this.addListener = net.Socket.prototype.addListener;
+10 -14
View File
@@ -22,13 +22,10 @@
'use strict';
const {
ArrayPrototypeForEach,
ArrayPrototypePush,
ArrayPrototypeSlice,
Boolean,
Error,
ErrorCaptureStackTrace,
FunctionPrototypeCall,
MathMin,
NumberIsNaN,
ObjectCreate,
@@ -39,7 +36,6 @@ const {
Promise,
PromiseReject,
PromiseResolve,
ReflectApply,
ReflectOwnKeys,
String,
Symbol,
@@ -76,7 +72,7 @@ const kMaxEventTargetListenersWarned =
Symbol('events.maxEventTargetListenersWarned');
function EventEmitter(opts) {
FunctionPrototypeCall(EventEmitter.init, this, opts);
EventEmitter.init.call(this, opts);
}
module.exports = EventEmitter;
module.exports.once = once;
@@ -165,8 +161,8 @@ EventEmitter.setMaxListeners =
if (isEventTarget === undefined)
isEventTarget = require('internal/event_target').isEventTarget;
// Performance for forEach is now comparable with regular for-loop
ArrayPrototypeForEach(eventTargets, (target) => {
for (let i = 0; i < eventTargets.length; i++) {
const target = eventTargets[i];
if (isEventTarget(target)) {
target[kMaxEventTargetListeners] = n;
target[kMaxEventTargetListenersWarned] = false;
@@ -178,7 +174,7 @@ EventEmitter.setMaxListeners =
['EventEmitter', 'EventTarget'],
target);
}
});
}
}
};
@@ -217,7 +213,7 @@ function addCatch(that, promise, type, args) {
const then = promise.then;
if (typeof then === 'function') {
FunctionPrototypeCall(then, promise, undefined, function(err) {
then.call(promise, undefined, function(err) {
// The callback is called with nextTick to avoid a follow-up
// rejection from this promise.
process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args);
@@ -366,7 +362,7 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
return false;
if (typeof handler === 'function') {
const result = ReflectApply(handler, this, args);
const result = handler.apply(this, args);
// We check if result is undefined first because that
// is the most common case so we do not pay any perf
@@ -378,7 +374,7 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
const len = handler.length;
const listeners = arrayClone(handler);
for (let i = 0; i < len; ++i) {
const result = ReflectApply(listeners[i], this, args);
const result = listeners[i].apply(this, args);
// We check if result is undefined first because that
// is the most common case so we do not pay any perf
@@ -690,7 +686,7 @@ function getEventListeners(emitterOrTarget, type) {
while (handler?.listener !== undefined) {
const listener = handler.listener?.deref ?
handler.listener.deref() : handler.listener;
ArrayPrototypePush(listeners, listener);
listeners.push(listener);
handler = handler.next;
}
return listeners;
@@ -807,7 +803,7 @@ function on(emitter, event, options) {
// Wait until an event happens
return new Promise(function(resolve, reject) {
ArrayPrototypePush(unconsumedPromises, { resolve, reject });
unconsumedPromises.push({ resolve, reject });
});
},
@@ -871,7 +867,7 @@ function on(emitter, event, options) {
if (promise) {
promise.resolve(createIterResult(args, false));
} else {
ArrayPrototypePush(unconsumedEvents, args);
unconsumedEvents.push(args);
}
}
+8 -12
View File
@@ -1,15 +1,11 @@
'use strict';
const {
ArrayPrototypePop,
ArrayPrototypeSlice,
ArrayPrototypeUnshift,
ErrorCaptureStackTrace,
FunctionPrototypeBind,
ObjectPrototypeHasOwnProperty,
ObjectDefineProperty,
Promise,
ReflectApply,
Symbol,
} = primordials;
@@ -129,16 +125,16 @@ function callbackTrampoline(asyncId, resource, cb, ...args) {
let result;
if (asyncId === 0 && typeof domain_cb === 'function') {
ArrayPrototypeUnshift(args, cb);
result = ReflectApply(domain_cb, this, args);
args.unshift(cb);
result = domain_cb.apply(this, args);
} else {
result = ReflectApply(cb, this, args);
result = cb.apply(this, args);
}
if (asyncId !== 0 && hasHooks(kAfter))
emitAfterNative(asyncId);
ArrayPrototypePop(execution_async_resources);
execution_async_resources.pop();
return result;
}
@@ -256,7 +252,7 @@ function emitHook(symbol, asyncId) {
}
function emitHookFactory(symbol, name) {
const fn = FunctionPrototypeBind(emitHook, undefined, symbol);
const fn = emitHook.bind(undefined, symbol);
// Set the name property of the function as it looks good in the stack trace.
ObjectDefineProperty(fn, 'name', {
@@ -429,14 +425,14 @@ function clearDefaultTriggerAsyncId() {
function defaultTriggerAsyncIdScope(triggerAsyncId, block, ...args) {
if (triggerAsyncId === undefined)
return ReflectApply(block, null, args);
return block.apply(null, args);
// CHECK(NumberIsSafeInteger(triggerAsyncId))
// CHECK(triggerAsyncId > 0)
const oldDefaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId];
async_id_fields[kDefaultTriggerAsyncId] = triggerAsyncId;
try {
return ReflectApply(block, null, args);
return block.apply(null, args);
} finally {
async_id_fields[kDefaultTriggerAsyncId] = oldDefaultTriggerAsyncId;
}
@@ -533,7 +529,7 @@ function popAsyncContext(asyncId) {
const offset = stackLength - 1;
async_id_fields[kExecutionAsyncId] = async_wrap.async_ids_stack[2 * offset];
async_id_fields[kTriggerAsyncId] = async_wrap.async_ids_stack[2 * offset + 1];
ArrayPrototypePop(execution_async_resources);
execution_async_resources.pop();
async_hook_fields[kStackLength] = offset;
return offset > 0;
}
+4
View File
@@ -6,6 +6,10 @@
// so that Node.js's builtin modules do not need to later look these up from
// the global proxy, which can be mutated by users.
// Use of primordials have sometimes a dramatic impact on performance, please
// benchmark all changes made in performance-sensitive areas of the codebase.
// See: https://github.com/nodejs/node/pull/38248
const {
defineProperty: ReflectDefineProperty,
getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,
+2 -5
View File
@@ -7,7 +7,6 @@ const {
},
} = require('internal/errors');
const {
FunctionPrototypeCall,
Symbol,
} = primordials;
@@ -99,8 +98,7 @@ function _destroy(self, err, cb) {
try {
const then = result.then;
if (typeof then === 'function') {
FunctionPrototypeCall(
then,
then.call(
result,
function() {
if (called)
@@ -318,8 +316,7 @@ function constructNT(stream) {
try {
const then = result.then;
if (typeof then === 'function') {
FunctionPrototypeCall(
then,
then.call(
result,
function() {
// If the callback was invoked, do nothing further.
+11 -16
View File
@@ -3,11 +3,6 @@
'use strict';
const {
FunctionPrototype,
FunctionPrototypeCall,
ReflectApply,
} = primordials;
const {
AbortError,
codes,
@@ -55,7 +50,7 @@ function isWritableFinished(stream) {
return wState.finished || (wState.ended && wState.length === 0);
}
const nop = FunctionPrototype;
const nop = () => {};
function isReadableEnded(stream) {
if (stream.readableEnded) return true;
@@ -113,7 +108,7 @@ function eos(stream, options, callback) {
if (stream.destroyed) willEmitClose = false;
if (willEmitClose && (!stream.readable || readable)) return;
if (!readable || readableEnded) FunctionPrototypeCall(callback, stream);
if (!readable || readableEnded) callback.call(stream);
};
let readableEnded = stream.readableEnded ||
@@ -126,25 +121,25 @@ function eos(stream, options, callback) {
if (stream.destroyed) willEmitClose = false;
if (willEmitClose && (!stream.writable || writable)) return;
if (!writable || writableFinished) FunctionPrototypeCall(callback, stream);
if (!writable || writableFinished) callback.call(stream);
};
const onerror = (err) => {
FunctionPrototypeCall(callback, stream, err);
callback.call(stream, err);
};
const onclose = () => {
if (readable && !readableEnded) {
if (!isReadableEnded(stream))
return FunctionPrototypeCall(callback, stream,
new ERR_STREAM_PREMATURE_CLOSE());
return callback.call(stream,
new ERR_STREAM_PREMATURE_CLOSE());
}
if (writable && !writableFinished) {
if (!isWritableFinished(stream))
return FunctionPrototypeCall(callback, stream,
new ERR_STREAM_PREMATURE_CLOSE());
return callback.call(stream,
new ERR_STREAM_PREMATURE_CLOSE());
}
FunctionPrototypeCall(callback, stream);
callback.call(stream);
};
const onrequest = () => {
@@ -218,7 +213,7 @@ function eos(stream, options, callback) {
// Keep it because cleanup removes it.
const endCallback = callback;
cleanup();
FunctionPrototypeCall(endCallback, stream, new AbortError());
endCallback.call(stream, new AbortError());
};
if (options.signal.aborted) {
process.nextTick(abort);
@@ -226,7 +221,7 @@ function eos(stream, options, callback) {
const originalCallback = callback;
callback = once((...args) => {
options.signal.removeEventListener('abort', abort);
ReflectApply(originalCallback, stream, args);
originalCallback.apply(stream, args);
});
options.signal.addEventListener('abort', abort);
}
+1 -2
View File
@@ -4,7 +4,6 @@
'use strict';
const {
FunctionPrototypeCall,
ObjectDefineProperties,
ObjectDefineProperty,
ObjectSetPrototypeOf,
@@ -26,7 +25,7 @@ ObjectSetPrototypeOf(LazyTransform, stream.Transform);
function makeGetter(name) {
return function() {
FunctionPrototypeCall(stream.Transform, this, this._options);
stream.Transform.call(this, this._options);
this._writableState.decodeStrings = false;
if (!this._options || !this._options.defaultEncoding) {
+2 -4
View File
@@ -2,15 +2,13 @@
const {
ArrayIsArray,
ArrayPrototypeUnshift,
FunctionPrototypeCall,
ObjectSetPrototypeOf,
} = primordials;
const EE = require('events');
function Stream(opts) {
FunctionPrototypeCall(EE, this, opts);
EE.call(this, opts);
}
ObjectSetPrototypeOf(Stream.prototype, EE.prototype);
ObjectSetPrototypeOf(Stream, EE);
@@ -108,7 +106,7 @@ function prependListener(emitter, event, fn) {
if (!emitter._events || !emitter._events[event])
emitter.on(event, fn);
else if (ArrayIsArray(emitter._events[event]))
ArrayPrototypeUnshift(emitter._events[event], fn);
emitter._events[event].unshift(fn);
else
emitter._events[event] = [fn, emitter._events[event]];
}
+1 -2
View File
@@ -26,7 +26,6 @@
'use strict';
const {
FunctionPrototypeCall,
ObjectSetPrototypeOf,
} = primordials;
@@ -40,7 +39,7 @@ function PassThrough(options) {
if (!(this instanceof PassThrough))
return new PassThrough(options);
FunctionPrototypeCall(Transform, this, options);
Transform.call(this, options);
}
PassThrough.prototype._transform = function(chunk, encoding, cb) {
+13 -18
View File
@@ -5,11 +5,6 @@
const {
ArrayIsArray,
ArrayPrototypePop,
ArrayPrototypePush,
ArrayPrototypeShift,
FunctionPrototypeCall,
ReflectApply,
SymbolAsyncIterator,
} = primordials;
@@ -84,7 +79,7 @@ function popCallback(streams) {
// a single stream. Therefore optimize for the average case instead of
// checking for length === 0 as well.
validateCallback(streams[streams.length - 1]);
return ArrayPrototypePop(streams);
return streams.pop();
}
function makeAsyncIterable(val) {
@@ -103,7 +98,7 @@ async function* fromReadable(val) {
Readable = require('internal/streams/readable');
}
yield* FunctionPrototypeCall(Readable.prototype[SymbolAsyncIterator], val);
yield* Readable.prototype[SymbolAsyncIterator].call(val);
}
async function pump(iterable, writable, finish) {
@@ -160,7 +155,7 @@ function pipeline(...streams) {
}
while (destroys.length) {
ArrayPrototypeShift(destroys)(error);
destroys.shift()(error);
}
if (final) {
@@ -176,7 +171,7 @@ function pipeline(...streams) {
if (isStream(stream)) {
finishCount++;
ArrayPrototypePush(destroys, destroyer(stream, reading, writing, finish));
destroys.push(destroyer(stream, reading, writing, finish));
}
if (i === 0) {
@@ -220,14 +215,14 @@ function pipeline(...streams) {
// second use.
const then = ret?.then;
if (typeof then === 'function') {
ReflectApply(then, ret, [
(val) => {
value = val;
pt.end(val);
}, (err) => {
pt.destroy(err);
},
]);
then.call(ret,
(val) => {
value = val;
pt.end(val);
}, (err) => {
pt.destroy(err);
},
);
} else if (isIterable(ret, true)) {
finishCount++;
pump(ret, pt, finish);
@@ -239,7 +234,7 @@ function pipeline(...streams) {
ret = pt;
finishCount++;
ArrayPrototypePush(destroys, destroyer(ret, false, true, finish));
destroys.push(destroyer(ret, false, true, finish));
}
} else if (isStream(stream)) {
if (isReadable(ret)) {
+19 -24
View File
@@ -22,13 +22,7 @@
'use strict';
const {
ArrayPrototypeForEach,
ArrayPrototypeIndexOf,
ArrayPrototypePush,
ArrayPrototypeSplice,
FunctionPrototype,
FunctionPrototypeBind,
FunctionPrototypeCall,
NumberIsInteger,
NumberIsNaN,
NumberParseInt,
@@ -36,7 +30,6 @@ const {
ObjectKeys,
ObjectSetPrototypeOf,
Promise,
ReflectApply,
SafeSet,
SymbolAsyncIterator,
Symbol
@@ -78,7 +71,7 @@ let from;
ObjectSetPrototypeOf(Readable.prototype, Stream.prototype);
ObjectSetPrototypeOf(Readable, Stream);
const nop = FunctionPrototype;
const nop = () => {};
const { errorOrDestroy } = destroyImpl;
@@ -208,7 +201,7 @@ function Readable(options) {
addAbortSignalNoValidate(options.signal, this);
}
FunctionPrototypeCall(Stream, this, options);
Stream.call(this, options);
destroyImpl.construct(this, () => {
if (this._readableState.needReadable) {
@@ -668,7 +661,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) {
}
}
ArrayPrototypePush(state.pipes, dest);
state.pipes.push(dest);
debug('pipe count=%d opts=%j', state.pipes.length, pipeOpts);
const doEnd = (!pipeOpts || pipeOpts.end !== false) &&
@@ -855,8 +848,8 @@ Readable.prototype.unpipe = function(dest) {
state.pipes = [];
this.pause();
ArrayPrototypeForEach(dests, (dest) =>
dest.emit('unpipe', this, { hasUnpiped: false }));
for (let i = 0; i < dests.length; i++)
dests[i].emit('unpipe', this, { hasUnpiped: false });
return this;
}
@@ -865,7 +858,7 @@ Readable.prototype.unpipe = function(dest) {
if (index === -1)
return this;
ArrayPrototypeSplice(state.pipes, index, 1);
state.pipes.splice(index, 1);
if (state.pipes.length === 0)
this.pause();
@@ -877,7 +870,7 @@ Readable.prototype.unpipe = function(dest) {
// Set up data events if they are asked for
// Ensure readable listeners eventually get something.
Readable.prototype.on = function(ev, fn) {
const res = FunctionPrototypeCall(Stream.prototype.on, this, ev, fn);
const res = Stream.prototype.on.call(this, ev, fn);
const state = this._readableState;
if (ev === 'data') {
@@ -907,8 +900,8 @@ Readable.prototype.on = function(ev, fn) {
Readable.prototype.addListener = Readable.prototype.on;
Readable.prototype.removeListener = function(ev, fn) {
const res = FunctionPrototypeCall(Stream.prototype.removeListener, this,
ev, fn);
const res = Stream.prototype.removeListener.call(this,
ev, fn);
if (ev === 'readable') {
// We need to check if there is someone still listening to
@@ -925,8 +918,8 @@ Readable.prototype.removeListener = function(ev, fn) {
Readable.prototype.off = Readable.prototype.removeListener;
Readable.prototype.removeAllListeners = function(ev) {
const res = ReflectApply(Stream.prototype.removeAllListeners, this,
arguments);
const res = Stream.prototype.removeAllListeners.apply(this,
arguments);
if (ev === 'readable' || ev === undefined) {
// We need to check if there is someone still listening to
@@ -1057,11 +1050,13 @@ Readable.prototype.wrap = function(stream) {
};
// Proxy all the other methods. Important when wrapping filters and duplexes.
ArrayPrototypeForEach(ObjectKeys(stream), (i) => {
const streamKeys = ObjectKeys(stream);
for (let j = 1; j < streamKeys.length; j++) {
const i = streamKeys[j];
if (this[i] === undefined && typeof stream[i] === 'function') {
this[i] = FunctionPrototypeBind(stream[i], stream);
this[i] = stream[i].bind(stream);
}
});
}
return this;
};
@@ -1110,15 +1105,15 @@ async function* createAsyncIterator(stream) {
.on('error', function(err) {
error = err;
errorEmitted = true;
FunctionPrototypeCall(next, this);
next.call(this);
})
.on('end', function() {
endEmitted = true;
FunctionPrototypeCall(next, this);
next.call(this);
})
.on('close', function() {
closeEmitted = true;
FunctionPrototypeCall(next, this);
next.call(this);
});
try {
+3 -6
View File
@@ -64,7 +64,6 @@
'use strict';
const {
FunctionPrototypeCall,
ObjectSetPrototypeOf,
Symbol
} = primordials;
@@ -133,8 +132,7 @@ function final(cb) {
try {
const then = result.then;
if (typeof then === 'function') {
FunctionPrototypeCall(
then,
then.call(
result,
(data) => {
if (called)
@@ -167,7 +165,7 @@ function final(cb) {
function prefinish() {
if (this._final !== final) {
FunctionPrototypeCall(final, this);
final.call(this);
}
}
@@ -209,8 +207,7 @@ Transform.prototype._write = function(chunk, encoding, callback) {
try {
const then = result.then;
if (typeof then === 'function') {
FunctionPrototypeCall(
then,
then.call(
result,
(val) => {
if (called)
+19 -20
View File
@@ -26,12 +26,8 @@
'use strict';
const {
ArrayPrototypeForEach,
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
Error,
FunctionPrototypeCall,
FunctionPrototypeSymbolHasInstance,
ObjectDefineProperty,
ObjectDefineProperties,
@@ -257,7 +253,7 @@ function Writable(options) {
addAbortSignalNoValidate(options.signal, this);
}
FunctionPrototypeCall(Stream, this, options);
Stream.call(this, options);
destroyImpl.construct(this, () => {
const state = this._writableState;
@@ -521,10 +517,10 @@ function errorBuffer(state) {
callback(new ERR_STREAM_DESTROYED('write'));
}
ArrayPrototypeForEach(
ArrayPrototypeSplice(state[kOnFinished], 0),
(callback) => callback(new ERR_STREAM_DESTROYED('end'))
);
const onfinishCallbacks = state[kOnFinished].splice(0);
for (let i = 0; i < onfinishCallbacks.length; i++) {
onfinishCallbacks[i](new ERR_STREAM_DESTROYED('end'));
}
resetBuffer(state);
}
@@ -576,7 +572,7 @@ function clearBuffer(stream, state) {
if (i === buffered.length) {
resetBuffer(state);
} else if (i > 256) {
ArrayPrototypeSplice(buffered, 0, i);
buffered.splice(0, i);
state.bufferedIndex = 0;
} else {
state.bufferedIndex = i;
@@ -644,7 +640,7 @@ Writable.prototype.end = function(chunk, encoding, cb) {
if (err || state.finished) {
process.nextTick(cb, err);
} else {
ArrayPrototypePush(state[kOnFinished], cb);
state[kOnFinished].push(cb);
}
}
@@ -667,8 +663,9 @@ function callFinal(stream, state) {
const result = stream._final((err) => {
state.pendingcb--;
if (err) {
for (const callback of ArrayPrototypeSplice(state[kOnFinished], 0)) {
callback(err);
const onfinishCallbacks = state[kOnFinished].splice(0);
for (let i = 0; i < onfinishCallbacks.length; i++) {
onfinishCallbacks[i](err);
}
errorOrDestroy(stream, err, state.sync);
} else if (needFinish(state)) {
@@ -685,8 +682,7 @@ function callFinal(stream, state) {
try {
const then = result.then;
if (typeof then === 'function') {
FunctionPrototypeCall(
then,
then.call(
result,
function() {
if (state.prefinished)
@@ -697,8 +693,9 @@ function callFinal(stream, state) {
process.nextTick(finish, stream, state);
},
function(err) {
for (const cb of ArrayPrototypeSplice(state[kOnFinished], 0)) {
process.nextTick(cb, err);
const onfinishCallbacks = state[kOnFinished].splice(0);
for (let i = 0; i < onfinishCallbacks.length; i++) {
process.nextTick(onfinishCallbacks[i], err);
}
process.nextTick(errorOrDestroy, stream, err, state.sync);
});
@@ -744,8 +741,10 @@ function finish(stream, state) {
state.finished = true;
ArrayPrototypeForEach(ArrayPrototypeSplice(state[kOnFinished], 0),
(callback) => callback());
const onfinishCallbacks = state[kOnFinished].splice(0);
for (let i = 0; i < onfinishCallbacks.length; i++) {
onfinishCallbacks[i]();
}
stream.emit('finish');
@@ -859,7 +858,7 @@ Writable.prototype.destroy = function(err, cb) {
process.nextTick(errorBuffer, state);
}
FunctionPrototypeCall(destroy, this, err, cb);
destroy.call(this, err, cb);
return this;
};
+1 -1
View File
@@ -78,8 +78,8 @@ const {
NumberIsFinite,
NumberMIN_SAFE_INTEGER,
ObjectCreate,
Symbol,
ReflectApply,
Symbol,
} = primordials;
const {
+8 -9
View File
@@ -3,7 +3,6 @@
const {
ArrayFrom,
ArrayIsArray,
ArrayPrototypePop,
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSort,
@@ -148,13 +147,13 @@ function slowCases(enc) {
case 4:
if (enc === 'UTF8') return 'utf8';
if (enc === 'ucs2' || enc === 'UCS2') return 'utf16le';
enc = StringPrototypeToLowerCase(`${enc}`);
enc = `${enc}`.toLowerCase();
if (enc === 'utf8') return 'utf8';
if (enc === 'ucs2') return 'utf16le';
break;
case 3:
if (enc === 'hex' || enc === 'HEX' ||
StringPrototypeToLowerCase(`${enc}`) === 'hex')
`${enc}`.toLowerCase() === 'hex')
return 'hex';
break;
case 5:
@@ -163,7 +162,7 @@ function slowCases(enc) {
if (enc === 'UTF-8') return 'utf8';
if (enc === 'ASCII') return 'ascii';
if (enc === 'UCS-2') return 'utf16le';
enc = StringPrototypeToLowerCase(`${enc}`);
enc = `${enc}`.toLowerCase();
if (enc === 'utf-8') return 'utf8';
if (enc === 'ascii') return 'ascii';
if (enc === 'ucs-2') return 'utf16le';
@@ -173,23 +172,23 @@ function slowCases(enc) {
if (enc === 'latin1' || enc === 'binary') return 'latin1';
if (enc === 'BASE64') return 'base64';
if (enc === 'LATIN1' || enc === 'BINARY') return 'latin1';
enc = StringPrototypeToLowerCase(`${enc}`);
enc = `${enc}`.toLowerCase();
if (enc === 'base64') return 'base64';
if (enc === 'latin1' || enc === 'binary') return 'latin1';
break;
case 7:
if (enc === 'utf16le' || enc === 'UTF16LE' ||
StringPrototypeToLowerCase(`${enc}`) === 'utf16le')
`${enc}`.toLowerCase() === 'utf16le')
return 'utf16le';
break;
case 8:
if (enc === 'utf-16le' || enc === 'UTF-16LE' ||
StringPrototypeToLowerCase(`${enc}`) === 'utf-16le')
`${enc}`.toLowerCase() === 'utf-16le')
return 'utf16le';
break;
case 9:
if (enc === 'base64url' || enc === 'BASE64URL' ||
StringPrototypeToLowerCase(`${enc}`) === 'base64url')
`${enc}`.toLowerCase() === 'base64url')
return 'base64url';
break;
default:
@@ -370,7 +369,7 @@ function join(output, separator) {
function spliceOne(list, index) {
for (; index + 1 < list.length; index++)
list[index] = list[index + 1];
ArrayPrototypePop(list);
list.pop();
}
const kNodeModulesRE = /^(.*)[\\/]node_modules[\\/]/;
+15 -4
View File
@@ -1,7 +1,6 @@
'use strict';
const {
FunctionPrototype,
FunctionPrototypeBind,
ObjectCreate,
ObjectDefineProperty,
@@ -45,7 +44,7 @@ function emitWarningIfNeeded(set) {
}
}
const noop = FunctionPrototype;
const noop = () => {};
function debuglogImpl(enabled, set) {
if (debugImpls[set] === undefined) {
@@ -81,7 +80,12 @@ function debuglog(set, cb) {
debug = debuglogImpl(enabled, set);
if (typeof cb === 'function')
cb(debug);
debug(...new SafeArrayIterator(args));
switch (args.length) {
case 0: return debug();
case 1: return debug(args[0]);
case 2: return debug(args[0], args[1]);
default: return debug(...new SafeArrayIterator(args));
}
};
let enabled;
let test = () => {
@@ -89,7 +93,14 @@ function debuglog(set, cb) {
test = () => enabled;
return enabled;
};
const logger = (...args) => debug(...new SafeArrayIterator(args));
const logger = (...args) => {
switch (args.length) {
case 0: return debug();
case 1: return debug(args[0]);
case 2: return debug(args[0], args[1]);
default: return debug(...new SafeArrayIterator(args));
}
};
ObjectDefineProperty(logger, 'enabled', {
get() {
return test();
+11 -16
View File
@@ -24,18 +24,13 @@
const {
ArrayIsArray,
ArrayPrototypeIndexOf,
ArrayPrototypePush,
ArrayPrototypeSplice,
Boolean,
Error,
FunctionPrototype,
FunctionPrototypeCall,
Number,
NumberIsNaN,
NumberParseInt,
ObjectDefineProperty,
ObjectSetPrototypeOf,
ReflectApply,
Symbol,
} = primordials;
@@ -132,7 +127,7 @@ const DEFAULT_IPV6_ADDR = '::';
const isWindows = process.platform === 'win32';
const noop = FunctionPrototype;
const noop = () => {};
function getFlags(ipv6Only) {
return ipv6Only === true ? TCPConstants.UV_TCP_IPV6ONLY : 0;
@@ -305,7 +300,7 @@ function Socket(options) {
options.autoDestroy = true;
// Handle strings directly.
options.decodeStrings = false;
ReflectApply(stream.Duplex, this, [options]);
stream.Duplex.call(this, options);
if (options.handle) {
this._handle = options.handle; // private
@@ -441,8 +436,7 @@ function afterShutdown() {
// is overly vague, and makes it seem like the user's code is to blame.
function writeAfterFIN(chunk, encoding, cb) {
if (!this.writableEnded) {
return ReflectApply(
stream.Duplex.prototype.write, this, [chunk, encoding, cb]);
return stream.Duplex.prototype.write.call(this, chunk, encoding, cb);
}
if (typeof encoding === 'function') {
@@ -586,7 +580,8 @@ Socket.prototype._read = function(n) {
Socket.prototype.end = function(data, encoding, callback) {
ReflectApply(stream.Duplex.prototype.end, this, [data, encoding, callback]);
stream.Duplex.prototype.end.call(this,
data, encoding, callback);
DTRACE_NET_STREAM_END(this);
return this;
};
@@ -602,7 +597,7 @@ Socket.prototype.pause = function() {
this.destroy(errnoException(err, 'read'));
}
}
return FunctionPrototypeCall(stream.Duplex.prototype.pause, this);
return stream.Duplex.prototype.pause.call(this);
};
@@ -611,7 +606,7 @@ Socket.prototype.resume = function() {
!this._handle.reading) {
tryReadStart(this);
}
return FunctionPrototypeCall(stream.Duplex.prototype.resume, this);
return stream.Duplex.prototype.resume.call(this);
};
@@ -620,7 +615,7 @@ Socket.prototype.read = function(n) {
!this._handle.reading) {
tryReadStart(this);
}
return ReflectApply(stream.Duplex.prototype.read, this, [n]);
return stream.Duplex.prototype.read.call(this, n);
};
@@ -1169,7 +1164,7 @@ function Server(options, connectionListener) {
if (!(this instanceof Server))
return new Server(options, connectionListener);
FunctionPrototypeCall(EventEmitter, this);
EventEmitter.call(this);
if (typeof options === 'function') {
connectionListener = options;
@@ -1681,10 +1676,10 @@ ObjectDefineProperty(Socket.prototype, '_handle', {
Server.prototype._setupWorker = function(socketList) {
this._usingWorkers = true;
ArrayPrototypePush(this._workers, socketList);
this._workers.push(socketList);
socketList.once('exit', (socketList) => {
const index = ArrayPrototypeIndexOf(this._workers, socketList);
ArrayPrototypeSplice(this._workers, index, 1);
this._workers.splice(index, 1);
});
};