diff --git a/lib/_http_common.js b/lib/_http_common.js index 229353ec735288..e3e732a8a180c6 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -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); diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js index d09683c9a8f1b1..e0f1354e6c969c 100644 --- a/lib/_http_incoming.js +++ b/lib/_http_incoming.js @@ -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]; } diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index b627608a527201..4d3b58cc84d00c 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -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); diff --git a/lib/_http_server.js b/lib/_http_server.js index 8ada9e8cfe987a..97df58a007daba 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -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; diff --git a/lib/events.js b/lib/events.js index 15c69c30271aa6..cc29b3358e0ce2 100644 --- a/lib/events.js +++ b/lib/events.js @@ -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); } } diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 69ca8d6db987ed..b8955f644d15d7 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -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; } diff --git a/lib/internal/per_context/primordials.js b/lib/internal/per_context/primordials.js index a1e9f3ae305e32..ff6408114c0710 100644 --- a/lib/internal/per_context/primordials.js +++ b/lib/internal/per_context/primordials.js @@ -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, +// benchmark all changes made in performance-sensitive area of the codebase. +// See: https://github.com/nodejs/node/pull/38248 + const { defineProperty: ReflectDefineProperty, getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor, diff --git a/lib/internal/streams/destroy.js b/lib/internal/streams/destroy.js index 467275c2edac35..a2892c67a0fcfa 100644 --- a/lib/internal/streams/destroy.js +++ b/lib/internal/streams/destroy.js @@ -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. diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index da48831a405dbe..318ab4c2e6a8b7 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -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); } diff --git a/lib/internal/streams/lazy_transform.js b/lib/internal/streams/lazy_transform.js index ad072e3474b3e1..555e6430e33588 100644 --- a/lib/internal/streams/lazy_transform.js +++ b/lib/internal/streams/lazy_transform.js @@ -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) { diff --git a/lib/internal/streams/legacy.js b/lib/internal/streams/legacy.js index d08df00259033b..0a0d0571c46378 100644 --- a/lib/internal/streams/legacy.js +++ b/lib/internal/streams/legacy.js @@ -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]]; } diff --git a/lib/internal/streams/passthrough.js b/lib/internal/streams/passthrough.js index acc1a148a7d7c1..d37f9caf0116b5 100644 --- a/lib/internal/streams/passthrough.js +++ b/lib/internal/streams/passthrough.js @@ -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) { diff --git a/lib/internal/streams/pipeline.js b/lib/internal/streams/pipeline.js index 5215d986ef1f1c..441fcb471858bc 100644 --- a/lib/internal/streams/pipeline.js +++ b/lib/internal/streams/pipeline.js @@ -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)) { diff --git a/lib/internal/streams/readable.js b/lib/internal/streams/readable.js index cc3f5e93fd0201..aa0f5f94886427 100644 --- a/lib/internal/streams/readable.js +++ b/lib/internal/streams/readable.js @@ -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 { diff --git a/lib/internal/streams/transform.js b/lib/internal/streams/transform.js index 971bf5126f250d..26e0b07c2956c8 100644 --- a/lib/internal/streams/transform.js +++ b/lib/internal/streams/transform.js @@ -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) diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index d00e175ceb1c1b..03f63b16bd04ff 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -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; }; diff --git a/lib/internal/timers.js b/lib/internal/timers.js index 9521c343038b4f..9a07fe3348f65e 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -78,8 +78,8 @@ const { NumberIsFinite, NumberMIN_SAFE_INTEGER, ObjectCreate, - Symbol, ReflectApply, + Symbol, } = primordials; const { diff --git a/lib/internal/util.js b/lib/internal/util.js index 4756459f4c5960..f77f1fc43368c4 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -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[\\/]/; diff --git a/lib/internal/util/debuglog.js b/lib/internal/util/debuglog.js index 3dc7a5157d5e65..b1f82b957b162a 100644 --- a/lib/internal/util/debuglog.js +++ b/lib/internal/util/debuglog.js @@ -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(); diff --git a/lib/net.js b/lib/net.js index 826cffd234852d..4b55366f87dae0 100644 --- a/lib/net.js +++ b/lib/net.js @@ -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); }); };