From 882e66e0bfa39f78bb3dcc9197a82a5f4603d44e Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 28 Oct 2020 00:04:22 +0100 Subject: [PATCH] lib: use more primordials This replaces all Function.prototype.apply, Function.prototype.bind, Function.prototype.call to their primordials alter ego. --- lib/_http_agent.js | 3 +- lib/_http_client.js | 8 +-- lib/_http_incoming.js | 4 +- lib/_http_outgoing.js | 6 ++- lib/_http_server.js | 56 +++++++++++++------- lib/_tls_wrap.js | 10 ++-- lib/assert.js | 8 +-- lib/async_hooks.js | 3 +- lib/buffer.js | 7 +-- lib/dgram.js | 14 ++--- lib/dns.js | 3 +- lib/events.js | 16 +++--- lib/fs.js | 3 +- lib/https.js | 7 +-- lib/internal/assert/calltracker.js | 3 +- lib/internal/bootstrap/node.js | 3 +- lib/internal/child_process.js | 14 ++--- lib/internal/cluster/child.js | 8 +-- lib/internal/cluster/utils.js | 3 +- lib/internal/cluster/worker.js | 8 +-- lib/internal/crypto/cipher.js | 19 ++++--- lib/internal/crypto/hash.js | 5 +- lib/internal/crypto/sig.js | 5 +- lib/internal/dgram.js | 5 +- lib/internal/dns/promises.js | 3 +- lib/internal/dns/utils.js | 3 +- lib/internal/errors.js | 2 +- lib/internal/event_target.js | 8 +-- lib/internal/fs/promises.js | 3 +- lib/internal/fs/read_file_context.js | 3 +- lib/internal/fs/streams.js | 10 ++-- lib/internal/fs/sync_write_stream.js | 3 +- lib/internal/fs/utils.js | 9 ++-- lib/internal/fs/watchers.js | 5 +- lib/internal/http2/compat.js | 13 +++-- lib/internal/http2/core.js | 72 +++++++++++++++----------- lib/internal/modules/cjs/loader.js | 5 +- lib/internal/modules/esm/loader.js | 3 +- lib/internal/modules/esm/module_job.js | 4 +- lib/internal/process/per_thread.js | 3 +- lib/internal/process/signal.js | 3 +- lib/internal/process/warning.js | 3 +- lib/internal/quic/core.js | 43 ++++++++------- lib/internal/repl/utils.js | 7 +-- lib/internal/stream_base_commons.js | 6 ++- lib/internal/streams/destroy.js | 14 +++-- lib/internal/streams/duplex.js | 5 +- lib/internal/streams/end-of-stream.js | 17 +++--- lib/internal/streams/lazy_transform.js | 3 +- lib/internal/streams/legacy.js | 3 +- lib/internal/streams/passthrough.js | 3 +- lib/internal/streams/pipeline.js | 3 +- lib/internal/streams/readable.js | 21 +++++--- lib/internal/streams/transform.js | 11 ++-- lib/internal/streams/writable.js | 18 ++++--- lib/internal/url.js | 34 +++++++----- lib/internal/util.js | 8 +-- lib/internal/util/inspect.js | 17 +++--- lib/internal/util/inspector.js | 7 +-- lib/internal/worker.js | 3 +- lib/internal/worker/io.js | 11 ++-- lib/net.js | 14 ++--- lib/path.js | 8 ++- lib/readline.js | 6 ++- lib/repl.js | 27 +++++----- lib/tty.js | 5 +- lib/url.js | 5 +- lib/vm.js | 5 +- lib/zlib.js | 33 +++++++----- 69 files changed, 437 insertions(+), 276 deletions(-) diff --git a/lib/_http_agent.js b/lib/_http_agent.js index 6f6a0920fd8c04..06aef3e6b59f45 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -22,6 +22,7 @@ 'use strict'; const { + FunctionPrototypeCall, NumberIsNaN, ObjectKeys, ObjectSetPrototypeOf, @@ -78,7 +79,7 @@ function Agent(options) { if (!(this instanceof Agent)) return new Agent(options); - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); this.defaultPort = 80; this.protocol = 'http:'; diff --git a/lib/_http_client.js b/lib/_http_client.js index 885016bf4856db..38d86e5cfe9986 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -25,10 +25,12 @@ const { ArrayIsArray, Boolean, Error, + FunctionPrototypeCall, NumberIsFinite, ObjectAssign, ObjectKeys, ObjectSetPrototypeOf, + ReflectApply, String, Symbol } = primordials; @@ -87,7 +89,7 @@ class HTTPClientAsyncResource { let urlWarningEmitted = false; function ClientRequest(input, options, cb) { - OutgoingMessage.call(this); + FunctionPrototypeCall(OutgoingMessage, this); if (typeof input === 'string') { const urlStr = input; @@ -329,7 +331,7 @@ ObjectSetPrototypeOf(ClientRequest, OutgoingMessage); ClientRequest.prototype._finish = function _finish() { DTRACE_HTTP_CLIENT_REQUEST(this, this.socket); - OutgoingMessage.prototype._finish.call(this); + FunctionPrototypeCall(OutgoingMessage.prototype._finish, this); }; ClientRequest.prototype._implicitHeader = function _implicitHeader() { @@ -840,7 +842,7 @@ function _deferToConnect(method, arguments_, cb) { const callSocketMethod = () => { if (method) - this.socket[method].apply(this.socket, arguments_); + ReflectApply(this.socket[method], this.socket, arguments_); if (typeof cb === 'function') cb(); diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js index 7943c69f54d911..c3aa99428f0b02 100644 --- a/lib/_http_incoming.js +++ b/lib/_http_incoming.js @@ -22,6 +22,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectDefineProperty, ObjectSetPrototypeOf, Symbol @@ -54,7 +55,8 @@ function IncomingMessage(socket) { }; } - Stream.Readable.call(this, { autoDestroy: false, ...streamOptions }); + FunctionPrototypeCall(Stream.Readable, + this, { autoDestroy: false, ...streamOptions }); this._readableState.readingMore = true; diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 48d113bb5cf232..222ae4271e4c28 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -23,6 +23,8 @@ const { ArrayIsArray, + FunctionPrototypeBind, + FunctionPrototypeCall, ObjectCreate, ObjectDefineProperty, ObjectKeys, @@ -87,7 +89,7 @@ function isCookieField(s) { function noopPendingOutput(amount) {} function OutgoingMessage() { - Stream.call(this); + FunctionPrototypeCall(Stream, 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). @@ -827,7 +829,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { if (typeof callback === 'function') this.once('finish', callback); - const finish = onFinish.bind(undefined, this); + const finish = FunctionPrototypeBind(onFinish, 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 7343d5f52791b9..dffb54440aca3f 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -24,6 +24,8 @@ const { ArrayIsArray, Error, + FunctionPrototypeBind, + FunctionPrototypeCall, ObjectKeys, ObjectSetPrototypeOf, Symbol, @@ -169,7 +171,7 @@ class HTTPServerAsyncResource { } function ServerResponse(req) { - OutgoingMessage.call(this); + FunctionPrototypeCall(OutgoingMessage, this); if (req.method === 'HEAD') this._hasBody = false; @@ -197,7 +199,7 @@ ServerResponse.prototype._finish = function _finish() { if (this[kServerResponseStatistics] !== undefined) { emitStatistics(this[kServerResponseStatistics]); } - OutgoingMessage.prototype._finish.call(this); + FunctionPrototypeCall(OutgoingMessage.prototype._finish, this); }; @@ -371,7 +373,7 @@ function Server(options, requestListener) { validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser'); this.insecureHTTPParser = insecureHTTPParser; - net.Server.call(this, { allowHalfOpen: true }); + FunctionPrototypeCall(net.Server, this, { allowHalfOpen: true }); if (requestListener) { this.on('request', requestListener); @@ -477,16 +479,21 @@ function connectionListenerInternal(server, socket) { outgoingData: 0, keepAliveTimeoutSet: false }; - 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); + 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); 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 = parserOnIncoming.bind(undefined, server, socket, state); + parser.onIncoming = FunctionPrototypeBind(parserOnIncoming, undefined, server, + socket, state); // We are consuming socket, so it won't get any actual data socket.on('resume', onSocketResume); @@ -505,16 +512,22 @@ function connectionListenerInternal(server, socket) { socket._handle._consumed = true; parser.consume(socket._handle); } - parser[kOnExecute] = - onParserExecute.bind(undefined, server, socket, parser, state); + parser[kOnExecute] = FunctionPrototypeBind( + onParserExecute, + undefined, + server, + socket, + parser, + state + ); parser[kOnTimeout] = - onParserTimeout.bind(undefined, server, socket); + FunctionPrototypeBind(onParserTimeout, undefined, server, socket); // When receiving new requests on the same socket (pipelining or keep alive) // make sure the requestTimeout is active. parser[kOnMessageBegin] = - setRequestTimeout.bind(undefined, server, socket); + FunctionPrototypeBind(setRequestTimeout, 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 @@ -592,7 +605,7 @@ function socketOnEnd(server, socket, parser, state) { if (ret instanceof Error) { debug('parse error'); - socketOnError.call(socket, ret); + FunctionPrototypeCall(socketOnError, socket, ret); return; } @@ -618,7 +631,7 @@ function socketOnData(server, socket, parser, state, d) { function onRequestTimeout(socket) { socket[kRequestTimeout] = undefined; - socketOnError.call(socket, new ERR_HTTP_REQUEST_TIMEOUT()); + FunctionPrototypeCall(socketOnError, socket, new ERR_HTTP_REQUEST_TIMEOUT()); } function onParserExecute(server, socket, parser, state, ret) { @@ -685,7 +698,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) { prepareError(ret, parser, d); ret.rawPacket = d || parser.getCurrentBuffer(); debug('parse error', ret); - socketOnError.call(socket, ret); + FunctionPrototypeCall(socketOnError, socket, ret); } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT const req = parser.incoming; @@ -724,7 +737,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] = - setRequestTimeout.bind(undefined, server, socket); + FunctionPrototypeBind(setRequestTimeout, undefined, server, socket); } if (socket._paused && socket.parser) { @@ -870,7 +883,8 @@ function parserOnIncoming(server, socket, state, req, keepAlive) { const res = new server[kServerResponse](req); res._keepAliveTimeout = server.keepAliveTimeout; - res._onPendingData = updateOutgoingData.bind(undefined, socket, state); + res._onPendingData = + FunctionPrototypeBind(updateOutgoingData, undefined, socket, state); res.shouldKeepAlive = keepAlive; DTRACE_HTTP_SERVER_REQUEST(req, socket); @@ -894,7 +908,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', - resOnFinish.bind(undefined, req, res, socket, state, server)); + FunctionPrototypeBind(resOnFinish, undefined, req, res, + socket, state, server)); if (req.headers.expect !== undefined && (req.httpVersionMajor === 1 && req.httpVersionMinor === 1)) { @@ -966,7 +981,10 @@ function unconsume(parser, socket) { function generateSocketListenerWrapper(originalFnName) { return function socketListenerWrap(ev, fn) { - const res = net.Socket.prototype[originalFnName].call(this, ev, fn); + const res = FunctionPrototypeCall( + net.Socket.prototype[originalFnName], + this, ev, fn + ); if (!this.parser) { this.on = net.Socket.prototype.on; this.addListener = net.Socket.prototype.addListener; diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 929114d74ad6b6..b440b9e6af458e 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -22,9 +22,11 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectAssign, ObjectDefineProperty, ObjectSetPrototypeOf, + ReflectApply, RegExp, Symbol, SymbolFor, @@ -496,7 +498,7 @@ function TLSSocket(socket, opts) { // distinguishable from regular ones. this.encrypted = true; - net.Socket.call(this, { + FunctionPrototypeCall(net.Socket, this, { handle: this._wrapHandle(wrap), allowHalfOpen: socket ? socket.allowHalfOpen : tlsOptions.allowHalfOpen, pauseOnCreate: tlsOptions.pauseOnConnect, @@ -535,7 +537,7 @@ const proxiedMethods = [ function makeMethodProxy(name) { return function methodProxy(...args) { if (this._parent[name]) - return this._parent[name].apply(this._parent, args); + return ReflectApply(this._parent[name], this._parent, args); }; } for (const proxiedMethod of proxiedMethods) { @@ -993,7 +995,7 @@ TLSSocket.prototype.getCertificate = function() { function makeSocketMethodProxy(name) { return function socketMethodProxy(...args) { if (this._handle) - return this._handle[name].apply(this._handle, args); + return ReflectApply(this._handle[name], this._handle, args); return null; }; } @@ -1209,7 +1211,7 @@ function Server(options, listener) { } // constructor call - net.Server.call(this, options, tlsConnectionListener); + FunctionPrototypeCall(net.Server, this, options, tlsConnectionListener); if (listener) { this.on('secureConnection', listener); diff --git a/lib/assert.js b/lib/assert.js index 43209df18f01d1..8a2e0911dbed58 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -23,6 +23,8 @@ const { Error, ErrorCaptureStackTrace, + FunctionPrototypeBind, + FunctionPrototypeCall, ObjectAssign, ObjectIs, ObjectKeys, @@ -234,7 +236,7 @@ function parseCode(code, offset) { classFields, staticClassFeatures ); - parseExpressionAt = Parser.parseExpressionAt.bind(Parser); + parseExpressionAt = FunctionPrototypeBind(Parser.parseExpressionAt, Parser); } let node; let start = 0; @@ -649,7 +651,7 @@ function expectedException(actual, expected, message, fn) { throwError = true; } else { // Check validation functions return value. - const res = expected.call({}, actual); + const res = FunctionPrototypeCall(expected, {}, actual); if (res !== true) { if (!message) { generatedMessage = true; @@ -794,7 +796,7 @@ function hasMatchingError(actual, expected) { if (ObjectPrototypeIsPrototypeOf(Error, expected)) { return false; } - return expected.call({}, actual) === true; + return FunctionPrototypeCall(expected, {}, actual) === true; } function expectsNoError(stackStartFn, actual, error, message) { diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 7dd888b61f79f9..dafc85dd66dc95 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeBind, NumberIsSafeInteger, ObjectDefineProperties, ObjectIs, @@ -218,7 +219,7 @@ class AsyncResource { bind(fn) { if (typeof fn !== 'function') throw new ERR_INVALID_ARG_TYPE('fn', 'Function', fn); - const ret = this.runInAsyncScope.bind(this, fn); + const ret = FunctionPrototypeBind(this.runInAsyncScope, this, fn); ObjectDefineProperties(ret, { 'length': { configurable: true, diff --git a/lib/buffer.js b/lib/buffer.js index 0daf5636edad46..ba8ddb42445995 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -25,6 +25,7 @@ const { Array, ArrayIsArray, Error, + FunctionPrototypeCall, MathFloor, MathMin, MathTrunc, @@ -566,7 +567,7 @@ Buffer.concat = function concat(list, length) { // Zero-fill the remaining bytes if the specified `length` was more than // the actual total length, i.e. if we have some remaining allocated bytes // there were not initialized. - TypedArrayFill.call(buffer, 0, pos, length); + FunctionPrototypeCall(TypedArrayFill, buffer, 0, pos, length); } return buffer; @@ -1005,12 +1006,12 @@ function _fill(buf, value, offset, end, encoding) { if (typeof value === 'number') { // OOB check - const byteLen = TypedArrayProto_byteLength.call(buf); + const byteLen = FunctionPrototypeCall(TypedArrayProto_byteLength, buf); const fillLength = end - offset; if (offset > end || fillLength + offset > byteLen) throw new ERR_BUFFER_OUT_OF_BOUNDS(); - TypedArrayFill.call(buf, value, offset, end); + FunctionPrototypeCall(TypedArrayFill, buf, value, offset, end); } else { const res = bindingFill(buf, value, offset, end, encoding); if (res < 0) { diff --git a/lib/dgram.js b/lib/dgram.js index 1c1b4781617695..543200cc17cf35 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -24,6 +24,8 @@ const { Array, ArrayIsArray, + FunctionPrototypeBind, + FunctionPrototypeCall, ObjectDefineProperty, ObjectSetPrototypeOf, } = primordials; @@ -87,7 +89,7 @@ const exceptionWithHostPort = errors.exceptionWithHostPort; function Socket(type, listener) { - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); let lookup; let recvBufferSize; let sendBufferSize; @@ -220,8 +222,8 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { } function onListening() { - removeListeners.call(this); - cb.call(this); + FunctionPrototypeCall(removeListeners, this); + FunctionPrototypeCall(cb, this); } this.on('error', removeListeners); @@ -373,7 +375,7 @@ Socket.prototype.connect = function(port, address, callback) { return; } - _connect.call(this, port, address, callback); + FunctionPrototypeCall(_connect, this, port, address, callback); }; @@ -504,7 +506,7 @@ function enqueue(self, toEnqueue) { function onListenSuccess() { this.removeListener(EventEmitter.errorMonitor, onListenError); - clearQueue.call(this); + FunctionPrototypeCall(clearQueue, this); } @@ -712,7 +714,7 @@ Socket.prototype.close = function(callback) { this.on('close', callback); if (queue !== undefined) { - queue.push(this.close.bind(this)); + queue.push(FunctionPrototypeBind(this.close, this)); return this; } diff --git a/lib/dns.js b/lib/dns.js index 8d45be73baf316..a9933eebc73f39 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -22,6 +22,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectCreate, ObjectDefineProperties, ObjectDefineProperty, @@ -261,7 +262,7 @@ function resolve(hostname, rrtype, callback) { } if (typeof resolver === 'function') { - return resolver.call(this, hostname, callback); + return FunctionPrototypeCall(resolver, this, hostname, callback); } throw new ERR_INVALID_ARG_VALUE('rrtype', rrtype); } diff --git a/lib/events.js b/lib/events.js index f82776072b1598..1a98ed811e813d 100644 --- a/lib/events.js +++ b/lib/events.js @@ -25,6 +25,8 @@ const { Boolean, Error, ErrorCaptureStackTrace, + FunctionPrototypeBind, + FunctionPrototypeCall, MathMin, NumberIsNaN, ObjectCreate, @@ -75,7 +77,7 @@ const lazyDOMException = hideStackFrames((message, name) => { }); function EventEmitter(opts) { - EventEmitter.init.call(this, opts); + FunctionPrototypeCall(EventEmitter.init, this, opts); } module.exports = EventEmitter; module.exports.once = once; @@ -175,7 +177,7 @@ function addCatch(that, promise, type, args) { const then = promise.then; if (typeof then === 'function') { - then.call(promise, undefined, function(err) { + FunctionPrototypeCall(then, 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); @@ -294,7 +296,7 @@ EventEmitter.prototype.emit = function emit(type, ...args) { const capture = {}; ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit); ObjectDefineProperty(er, kEnhanceStackBeforeInspector, { - value: enhanceStackTrace.bind(this, er, capture), + value: FunctionPrototypeBind(enhanceStackTrace, this, er, capture), configurable: true }); } catch {} @@ -429,15 +431,13 @@ function onceWrapper() { if (!this.fired) { this.target.removeListener(this.type, this.wrapFn); this.fired = true; - if (arguments.length === 0) - return this.listener.call(this.target); - return this.listener.apply(this.target, arguments); + return ReflectApply(this.listener, this.target, arguments); } } function _onceWrap(target, type, listener) { const state = { fired: false, wrapFn: undefined, target, type, listener }; - const wrapped = onceWrapper.bind(state); + const wrapped = FunctionPrototypeBind(onceWrapper, state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; @@ -587,7 +587,7 @@ EventEmitter.listenerCount = function(emitter, type) { if (typeof emitter.listenerCount === 'function') { return emitter.listenerCount(type); } - return listenerCount.call(emitter, type); + return FunctionPrototypeCall(listenerCount, emitter, type); }; EventEmitter.prototype.listenerCount = listenerCount; diff --git a/lib/fs.js b/lib/fs.js index fa64ae7e53d79c..5fd9a7413d55c9 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -41,6 +41,7 @@ const { ObjectDefineProperties, ObjectDefineProperty, Promise, + ReflectApply, String, } = primordials; @@ -320,7 +321,7 @@ function readFile(path, options, callback) { } if (context.isUserFd) { process.nextTick(function tick(context) { - readFileAfterOpen.call({ context }, null, path); + ReflectApply(readFileAfterOpen, { context }, [null, path]); }, context); return; } diff --git a/lib/https.js b/lib/https.js index 6aafef6cb639e1..33e7e4b7c211a5 100644 --- a/lib/https.js +++ b/lib/https.js @@ -22,6 +22,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectAssign, ObjectSetPrototypeOf, } = primordials; @@ -63,7 +64,7 @@ function Server(opts, requestListener) { this[kIncomingMessage] = opts.IncomingMessage || IncomingMessage; this[kServerResponse] = opts.ServerResponse || ServerResponse; - tls.Server.call(this, opts, _connectionListener); + FunctionPrototypeCall(tls.Server, this, opts, _connectionListener); this.httpAllowHalfOpen = false; @@ -149,7 +150,7 @@ function Agent(options) { if (!(this instanceof Agent)) return new Agent(options); - HttpAgent.call(this, options); + FunctionPrototypeCall(HttpAgent, this, options); this.defaultPort = 443; this.protocol = 'https:'; this.maxCachedSessions = this.options.maxCachedSessions; @@ -166,7 +167,7 @@ ObjectSetPrototypeOf(Agent, HttpAgent); Agent.prototype.createConnection = createConnection; Agent.prototype.getName = function getName(options) { - let name = HttpAgent.prototype.getName.call(this, options); + let name = FunctionPrototypeCall(HttpAgent.prototype.getName, this, options); name += ':'; if (options.ca) diff --git a/lib/internal/assert/calltracker.js b/lib/internal/assert/calltracker.js index 74f517f3f9e99b..64db7e743f9171 100644 --- a/lib/internal/assert/calltracker.js +++ b/lib/internal/assert/calltracker.js @@ -2,6 +2,7 @@ const { Error, + ReflectApply, SafeSet, } = primordials; @@ -55,7 +56,7 @@ class CallTracker { if (context.actual === context.exact + 1) { callChecks.add(context); } - return fn.apply(this, arguments); + return ReflectApply(fn, this, arguments); }; } diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index bb4689d0d342e8..8077c462983154 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -39,6 +39,7 @@ setupPrepareStackTrace(); const { + FunctionPrototypeCall, JSONParse, ObjectDefineProperty, ObjectGetPrototypeOf, @@ -299,7 +300,7 @@ function setupProcessObject() { const EventEmitter = require('events'); const origProcProto = ObjectGetPrototypeOf(process); ObjectSetPrototypeOf(origProcProto, EventEmitter.prototype); - EventEmitter.call(process); + FunctionPrototypeCall(EventEmitter, process); ObjectDefineProperty(process, SymbolToStringTag, { enumerable: false, writable: true, diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 76e67317b93357..18c82a4f689314 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -2,6 +2,7 @@ const { ArrayIsArray, + FunctionPrototypeCall, ObjectDefineProperty, ObjectSetPrototypeOf, Symbol, @@ -236,7 +237,7 @@ function stdioStringToArray(stdio, channel) { } function ChildProcess() { - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); this._closesNeeded = 1; this._closesGot = 0; @@ -686,7 +687,7 @@ function setupChannel(target, channel, serializationMode) { } // Convert handle object - obj.got.call(this, message, handle, (handle) => { + FunctionPrototypeCall(obj.got, this, message, handle, (handle) => { handleMessage(message.msg, handle, isInternal(message.msg)); }); }); @@ -780,10 +781,11 @@ function setupChannel(target, channel, serializationMode) { obj = handleConversion[message.type]; // convert TCP object to native handle object - handle = handleConversion[message.type].send.call(target, - message, - handle, - options); + handle = FunctionPrototypeCall(handleConversion[message.type].send, + target, + message, + handle, + options); // If handle was sent twice, or it is impossible to get native handle // out of it - just send a text without the handle. diff --git a/lib/internal/cluster/child.js b/lib/internal/cluster/child.js index 74f30c0d2ece90..b2f4d40742c46d 100644 --- a/lib/internal/cluster/child.js +++ b/lib/internal/cluster/child.js @@ -1,8 +1,10 @@ 'use strict'; const { + FunctionPrototypeCall, Map, ObjectAssign, + ReflectApply, } = primordials; const assert = require('internal/assert'); @@ -49,7 +51,7 @@ cluster._setupWorker = function() { if (message.act === 'newconn') onconnection(message, handle); else if (message.act === 'disconnect') - _disconnect.call(worker, true); + FunctionPrototypeCall(_disconnect, worker, true); } }; @@ -119,7 +121,7 @@ function shared(message, handle, indexesKey, cb) { send({ act: 'close', key }); handles.delete(key); indexes.delete(indexesKey); - return close.apply(handle, arguments); + return ReflectApply(close, handle, arguments); }; assert(handles.has(key) === false); handles.set(key, handle); @@ -230,7 +232,7 @@ function _disconnect(masterInitiated) { Worker.prototype.disconnect = function() { if (![ 'disconnecting', 'destroying' ].includes(this.state)) { this.state = 'disconnecting'; - _disconnect.call(this); + FunctionPrototypeCall(_disconnect, this); } return this; diff --git a/lib/internal/cluster/utils.js b/lib/internal/cluster/utils.js index 9e7a1186ffc2bf..973ff670a36510 100644 --- a/lib/internal/cluster/utils.js +++ b/lib/internal/cluster/utils.js @@ -2,6 +2,7 @@ const { Map, + ReflectApply, } = primordials; module.exports = { @@ -44,6 +45,6 @@ function internal(worker, cb) { } } - fn.apply(worker, arguments); + ReflectApply(fn, worker, arguments); }; } diff --git a/lib/internal/cluster/worker.js b/lib/internal/cluster/worker.js index 516b7a3b73d787..9e5d19fdfdde31 100644 --- a/lib/internal/cluster/worker.js +++ b/lib/internal/cluster/worker.js @@ -1,7 +1,9 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectSetPrototypeOf, + ReflectApply, } = primordials; const EventEmitter = require('events'); @@ -13,7 +15,7 @@ function Worker(options) { if (!(this instanceof Worker)) return new Worker(options); - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); if (options === null || typeof options !== 'object') options = {}; @@ -38,11 +40,11 @@ ObjectSetPrototypeOf(Worker.prototype, EventEmitter.prototype); ObjectSetPrototypeOf(Worker, EventEmitter); Worker.prototype.kill = function() { - this.destroy.apply(this, arguments); + ReflectApply(this.destroy, this, arguments); }; Worker.prototype.send = function() { - return this.process.send.apply(this.process, arguments); + return ReflectApply(this.process.send, this.process, arguments); }; Worker.prototype.isDead = function() { diff --git a/lib/internal/crypto/cipher.js b/lib/internal/crypto/cipher.js index 299d387d1c5e84..a99b275feb0376 100644 --- a/lib/internal/crypto/cipher.js +++ b/lib/internal/crypto/cipher.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectSetPrototypeOf, } = primordials; @@ -118,14 +119,15 @@ function createCipherBase(cipher, credential, options, decipher, iv) { } this._decoder = null; - LazyTransform.call(this, options); + FunctionPrototypeCall(LazyTransform, this, options); } function createCipher(cipher, password, options, decipher) { validateString(cipher, 'cipher'); password = getArrayBufferOrView(password, 'password'); - createCipherBase.call(this, cipher, password, options, decipher); + FunctionPrototypeCall(createCipherBase, this, cipher, + password, options, decipher); } function createCipherWithIV(cipher, key, options, decipher, iv) { @@ -133,7 +135,8 @@ function createCipherWithIV(cipher, key, options, decipher, iv) { const encoding = getStringOption(options, 'encoding'); key = prepareSecretKey(key, encoding); iv = iv === null ? null : getArrayBufferOrView(iv, 'iv'); - createCipherBase.call(this, cipher, key, options, decipher, iv); + FunctionPrototypeCall(createCipherBase, this, cipher, + key, options, decipher, iv); } // The Cipher class is part of the legacy Node.js crypto API. It exposes @@ -145,7 +148,7 @@ function Cipher(cipher, password, options) { if (!(this instanceof Cipher)) return new Cipher(cipher, password, options); - createCipher.call(this, cipher, password, options, true); + FunctionPrototypeCall(createCipher, this, cipher, password, options, true); } ObjectSetPrototypeOf(Cipher.prototype, LazyTransform.prototype); @@ -241,7 +244,8 @@ function Cipheriv(cipher, key, iv, options) { if (!(this instanceof Cipheriv)) return new Cipheriv(cipher, key, iv, options); - createCipherWithIV.call(this, cipher, key, options, true, iv); + FunctionPrototypeCall(createCipherWithIV, this, cipher, + key, options, true, iv); } function addCipherPrototypeFunctions(constructor) { @@ -271,7 +275,7 @@ function Decipher(cipher, password, options) { if (!(this instanceof Decipher)) return new Decipher(cipher, password, options); - createCipher.call(this, cipher, password, options, false); + FunctionPrototypeCall(createCipher, this, cipher, password, options, false); } ObjectSetPrototypeOf(Decipher.prototype, LazyTransform.prototype); @@ -287,7 +291,8 @@ function Decipheriv(cipher, key, iv, options) { if (!(this instanceof Decipheriv)) return new Decipheriv(cipher, key, iv, options); - createCipherWithIV.call(this, cipher, key, options, false, iv); + FunctionPrototypeCall(createCipherWithIV, this, cipher, + key, options, false, iv); } ObjectSetPrototypeOf(Decipheriv.prototype, LazyTransform.prototype); diff --git a/lib/internal/crypto/hash.js b/lib/internal/crypto/hash.js index 4647e98c671ab8..5eb00142f2b6ab 100644 --- a/lib/internal/crypto/hash.js +++ b/lib/internal/crypto/hash.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectSetPrototypeOf, Symbol, } = primordials; @@ -67,7 +68,7 @@ function Hash(algorithm, options) { this[kState] = { [kFinalized]: false }; - LazyTransform.call(this, options); + FunctionPrototypeCall(LazyTransform, this, options); } ObjectSetPrototypeOf(Hash.prototype, LazyTransform.prototype); @@ -134,7 +135,7 @@ function Hmac(hmac, key, options) { this[kState] = { [kFinalized]: false }; - LazyTransform.call(this, options); + FunctionPrototypeCall(LazyTransform, this, options); } ObjectSetPrototypeOf(Hmac.prototype, LazyTransform.prototype); diff --git a/lib/internal/crypto/sig.js b/lib/internal/crypto/sig.js index 27b26a87f0d6f3..b1c752ce9f8c53 100644 --- a/lib/internal/crypto/sig.js +++ b/lib/internal/crypto/sig.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectSetPrototypeOf, } = primordials; @@ -50,7 +51,7 @@ function Sign(algorithm, options) { this[kHandle] = new _Sign(); this[kHandle].init(algorithm); - Writable.call(this, options); + FunctionPrototypeCall(Writable, this, options); } ObjectSetPrototypeOf(Sign.prototype, Writable.prototype); @@ -164,7 +165,7 @@ function Verify(algorithm, options) { this[kHandle] = new _Verify(); this[kHandle].init(algorithm); - Writable.call(this, options); + FunctionPrototypeCall(Writable, this, options); } ObjectSetPrototypeOf(Verify.prototype, Writable.prototype); diff --git a/lib/internal/dgram.js b/lib/internal/dgram.js index 8a8d9ba8c0ddd4..950a82392c8e63 100644 --- a/lib/internal/dgram.js +++ b/lib/internal/dgram.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeBind, Symbol, } = primordials; @@ -37,14 +38,14 @@ function newHandle(type, lookup) { if (type === 'udp4') { const handle = new UDP(); - handle.lookup = lookup4.bind(handle, lookup); + handle.lookup = FunctionPrototypeBind(lookup4, handle, lookup); return handle; } if (type === 'udp6') { const handle = new UDP(); - handle.lookup = lookup6.bind(handle, lookup); + handle.lookup = FunctionPrototypeBind(lookup6, handle, lookup); handle.bind = handle.bind6; handle.connect = handle.connect6; handle.send = handle.send6; diff --git a/lib/internal/dns/promises.js b/lib/internal/dns/promises.js index e8505a95d12fed..bd2bb93f6642b1 100644 --- a/lib/internal/dns/promises.js +++ b/lib/internal/dns/promises.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectCreate, ObjectDefineProperty, Promise, @@ -245,7 +246,7 @@ Resolver.prototype.resolve = function resolve(hostname, rrtype) { throw new ERR_INVALID_ARG_TYPE('rrtype', 'string', rrtype); } - return resolver.call(this, hostname); + return FunctionPrototypeCall(resolver, this, hostname); }; diff --git a/lib/internal/dns/utils.js b/lib/internal/dns/utils.js index 1c50a089d1d89a..3a01f9a14a83fa 100644 --- a/lib/internal/dns/utils.js +++ b/lib/internal/dns/utils.js @@ -3,6 +3,7 @@ const { ArrayIsArray, ArrayPrototypePush, + FunctionPrototypeBind, NumberParseInt, StringPrototypeReplace, } = primordials; @@ -157,7 +158,7 @@ function setDefaultResolver(resolver) { function bindDefaultResolver(target, source) { resolverKeys.forEach((key) => { - target[key] = source[key].bind(defaultResolver); + target[key] = FunctionPrototypeBind(source[key], defaultResolver); }); } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 20a9e3e7df3e8a..cefb38368a9f0a 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -376,7 +376,7 @@ function getMessage(key, args, self) { `Code: ${key}; The provided arguments length (${args.length}) does not ` + `match the required ones (${msg.length}).` ); - return msg.apply(self, args); + return ReflectApply(msg, self, args); } const expectedLength = (msg.match(/%[dfijoOs]/g) || []).length; diff --git a/lib/internal/event_target.js b/lib/internal/event_target.js index 8c3ca67337baea..bd9f1c2c978dcb 100644 --- a/lib/internal/event_target.js +++ b/lib/internal/event_target.js @@ -4,6 +4,8 @@ const { ArrayFrom, Boolean, Error, + FunctionPrototypeBind, + FunctionPrototypeCall, Map, NumberIsInteger, ObjectAssign, @@ -194,7 +196,7 @@ class Listener { this.callback = typeof listener === 'function' ? listener : - listener.handleEvent.bind(listener); + FunctionPrototypeBind(listener.handleEvent, listener); } same(listener, capture) { @@ -363,7 +365,7 @@ class EventTarget { } else { arg = createEvent(); } - const result = handler.callback.call(this, arg); + const result = FunctionPrototypeCall(handler.callback, this, arg); if (result !== undefined && result !== null) addCatch(this, result, createEvent()); } catch (err) { @@ -545,7 +547,7 @@ function isEventTarget(obj) { function addCatch(that, promise, event) { const then = promise.then; if (typeof then === 'function') { - then.call(promise, undefined, function(err) { + FunctionPrototypeCall(then, promise, undefined, function(err) { // The callback is called with nextTick to avoid a follow-up // rejection from this promise. process.nextTick(emitUnhandledRejectionOrErr, that, err, event); diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 39c662fdc5b9c8..5d5a9864618763 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -11,6 +11,7 @@ const kWriteFileMaxChunkSize = 2 ** 14; const { Error, + FunctionPrototypeBind, MathMax, MathMin, NumberIsSafeInteger, @@ -431,7 +432,7 @@ async function rename(oldPath, newPath) { async function truncate(path, len = 0) { const fd = await open(path, 'r+'); - return ftruncate(fd, len).finally(fd.close.bind(fd)); + return ftruncate(fd, len).finally(FunctionPrototypeBind(fd.close, fd)); } async function ftruncate(handle, len = 0) { diff --git a/lib/internal/fs/read_file_context.js b/lib/internal/fs/read_file_context.js index faca0e0c331e39..d08b8196c808ef 100644 --- a/lib/internal/fs/read_file_context.js +++ b/lib/internal/fs/read_file_context.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, MathMin, } = primordials; @@ -118,7 +119,7 @@ class ReadFileContext { close(err) { if (this.isUserFd) { process.nextTick(function tick(context) { - readFileAfterClose.call({ context }, null); + FunctionPrototypeCall(readFileAfterClose, { context }, null); }, this); return; } diff --git a/lib/internal/fs/streams.js b/lib/internal/fs/streams.js index 5944a3980088eb..d29c84acdda9ac 100644 --- a/lib/internal/fs/streams.js +++ b/lib/internal/fs/streams.js @@ -2,9 +2,11 @@ const { Array, + FunctionPrototypeCall, MathMin, ObjectDefineProperty, ObjectSetPrototypeOf, + ReflectApply, Symbol, } = primordials; @@ -42,12 +44,12 @@ function _construct(callback) { if (args[0] === 'open') { this.emit = orgEmit; callback(); - orgEmit.apply(this, args); + ReflectApply(orgEmit, this, args); } else if (args[0] === 'error') { this.emit = orgEmit; callback(args[1]); } else { - orgEmit.apply(this, args); + ReflectApply(orgEmit, this, args); } }; stream.open(); @@ -145,7 +147,7 @@ function ReadStream(path, options) { } } - Readable.call(this, options); + FunctionPrototypeCall(Readable, this, options); } ObjectSetPrototypeOf(ReadStream.prototype, Readable.prototype); ObjectSetPrototypeOf(ReadStream, Readable); @@ -302,7 +304,7 @@ function WriteStream(path, options) { this.pos = this.start; } - Writable.call(this, options); + FunctionPrototypeCall(Writable, this, options); if (options.encoding) this.setDefaultEncoding(options.encoding); diff --git a/lib/internal/fs/sync_write_stream.js b/lib/internal/fs/sync_write_stream.js index 7d1209ba2decb4..c83c76df6aa77e 100644 --- a/lib/internal/fs/sync_write_stream.js +++ b/lib/internal/fs/sync_write_stream.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectSetPrototypeOf, } = primordials; @@ -8,7 +9,7 @@ const { Writable } = require('stream'); const { closeSync, writeSync } = require('fs'); function SyncWriteStream(fd, options) { - Writable.call(this, { autoDestroy: true }); + FunctionPrototypeCall(Writable, this, { autoDestroy: true }); options = options || {}; diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 24e2224c2e3945..e4e7467a5f5f1a 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -5,6 +5,7 @@ const { BigInt, DateNow, ErrorCaptureStackTrace, + FunctionPrototypeCall, ObjectPrototypeHasOwnProperty, Number, NumberIsFinite, @@ -431,8 +432,8 @@ function dateFromMs(ms) { function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, ino, size, blocks, atimeNs, mtimeNs, ctimeNs, birthtimeNs) { - StatsBase.call(this, dev, mode, nlink, uid, gid, rdev, blksize, - ino, size, blocks); + FunctionPrototypeCall(StatsBase, this, dev, mode, nlink, uid, gid, rdev, + blksize, ino, size, blocks); this.atimeMs = atimeNs / kNsPerMsBigInt; this.mtimeMs = mtimeNs / kNsPerMsBigInt; @@ -462,8 +463,8 @@ BigIntStats.prototype._checkModeProperty = function(property) { function Stats(dev, mode, nlink, uid, gid, rdev, blksize, ino, size, blocks, atimeMs, mtimeMs, ctimeMs, birthtimeMs) { - StatsBase.call(this, dev, mode, nlink, uid, gid, rdev, blksize, - ino, size, blocks); + FunctionPrototypeCall(StatsBase, this, dev, mode, nlink, uid, gid, rdev, + blksize, ino, size, blocks); this.atimeMs = atimeMs; this.mtimeMs = mtimeMs; this.ctimeMs = ctimeMs; diff --git a/lib/internal/fs/watchers.js b/lib/internal/fs/watchers.js index 01db66c551c9d3..43c6a8f9a938fa 100644 --- a/lib/internal/fs/watchers.js +++ b/lib/internal/fs/watchers.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectDefineProperty, ObjectSetPrototypeOf, Symbol, @@ -40,7 +41,7 @@ function emitStop(self) { } function StatWatcher(bigint) { - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); this._handle = null; this[kOldStatus] = -1; @@ -159,7 +160,7 @@ StatWatcher.prototype.unref = function() { function FSWatcher() { - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); this._handle = new FSEvent(); this._handle[owner_symbol] = this; diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index ec86be1ceaab45..8a2a28cade6c01 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -3,6 +3,8 @@ const { ArrayIsArray, Boolean, + FunctionPrototypeBind, + FunctionPrototypeCall, ObjectAssign, ObjectCreate, ObjectKeys, @@ -195,7 +197,7 @@ const proxySocketHandler = { case 'end': case 'emit': case 'destroy': - return stream[prop].bind(stream); + return FunctionPrototypeBind(stream[prop], stream); case 'writable': case 'destroyed': return stream[prop]; @@ -207,8 +209,8 @@ const proxySocketHandler = { case 'setTimeout': const session = stream.session; if (session !== undefined) - return session.setTimeout.bind(session); - return stream.setTimeout.bind(stream); + return FunctionPrototypeBind(session.setTimeout, session); + return FunctionPrototypeBind(stream.setTimeout, stream); case 'write': case 'read': case 'pause': @@ -218,7 +220,8 @@ const proxySocketHandler = { const ref = stream.session !== undefined ? stream.session[kSocket] : stream; const value = ref[prop]; - return typeof value === 'function' ? value.bind(ref) : value; + return typeof value === 'function' ? + FunctionPrototypeBind(value, ref) : value; } }, getPrototypeOf(stream) { @@ -750,7 +753,7 @@ class Http2ServerResponse extends Stream { this.writeHead(this[kState].statusCode); if (this[kState].closed || stream.destroyed) - onStreamCloseResponse.call(stream); + FunctionPrototypeCall(onStreamCloseResponse, stream); else stream.end(); diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 7ae3a7565d97ee..74c3a2ab64fc46 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -5,6 +5,8 @@ const { ArrayFrom, ArrayIsArray, + FunctionPrototypeBind, + FunctionPrototypeCall, Map, MathMin, ObjectAssign, @@ -781,7 +783,9 @@ function submitSettings(settings, callback) { debugSessionObj(this, 'submitting settings'); this[kUpdateTimer](); updateSettingsBuffer(settings); - if (!this[kHandle].settings(settingsCallback.bind(this, callback))) { + if (!this[kHandle].settings( + FunctionPrototypeBind(settingsCallback, this, callback) + )) { this.destroy(new ERR_HTTP2_MAX_PENDING_SETTINGS_ACK()); } } @@ -823,7 +827,7 @@ const proxySocketHandler = { case 'setTimeout': case 'ref': case 'unref': - return session[prop].bind(session); + return FunctionPrototypeBind(session[prop], session); case 'destroy': case 'emit': case 'end': @@ -840,7 +844,8 @@ const proxySocketHandler = { if (socket === undefined) throw new ERR_HTTP2_SOCKET_UNBOUND(); const value = socket[prop]; - return typeof value === 'function' ? value.bind(socket) : value; + return typeof value === 'function' ? + FunctionPrototypeBind(value, socket) : value; } }, getPrototypeOf(session) { @@ -1078,7 +1083,8 @@ function closeSession(session, code, error) { // Destroy the handle if it exists at this point. if (handle !== undefined) { - handle.ondone = finishSessionClose.bind(null, session, error); + handle.ondone = + FunctionPrototypeBind(finishSessionClose, null, session, error); handle.destroy(code, socket.destroyed); } else { finishSessionClose(session, error); @@ -1168,7 +1174,8 @@ class Http2Session extends EventEmitter { if (typeof socket.disableRenegotiation === 'function') socket.disableRenegotiation(); - const setupFn = setupHandle.bind(this, socket, type, options); + const setupFn = + FunctionPrototypeBind(setupHandle, this, socket, type, options); if (socket.connecting || socket.secureConnecting) { const connectEvent = socket instanceof tls.TLSSocket ? 'secureConnect' : 'connect'; @@ -1373,7 +1380,8 @@ class Http2Session extends EventEmitter { this[kState].pendingAck++; - const settingsFn = submitSettings.bind(this, { ...settings }, callback); + const settingsFn = + FunctionPrototypeBind(submitSettings, this, { ...settings }, callback); if (this.connecting) { this.once('connect', settingsFn); return; @@ -1397,7 +1405,8 @@ class Http2Session extends EventEmitter { validateNumber(code, 'code'); validateNumber(lastStreamID, 'lastStreamID'); - const goawayFn = submitGoaway.bind(this, code, lastStreamID, opaqueData); + const goawayFn = + FunctionPrototypeBind(submitGoaway, this, code, lastStreamID, opaqueData); if (this.connecting) { this.once('connect', goawayFn); return; @@ -1680,7 +1689,8 @@ class ClientHttp2Session extends Http2Session { if (options.waitForTrailers) stream[kState].flags |= STREAM_FLAGS_HAS_TRAILERS; - const onConnect = requestOnConnect.bind(stream, headersList, options); + const onConnect = + FunctionPrototypeBind(requestOnConnect, stream, headersList, options); if (this.connecting) { if (this[kPendingRequestCalls] !== null) { this[kPendingRequestCalls].push(onConnect); @@ -1742,7 +1752,7 @@ function shutdownWritable(callback) { req.handle = handle; const err = handle.shutdown(req); if (err === 1) // synchronous finish - return afterShutdown.call(req, 0); + return FunctionPrototypeCall(afterShutdown, req, 0); } function finishSendTrailers(stream, headersList) { @@ -1791,7 +1801,7 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) { } if (rstStreamStatus !== kNoRstStream) { - const finishFn = finishCloseStream.bind(stream, code); + const finishFn = FunctionPrototypeBind(finishCloseStream, stream, code); if (!ending || stream.writableFinished || code !== NGHTTP2_NO_ERROR || rstStreamStatus === kForceRstStream) finishFn(); @@ -1801,7 +1811,7 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) { } function finishCloseStream(code) { - const rstStreamFn = submitRstStream.bind(this, code); + const rstStreamFn = FunctionPrototypeBind(submitRstStream, this, code); // If the handle has not yet been assigned, queue up the request to // ensure that the RST_STREAM frame is sent after the stream ID has // been determined. @@ -1985,7 +1995,8 @@ class Http2Stream extends Duplex { if (this.pending) { this.once( 'ready', - this[kWriteGeneric].bind(this, writev, data, encoding, cb) + FunctionPrototypeBind(this[kWriteGeneric], this, + writev, data, encoding, cb) ); return; } @@ -2039,7 +2050,7 @@ class Http2Stream extends Duplex { (this[kState].flags & STREAM_FLAGS_HAS_TRAILERS)) return endCheckCallback(); debugStreamObj(this, 'shutting down writable on last write'); - shutdownWritable.call(this, endCheckCallback); + FunctionPrototypeCall(shutdownWritable, this, endCheckCallback); }); if (writev) @@ -2064,7 +2075,7 @@ class Http2Stream extends Duplex { return; } debugStreamObj(this, 'shutting down writable on _final'); - shutdownWritable.call(this, cb); + FunctionPrototypeCall(shutdownWritable, this, cb); } _read(nread) { @@ -2077,7 +2088,7 @@ class Http2Stream extends Duplex { this[kState].didRead = true; } if (!this.pending) { - streamOnResume.call(this); + FunctionPrototypeCall(streamOnResume, this); } else { this.once('ready', streamOnResume); } @@ -2091,7 +2102,7 @@ class Http2Stream extends Duplex { options = { ...options }; setAndValidatePriorityOptions(options); - const priorityFn = submitPriority.bind(this, options); + const priorityFn = FunctionPrototypeBind(submitPriority, this, options); // If the handle has not yet been assigned, queue up the priority // frame to be sent as soon as the ready event is emitted. @@ -2321,7 +2332,7 @@ function processHeaders(oldHeaders, options) { function onFileUnpipe() { const stream = this.sink[kOwner]; if (stream.ownsFd) - this.source.close().catch(stream.destroy.bind(stream)); + this.source.close().catch(FunctionPrototypeBind(stream.destroy, stream)); else this.source.releaseFD(); } @@ -2406,7 +2417,8 @@ function doSendFD(session, options, fd, headers, streamOptions, err, stat) { // response is canceled. The user code may also send a separate type // of response so check again for the HEADERS_SENT flag if ((typeof options.statCheck === 'function' && - options.statCheck.call(this, stat, headers, statOptions) === false) || + FunctionPrototypeCall(options.statCheck, this, stat, headers, + statOptions) === false) || (this[kState].flags & STREAM_FLAGS_HEADERS_SENT)) { return; } @@ -2465,7 +2477,8 @@ function doSendFileFD(session, options, fd, headers, streamOptions, err, stat) { // response is canceled. The user code may also send a separate type // of response so check again for the HEADERS_SENT flag if ((typeof options.statCheck === 'function' && - options.statCheck.call(this, stat, headers) === false) || + FunctionPrototypeCall(options.statCheck, this, stat, headers) === false + ) || (this[kState].flags & STREAM_FLAGS_HEADERS_SENT)) { tryClose(fd); return; @@ -2503,8 +2516,8 @@ function afterOpen(session, options, headers, streamOptions, err, fd) { state.fd = fd; fs.fstat(fd, - doSendFileFD.bind(this, session, options, fd, - headers, streamOptions)); + FunctionPrototypeBind(doSendFileFD, this, session, options, fd, + headers, streamOptions)); } class ServerHttp2Stream extends Http2Stream { @@ -2707,8 +2720,8 @@ class ServerHttp2Stream extends Http2Stream { if (options.statCheck !== undefined) { fs.fstat(fd, - doSendFD.bind(this, session, options, fd, - headers, streamOptions)); + FunctionPrototypeBind(doSendFD, this, session, options, fd, + headers, streamOptions)); return; } @@ -2767,7 +2780,8 @@ class ServerHttp2Stream extends Http2Stream { } fs.open(path, 'r', - afterOpen.bind(this, session, options, headers, streamOptions)); + FunctionPrototypeBind(afterOpen, this, session, options, headers, + streamOptions)); } // Sends a block of informational headers. In theory, the HTTP/2 spec @@ -2889,7 +2903,7 @@ function connectionListener(socket) { if (options.allowHTTP1 === true) { socket.server[kIncomingMessage] = options.Http1IncomingMessage; socket.server[kServerResponse] = options.Http1ServerResponse; - return httpConnectionListener.call(this, socket); + return FunctionPrototypeCall(httpConnectionListener, this, socket); } // Let event handler deal with the socket debug('Unknown protocol from %s:%s', @@ -3065,10 +3079,10 @@ Http2Server.prototype[EventEmitter.captureRejectionSymbol] = function( function setupCompat(ev) { if (ev === 'request') { this.removeListener('newListener', setupCompat); - this.on('stream', onServerStream.bind( - this, - this[kOptions].Http2ServerRequest, - this[kOptions].Http2ServerResponse) + this.on('stream', FunctionPrototypeBind(onServerStream, + this, + this[kOptions].Http2ServerRequest, + this[kOptions].Http2ServerResponse) ); } } diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 051cc23277865f..f8702476242124 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -36,6 +36,7 @@ const { ObjectPrototype, ObjectPrototypeHasOwnProperty, ObjectSetPrototypeOf, + ReflectApply, ReflectSet, RegExpPrototypeTest, SafeMap, @@ -1080,8 +1081,8 @@ Module.prototype._compile = function(content, filename) { result = inspectorWrapper(compiledWrapper, thisValue, exports, require, module, filename, dirname); } else { - result = compiledWrapper.call(thisValue, exports, require, module, - filename, dirname); + result = ReflectApply(compiledWrapper, thisValue, + [exports, require, module, filename, dirname]); } hasLoadedAnyUserCJSModule = true; if (requireDepth === 0) statCache = null; diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 110464cbdb1da3..5098ca325d4f44 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -5,6 +5,7 @@ require('internal/modules/cjs/loader'); const { FunctionPrototypeBind, + FunctionPrototypeCall, ObjectSetPrototypeOf, SafeWeakMap, } = primordials; @@ -217,7 +218,7 @@ class Loader { }); const { NativeModule } = require('internal/bootstrap/loaders'); - preloadInit.call(globalThis, (builtinName) => { + FunctionPrototypeCall(preloadInit, globalThis, (builtinName) => { if (NativeModule.canBeRequiredByUsers(builtinName)) { return require(builtinName); } diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index 7b8f146771c530..b54687fb3f91c2 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -2,6 +2,7 @@ const { ArrayPrototypeJoin, + FunctionPrototypeCall, ObjectSetPrototypeOf, PromiseAll, SafeSet, @@ -35,7 +36,8 @@ class ModuleJob { this.module = undefined; // Expose the promise to the ModuleWrap directly for linking below. // `this.module` is also filled in below. - this.modulePromise = moduleProvider.call(loader, url, isMain); + this.modulePromise = + FunctionPrototypeCall(moduleProvider, loader, url, isMain); // Wait for the ModuleWrap instance being linked with all dependencies. const link = async () => { diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index b061dd340c78cc..f883b004e594c1 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -13,6 +13,7 @@ const { ObjectDefineProperty, ObjectFreeze, ObjectGetOwnPropertyDescriptors, + ReflectApply, RegExpPrototypeTest, Set, SetPrototype, @@ -94,7 +95,7 @@ function wrapProcessMethods(binding) { } = binding; function _rawDebug(...args) { - binding._rawDebug(format.apply(null, args)); + binding._rawDebug(ReflectApply(format, null, args)); } // Create the argument array that will be passed to the native function. diff --git a/lib/internal/process/signal.js b/lib/internal/process/signal.js index abc2b93dbfb7f3..ed63048428dc94 100644 --- a/lib/internal/process/signal.js +++ b/lib/internal/process/signal.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeBind, Map, } = primordials; @@ -26,7 +27,7 @@ function startListeningIfSignal(type) { wrap.unref(); - wrap.onsignal = process.emit.bind(process, type, type); + wrap.onsignal = FunctionPrototypeBind(process.emit, process, type, type); const signum = signals[type]; const err = wrap.start(signum); diff --git a/lib/internal/process/warning.js b/lib/internal/process/warning.js index 3182988fe2ba09..e9d49c3988993e 100644 --- a/lib/internal/process/warning.js +++ b/lib/internal/process/warning.js @@ -4,6 +4,7 @@ const { ArrayIsArray, Error, ErrorCaptureStackTrace, + ReflectApply, String, } = primordials; @@ -84,7 +85,7 @@ function onWarning(warning) { const toString = typeof warning.toString === 'function' ? warning.toString : Error.prototype.toString; - msg += `${toString.apply(warning)}`; + msg += `${ReflectApply(toString, warning, [])}`; } if (typeof warning.detail === 'string') { msg += `\n${warning.detail}`; diff --git a/lib/internal/quic/core.js b/lib/internal/quic/core.js index 2df63c2be67cdf..2e486879b490a3 100644 --- a/lib/internal/quic/core.js +++ b/lib/internal/quic/core.js @@ -14,12 +14,15 @@ const { BigInt64Array, Boolean, Error, + FunctionPrototypeBind, + FunctionPrototypeCall, Map, Number, Promise, PromiseAll, PromiseReject, PromiseResolve, + ReflectApply, Set, Symbol, } = primordials; @@ -369,11 +372,11 @@ function onSessionHandshake( function onSessionTicket(sessionTicket, transportParams) { if (this[owner_symbol]) { process.nextTick( - emit.bind( - this[owner_symbol], - 'sessionTicket', - sessionTicket, - transportParams)); + FunctionPrototypeBind(emit, + this[owner_symbol], + 'sessionTicket', + sessionTicket, + transportParams)); } } @@ -384,7 +387,8 @@ function onSessionPathValidation(res, local, remote) { const session = this[owner_symbol]; if (session) { process.nextTick( - emit.bind( + FunctionPrototypeBind( + emit, session, 'pathValidation', res === NGTCP2_PATH_VALIDATION_RESULT_FAILURE ? 'failure' : 'success', @@ -485,7 +489,7 @@ function onStreamHeaders(id, headers, kind, push_id) { // When a stream is flow control blocked, causes a blocked event // to be emitted. This is a purely informational event. function onStreamBlocked() { - process.nextTick(emit.bind(this[owner_symbol], 'blocked')); + process.nextTick(FunctionPrototypeBind(emit, this[owner_symbol], 'blocked')); } // Register the callbacks with the QUIC internal binding. @@ -612,7 +616,7 @@ class QuicEndpoint { // artificially test the endpoint. This code path should never be // used in user code. if (typeof options[kUDPHandleForTesting] === 'object') { - state.udpSocket.bind(options[kUDPHandleForTesting]); + FunctionPrototypeBind(state.udpSocket, options[kUDPHandleForTesting]); state.state = kSocketBound; state.socket[kEndpointBound](this); } @@ -702,7 +706,7 @@ class QuicEndpoint { (state.reuseAddr ? UV_UDP_REUSEADDR : 0) | (state.ipv6Only ? UV_UDP_IPV6ONLY : 0); - const ret = udpHandle.bind(ip, state.port, flags); + const ret = FunctionPrototypeBind(udpHandle, ip, state.port, flags); if (ret) throw exceptionWithHostPort(ret, 'bind', ip, state.port); @@ -1073,7 +1077,7 @@ class QuicSocket extends EventEmitter { const binds = []; for (const endpoint of state.endpoints) - binds.push(endpoint.bind({ signal })); + binds.push(FunctionPrototypeBind(endpoint, { signal })); await PromiseAll(binds); @@ -1440,11 +1444,11 @@ class QuicSocket extends EventEmitter { if (error) { if (typeof state.closePromiseReject === 'function') state.closePromiseReject(error); - process.nextTick(emit.bind(this, 'error', error)); + process.nextTick(FunctionPrototypeBind(emit, this, 'error', error)); } else if (typeof state.closePromiseResolve === 'function') { state.closePromiseResolve(); } - process.nextTick(emit.bind(this, 'close')); + process.nextTick(FunctionPrototypeBind(emit, this, 'close')); } ref() { @@ -1984,7 +1988,7 @@ class QuicSession extends EventEmitter { if (error) { if (typeof state.closePromiseReject === 'function') state.closePromiseReject(error); - process.nextTick(emit.bind(this, 'error', error)); + process.nextTick(FunctionPrototypeBind(emit, this, 'error', error)); } else if (typeof state.closePromiseResolve === 'function') state.closePromiseResolve(); @@ -1993,7 +1997,7 @@ class QuicSession extends EventEmitter { new ERR_OPERATION_FAILED('Handshake failed')); } - process.nextTick(emit.bind(this, 'close')); + process.nextTick(FunctionPrototypeBind(emit, this, 'close')); } // For server QuicSession instances, true if earlyData is @@ -2697,7 +2701,7 @@ class QuicStream extends Duplex { default: assert.fail('Invalid headers kind'); } - process.nextTick(emit.bind(this, name, headers, push_id)); + process.nextTick(FunctionPrototypeBind(emit, this, name, headers, push_id)); } [kAfterAsyncWrite]({ bytes }) { @@ -2808,7 +2812,7 @@ class QuicStream extends Duplex { if (!this.destroyed) { if (!this.detached) this[kInternalState].sharedState.writeEnded = true; - super.end.apply(this, args); + ReflectApply(super.end, this, args); } return this; } @@ -2824,13 +2828,14 @@ class QuicStream extends Duplex { state.didRead = true; } - streamOnResume.call(this); + FunctionPrototypeCall(streamOnResume, this); } sendFile(path, options = {}) { if (this.detached) throw new ERR_INVALID_STATE('Unable to send file'); - fs.open(path, 'r', QuicStream[kOnFileOpened].bind(this, options)); + fs.open(path, 'r', + FunctionPrototypeBind(QuicStream[kOnFileOpened], this, options)); } static [kOnFileOpened](options, err, fd) { @@ -2894,7 +2899,7 @@ class QuicStream extends Duplex { static [kOnFileUnpipe]() { // Called on the StreamPipe instance. const stream = this.sink[owner_symbol]; if (stream.ownsFd) - this.source.close().catch(stream.destroy.bind(stream)); + this.source.close().catch(FunctionPrototypeBind(stream.destroy, stream)); else this.source.releaseFD(); stream.end(); diff --git a/lib/internal/repl/utils.js b/lib/internal/repl/utils.js index 058f262b5a6b47..e392003ba79a41 100644 --- a/lib/internal/repl/utils.js +++ b/lib/internal/repl/utils.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeBind, MathMin, Set, Symbol, @@ -452,7 +453,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { // Refresh prints the whole screen again and the preview will be removed // during that procedure. Print the preview again. This also makes sure // the preview is always correct after resizing the terminal window. - const originalRefresh = repl._refreshLine.bind(repl); + const originalRefresh = FunctionPrototypeBind(repl._refreshLine, repl); repl._refreshLine = () => { inputPreview = null; originalRefresh(); @@ -462,7 +463,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { let insertCompletionPreview = true; // Insert the longest common suffix of the current input in case the user // moves to the right while already being at the current input end. - const originalMoveCursor = repl._moveCursor.bind(repl); + const originalMoveCursor = FunctionPrototypeBind(repl._moveCursor, repl); repl._moveCursor = (dx) => { const currentCursor = repl.cursor; originalMoveCursor(dx); @@ -476,7 +477,7 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { // This is the only function that interferes with the completion insertion. // Monkey patch it to prevent inserting the completion when it shouldn't be. - const originalClearLine = repl.clearLine.bind(repl); + const originalClearLine = FunctionPrototypeBind(repl.clearLine, repl); repl.clearLine = () => { insertCompletionPreview = false; originalClearLine(); diff --git a/lib/internal/stream_base_commons.js b/lib/internal/stream_base_commons.js index 0dfee0c9c7b619..8cd9b541fdadf6 100644 --- a/lib/internal/stream_base_commons.js +++ b/lib/internal/stream_base_commons.js @@ -2,6 +2,7 @@ const { Array, + FunctionPrototypeBind, Symbol, } = primordials; @@ -264,7 +265,10 @@ function setStreamTimeout(msecs, callback) { this.removeListener('timeout', callback); } } else { - this[kTimeout] = setUnrefTimeout(this._onTimeout.bind(this), msecs); + this[kTimeout] = setUnrefTimeout( + FunctionPrototypeBind(this._onTimeout, this), + msecs + ); if (this[kSession]) this[kSession][kUpdateTimer](); if (callback !== undefined) { diff --git a/lib/internal/streams/destroy.js b/lib/internal/streams/destroy.js index 7477ec97379ff9..89a7c6f2e81b34 100644 --- a/lib/internal/streams/destroy.js +++ b/lib/internal/streams/destroy.js @@ -3,7 +3,10 @@ const { ERR_MULTIPLE_CALLBACK } = require('internal/errors').codes; -const { Symbol } = primordials; +const { + FunctionPrototypeCall, + Symbol, +} = primordials; const kDestroy = Symbol('kDestroy'); const kConstruct = Symbol('kConstruct'); @@ -93,7 +96,8 @@ function _destroy(self, err, cb) { try { const then = result.then; if (typeof then === 'function') { - then.call( + FunctionPrototypeCall( + then, result, function() { if (called) @@ -311,7 +315,8 @@ function constructNT(stream) { try { const then = result.then; if (typeof then === 'function') { - then.call( + FunctionPrototypeCall( + then, result, function() { // If the callback was invoked, do nothing further. @@ -342,7 +347,8 @@ function constructNT(stream) { } else { process.nextTick(errorOrDestroy, stream, err); } - }); + } + ); } } catch (err) { process.nextTick(emitErrorNT, stream, err); diff --git a/lib/internal/streams/duplex.js b/lib/internal/streams/duplex.js index 3bab26d9cef934..35d5efda03fa24 100644 --- a/lib/internal/streams/duplex.js +++ b/lib/internal/streams/duplex.js @@ -27,6 +27,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectDefineProperties, ObjectGetOwnPropertyDescriptor, ObjectKeys, @@ -53,8 +54,8 @@ function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); - Readable.call(this, options); - Writable.call(this, options); + FunctionPrototypeCall(Readable, this, options); + FunctionPrototypeCall(Writable, this, options); this.allowHalfOpen = true; if (options) { diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index 8c5cf937df335e..e7447d2ac25cdd 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -3,6 +3,9 @@ 'use strict'; +const { + FunctionPrototypeCall, +} = primordials; const { ERR_INVALID_ARG_TYPE, ERR_STREAM_PREMATURE_CLOSE @@ -91,7 +94,7 @@ function eos(stream, options, callback) { if (stream.destroyed) willEmitClose = false; if (willEmitClose && (!stream.readable || readable)) return; - if (!readable || readableEnded) callback.call(stream); + if (!readable || readableEnded) FunctionPrototypeCall(callback, stream); }; let readableEnded = stream.readableEnded || @@ -104,23 +107,25 @@ function eos(stream, options, callback) { if (stream.destroyed) willEmitClose = false; if (willEmitClose && (!stream.writable || writable)) return; - if (!writable || writableFinished) callback.call(stream); + if (!writable || writableFinished) FunctionPrototypeCall(callback, stream); }; const onerror = (err) => { - callback.call(stream, err); + FunctionPrototypeCall(callback, stream, err); }; const onclose = () => { if (readable && !readableEnded) { if (!isReadableEnded(stream)) - return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); + return FunctionPrototypeCall( + callback, stream, new ERR_STREAM_PREMATURE_CLOSE()); } if (writable && !writableFinished) { if (!isWritableFinished(stream)) - return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()); + return FunctionPrototypeCall( + callback, stream, new ERR_STREAM_PREMATURE_CLOSE()); } - callback.call(stream); + FunctionPrototypeCall(callback, stream); }; const onrequest = () => { diff --git a/lib/internal/streams/lazy_transform.js b/lib/internal/streams/lazy_transform.js index 555e6430e33588..ad072e3474b3e1 100644 --- a/lib/internal/streams/lazy_transform.js +++ b/lib/internal/streams/lazy_transform.js @@ -4,6 +4,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectDefineProperties, ObjectDefineProperty, ObjectSetPrototypeOf, @@ -25,7 +26,7 @@ ObjectSetPrototypeOf(LazyTransform, stream.Transform); function makeGetter(name) { return function() { - stream.Transform.call(this, this._options); + FunctionPrototypeCall(stream.Transform, 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 0a0d0571c46378..a2f384f0ce9e01 100644 --- a/lib/internal/streams/legacy.js +++ b/lib/internal/streams/legacy.js @@ -2,13 +2,14 @@ const { ArrayIsArray, + FunctionPrototypeCall, ObjectSetPrototypeOf, } = primordials; const EE = require('events'); function Stream(opts) { - EE.call(this, opts); + FunctionPrototypeCall(EE, this, opts); } ObjectSetPrototypeOf(Stream.prototype, EE.prototype); ObjectSetPrototypeOf(Stream, EE); diff --git a/lib/internal/streams/passthrough.js b/lib/internal/streams/passthrough.js index d37f9caf0116b5..acc1a148a7d7c1 100644 --- a/lib/internal/streams/passthrough.js +++ b/lib/internal/streams/passthrough.js @@ -26,6 +26,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectSetPrototypeOf, } = primordials; @@ -39,7 +40,7 @@ function PassThrough(options) { if (!(this instanceof PassThrough)) return new PassThrough(options); - Transform.call(this, options); + FunctionPrototypeCall(Transform, this, options); } PassThrough.prototype._transform = function(chunk, encoding, cb) { diff --git a/lib/internal/streams/pipeline.js b/lib/internal/streams/pipeline.js index c662bce8db1ab3..8c845233cb1f71 100644 --- a/lib/internal/streams/pipeline.js +++ b/lib/internal/streams/pipeline.js @@ -5,6 +5,7 @@ const { ArrayIsArray, + FunctionPrototypeCall, SymbolAsyncIterator, SymbolIterator } = primordials; @@ -117,7 +118,7 @@ async function* fromReadable(val) { Readable = require('internal/streams/readable'); } - yield* Readable.prototype[SymbolAsyncIterator].call(val); + yield* FunctionPrototypeCall(Readable.prototype[SymbolAsyncIterator], val); } async function pump(iterable, writable, finish) { diff --git a/lib/internal/streams/readable.js b/lib/internal/streams/readable.js index 43b53447d8734e..e886853424cb26 100644 --- a/lib/internal/streams/readable.js +++ b/lib/internal/streams/readable.js @@ -22,6 +22,8 @@ 'use strict'; const { + FunctionPrototypeBind, + FunctionPrototypeCall, NumberIsInteger, NumberIsNaN, NumberParseInt, @@ -29,6 +31,7 @@ const { ObjectKeys, ObjectSetPrototypeOf, Promise, + ReflectApply, Set, SymbolAsyncIterator, Symbol @@ -193,7 +196,7 @@ function Readable(options) { this._construct = options.construct; } - Stream.call(this, options); + FunctionPrototypeCall(Stream, this, options); destroyImpl.construct(this, () => { maybeReadMore(this, this._readableState); @@ -851,7 +854,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 = Stream.prototype.on.call(this, ev, fn); + const res = FunctionPrototypeCall(Stream.prototype.on, this, ev, fn); const state = this._readableState; if (ev === 'data') { @@ -881,7 +884,8 @@ Readable.prototype.on = function(ev, fn) { Readable.prototype.addListener = Readable.prototype.on; Readable.prototype.removeListener = function(ev, fn) { - const res = Stream.prototype.removeListener.call(this, ev, fn); + const res = FunctionPrototypeCall( + Stream.prototype.removeListener, this, ev, fn); if (ev === 'readable') { // We need to check if there is someone still listening to @@ -898,7 +902,8 @@ Readable.prototype.removeListener = function(ev, fn) { Readable.prototype.off = Readable.prototype.removeListener; Readable.prototype.removeAllListeners = function(ev) { - const res = Stream.prototype.removeAllListeners.apply(this, arguments); + const res = ReflectApply( + Stream.prototype.removeAllListeners, this, arguments); if (ev === 'readable' || ev === undefined) { // We need to check if there is someone still listening to @@ -1031,7 +1036,7 @@ Readable.prototype.wrap = function(stream) { // Proxy all the other methods. Important when wrapping filters and duplexes. for (const i of ObjectKeys(stream)) { if (this[i] === undefined && typeof stream[i] === 'function') { - this[i] = stream[i].bind(stream); + this[i] = FunctionPrototypeBind(stream[i], stream); } } @@ -1082,15 +1087,15 @@ async function* createAsyncIterator(stream) { .on('error', function(err) { error = err; errorEmitted = true; - next.call(this); + FunctionPrototypeCall(next, this); }) .on('end', function() { endEmitted = true; - next.call(this); + FunctionPrototypeCall(next, this); }) .on('close', function() { closeEmitted = true; - next.call(this); + FunctionPrototypeCall(next, this); }); try { diff --git a/lib/internal/streams/transform.js b/lib/internal/streams/transform.js index 26e0b07c2956c8..a3b9cb54113af4 100644 --- a/lib/internal/streams/transform.js +++ b/lib/internal/streams/transform.js @@ -64,6 +64,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectSetPrototypeOf, Symbol } = primordials; @@ -82,7 +83,7 @@ function Transform(options) { if (!(this instanceof Transform)) return new Transform(options); - Duplex.call(this, options); + FunctionPrototypeCall(Duplex, this, options); // We have implemented the _read method, and done the other things // that Readable wants before the first _read call, so unset the @@ -132,7 +133,8 @@ function final(cb) { try { const then = result.then; if (typeof then === 'function') { - then.call( + FunctionPrototypeCall( + then, result, (data) => { if (called) @@ -165,7 +167,7 @@ function final(cb) { function prefinish() { if (this._final !== final) { - final.call(this); + FunctionPrototypeCall(final, this); } } @@ -207,7 +209,8 @@ Transform.prototype._write = function(chunk, encoding, callback) { try { const then = result.then; if (typeof then === 'function') { - then.call( + FunctionPrototypeCall( + then, result, (val) => { if (called) diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index a3fc3dba50a93f..8670bc0c60e6a9 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -27,6 +27,8 @@ const { FunctionPrototype, + FunctionPrototypeBind, + FunctionPrototypeCall, ObjectDefineProperty, ObjectDefineProperties, ObjectSetPrototypeOf, @@ -140,7 +142,7 @@ function WritableState(options, stream, isDuplex) { this.bufferProcessing = false; // The callback that's passed to _write(chunk, cb). - this.onwrite = onwrite.bind(undefined, stream); + this.onwrite = FunctionPrototypeBind(onwrite, undefined, stream); // The callback that the user supplies to write(chunk, encoding, cb). this.writecb = null; @@ -216,7 +218,7 @@ if (typeof Symbol === 'function' && SymbolHasInstance) { realHasInstance = FunctionPrototype[SymbolHasInstance]; ObjectDefineProperty(Writable, SymbolHasInstance, { value: function(object) { - if (realHasInstance.call(this, object)) + if (FunctionPrototypeCall(realHasInstance, this, object)) return true; if (this !== Writable) return false; @@ -243,7 +245,7 @@ function Writable(options) { // the WritableState constructor, at least with V8 6.5. const isDuplex = (this instanceof Stream.Duplex); - if (!isDuplex && !realHasInstance.call(Writable, this)) + if (!isDuplex && !FunctionPrototypeCall(realHasInstance, Writable, this)) return new Writable(options); this._writableState = new WritableState(options, this, isDuplex); @@ -265,7 +267,7 @@ function Writable(options) { this._construct = options.construct; } - Stream.call(this, options); + FunctionPrototypeCall(Stream, this, options); destroyImpl.construct(this, () => { const state = this._writableState; @@ -669,7 +671,8 @@ function callFinal(stream, state) { try { const then = result.then; if (typeof then === 'function') { - then.call( + FunctionPrototypeCall( + then, result, function() { if (state.prefinished) @@ -684,7 +687,8 @@ function callFinal(stream, state) { process.nextTick(callback, err); } process.nextTick(errorOrDestroy, stream, err, state.sync); - }); + } + ); } } catch (err) { process.nextTick(errorOrDestroy, stream, err, state.sync); @@ -837,7 +841,7 @@ Writable.prototype.destroy = function(err, cb) { process.nextTick(errorBuffer, state); } - destroy.call(this, err, cb); + FunctionPrototypeCall(destroy, this, err, cb); return this; }; diff --git a/lib/internal/url.js b/lib/internal/url.js index b82c36db92e0bb..892633b59c7769 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -2,6 +2,8 @@ const { Array, + FunctionPrototypeBind, + FunctionPrototypeCall, Number, ObjectCreate, ObjectDefineProperties, @@ -9,6 +11,7 @@ const { ObjectGetOwnPropertySymbols, ObjectGetPrototypeOf, ObjectKeys, + ReflectApply, ReflectGetOwnPropertyDescriptor, ReflectOwnKeys, String, @@ -289,9 +292,9 @@ function onParsePortComplete(flags, protocol, username, password, function onParseHostComplete(flags, protocol, username, password, host, port, path, query, fragment) { - onParseHostnameComplete.apply(this, arguments); + ReflectApply(onParseHostnameComplete, this, arguments); if (port !== null || ((flags & URL_FLAGS_IS_DEFAULT_SCHEME_PORT) !== 0)) - onParsePortComplete.apply(this, arguments); + ReflectApply(onParsePortComplete, this, arguments); } function onParsePathComplete(flags, protocol, username, password, @@ -331,7 +334,8 @@ class URL { base_context = new URL(base)[context]; } this[context] = new URLContext(); - parse(input, -1, base_context, undefined, onParseComplete.bind(this), + parse(input, -1, base_context, undefined, + FunctionPrototypeBind(onParseComplete, this), onParseError); } @@ -460,7 +464,8 @@ ObjectDefineProperties(URL.prototype, { set(input) { // toUSVString is not needed. input = `${input}`; - parse(input, -1, undefined, undefined, onParseComplete.bind(this), + parse(input, -1, undefined, undefined, + FunctionPrototypeBind(onParseComplete, this), onParseError); } }, @@ -503,7 +508,7 @@ ObjectDefineProperties(URL.prototype, { return; const ctx = this[context]; parse(scheme, kSchemeStart, null, ctx, - onParseProtocolComplete.bind(this)); + FunctionPrototypeBind(onParseProtocolComplete, this)); } }, username: { @@ -566,7 +571,8 @@ ObjectDefineProperties(URL.prototype, { // Cannot set the host if cannot-be-base is set return; } - parse(host, kHost, null, ctx, onParseHostComplete.bind(this)); + parse(host, kHost, null, ctx, + FunctionPrototypeBind(onParseHostComplete, this)); } }, hostname: { @@ -583,7 +589,8 @@ ObjectDefineProperties(URL.prototype, { // Cannot set the host if cannot-be-base is set return; } - parse(host, kHostname, null, ctx, onParseHostnameComplete.bind(this)); + parse(host, kHostname, null, ctx, + FunctionPrototypeBind(onParseHostnameComplete, this)); } }, port: { @@ -603,7 +610,8 @@ ObjectDefineProperties(URL.prototype, { ctx.port = null; return; } - parse(port, kPort, null, ctx, onParsePortComplete.bind(this)); + parse(port, kPort, null, ctx, + FunctionPrototypeBind(onParsePortComplete, this)); } }, pathname: { @@ -623,7 +631,7 @@ ObjectDefineProperties(URL.prototype, { if (this[cannotBeBase]) return; parse(path, kPathStart, null, this[context], - onParsePathComplete.bind(this)); + FunctionPrototypeBind(onParsePathComplete, this)); } }, search: { @@ -646,7 +654,8 @@ ObjectDefineProperties(URL.prototype, { ctx.query = ''; ctx.flags |= URL_FLAGS_HAS_QUERY; if (search) { - parse(search, kQuery, null, ctx, onParseSearchComplete.bind(this)); + parse(search, kQuery, null, ctx, + FunctionPrototypeBind(onParseSearchComplete, this)); } } initSearchParams(this[searchParams], search); @@ -680,7 +689,8 @@ ObjectDefineProperties(URL.prototype, { if (hash[0] === '#') hash = hash.slice(1); ctx.fragment = ''; ctx.flags |= URL_FLAGS_HAS_FRAGMENT; - parse(hash, kFragment, null, ctx, onParseHashComplete.bind(this)); + parse(hash, kFragment, null, ctx, + FunctionPrototypeBind(onParseHashComplete, this)); } }, toJSON: { @@ -1115,7 +1125,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { while (i < list.length) { const key = list[i]; const value = list[i + 1]; - callback.call(thisArg, value, key, this); + FunctionPrototypeCall(callback, thisArg, value, key, this); // In case the URL object's `search` is updated list = this[searchParams]; i += 2; diff --git a/lib/internal/util.js b/lib/internal/util.js index f26ea970e8dce0..b55436d50471eb 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -4,6 +4,7 @@ const { ArrayFrom, ArrayIsArray, Error, + FunctionPrototypeCall, Map, ObjectCreate, ObjectDefineProperties, @@ -13,6 +14,7 @@ const { ObjectGetPrototypeOf, ObjectSetPrototypeOf, Promise, + ReflectApply, ReflectConstruct, Set, Symbol, @@ -86,7 +88,7 @@ function deprecate(fn, msg, code) { if (new.target) { return ReflectConstruct(fn, args, new.target); } - return fn.apply(this, args); + return ReflectApply(fn, this, args); } // The wrapper will keep the same prototype as fn to maintain prototype chain @@ -294,7 +296,7 @@ function promisify(original) { function fn(...args) { return new Promise((resolve, reject) => { - original.call(this, ...args, (err, ...values) => { + FunctionPrototypeCall(original, this, ...args, (err, ...values) => { if (err) { return reject(err); } @@ -389,7 +391,7 @@ function once(callback) { return function(...args) { if (called) return; called = true; - callback.apply(this, args); + ReflectApply(callback, this, args); }; } diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index e6787760fea392..69532986b2c284 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -13,6 +13,7 @@ const { ErrorPrototypeToString, Float32Array, Float64Array, + FunctionPrototypeBind, FunctionPrototypeCall, FunctionPrototypeToString, Int8Array, @@ -858,8 +859,8 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { const prefix = getPrefix(constructor, tag, 'Set', `(${size})`); keys = getKeys(value, ctx.showHidden); formatter = constructor !== null ? - formatSet.bind(null, value) : - formatSet.bind(null, SetPrototypeValues(value)); + FunctionPrototypeBind(formatSet, null, value) : + FunctionPrototypeBind(formatSet, null, SetPrototypeValues(value)); if (size === 0 && keys.length === 0 && protoProps === undefined) return `${prefix}{}`; braces = [`${prefix}{`, '}']; @@ -868,8 +869,8 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { const prefix = getPrefix(constructor, tag, 'Map', `(${size})`); keys = getKeys(value, ctx.showHidden); formatter = constructor !== null ? - formatMap.bind(null, value) : - formatMap.bind(null, MapPrototypeEntries(value)); + FunctionPrototypeBind(formatMap, null, value) : + FunctionPrototypeBind(formatMap, null, MapPrototypeEntries(value)); if (size === 0 && keys.length === 0 && protoProps === undefined) return `${prefix}{}`; braces = [`${prefix}{`, '}']; @@ -890,18 +891,18 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { return `${braces[0]}]`; // Special handle the value. The original value is required below. The // bound function is required to reconstruct missing information. - formatter = formatTypedArray.bind(null, bound, size); + formatter = FunctionPrototypeBind(formatTypedArray, null, bound, size); extrasType = kArrayExtrasType; } else if (isMapIterator(value)) { keys = getKeys(value, ctx.showHidden); braces = getIteratorBraces('Map', tag); // Add braces to the formatter parameters. - formatter = formatIterator.bind(null, braces); + formatter = FunctionPrototypeBind(formatIterator, null, braces); } else if (isSetIterator(value)) { keys = getKeys(value, ctx.showHidden); braces = getIteratorBraces('Set', tag); // Add braces to the formatter parameters. - formatter = formatIterator.bind(null, braces); + formatter = FunctionPrototypeBind(formatIterator, null, braces); } else { noIterator = true; } @@ -980,7 +981,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { } else if (isModuleNamespaceObject(value)) { braces[0] = `[${tag}] {`; // Special handle keys for namespace objects. - formatter = formatNamespaceObject.bind(null, keys); + formatter = FunctionPrototypeBind(formatNamespaceObject, null, keys); } else if (isBoxedPrimitive(value)) { base = getBoxedBase(value, ctx, keys, constructor, tag); if (keys.length === 0 && protoProps === undefined) { diff --git a/lib/internal/util/inspector.js b/lib/internal/util/inspector.js index 8d413b116fd0f2..b3cfbfe1956811 100644 --- a/lib/internal/util/inspector.js +++ b/lib/internal/util/inspector.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeBind, ObjectDefineProperty, ObjectKeys, } = primordials; @@ -40,9 +41,9 @@ function wrapConsole(consoleFromNode, consoleFromVM) { // then wrap these two methods into one. Native wrapper will preserve // the original stack. if (consoleFromNode.hasOwnProperty(key)) { - consoleFromNode[key] = consoleCall.bind(consoleFromNode, - consoleFromVM[key], - consoleFromNode[key]); + consoleFromNode[key] = FunctionPrototypeBind(consoleCall, consoleFromNode, + consoleFromVM[key], + consoleFromNode[key]); ObjectDefineProperty(consoleFromNode[key], 'name', { value: key }); diff --git a/lib/internal/worker.js b/lib/internal/worker.js index b3c310e93e8ff1..888a24649c2d71 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -5,6 +5,7 @@ const { ArrayIsArray, Float64Array, + FunctionPrototypeBind, JSONStringify, MathMax, ObjectCreate, @@ -230,7 +231,7 @@ class Worker extends EventEmitter { this[kLoopStartTime] = -1; this[kIsOnline] = false; this.performance = { - eventLoopUtilization: eventLoopUtilization.bind(this), + eventLoopUtilization: FunctionPrototypeBind(eventLoopUtilization, this), }; // Actually start the new thread now that everything is in place. this[kHandle].startThread(); diff --git a/lib/internal/worker/io.js b/lib/internal/worker/io.js index e3ca6fe0cc10b5..8c874f4e9e0e4c 100644 --- a/lib/internal/worker/io.js +++ b/lib/internal/worker/io.js @@ -1,6 +1,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectAssign, ObjectCreate, ObjectDefineProperty, @@ -175,7 +176,7 @@ ObjectDefineProperty(MessagePort.prototype, handleOnCloseSymbol, { MessagePort.prototype.close = function(cb) { if (typeof cb === 'function') this.once('close', cb); - MessagePortPrototype.close.call(this); + FunctionPrototypeCall(MessagePortPrototype.close, this); }; ObjectDefineProperty(MessagePort.prototype, inspect.custom, { @@ -186,7 +187,7 @@ ObjectDefineProperty(MessagePort.prototype, inspect.custom, { try { // This may throw when `this` does not refer to a native object, // e.g. when accessing the prototype directly. - ref = MessagePortPrototype.hasRef.call(this); + ref = FunctionPrototypeCall(MessagePortPrototype.hasRef, this); } catch { return this; } return ObjectAssign(ObjectCreate(MessagePort.prototype), ref === undefined ? { @@ -214,18 +215,18 @@ function setupPortReferencing(port, eventEmitter, eventName) { const origNewListener = eventEmitter[kNewListener]; eventEmitter[kNewListener] = function(size, type, ...args) { if (type === eventName) newListener(size - 1); - return origNewListener.call(this, size, type, ...args); + return FunctionPrototypeCall(origNewListener, this, size, type, ...args); }; const origRemoveListener = eventEmitter[kRemoveListener]; eventEmitter[kRemoveListener] = function(size, type, ...args) { if (type === eventName) removeListener(size); - return origRemoveListener.call(this, size, type, ...args); + return FunctionPrototypeCall(origRemoveListener, this, size, type, ...args); }; function newListener(size) { if (size === 0) { port.ref(); - MessagePortPrototype.start.call(port); + FunctionPrototypeCall(MessagePortPrototype.start, port); } } diff --git a/lib/net.js b/lib/net.js index 45598114770646..936ea569307571 100644 --- a/lib/net.js +++ b/lib/net.js @@ -25,6 +25,7 @@ const { ArrayIsArray, Boolean, Error, + FunctionPrototypeCall, Number, NumberIsNaN, NumberParseInt, @@ -299,7 +300,7 @@ function Socket(options) { options.autoDestroy = true; // Handle strings directly. options.decodeStrings = false; - stream.Duplex.call(this, options); + FunctionPrototypeCall(stream.Duplex, this, options); if (options.handle) { this._handle = options.handle; // private @@ -575,7 +576,8 @@ Socket.prototype._read = function(n) { Socket.prototype.end = function(data, encoding, callback) { - stream.Duplex.prototype.end.call(this, data, encoding, callback); + FunctionPrototypeCall( + stream.Duplex.prototype.end, this, data, encoding, callback); DTRACE_NET_STREAM_END(this); return this; }; @@ -591,7 +593,7 @@ Socket.prototype.pause = function() { this.destroy(errnoException(err, 'read')); } } - return stream.Duplex.prototype.pause.call(this); + return FunctionPrototypeCall(stream.Duplex.prototype.pause, this); }; @@ -600,7 +602,7 @@ Socket.prototype.resume = function() { !this._handle.reading) { tryReadStart(this); } - return stream.Duplex.prototype.resume.call(this); + return FunctionPrototypeCall(stream.Duplex.prototype.resume, this); }; @@ -609,7 +611,7 @@ Socket.prototype.read = function(n) { !this._handle.reading) { tryReadStart(this); } - return stream.Duplex.prototype.read.call(this, n); + return FunctionPrototypeCall(stream.Duplex.prototype.read, this, n); }; @@ -1143,7 +1145,7 @@ function Server(options, connectionListener) { if (!(this instanceof Server)) return new Server(options, connectionListener); - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); if (typeof options === 'function') { connectionListener = options; diff --git a/lib/path.js b/lib/path.js index 7532b795bf63f7..ad466263cd65e1 100644 --- a/lib/path.js +++ b/lib/path.js @@ -21,6 +21,10 @@ 'use strict'; +const { + FunctionPrototypeBind, +} = primordials; + const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes; const { CHAR_UPPERCASE_A, @@ -812,7 +816,7 @@ const win32 = { return path.slice(startDot, end); }, - format: _format.bind(null, '\\'), + format: FunctionPrototypeBind(_format, null, '\\'), parse(path) { validateString(path, 'path'); @@ -1277,7 +1281,7 @@ const posix = { return path.slice(startDot, end); }, - format: _format.bind(null, '/'), + format: FunctionPrototypeBind(_format, null, '/'), parse(path) { validateString(path, 'path'); diff --git a/lib/readline.js b/lib/readline.js index 109acc30819167..4d495ef5575093 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -29,6 +29,8 @@ const { DateNow, + FunctionPrototypeBind, + FunctionPrototypeCall, MathCeil, MathFloor, MathMax, @@ -110,7 +112,7 @@ function Interface(input, output, completer, terminal) { this.escapeCodeTimeout = ESCAPE_CODE_TIMEOUT; this.tabSize = 8; - EventEmitter.call(this); + FunctionPrototypeCall(EventEmitter, this); let historySize; let removeHistoryDuplicates = false; let crlfDelay; @@ -187,7 +189,7 @@ function Interface(input, output, completer, terminal) { this.terminal = !!terminal; if (process.env.TERM === 'dumb') { - this._ttyWrite = _ttyWriteDumb.bind(this); + this._ttyWrite = FunctionPrototypeBind(_ttyWriteDumb, this); } function ondata(data) { diff --git a/lib/repl.js b/lib/repl.js index 78c256d60b5559..a279cbe2386d23 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -44,6 +44,7 @@ const { Error, + FunctionPrototypeCall, MathMax, NumberIsNaN, NumberParseFloat, @@ -57,6 +58,7 @@ const { ObjectSetPrototypeOf, Promise, PromiseRace, + ReflectApply, RegExp, Set, StringPrototypeCharAt, @@ -650,11 +652,11 @@ function REPLServer(prompt, self.clearBufferedCommand(); function completer(text, cb) { - complete.call(self, text, self.editorMode ? + FunctionPrototypeCall(complete, self, text, self.editorMode ? self.completeOnEditorMode(cb) : cb); } - Interface.call(this, { + FunctionPrototypeCall(Interface, this, { input: options.input, output: options.output, completer: options.completer || completer, @@ -695,7 +697,7 @@ function REPLServer(prompt, function _parseREPLKeyword(keyword, rest) { const cmd = this.commands[keyword]; if (cmd) { - cmd.action.call(this, rest); + FunctionPrototypeCall(cmd.action, this, rest); return true; } return false; @@ -760,7 +762,7 @@ function REPLServer(prompt, self.line = prefix; self.cursor = prefix.length; } - _memory.call(self, cmd); + FunctionPrototypeCall(_memory, self, cmd); return; } @@ -776,7 +778,8 @@ function REPLServer(prompt, const matches = StringPrototypeMatch(trimmedCmd, /^\.([^\s]+)\s*(.*)$/); const keyword = matches && matches[1]; const rest = matches && matches[2]; - if (_parseREPLKeyword.call(self, keyword, rest) === true) { + if (FunctionPrototypeCall(_parseREPLKeyword, self, keyword, rest) === + true) { return; } if (!self[kBufferedCommandSymbol]) { @@ -794,7 +797,7 @@ function REPLServer(prompt, function finish(e, ret) { debug('finish', e, ret); - _memory.call(self, cmd); + FunctionPrototypeCall(_memory, self, cmd); if (e && !self[kBufferedCommandSymbol] && cmd.trim().startsWith('npm ')) { self.output.write('npm should be run outside of the ' + @@ -942,13 +945,13 @@ REPLServer.prototype.close = function close() { if (this.terminal && this._flushing && !this._closingOnFlush) { this._closingOnFlush = true; this.once('flushHistory', () => - Interface.prototype.close.call(this) + FunctionPrototypeCall(Interface.prototype.close, this) ); return; } process.nextTick(() => - Interface.prototype.close.call(this) + FunctionPrototypeCall(Interface.prototype.close, this) ); }; @@ -1049,14 +1052,14 @@ REPLServer.prototype.displayPrompt = function(preserveCursor) { } // Do not overwrite `_initialPrompt` here - Interface.prototype.setPrompt.call(this, prompt); + FunctionPrototypeCall(Interface.prototype.setPrompt, this, prompt); this.prompt(preserveCursor); }; // When invoked as an API method, overwrite _initialPrompt REPLServer.prototype.setPrompt = function setPrompt(prompt) { this._initialPrompt = prompt; - Interface.prototype.setPrompt.call(this, prompt); + FunctionPrototypeCall(Interface.prototype.setPrompt, this, prompt); }; const requireRE = /\brequire\s*\(\s*['"`](([\w@./-]+\/)?(?:[\w@./-]*))(?![^'"`])$/; @@ -1104,7 +1107,7 @@ function getGlobalLexicalScopeNames(contextId) { } REPLServer.prototype.complete = function() { - this.completer.apply(this, arguments); + ReflectApply(this.completer, this, arguments); }; function gracefulReaddir(...args) { @@ -1459,7 +1462,7 @@ function addCommonWords(completionGroups) { function _turnOnEditorMode(repl) { repl.editorMode = true; - Interface.prototype.setPrompt.call(repl, ''); + FunctionPrototypeCall(Interface.prototype.setPrompt, repl, ''); } function _turnOffEditorMode(repl) { diff --git a/lib/tty.js b/lib/tty.js index 583cc1329830c9..a7cfbbb2341ab8 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -23,6 +23,7 @@ const { Array, + FunctionPrototypeCall, NumberIsInteger, ObjectSetPrototypeOf, } = primordials; @@ -55,7 +56,7 @@ function ReadStream(fd, options) { throw new ERR_TTY_INIT_FAILED(ctx); } - net.Socket.call(this, { + FunctionPrototypeCall(net.Socket, this, { highWaterMark: 0, readable: true, writable: false, @@ -93,7 +94,7 @@ function WriteStream(fd) { throw new ERR_TTY_INIT_FAILED(ctx); } - net.Socket.call(this, { + FunctionPrototypeCall(net.Socket, this, { handle: tty, readable: false, writable: true diff --git a/lib/url.js b/lib/url.js index 735390dfd2e59b..a7292a6f4b7255 100644 --- a/lib/url.js +++ b/lib/url.js @@ -22,6 +22,7 @@ 'use strict'; const { + FunctionPrototypeCall, ObjectCreate, ObjectKeys, SafeSet, @@ -549,8 +550,8 @@ function urlFormat(urlObject, options) { } else if (!(urlObject instanceof Url)) { const format = urlObject[formatSymbol]; return format ? - format.call(urlObject, options) : - Url.prototype.format.call(urlObject); + FunctionPrototypeCall(format, urlObject, options) : + FunctionPrototypeCall(Url.prototype.format, urlObject); } return urlObject.format(); } diff --git a/lib/vm.js b/lib/vm.js index 45a2edf0bb20b3..a37898eeb06a14 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -23,8 +23,9 @@ const { ArrayPrototypeForEach, + PromiseReject, + ReflectApply, Symbol, - PromiseReject } = primordials; const { @@ -269,7 +270,7 @@ function sigintHandlersWrap(fn, thisArg, argsArray) { process.removeAllListeners('SIGINT'); try { - return fn.apply(thisArg, argsArray); + return ReflectApply(fn, thisArg, argsArray); } finally { // Add using the public methods so that the `newListener` handler of // process can re-attach the listeners. diff --git a/lib/zlib.js b/lib/zlib.js index faa84401e9a04b..15983ae6b5108b 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -24,6 +24,8 @@ const { ArrayBuffer, Error, + FunctionPrototypeBind, + FunctionPrototypeCall, MathMax, NumberIsFinite, NumberIsNaN, @@ -268,7 +270,7 @@ function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) { } } - Transform.call(this, { autoDestroy: true, ...opts }); + FunctionPrototypeCall(Transform, this, { autoDestroy: true, ...opts }); this[kError] = null; this.bytesWritten = 0; this._handle = handle; @@ -671,7 +673,7 @@ function Zlib(opts, mode) { processCallback, dictionary); - ZlibBase.call(this, opts, mode, handle, zlibDefaultOpts); + FunctionPrototypeCall(ZlibBase, this, opts, mode, handle, zlibDefaultOpts); this._level = level; this._strategy = strategy; @@ -698,8 +700,11 @@ Zlib.prototype.params = function params(level, strategy, callback) { checkRangesOrGetDefault(strategy, 'strategy', Z_DEFAULT_STRATEGY, Z_FIXED); if (this._level !== level || this._strategy !== strategy) { - this.flush(Z_SYNC_FLUSH, - paramsAfterFlushCallback.bind(this, level, strategy, callback)); + this.flush( + Z_SYNC_FLUSH, + FunctionPrototypeBind(paramsAfterFlushCallback, this, + level, strategy, callback) + ); } else { process.nextTick(callback); } @@ -710,7 +715,7 @@ Zlib.prototype.params = function params(level, strategy, callback) { function Deflate(opts) { if (!(this instanceof Deflate)) return new Deflate(opts); - Zlib.call(this, opts, DEFLATE); + FunctionPrototypeCall(Zlib, this, opts, DEFLATE); } ObjectSetPrototypeOf(Deflate.prototype, Zlib.prototype); ObjectSetPrototypeOf(Deflate, Zlib); @@ -718,7 +723,7 @@ ObjectSetPrototypeOf(Deflate, Zlib); function Inflate(opts) { if (!(this instanceof Inflate)) return new Inflate(opts); - Zlib.call(this, opts, INFLATE); + FunctionPrototypeCall(Zlib, this, opts, INFLATE); } ObjectSetPrototypeOf(Inflate.prototype, Zlib.prototype); ObjectSetPrototypeOf(Inflate, Zlib); @@ -726,7 +731,7 @@ ObjectSetPrototypeOf(Inflate, Zlib); function Gzip(opts) { if (!(this instanceof Gzip)) return new Gzip(opts); - Zlib.call(this, opts, GZIP); + FunctionPrototypeCall(Zlib, this, opts, GZIP); } ObjectSetPrototypeOf(Gzip.prototype, Zlib.prototype); ObjectSetPrototypeOf(Gzip, Zlib); @@ -734,7 +739,7 @@ ObjectSetPrototypeOf(Gzip, Zlib); function Gunzip(opts) { if (!(this instanceof Gunzip)) return new Gunzip(opts); - Zlib.call(this, opts, GUNZIP); + FunctionPrototypeCall(Zlib, this, opts, GUNZIP); } ObjectSetPrototypeOf(Gunzip.prototype, Zlib.prototype); ObjectSetPrototypeOf(Gunzip, Zlib); @@ -743,7 +748,7 @@ function DeflateRaw(opts) { if (opts && opts.windowBits === 8) opts.windowBits = 9; if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts); - Zlib.call(this, opts, DEFLATERAW); + FunctionPrototypeCall(Zlib, this, opts, DEFLATERAW); } ObjectSetPrototypeOf(DeflateRaw.prototype, Zlib.prototype); ObjectSetPrototypeOf(DeflateRaw, Zlib); @@ -751,7 +756,7 @@ ObjectSetPrototypeOf(DeflateRaw, Zlib); function InflateRaw(opts) { if (!(this instanceof InflateRaw)) return new InflateRaw(opts); - Zlib.call(this, opts, INFLATERAW); + FunctionPrototypeCall(Zlib, this, opts, INFLATERAW); } ObjectSetPrototypeOf(InflateRaw.prototype, Zlib.prototype); ObjectSetPrototypeOf(InflateRaw, Zlib); @@ -759,7 +764,7 @@ ObjectSetPrototypeOf(InflateRaw, Zlib); function Unzip(opts) { if (!(this instanceof Unzip)) return new Unzip(opts); - Zlib.call(this, opts, UNZIP); + FunctionPrototypeCall(Zlib, this, opts, UNZIP); } ObjectSetPrototypeOf(Unzip.prototype, Zlib.prototype); ObjectSetPrototypeOf(Unzip, Zlib); @@ -824,7 +829,7 @@ function Brotli(opts, mode) { throw new ERR_ZLIB_INITIALIZATION_FAILED(); } - ZlibBase.call(this, opts, mode, handle, brotliDefaultOpts); + FunctionPrototypeCall(ZlibBase, this, opts, mode, handle, brotliDefaultOpts); } ObjectSetPrototypeOf(Brotli.prototype, Zlib.prototype); ObjectSetPrototypeOf(Brotli, Zlib); @@ -832,7 +837,7 @@ ObjectSetPrototypeOf(Brotli, Zlib); function BrotliCompress(opts) { if (!(this instanceof BrotliCompress)) return new BrotliCompress(opts); - Brotli.call(this, opts, BROTLI_ENCODE); + FunctionPrototypeCall(Brotli, this, opts, BROTLI_ENCODE); } ObjectSetPrototypeOf(BrotliCompress.prototype, Brotli.prototype); ObjectSetPrototypeOf(BrotliCompress, Brotli); @@ -840,7 +845,7 @@ ObjectSetPrototypeOf(BrotliCompress, Brotli); function BrotliDecompress(opts) { if (!(this instanceof BrotliDecompress)) return new BrotliDecompress(opts); - Brotli.call(this, opts, BROTLI_DECODE); + FunctionPrototypeCall(Brotli, this, opts, BROTLI_DECODE); } ObjectSetPrototypeOf(BrotliDecompress.prototype, Brotli.prototype); ObjectSetPrototypeOf(BrotliDecompress, Brotli);