Skip to content

Commit 8cf5ae0

Browse files
committedDec 29, 2020
http: refactor to use more primordials
PR-URL: nodejs#36194 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent e57d8af commit 8cf5ae0

8 files changed

+147
-88
lines changed
 

‎lib/_http_agent.js

+28-17
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,22 @@
2222
'use strict';
2323

2424
const {
25+
ArrayPrototypeIncludes,
26+
ArrayPrototypeIndexOf,
27+
ArrayPrototypePop,
28+
ArrayPrototypePush,
29+
ArrayPrototypeShift,
30+
ArrayPrototypeSplice,
31+
FunctionPrototypeCall,
2532
NumberIsNaN,
2633
ObjectCreate,
2734
ObjectKeys,
2835
ObjectSetPrototypeOf,
2936
ObjectValues,
37+
StringPrototypeIndexOf,
38+
StringPrototypeSplit,
39+
StringPrototypeStartsWith,
40+
StringPrototypeSubstr,
3041
Symbol,
3142
} = primordials;
3243

@@ -79,7 +90,7 @@ function Agent(options) {
7990
if (!(this instanceof Agent))
8091
return new Agent(options);
8192

82-
EventEmitter.call(this);
93+
FunctionPrototypeCall(EventEmitter, this);
8394

8495
this.defaultPort = 80;
8596
this.protocol = 'http:';
@@ -126,7 +137,7 @@ function Agent(options) {
126137

127138
const requests = this.requests[name];
128139
if (requests && requests.length) {
129-
const req = requests.shift();
140+
const req = ArrayPrototypeShift(requests);
130141
const reqAsyncRes = req[kRequestAsyncResource];
131142
if (reqAsyncRes) {
132143
// Run request within the original async context.
@@ -172,7 +183,7 @@ function Agent(options) {
172183
this.removeSocket(socket, options);
173184

174185
socket.once('error', freeSocketErrorListener);
175-
freeSockets.push(socket);
186+
ArrayPrototypePush(freeSockets, socket);
176187
});
177188

178189
// Don't emit keylog events unless there is a listener for them.
@@ -251,11 +262,11 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */,
251262
let socket;
252263
if (freeSockets) {
253264
while (freeSockets.length && freeSockets[0].destroyed) {
254-
freeSockets.shift();
265+
ArrayPrototypeShift(freeSockets);
255266
}
256267
socket = this.scheduling === 'fifo' ?
257-
freeSockets.shift() :
258-
freeSockets.pop();
268+
ArrayPrototypeShift(freeSockets) :
269+
ArrayPrototypePop(freeSockets);
259270
if (!freeSockets.length)
260271
delete this.freeSockets[name];
261272
}
@@ -267,7 +278,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */,
267278
asyncResetHandle(socket);
268279
this.reuseSocket(socket, req);
269280
setRequestSocket(this, req, socket);
270-
this.sockets[name].push(socket);
281+
ArrayPrototypePush(this.sockets[name], socket);
271282
this.totalSocketCount++;
272283
} else if (sockLen < this.maxSockets &&
273284
this.totalSocketCount < this.maxTotalSockets) {
@@ -291,7 +302,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */,
291302
// Used to capture the original async context.
292303
req[kRequestAsyncResource] = new AsyncResource('QueuedRequest');
293304

294-
this.requests[name].push(req);
305+
ArrayPrototypePush(this.requests[name], req);
295306
}
296307
};
297308

@@ -315,7 +326,7 @@ Agent.prototype.createSocket = function createSocket(req, options, cb) {
315326
if (!this.sockets[name]) {
316327
this.sockets[name] = [];
317328
}
318-
this.sockets[name].push(s);
329+
ArrayPrototypePush(this.sockets[name], s);
319330
this.totalSocketCount++;
320331
debug('sockets', name, this.sockets[name].length, this.totalSocketCount);
321332
installListeners(this, s, options);
@@ -340,16 +351,16 @@ function calculateServerName(options, req) {
340351
// abc:123 => abc
341352
// [::1] => ::1
342353
// [::1]:123 => ::1
343-
if (hostHeader.startsWith('[')) {
344-
const index = hostHeader.indexOf(']');
354+
if (StringPrototypeStartsWith(hostHeader, '[')) {
355+
const index = StringPrototypeIndexOf(hostHeader, ']');
345356
if (index === -1) {
346357
// Leading '[', but no ']'. Need to do something...
347358
servername = hostHeader;
348359
} else {
349-
servername = hostHeader.substr(1, index - 1);
360+
servername = StringPrototypeSubstr(hostHeader, 1, index - 1);
350361
}
351362
} else {
352-
servername = hostHeader.split(':', 1)[0];
363+
servername = StringPrototypeSplit(hostHeader, ':', 1)[0];
353364
}
354365
}
355366
// Don't implicitly set invalid (IP) servernames.
@@ -381,7 +392,7 @@ function installListeners(agent, s, options) {
381392
// TODO(ronag): Always destroy, even if not in free list.
382393
const sockets = agent.freeSockets;
383394
for (const name of ObjectKeys(sockets)) {
384-
if (sockets[name].includes(s)) {
395+
if (ArrayPrototypeIncludes(sockets[name], s)) {
385396
return s.destroy();
386397
}
387398
}
@@ -413,13 +424,13 @@ Agent.prototype.removeSocket = function removeSocket(s, options) {
413424

414425
// If the socket was destroyed, remove it from the free buffers too.
415426
if (!s.writable)
416-
sets.push(this.freeSockets);
427+
ArrayPrototypePush(sets, this.freeSockets);
417428

418429
for (const sockets of sets) {
419430
if (sockets[name]) {
420-
const index = sockets[name].indexOf(s);
431+
const index = ArrayPrototypeIndexOf(sockets[name], s);
421432
if (index !== -1) {
422-
sockets[name].splice(index, 1);
433+
ArrayPrototypeSplice(sockets[name], index, 1);
423434
// Don't leak
424435
if (sockets[name].length === 0)
425436
delete sockets[name];

‎lib/_http_client.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,20 @@ const {
2525
ArrayIsArray,
2626
Boolean,
2727
Error,
28+
FunctionPrototypeCall,
2829
NumberIsFinite,
2930
ObjectAssign,
3031
ObjectKeys,
3132
ObjectSetPrototypeOf,
33+
ReflectApply,
34+
RegExpPrototypeTest,
3235
String,
33-
Symbol
36+
StringPrototypeCharCodeAt,
37+
StringPrototypeIncludes,
38+
StringPrototypeIndexOf,
39+
StringPrototypeToUpperCase,
40+
Symbol,
41+
TypedArrayPrototypeSlice,
3442
} = primordials;
3543

3644
const net = require('net');
@@ -91,7 +99,7 @@ class HTTPClientAsyncResource {
9199

92100
let urlWarningEmitted = false;
93101
function ClientRequest(input, options, cb) {
94-
OutgoingMessage.call(this);
102+
FunctionPrototypeCall(OutgoingMessage, this);
95103

96104
if (typeof input === 'string') {
97105
const urlStr = input;
@@ -151,7 +159,7 @@ function ClientRequest(input, options, cb) {
151159

152160
if (options.path) {
153161
const path = String(options.path);
154-
if (INVALID_PATH_REGEX.test(path))
162+
if (RegExpPrototypeTest(INVALID_PATH_REGEX, path))
155163
throw new ERR_UNESCAPED_CHARACTERS('Request path');
156164
}
157165

@@ -187,7 +195,7 @@ function ClientRequest(input, options, cb) {
187195
if (!checkIsHttpToken(method)) {
188196
throw new ERR_INVALID_HTTP_TOKEN('Method', method);
189197
}
190-
method = this.method = method.toUpperCase();
198+
method = this.method = StringPrototypeToUpperCase(method);
191199
} else {
192200
method = this.method = 'GET';
193201
}
@@ -266,10 +274,10 @@ function ClientRequest(input, options, cb) {
266274
// For the Host header, ensure that IPv6 addresses are enclosed
267275
// in square brackets, as defined by URI formatting
268276
// https://tools.ietf.org/html/rfc3986#section-3.2.2
269-
const posColon = hostHeader.indexOf(':');
277+
const posColon = StringPrototypeIndexOf(hostHeader, ':');
270278
if (posColon !== -1 &&
271-
hostHeader.includes(':', posColon + 1) &&
272-
hostHeader.charCodeAt(0) !== 91/* '[' */) {
279+
StringPrototypeIncludes(hostHeader, ':', posColon + 1) &&
280+
StringPrototypeCharCodeAt(hostHeader, 0) !== 91/* '[' */) {
273281
hostHeader = `[${hostHeader}]`;
274282
}
275283

@@ -337,7 +345,7 @@ ObjectSetPrototypeOf(ClientRequest, OutgoingMessage);
337345

338346
ClientRequest.prototype._finish = function _finish() {
339347
DTRACE_HTTP_CLIENT_REQUEST(this, this.socket);
340-
OutgoingMessage.prototype._finish.call(this);
348+
FunctionPrototypeCall(OutgoingMessage.prototype._finish, this);
341349
};
342350

343351
ClientRequest.prototype._implicitHeader = function _implicitHeader() {
@@ -535,7 +543,7 @@ function socketOnData(d) {
535543
parser.finish();
536544
freeParser(parser, req, socket);
537545

538-
const bodyHead = d.slice(bytesParsed, d.length);
546+
const bodyHead = TypedArrayPrototypeSlice(d, bytesParsed, d.length);
539547

540548
const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
541549
if (req.listenerCount(eventName) > 0) {
@@ -831,7 +839,7 @@ function _deferToConnect(method, arguments_, cb) {
831839

832840
const callSocketMethod = () => {
833841
if (method)
834-
this.socket[method].apply(this.socket, arguments_);
842+
ReflectApply(this.socket[method], this.socket, arguments_);
835843

836844
if (typeof cb === 'function')
837845
cb();

‎lib/_http_common.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@
2222
'use strict';
2323

2424
const {
25+
ArrayPrototypeConcat,
2526
MathMin,
2627
Symbol,
28+
RegExpPrototypeTest,
29+
TypedArrayPrototypeSlice,
2730
} = primordials;
2831
const { setImmediate } = require('timers');
2932

@@ -63,7 +66,7 @@ function parserOnHeaders(headers, url) {
6366
// Once we exceeded headers limit - stop collecting them
6467
if (this.maxHeaderPairs <= 0 ||
6568
this._headers.length < this.maxHeaderPairs) {
66-
this._headers = this._headers.concat(headers);
69+
this._headers = ArrayPrototypeConcat(this._headers, headers);
6770
}
6871
this._url += url;
6972
}
@@ -135,7 +138,7 @@ function parserOnBody(b, start, len) {
135138

136139
// Pretend this was the result of a stream._read call.
137140
if (len > 0 && !stream._dumped) {
138-
const slice = b.slice(start, start + len);
141+
const slice = TypedArrayPrototypeSlice(b, start, start + len);
139142
const ret = stream.push(slice);
140143
if (!ret)
141144
readStop(this.socket);
@@ -217,7 +220,7 @@ const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
217220
* See https://tools.ietf.org/html/rfc7230#section-3.2.6
218221
*/
219222
function checkIsHttpToken(val) {
220-
return tokenRegExp.test(val);
223+
return RegExpPrototypeTest(tokenRegExp, val);
221224
}
222225

223226
const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
@@ -228,7 +231,7 @@ const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
228231
* field-vchar = VCHAR / obs-text
229232
*/
230233
function checkInvalidHeaderChar(val) {
231-
return headerCharRegex.test(val);
234+
return RegExpPrototypeTest(headerCharRegex, val);
232235
}
233236

234237
function cleanParser(parser) {

‎lib/_http_incoming.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@
2222
'use strict';
2323

2424
const {
25+
ArrayPrototypePush,
26+
FunctionPrototypeCall,
2527
ObjectDefineProperty,
2628
ObjectSetPrototypeOf,
29+
StringPrototypeCharCodeAt,
30+
StringPrototypeSlice,
31+
StringPrototypeToLowerCase,
2732
Symbol
2833
} = primordials;
2934

@@ -54,7 +59,7 @@ function IncomingMessage(socket) {
5459
};
5560
}
5661

57-
Readable.call(this, streamOptions);
62+
FunctionPrototypeCall(Readable, this, streamOptions);
5863

5964
this._readableState.readingMore = true;
6065

@@ -312,7 +317,7 @@ function matchKnownFields(field, lowercased) {
312317
if (lowercased) {
313318
return '\u0000' + field;
314319
}
315-
return matchKnownFields(field.toLowerCase(), true);
320+
return matchKnownFields(StringPrototypeToLowerCase(field), true);
316321
}
317322
// Add the given (field, value) pair to the message
318323
//
@@ -326,9 +331,9 @@ function matchKnownFields(field, lowercased) {
326331
IncomingMessage.prototype._addHeaderLine = _addHeaderLine;
327332
function _addHeaderLine(field, value, dest) {
328333
field = matchKnownFields(field);
329-
const flag = field.charCodeAt(0);
334+
const flag = StringPrototypeCharCodeAt(field, 0);
330335
if (flag === 0 || flag === 2) {
331-
field = field.slice(1);
336+
field = StringPrototypeSlice(field, 1);
332337
// Make a delimited list
333338
if (typeof dest[field] === 'string') {
334339
dest[field] += (flag === 0 ? ', ' : '; ') + value;
@@ -338,7 +343,7 @@ function _addHeaderLine(field, value, dest) {
338343
} else if (flag === 1) {
339344
// Array header -- only Set-Cookie at the moment
340345
if (dest['set-cookie'] !== undefined) {
341-
dest['set-cookie'].push(value);
346+
ArrayPrototypePush(dest['set-cookie'], value);
342347
} else {
343348
dest['set-cookie'] = [value];
344349
}

‎lib/_http_outgoing.js

+28-20
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,21 @@
2323

2424
const {
2525
ArrayIsArray,
26+
ArrayPrototypeJoin,
27+
ArrayPrototypePush,
28+
ArrayPrototypeUnshift,
29+
FunctionPrototype,
30+
FunctionPrototypeBind,
31+
FunctionPrototypeCall,
32+
MathFloor,
33+
NumberPrototypeToString,
2634
ObjectCreate,
2735
ObjectDefineProperty,
2836
ObjectKeys,
2937
ObjectPrototypeHasOwnProperty,
3038
ObjectSetPrototypeOf,
31-
MathFloor,
39+
RegExpPrototypeTest,
40+
StringPrototypeToLowerCase,
3241
Symbol,
3342
} = primordials;
3443

@@ -72,7 +81,7 @@ const { CRLF, debug } = common;
7281

7382
const kCorked = Symbol('corked');
7483

75-
function nop() {}
84+
const nop = FunctionPrototype;
7685

7786
const RE_CONN_CLOSE = /(?:^|\W)close(?:$|\W)/i;
7887
const RE_TE_CHUNKED = common.chunkExpression;
@@ -81,13 +90,11 @@ const RE_TE_CHUNKED = common.chunkExpression;
8190
// against the word "cookie." As of V8 6.6 this is faster than handrolling or
8291
// using a case-insensitive RegExp.
8392
function isCookieField(s) {
84-
return s.length === 6 && s.toLowerCase() === 'cookie';
93+
return s.length === 6 && StringPrototypeToLowerCase(s) === 'cookie';
8594
}
8695

87-
function noopPendingOutput(amount) {}
88-
8996
function OutgoingMessage() {
90-
Stream.call(this);
97+
FunctionPrototypeCall(Stream, this);
9198

9299
// Queue that holds all currently pending data, until the response will be
93100
// assigned to the socket (until it will its turn in the HTTP pipeline).
@@ -128,7 +135,7 @@ function OutgoingMessage() {
128135

129136
this._keepAliveTimeout = 0;
130137

131-
this._onPendingData = noopPendingOutput;
138+
this._onPendingData = nop;
132139
}
133140
ObjectSetPrototypeOf(OutgoingMessage.prototype, Stream.prototype);
134141
ObjectSetPrototypeOf(OutgoingMessage, Stream);
@@ -182,7 +189,7 @@ ObjectDefineProperty(OutgoingMessage.prototype, '_headers', {
182189
// Refs: https://github.com/nodejs/node/pull/30958
183190
for (let i = 0; i < keys.length; ++i) {
184191
const name = keys[i];
185-
headers[name.toLowerCase()] = [name, val[name]];
192+
headers[StringPrototypeToLowerCase(name)] = [name, val[name]];
186193
}
187194
}
188195
}, 'OutgoingMessage.prototype._headers is deprecated', 'DEP0066')
@@ -317,7 +324,7 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback) {
317324
data = this._header + data;
318325
} else {
319326
const header = this._header;
320-
this.outputData.unshift({
327+
ArrayPrototypeUnshift(this.outputData, {
321328
data: header,
322329
encoding: 'latin1',
323330
callback: null
@@ -354,7 +361,7 @@ function _writeRaw(data, encoding, callback) {
354361
return conn.write(data, encoding, callback);
355362
}
356363
// Buffer, as long as we're not destroyed.
357-
this.outputData.push({ data, encoding, callback });
364+
ArrayPrototypePush(this.outputData, { data, encoding, callback });
358365
this.outputSize += data.length;
359366
this._onPendingData(data.length);
360367
return this.outputSize < HIGH_WATER_MARK;
@@ -497,7 +504,7 @@ function processHeader(self, state, key, value, validate) {
497504
storeHeader(self, state, key, value[i], validate);
498505
return;
499506
}
500-
value = value.join('; ');
507+
value = ArrayPrototypeJoin(value, '; ');
501508
}
502509
storeHeader(self, state, key, value, validate);
503510
}
@@ -512,20 +519,21 @@ function storeHeader(self, state, key, value, validate) {
512519
function matchHeader(self, state, field, value) {
513520
if (field.length < 4 || field.length > 17)
514521
return;
515-
field = field.toLowerCase();
522+
field = StringPrototypeToLowerCase(field);
516523
switch (field) {
517524
case 'connection':
518525
state.connection = true;
519526
self._removedConnection = false;
520-
if (RE_CONN_CLOSE.test(value))
527+
if (RegExpPrototypeTest(RE_CONN_CLOSE, value))
521528
self._last = true;
522529
else
523530
self.shouldKeepAlive = true;
524531
break;
525532
case 'transfer-encoding':
526533
state.te = true;
527534
self._removedTE = false;
528-
if (RE_TE_CHUNKED.test(value)) self.chunkedEncoding = true;
535+
if (RegExpPrototypeTest(RE_TE_CHUNKED, value))
536+
self.chunkedEncoding = true;
529537
break;
530538
case 'content-length':
531539
state.contLen = true;
@@ -569,7 +577,7 @@ OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
569577
if (headers === null)
570578
this[kOutHeaders] = headers = ObjectCreate(null);
571579

572-
headers[name.toLowerCase()] = [name, value];
580+
headers[StringPrototypeToLowerCase(name)] = [name, value];
573581
return this;
574582
};
575583

@@ -581,7 +589,7 @@ OutgoingMessage.prototype.getHeader = function getHeader(name) {
581589
if (headers === null)
582590
return;
583591

584-
const entry = headers[name.toLowerCase()];
592+
const entry = headers[StringPrototypeToLowerCase(name)];
585593
return entry && entry[1];
586594
};
587595

@@ -613,7 +621,7 @@ OutgoingMessage.prototype.getHeaders = function getHeaders() {
613621
OutgoingMessage.prototype.hasHeader = function hasHeader(name) {
614622
validateString(name, 'name');
615623
return this[kOutHeaders] !== null &&
616-
!!this[kOutHeaders][name.toLowerCase()];
624+
!!this[kOutHeaders][StringPrototypeToLowerCase(name)];
617625
};
618626

619627

@@ -624,7 +632,7 @@ OutgoingMessage.prototype.removeHeader = function removeHeader(name) {
624632
throw new ERR_HTTP_HEADERS_SENT('remove');
625633
}
626634

627-
const key = name.toLowerCase();
635+
const key = StringPrototypeToLowerCase(name);
628636

629637
switch (key) {
630638
case 'connection':
@@ -750,7 +758,7 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
750758

751759
let ret;
752760
if (msg.chunkedEncoding && chunk.length !== 0) {
753-
msg._send(len.toString(16), 'latin1', null);
761+
msg._send(NumberPrototypeToString(len, 16), 'latin1', null);
754762
msg._send(crlf_buf, null, null);
755763
msg._send(chunk, encoding, null);
756764
ret = msg._send(crlf_buf, null, callback);
@@ -839,7 +847,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
839847
if (typeof callback === 'function')
840848
this.once('finish', callback);
841849

842-
const finish = onFinish.bind(undefined, this);
850+
const finish = FunctionPrototypeBind(onFinish, undefined, this);
843851

844852
if (this._hasBody && this.chunkedEncoding) {
845853
this._send('0\r\n' + this._trailer + '\r\n', 'latin1', finish);

‎lib/_http_server.js

+49-29
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,19 @@
2323

2424
const {
2525
ArrayIsArray,
26+
ArrayPrototypePush,
27+
ArrayPrototypeShift,
2628
Error,
29+
FunctionPrototype,
30+
FunctionPrototypeBind,
31+
FunctionPrototypeCall,
2732
ObjectKeys,
2833
ObjectSetPrototypeOf,
34+
ReflectApply,
35+
RegExpPrototypeTest,
2936
Symbol,
3037
SymbolFor,
38+
TypedArrayPrototypeSlice,
3139
} = primordials;
3240

3341
const net = require('net');
@@ -169,7 +177,7 @@ class HTTPServerAsyncResource {
169177
}
170178

171179
function ServerResponse(req) {
172-
OutgoingMessage.call(this);
180+
FunctionPrototypeCall(OutgoingMessage, this);
173181

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

@@ -178,7 +186,8 @@ function ServerResponse(req) {
178186
this._expect_continue = false;
179187

180188
if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
181-
this.useChunkedEncodingByDefault = chunkExpression.test(req.headers.te);
189+
this.useChunkedEncodingByDefault = RegExpPrototypeTest(chunkExpression,
190+
req.headers.te);
182191
this.shouldKeepAlive = false;
183192
}
184193

@@ -197,7 +206,7 @@ ServerResponse.prototype._finish = function _finish() {
197206
if (this[kServerResponseStatistics] !== undefined) {
198207
emitStatistics(this[kServerResponseStatistics]);
199208
}
200-
OutgoingMessage.prototype._finish.call(this);
209+
FunctionPrototypeCall(OutgoingMessage.prototype._finish, this);
201210
};
202211

203212

@@ -371,7 +380,7 @@ function Server(options, requestListener) {
371380
validateBoolean(insecureHTTPParser, 'options.insecureHTTPParser');
372381
this.insecureHTTPParser = insecureHTTPParser;
373382

374-
net.Server.call(this, { allowHalfOpen: true });
383+
FunctionPrototypeCall(net.Server, this, { allowHalfOpen: true });
375384

376385
if (requestListener) {
377386
this.on('request', requestListener);
@@ -417,8 +426,8 @@ Server.prototype[EE.captureRejectionSymbol] = function(err, event, ...args) {
417426
}
418427
break;
419428
default:
420-
net.Server.prototype[SymbolFor('nodejs.rejection')]
421-
.call(this, err, event, ...args);
429+
ReflectApply(net.Server.prototype[SymbolFor('nodejs.rejection')],
430+
this, arguments);
422431
}
423432
};
424433

@@ -477,16 +486,21 @@ function connectionListenerInternal(server, socket) {
477486
outgoingData: 0,
478487
keepAliveTimeoutSet: false
479488
};
480-
state.onData = socketOnData.bind(undefined, server, socket, parser, state);
481-
state.onEnd = socketOnEnd.bind(undefined, server, socket, parser, state);
482-
state.onClose = socketOnClose.bind(undefined, socket, state);
483-
state.onDrain = socketOnDrain.bind(undefined, socket, state);
489+
state.onData = FunctionPrototypeBind(socketOnData, undefined,
490+
server, socket, parser, state);
491+
state.onEnd = FunctionPrototypeBind(socketOnEnd, undefined,
492+
server, socket, parser, state);
493+
state.onClose = FunctionPrototypeBind(socketOnClose, undefined,
494+
socket, state);
495+
state.onDrain = FunctionPrototypeBind(socketOnDrain, undefined,
496+
socket, state);
484497
socket.on('data', state.onData);
485498
socket.on('error', socketOnError);
486499
socket.on('end', state.onEnd);
487500
socket.on('close', state.onClose);
488501
socket.on('drain', state.onDrain);
489-
parser.onIncoming = parserOnIncoming.bind(undefined, server, socket, state);
502+
parser.onIncoming = FunctionPrototypeBind(parserOnIncoming, undefined,
503+
server, socket, state);
490504

491505
// We are consuming socket, so it won't get any actual data
492506
socket.on('resume', onSocketResume);
@@ -506,15 +520,18 @@ function connectionListenerInternal(server, socket) {
506520
parser.consume(socket._handle);
507521
}
508522
parser[kOnExecute] =
509-
onParserExecute.bind(undefined, server, socket, parser, state);
523+
FunctionPrototypeBind(onParserExecute, undefined,
524+
server, socket, parser, state);
510525

511526
parser[kOnTimeout] =
512-
onParserTimeout.bind(undefined, server, socket);
527+
FunctionPrototypeBind(onParserTimeout, undefined,
528+
server, socket);
513529

514530
// When receiving new requests on the same socket (pipelining or keep alive)
515531
// make sure the requestTimeout is active.
516532
parser[kOnMessageBegin] =
517-
setRequestTimeout.bind(undefined, server, socket);
533+
FunctionPrototypeBind(setRequestTimeout, undefined,
534+
server, socket);
518535

519536
// This protects from DOS attack where an attacker establish the connection
520537
// without sending any data on applications where server.timeout is left to
@@ -574,7 +591,7 @@ function socketOnClose(socket, state) {
574591

575592
function abortIncoming(incoming) {
576593
while (incoming.length) {
577-
const req = incoming.shift();
594+
const req = ArrayPrototypeShift(incoming);
578595
req.destroy(connResetException('aborted'));
579596
}
580597
// Abort socket._httpMessage ?
@@ -585,7 +602,7 @@ function socketOnEnd(server, socket, parser, state) {
585602

586603
if (ret instanceof Error) {
587604
debug('parse error');
588-
socketOnError.call(socket, ret);
605+
FunctionPrototypeCall(socketOnError, socket, ret);
589606
return;
590607
}
591608

@@ -611,7 +628,7 @@ function socketOnData(server, socket, parser, state, d) {
611628

612629
function onRequestTimeout(socket) {
613630
socket[kRequestTimeout] = undefined;
614-
socketOnError.call(socket, new ERR_HTTP_REQUEST_TIMEOUT());
631+
ReflectApply(socketOnError, socket, [new ERR_HTTP_REQUEST_TIMEOUT()]);
615632
}
616633

617634
function onParserExecute(server, socket, parser, state, ret) {
@@ -631,7 +648,7 @@ function onParserTimeout(server, socket) {
631648
socket.destroy();
632649
}
633650

634-
const noop = () => {};
651+
const noop = FunctionPrototype;
635652
const badRequestResponse = Buffer.from(
636653
`HTTP/1.1 400 ${STATUS_CODES[400]}${CRLF}` +
637654
`Connection: close${CRLF}${CRLF}`, 'ascii'
@@ -678,7 +695,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
678695
prepareError(ret, parser, d);
679696
ret.rawPacket = d || parser.getCurrentBuffer();
680697
debug('parse error', ret);
681-
socketOnError.call(socket, ret);
698+
FunctionPrototypeCall(socketOnError, socket, ret);
682699
} else if (parser.incoming && parser.incoming.upgrade) {
683700
// Upgrade or CONNECT
684701
const req = parser.incoming;
@@ -701,7 +718,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
701718
const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
702719
if (eventName === 'upgrade' || server.listenerCount(eventName) > 0) {
703720
debug('SERVER have listener for %s', eventName);
704-
const bodyHead = d.slice(ret, d.length);
721+
const bodyHead = TypedArrayPrototypeSlice(d, ret, d.length);
705722

706723
socket.readableFlowing = null;
707724

@@ -717,7 +734,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) {
717734
// When receiving new requests on the same socket (pipelining or keep alive)
718735
// make sure the requestTimeout is active.
719736
parser[kOnMessageBegin] =
720-
setRequestTimeout.bind(undefined, server, socket);
737+
FunctionPrototypeBind(setRequestTimeout, undefined, server, socket);
721738
}
722739

723740
if (socket._paused && socket.parser) {
@@ -781,7 +798,7 @@ function resOnFinish(req, res, socket, state, server) {
781798
// array will be empty.
782799
assert(state.incoming.length === 0 || state.incoming[0] === req);
783800

784-
state.incoming.shift();
801+
ArrayPrototypeShift(state.incoming);
785802

786803
// If the user never called req.read(), and didn't pipe() or
787804
// .resume() or .on('data'), then we call req._dump() so that the
@@ -814,7 +831,7 @@ function resOnFinish(req, res, socket, state, server) {
814831
}
815832
} else {
816833
// Start sending the next message
817-
const m = state.outgoing.shift();
834+
const m = ArrayPrototypeShift(state.outgoing);
818835
if (m) {
819836
m.assignSocket(socket);
820837
}
@@ -840,7 +857,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
840857
return 2;
841858
}
842859

843-
state.incoming.push(req);
860+
ArrayPrototypePush(state.incoming, req);
844861

845862
// If the writable end isn't consuming, then stop reading
846863
// so that we don't become overwhelmed by a flood of
@@ -858,7 +875,8 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
858875

859876
const res = new server[kServerResponse](req);
860877
res._keepAliveTimeout = server.keepAliveTimeout;
861-
res._onPendingData = updateOutgoingData.bind(undefined, socket, state);
878+
res._onPendingData = FunctionPrototypeBind(updateOutgoingData, undefined,
879+
socket, state);
862880

863881
res.shouldKeepAlive = keepAlive;
864882
DTRACE_HTTP_SERVER_REQUEST(req, socket);
@@ -874,19 +892,20 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
874892

875893
if (socket._httpMessage) {
876894
// There are already pending outgoing res, append.
877-
state.outgoing.push(res);
895+
ArrayPrototypePush(state.outgoing, res);
878896
} else {
879897
res.assignSocket(socket);
880898
}
881899

882900
// When we're finished writing the response, check if this is the last
883901
// response, if so destroy the socket.
884902
res.on('finish',
885-
resOnFinish.bind(undefined, req, res, socket, state, server));
903+
FunctionPrototypeBind(resOnFinish, undefined,
904+
req, res, socket, state, server));
886905

887906
if (req.headers.expect !== undefined &&
888907
(req.httpVersionMajor === 1 && req.httpVersionMinor === 1)) {
889-
if (continueExpression.test(req.headers.expect)) {
908+
if (RegExpPrototypeTest(continueExpression, req.headers.expect)) {
890909
res._expect_continue = true;
891910

892911
if (server.listenerCount('checkContinue') > 0) {
@@ -954,7 +973,8 @@ function unconsume(parser, socket) {
954973

955974
function generateSocketListenerWrapper(originalFnName) {
956975
return function socketListenerWrap(ev, fn) {
957-
const res = net.Socket.prototype[originalFnName].call(this, ev, fn);
976+
const res = ReflectApply(net.Socket.prototype[originalFnName], this,
977+
[ev, fn]);
958978
if (!this.parser) {
959979
this.on = net.Socket.prototype.on;
960980
this.addListener = net.Socket.prototype.addListener;

‎lib/http.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
'use strict';
2323

2424
const {
25+
ArrayPrototypeSlice,
26+
ArrayPrototypeSort,
2527
ObjectDefineProperty,
2628
} = primordials;
2729

@@ -58,7 +60,7 @@ function get(url, options, cb) {
5860

5961
module.exports = {
6062
_connectionListener,
61-
METHODS: methods.slice().sort(),
63+
METHODS: ArrayPrototypeSort(ArrayPrototypeSlice(methods)),
6264
STATUS_CODES,
6365
Agent: httpAgent.Agent,
6466
ClientRequest,

‎lib/internal/http.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
const {
44
Symbol,
55
Date,
6+
DatePrototypeGetMilliseconds,
7+
DatePrototypeToUTCString,
68
} = primordials;
79

810
const { setUnrefTimeout } = require('internal/timers');
@@ -17,8 +19,8 @@ function utcDate() {
1719

1820
function cache() {
1921
const d = new Date();
20-
utcCache = d.toUTCString();
21-
setUnrefTimeout(resetCache, 1000 - d.getMilliseconds());
22+
utcCache = DatePrototypeToUTCString(d);
23+
setUnrefTimeout(resetCache, 1000 - DatePrototypeGetMilliseconds(d));
2224
}
2325

2426
function resetCache() {

0 commit comments

Comments
 (0)
Please sign in to comment.