Skip to content

Commit

Permalink
lib: use more primordials
Browse files Browse the repository at this point in the history
This replaces all Function.prototype.apply, Function.prototype.bind,
Function.prototype.call to their primordials alter ego.
  • Loading branch information
aduh95 committed Nov 6, 2020
1 parent 2a1273c commit 882e66e
Show file tree
Hide file tree
Showing 69 changed files with 437 additions and 276 deletions.
3 changes: 2 additions & 1 deletion lib/_http_agent.js
Expand Up @@ -22,6 +22,7 @@
'use strict';

const {
FunctionPrototypeCall,
NumberIsNaN,
ObjectKeys,
ObjectSetPrototypeOf,
Expand Down Expand Up @@ -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:';
Expand Down
8 changes: 5 additions & 3 deletions lib/_http_client.js
Expand Up @@ -25,10 +25,12 @@ const {
ArrayIsArray,
Boolean,
Error,
FunctionPrototypeCall,
NumberIsFinite,
ObjectAssign,
ObjectKeys,
ObjectSetPrototypeOf,
ReflectApply,
String,
Symbol
} = primordials;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
Expand Down
4 changes: 3 additions & 1 deletion lib/_http_incoming.js
Expand Up @@ -22,6 +22,7 @@
'use strict';

const {
FunctionPrototypeCall,
ObjectDefineProperty,
ObjectSetPrototypeOf,
Symbol
Expand Down Expand Up @@ -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;

Expand Down
6 changes: 4 additions & 2 deletions lib/_http_outgoing.js
Expand Up @@ -23,6 +23,8 @@

const {
ArrayIsArray,
FunctionPrototypeBind,
FunctionPrototypeCall,
ObjectCreate,
ObjectDefineProperty,
ObjectKeys,
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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);
Expand Down
56 changes: 37 additions & 19 deletions lib/_http_server.js
Expand Up @@ -24,6 +24,8 @@
const {
ArrayIsArray,
Error,
FunctionPrototypeBind,
FunctionPrototypeCall,
ObjectKeys,
ObjectSetPrototypeOf,
Symbol,
Expand Down Expand Up @@ -169,7 +171,7 @@ class HTTPServerAsyncResource {
}

function ServerResponse(req) {
OutgoingMessage.call(this);
FunctionPrototypeCall(OutgoingMessage, this);

if (req.method === 'HEAD') this._hasBody = false;

Expand Down Expand Up @@ -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);
};


Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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)) {
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 6 additions & 4 deletions lib/_tls_wrap.js
Expand Up @@ -22,9 +22,11 @@
'use strict';

const {
FunctionPrototypeCall,
ObjectAssign,
ObjectDefineProperty,
ObjectSetPrototypeOf,
ReflectApply,
RegExp,
Symbol,
SymbolFor,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
};
}
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 5 additions & 3 deletions lib/assert.js
Expand Up @@ -23,6 +23,8 @@
const {
Error,
ErrorCaptureStackTrace,
FunctionPrototypeBind,
FunctionPrototypeCall,
ObjectAssign,
ObjectIs,
ObjectKeys,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion lib/async_hooks.js
@@ -1,6 +1,7 @@
'use strict';

const {
FunctionPrototypeBind,
NumberIsSafeInteger,
ObjectDefineProperties,
ObjectIs,
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 4 additions & 3 deletions lib/buffer.js
Expand Up @@ -25,6 +25,7 @@ const {
Array,
ArrayIsArray,
Error,
FunctionPrototypeCall,
MathFloor,
MathMin,
MathTrunc,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 882e66e

Please sign in to comment.