Skip to content

Commit 5e499c4

Browse files
aduh95danielleadams
authored andcommitted
http: refactor to use more primordials
PR-URL: #36194 Backport-PR-URL: #36803 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent c784f15 commit 5e499c4

8 files changed

+150
-89
lines changed

lib/_http_agent.js

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

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

@@ -78,7 +89,7 @@ function Agent(options) {
7889
if (!(this instanceof Agent))
7990
return new Agent(options);
8091

81-
EventEmitter.call(this);
92+
FunctionPrototypeCall(EventEmitter, this);
8293

8394
this.defaultPort = 80;
8495
this.protocol = 'http:';
@@ -125,7 +136,7 @@ function Agent(options) {
125136

126137
const requests = this.requests[name];
127138
if (requests && requests.length) {
128-
const req = requests.shift();
139+
const req = ArrayPrototypeShift(requests);
129140
const reqAsyncRes = req[kRequestAsyncResource];
130141
if (reqAsyncRes) {
131142
// Run request within the original async context.
@@ -171,7 +182,7 @@ function Agent(options) {
171182
this.removeSocket(socket, options);
172183

173184
socket.once('error', freeSocketErrorListener);
174-
freeSockets.push(socket);
185+
ArrayPrototypePush(freeSockets, socket);
175186
});
176187

177188
// Don't emit keylog events unless there is a listener for them.
@@ -249,11 +260,11 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */,
249260
let socket;
250261
if (freeSockets) {
251262
while (freeSockets.length && freeSockets[0].destroyed) {
252-
freeSockets.shift();
263+
ArrayPrototypeShift(freeSockets);
253264
}
254265
socket = this.scheduling === 'fifo' ?
255-
freeSockets.shift() :
256-
freeSockets.pop();
266+
ArrayPrototypeShift(freeSockets) :
267+
ArrayPrototypePop(freeSockets);
257268
if (!freeSockets.length)
258269
delete this.freeSockets[name];
259270
}
@@ -265,7 +276,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */,
265276
asyncResetHandle(socket);
266277
this.reuseSocket(socket, req);
267278
setRequestSocket(this, req, socket);
268-
this.sockets[name].push(socket);
279+
ArrayPrototypePush(this.sockets[name], socket);
269280
this.totalSocketCount++;
270281
} else if (sockLen < this.maxSockets &&
271282
this.totalSocketCount < this.maxTotalSockets) {
@@ -289,7 +300,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */,
289300
// Used to capture the original async context.
290301
req[kRequestAsyncResource] = new AsyncResource('QueuedRequest');
291302

292-
this.requests[name].push(req);
303+
ArrayPrototypePush(this.requests[name], req);
293304
}
294305
};
295306

@@ -313,7 +324,7 @@ Agent.prototype.createSocket = function createSocket(req, options, cb) {
313324
if (!this.sockets[name]) {
314325
this.sockets[name] = [];
315326
}
316-
this.sockets[name].push(s);
327+
ArrayPrototypePush(this.sockets[name], s);
317328
this.totalSocketCount++;
318329
debug('sockets', name, this.sockets[name].length, this.totalSocketCount);
319330
installListeners(this, s, options);
@@ -338,16 +349,16 @@ function calculateServerName(options, req) {
338349
// abc:123 => abc
339350
// [::1] => ::1
340351
// [::1]:123 => ::1
341-
if (hostHeader.startsWith('[')) {
342-
const index = hostHeader.indexOf(']');
352+
if (StringPrototypeStartsWith(hostHeader, '[')) {
353+
const index = StringPrototypeIndexOf(hostHeader, ']');
343354
if (index === -1) {
344355
// Leading '[', but no ']'. Need to do something...
345356
servername = hostHeader;
346357
} else {
347-
servername = hostHeader.substr(1, index - 1);
358+
servername = StringPrototypeSubstr(hostHeader, 1, index - 1);
348359
}
349360
} else {
350-
servername = hostHeader.split(':', 1)[0];
361+
servername = StringPrototypeSplit(hostHeader, ':', 1)[0];
351362
}
352363
}
353364
// Don't implicitly set invalid (IP) servernames.
@@ -379,7 +390,7 @@ function installListeners(agent, s, options) {
379390
// TODO(ronag): Always destroy, even if not in free list.
380391
const sockets = agent.freeSockets;
381392
for (const name of ObjectKeys(sockets)) {
382-
if (sockets[name].includes(s)) {
393+
if (ArrayPrototypeIncludes(sockets[name], s)) {
383394
return s.destroy();
384395
}
385396
}
@@ -411,13 +422,13 @@ Agent.prototype.removeSocket = function removeSocket(s, options) {
411422

412423
// If the socket was destroyed, remove it from the free buffers too.
413424
if (!s.writable)
414-
sets.push(this.freeSockets);
425+
ArrayPrototypePush(sets, this.freeSockets);
415426

416427
for (const sockets of sets) {
417428
if (sockets[name]) {
418-
const index = sockets[name].indexOf(s);
429+
const index = ArrayPrototypeIndexOf(sockets[name], s);
419430
if (index !== -1) {
420-
sockets[name].splice(index, 1);
431+
ArrayPrototypeSplice(sockets[name], index, 1);
421432
// Don't leak
422433
if (sockets[name].length === 0)
423434
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() {
@@ -547,7 +555,7 @@ function socketOnData(d) {
547555
parser.finish();
548556
freeParser(parser, req, socket);
549557

550-
const bodyHead = d.slice(bytesParsed, d.length);
558+
const bodyHead = TypedArrayPrototypeSlice(d, bytesParsed, d.length);
551559

552560
const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
553561
if (req.listenerCount(eventName) > 0) {
@@ -848,7 +856,7 @@ function _deferToConnect(method, arguments_, cb) {
848856

849857
const callSocketMethod = () => {
850858
if (method)
851-
this.socket[method].apply(this.socket, arguments_);
859+
ReflectApply(this.socket[method], this.socket, arguments_);
852860

853861
if (typeof cb === 'function')
854862
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

+11-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,8 @@ function IncomingMessage(socket) {
5459
};
5560
}
5661

57-
Stream.Readable.call(this, { autoDestroy: false, ...streamOptions });
62+
FunctionPrototypeCall(Stream.Readable, this,
63+
{ autoDestroy: false, ...streamOptions });
5864

5965
this._readableState.readingMore = true;
6066

@@ -300,7 +306,7 @@ function matchKnownFields(field, lowercased) {
300306
if (lowercased) {
301307
return '\u0000' + field;
302308
}
303-
return matchKnownFields(field.toLowerCase(), true);
309+
return matchKnownFields(StringPrototypeToLowerCase(field), true);
304310
}
305311
// Add the given (field, value) pair to the message
306312
//
@@ -314,9 +320,9 @@ function matchKnownFields(field, lowercased) {
314320
IncomingMessage.prototype._addHeaderLine = _addHeaderLine;
315321
function _addHeaderLine(field, value, dest) {
316322
field = matchKnownFields(field);
317-
const flag = field.charCodeAt(0);
323+
const flag = StringPrototypeCharCodeAt(field, 0);
318324
if (flag === 0 || flag === 2) {
319-
field = field.slice(1);
325+
field = StringPrototypeSlice(field, 1);
320326
// Make a delimited list
321327
if (typeof dest[field] === 'string') {
322328
dest[field] += (flag === 0 ? ', ' : '; ') + value;
@@ -326,7 +332,7 @@ function _addHeaderLine(field, value, dest) {
326332
} else if (flag === 1) {
327333
// Array header -- only Set-Cookie at the moment
328334
if (dest['set-cookie'] !== undefined) {
329-
dest['set-cookie'].push(value);
335+
ArrayPrototypePush(dest['set-cookie'], value);
330336
} else {
331337
dest['set-cookie'] = [value];
332338
}

0 commit comments

Comments
 (0)