Skip to content

Commit 99f96eb

Browse files
aduh95anonrig
authored andcommittedSep 21, 2024
http2: remove prototype primordials
Co-authored-by: Yagiz Nizipli <yagiz@nizipli.com> PR-URL: #53696 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 3000e5d commit 99f96eb

File tree

4 files changed

+64
-101
lines changed

4 files changed

+64
-101
lines changed
 

‎doc/contributing/primordials.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@ The file `lib/internal/per_context/primordials.js` subclasses and stores the JS
44
built-ins that come from the VM so that Node.js built-in modules do not need to
55
later look these up from the global proxy, which can be mutated by users.
66

7-
Usage of primordials should be preferred for any new code, but replacing current
8-
code with primordials should be
7+
For some area of the codebase, performance and code readability are deemed more
8+
important than reliability against prototype pollution:
9+
10+
* `node:http2`
11+
12+
Usage of primordials should be preferred for new code in other areas, but
13+
replacing current code with primordials should be
914
[done with care](#primordials-with-known-performance-issues). It is highly
1015
recommended to ping the relevant team when reviewing a pull request that touches
1116
one of the subsystems they "own".

‎lib/internal/http2/compat.js

+15-22
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,13 @@
22

33
const {
44
ArrayIsArray,
5-
ArrayPrototypePush,
65
Boolean,
7-
FunctionPrototypeBind,
86
ObjectAssign,
7+
ObjectHasOwn,
98
ObjectKeys,
10-
ObjectPrototypeHasOwnProperty,
119
Proxy,
1210
ReflectApply,
1311
ReflectGetPrototypeOf,
14-
StringPrototypeIncludes,
15-
SafeArrayIterator,
16-
StringPrototypeToLowerCase,
17-
StringPrototypeTrim,
1812
Symbol,
1913
} = primordials;
2014

@@ -89,7 +83,7 @@ let statusConnectionHeaderWarned = false;
8983
const assertValidHeader = hideStackFrames((name, value) => {
9084
if (name === '' ||
9185
typeof name !== 'string' ||
92-
StringPrototypeIncludes(name, ' ')) {
86+
name.includes(' ')) {
9387
throw new ERR_INVALID_HTTP_TOKEN.HideStackFramesError('Header name', name);
9488
}
9589
if (isPseudoHeader(name)) {
@@ -153,8 +147,7 @@ function onStreamTrailers(trailers, flags, rawTrailers) {
153147
const request = this[kRequest];
154148
if (request !== undefined) {
155149
ObjectAssign(request[kTrailers], trailers);
156-
ArrayPrototypePush(request[kRawTrailers],
157-
...new SafeArrayIterator(rawTrailers));
150+
request[kRawTrailers].push(...rawTrailers);
158151
}
159152
}
160153

@@ -216,7 +209,7 @@ const proxySocketHandler = {
216209
case 'end':
217210
case 'emit':
218211
case 'destroy':
219-
return FunctionPrototypeBind(stream[prop], stream);
212+
return stream[prop].bind(stream);
220213
case 'writable':
221214
case 'destroyed':
222215
return stream[prop];
@@ -229,8 +222,8 @@ const proxySocketHandler = {
229222
case 'setTimeout': {
230223
const session = stream.session;
231224
if (session !== undefined)
232-
return FunctionPrototypeBind(session.setTimeout, session);
233-
return FunctionPrototypeBind(stream.setTimeout, stream);
225+
return session.setTimeout.bind(session);
226+
return stream.setTimeout.bind(stream);
234227
}
235228
case 'write':
236229
case 'read':
@@ -242,7 +235,7 @@ const proxySocketHandler = {
242235
stream.session[kSocket] : stream;
243236
const value = ref[prop];
244237
return typeof value === 'function' ?
245-
FunctionPrototypeBind(value, ref) :
238+
value.bind(ref) :
246239
value;
247240
}
248241
}
@@ -417,7 +410,7 @@ class Http2ServerRequest extends Readable {
417410

418411
set method(method) {
419412
validateString(method, 'method');
420-
if (StringPrototypeTrim(method) === '')
413+
if (method.trim() === '')
421414
throw new ERR_INVALID_ARG_VALUE('method', method);
422415

423416
this[kHeaders][HTTP2_HEADER_METHOD] = method;
@@ -578,7 +571,7 @@ class Http2ServerResponse extends Stream {
578571

579572
setTrailer(name, value) {
580573
validateString(name, 'name');
581-
name = StringPrototypeToLowerCase(StringPrototypeTrim(name));
574+
name = name.trim().toLowerCase();
582575
assertValidHeader(name, value);
583576
this[kTrailers][name] = value;
584577
}
@@ -594,7 +587,7 @@ class Http2ServerResponse extends Stream {
594587

595588
getHeader(name) {
596589
validateString(name, 'name');
597-
name = StringPrototypeToLowerCase(StringPrototypeTrim(name));
590+
name = name.trim().toLowerCase();
598591
return this[kHeaders][name];
599592
}
600593

@@ -609,16 +602,16 @@ class Http2ServerResponse extends Stream {
609602

610603
hasHeader(name) {
611604
validateString(name, 'name');
612-
name = StringPrototypeToLowerCase(StringPrototypeTrim(name));
613-
return ObjectPrototypeHasOwnProperty(this[kHeaders], name);
605+
name = name.trim().toLowerCase();
606+
return ObjectHasOwn(this[kHeaders], name);
614607
}
615608

616609
removeHeader(name) {
617610
validateString(name, 'name');
618611
if (this[kStream].headersSent)
619612
throw new ERR_HTTP2_HEADERS_SENT();
620613

621-
name = StringPrototypeToLowerCase(StringPrototypeTrim(name));
614+
name = name.trim().toLowerCase();
622615

623616
if (name === 'date') {
624617
this[kState].sendDate = false;
@@ -638,7 +631,7 @@ class Http2ServerResponse extends Stream {
638631
}
639632

640633
[kSetHeader](name, value) {
641-
name = StringPrototypeToLowerCase(StringPrototypeTrim(name));
634+
name = name.trim().toLowerCase();
642635
assertValidHeader(name, value);
643636

644637
if (!isConnectionHeaderAllowed(name, value)) {
@@ -662,7 +655,7 @@ class Http2ServerResponse extends Stream {
662655
}
663656

664657
[kAppendHeader](name, value) {
665-
name = StringPrototypeToLowerCase(StringPrototypeTrim(name));
658+
name = name.trim().toLowerCase();
666659
assertValidHeader(name, value);
667660

668661
if (!isConnectionHeaderAllowed(name, value)) {

‎lib/internal/http2/core.js

+37-65
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,24 @@
33
const {
44
ArrayFrom,
55
ArrayIsArray,
6-
ArrayPrototypeForEach,
7-
ArrayPrototypePush,
8-
ArrayPrototypeUnshift,
9-
FunctionPrototypeBind,
10-
FunctionPrototypeCall,
116
MathMin,
127
Number,
138
ObjectAssign,
14-
ObjectKeys,
159
ObjectDefineProperty,
1610
ObjectEntries,
17-
ObjectPrototypeHasOwnProperty,
11+
ObjectHasOwn,
12+
ObjectKeys,
1813
Promise,
19-
PromisePrototypeThen,
2014
Proxy,
2115
ReflectApply,
2216
ReflectGet,
2317
ReflectGetPrototypeOf,
2418
ReflectSet,
25-
RegExpPrototypeExec,
26-
SafeArrayIterator,
2719
SafeMap,
2820
SafeSet,
29-
StringPrototypeSlice,
3021
Symbol,
3122
SymbolAsyncDispose,
3223
SymbolDispose,
33-
TypedArrayPrototypeGetLength,
3424
Uint32Array,
3525
Uint8Array,
3626
} = primordials;
@@ -205,22 +195,22 @@ function debugStream(id, sessionType, message, ...args) {
205195
return;
206196
}
207197
debug('Http2Stream %s [Http2Session %s]: ' + message,
208-
id, sessionName(sessionType), ...new SafeArrayIterator(args));
198+
id, sessionName(sessionType), ...args);
209199
}
210200

211201
function debugStreamObj(stream, message, ...args) {
212202
const session = stream[kSession];
213203
const type = session ? session[kType] : undefined;
214-
debugStream(stream[kID], type, message, ...new SafeArrayIterator(args));
204+
debugStream(stream[kID], type, message, ...args);
215205
}
216206

217207
function debugSession(sessionType, message, ...args) {
218208
debug('Http2Session %s: ' + message, sessionName(sessionType),
219-
...new SafeArrayIterator(args));
209+
...args);
220210
}
221211

222212
function debugSessionObj(session, message, ...args) {
223-
debugSession(session[kType], message, ...new SafeArrayIterator(args));
213+
debugSession(session[kType], message, ...args);
224214
}
225215

226216
const kMaxFrameSize = (2 ** 24) - 1;
@@ -826,8 +816,7 @@ function submitSettings(settings, callback) {
826816
debugSessionObj(this, 'submitting settings');
827817
this[kUpdateTimer]();
828818
updateSettingsBuffer(settings);
829-
if (!this[kHandle].settings(FunctionPrototypeBind(settingsCallback,
830-
this, callback))) {
819+
if (!this[kHandle].settings(settingsCallback.bind(this, callback))) {
831820
this.destroy(new ERR_HTTP2_MAX_PENDING_SETTINGS_ACK());
832821
}
833822
}
@@ -869,7 +858,7 @@ const proxySocketHandler = {
869858
case 'setTimeout':
870859
case 'ref':
871860
case 'unref':
872-
return FunctionPrototypeBind(session[prop], session);
861+
return session[prop].bind(session);
873862
case 'destroy':
874863
case 'emit':
875864
case 'end':
@@ -887,7 +876,7 @@ const proxySocketHandler = {
887876
throw new ERR_HTTP2_SOCKET_UNBOUND();
888877
const value = socket[prop];
889878
return typeof value === 'function' ?
890-
FunctionPrototypeBind(value, socket) :
879+
value.bind(socket) :
891880
value;
892881
}
893882
}
@@ -998,7 +987,7 @@ const validateSettings = hideStackFrames((settings) => {
998987
// Wrap a typed array in a proxy, and allow selectively copying the entries
999988
// that have explicitly been set to another typed array.
1000989
function trackAssignmentsTypedArray(typedArray) {
1001-
const typedArrayLength = TypedArrayPrototypeGetLength(typedArray);
990+
const typedArrayLength = typedArray.length;
1002991
const modifiedEntries = new Uint8Array(typedArrayLength);
1003992

1004993
function copyAssigned(target) {
@@ -1183,8 +1172,7 @@ function closeSession(session, code, error) {
11831172

11841173
// Destroy the handle if it exists at this point.
11851174
if (handle !== undefined) {
1186-
handle.ondone = FunctionPrototypeBind(finishSessionClose,
1187-
null, session, error);
1175+
handle.ondone = finishSessionClose.bind(null, session, error);
11881176
handle.destroy(code, socket.destroyed);
11891177
} else {
11901178
finishSessionClose(session, error);
@@ -1276,8 +1264,7 @@ class Http2Session extends EventEmitter {
12761264
if (typeof socket.disableRenegotiation === 'function')
12771265
socket.disableRenegotiation();
12781266

1279-
const setupFn = FunctionPrototypeBind(setupHandle, this,
1280-
socket, type, options);
1267+
const setupFn = setupHandle.bind(this, socket, type, options);
12811268
if (socket.connecting || socket.secureConnecting) {
12821269
const connectEvent =
12831270
socket instanceof tls.TLSSocket ? 'secureConnect' : 'connect';
@@ -1512,8 +1499,7 @@ class Http2Session extends EventEmitter {
15121499

15131500
this[kState].pendingAck++;
15141501

1515-
const settingsFn = FunctionPrototypeBind(submitSettings, this,
1516-
{ ...settings }, callback);
1502+
const settingsFn = submitSettings.bind(this, { ...settings }, callback);
15171503
if (this.connecting) {
15181504
this.once('connect', settingsFn);
15191505
return;
@@ -1535,9 +1521,7 @@ class Http2Session extends EventEmitter {
15351521
validateNumber(code, 'code');
15361522
validateNumber(lastStreamID, 'lastStreamID');
15371523

1538-
const goawayFn = FunctionPrototypeBind(submitGoaway,
1539-
this,
1540-
code, lastStreamID, opaqueData);
1524+
const goawayFn = submitGoaway.bind(this, code, lastStreamID, opaqueData);
15411525
if (this.connecting) {
15421526
this.once('connect', goawayFn);
15431527
return;
@@ -1693,7 +1677,7 @@ class ServerHttp2Session extends Http2Session {
16931677
}
16941678

16951679
validateString(alt, 'alt');
1696-
if (RegExpPrototypeExec(kQuotedString, alt) === null)
1680+
if (!kQuotedString.test(alt))
16971681
throw new ERR_INVALID_CHAR('alt');
16981682

16991683
// Max length permitted for ALTSVC
@@ -1786,8 +1770,7 @@ class ClientHttp2Session extends Http2Session {
17861770
if (getAuthority(headers) === undefined)
17871771
headers[HTTP2_HEADER_AUTHORITY] = this[kAuthority];
17881772
if (headers[HTTP2_HEADER_SCHEME] === undefined)
1789-
headers[HTTP2_HEADER_SCHEME] = StringPrototypeSlice(this[kProtocol],
1790-
0, -1);
1773+
headers[HTTP2_HEADER_SCHEME] = this[kProtocol].slice(0, -1);
17911774
if (headers[HTTP2_HEADER_PATH] === undefined)
17921775
headers[HTTP2_HEADER_PATH] = '/';
17931776
} else {
@@ -1839,15 +1822,14 @@ class ClientHttp2Session extends Http2Session {
18391822
}
18401823
}
18411824

1842-
const onConnect = FunctionPrototypeBind(requestOnConnect,
1843-
stream, headersList, options);
1825+
const onConnect = requestOnConnect.bind(stream, headersList, options);
18441826
if (this.connecting) {
18451827
if (this[kPendingRequestCalls] !== null) {
1846-
ArrayPrototypePush(this[kPendingRequestCalls], onConnect);
1828+
this[kPendingRequestCalls].push(onConnect);
18471829
} else {
18481830
this[kPendingRequestCalls] = [onConnect];
18491831
this.once('connect', () => {
1850-
ArrayPrototypeForEach(this[kPendingRequestCalls], (f) => f());
1832+
this[kPendingRequestCalls].forEach((f) => f());
18511833
this[kPendingRequestCalls] = null;
18521834
});
18531835
}
@@ -1951,7 +1933,7 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) {
19511933
}
19521934

19531935
if (rstStreamStatus !== kNoRstStream) {
1954-
const finishFn = FunctionPrototypeBind(finishCloseStream, stream, code);
1936+
const finishFn = finishCloseStream.bind(stream, code);
19551937
if (!ending || stream.writableFinished || code !== NGHTTP2_NO_ERROR ||
19561938
rstStreamStatus === kForceRstStream)
19571939
finishFn();
@@ -1961,7 +1943,7 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) {
19611943
}
19621944

19631945
function finishCloseStream(code) {
1964-
const rstStreamFn = FunctionPrototypeBind(submitRstStream, this, code);
1946+
const rstStreamFn = submitRstStream.bind(this, code);
19651947
// If the handle has not yet been assigned, queue up the request to
19661948
// ensure that the RST_STREAM frame is sent after the stream ID has
19671949
// been determined.
@@ -2145,8 +2127,7 @@ class Http2Stream extends Duplex {
21452127
if (this.pending) {
21462128
this.once(
21472129
'ready',
2148-
FunctionPrototypeBind(this[kWriteGeneric],
2149-
this, writev, data, encoding, cb),
2130+
this[kWriteGeneric].bind(this, writev, data, encoding, cb),
21502131
);
21512132
return;
21522133
}
@@ -2238,7 +2219,7 @@ class Http2Stream extends Duplex {
22382219
this[kState].didRead = true;
22392220
}
22402221
if (!this.pending) {
2241-
FunctionPrototypeCall(streamOnResume, this);
2222+
streamOnResume.call(this);
22422223
} else {
22432224
this.once('ready', streamOnResume);
22442225
}
@@ -2252,7 +2233,7 @@ class Http2Stream extends Duplex {
22522233
options = { ...options };
22532234
setAndValidatePriorityOptions(options);
22542235

2255-
const priorityFn = FunctionPrototypeBind(submitPriority, this, options);
2236+
const priorityFn = submitPriority.bind(this, options);
22562237

22572238
// If the handle has not yet been assigned, queue up the priority
22582239
// frame to be sent as soon as the ready event is emitted.
@@ -2455,7 +2436,7 @@ function processHeaders(oldHeaders, options) {
24552436
if (oldHeaders !== null && oldHeaders !== undefined) {
24562437
// This loop is here for performance reason. Do not change.
24572438
for (const key in oldHeaders) {
2458-
if (ObjectPrototypeHasOwnProperty(oldHeaders, key)) {
2439+
if (ObjectHasOwn(oldHeaders, key)) {
24592440
headers[key] = oldHeaders[key];
24602441
}
24612442
}
@@ -2493,8 +2474,7 @@ function processHeaders(oldHeaders, options) {
24932474
function onFileUnpipe() {
24942475
const stream = this.sink[kOwner];
24952476
if (stream.ownsFd)
2496-
PromisePrototypeThen(this.source.close(), undefined,
2497-
FunctionPrototypeBind(stream.destroy, stream));
2477+
this.source.close().catch(stream.destroy.bind(stream));
24982478
else
24992479
this.source.releaseFD();
25002480
}
@@ -2677,9 +2657,7 @@ function afterOpen(session, options, headers, streamOptions, err, fd) {
26772657
state.fd = fd;
26782658

26792659
fs.fstat(fd,
2680-
FunctionPrototypeBind(doSendFileFD, this,
2681-
session, options, fd,
2682-
headers, streamOptions));
2660+
doSendFileFD.bind(this, session, options, fd, headers, streamOptions));
26832661
}
26842662

26852663
class ServerHttp2Stream extends Http2Stream {
@@ -2882,9 +2860,7 @@ class ServerHttp2Stream extends Http2Stream {
28822860

28832861
if (options.statCheck !== undefined) {
28842862
fs.fstat(fd,
2885-
FunctionPrototypeBind(doSendFD, this,
2886-
session, options, fd,
2887-
headers, streamOptions));
2863+
doSendFD.bind(this, session, options, fd, headers, streamOptions));
28882864
return;
28892865
}
28902866

@@ -2943,8 +2919,7 @@ class ServerHttp2Stream extends Http2Stream {
29432919
}
29442920

29452921
fs.open(path, 'r',
2946-
FunctionPrototypeBind(afterOpen, this,
2947-
session, options, headers, streamOptions));
2922+
afterOpen.bind(this, session, options, headers, streamOptions));
29482923
}
29492924

29502925
// Sends a block of informational headers. In theory, the HTTP/2 spec
@@ -2980,7 +2955,7 @@ class ServerHttp2Stream extends Http2Stream {
29802955
if (!this[kInfoHeaders])
29812956
this[kInfoHeaders] = [headers];
29822957
else
2983-
ArrayPrototypePush(this[kInfoHeaders], headers);
2958+
this[kInfoHeaders].push(headers);
29842959

29852960
const ret = this[kHandle].info(headersList);
29862961
if (ret < 0)
@@ -3066,7 +3041,7 @@ function connectionListener(socket) {
30663041
if (options.allowHTTP1 === true) {
30673042
socket.server[kIncomingMessage] = options.Http1IncomingMessage;
30683043
socket.server[kServerResponse] = options.Http1ServerResponse;
3069-
return FunctionPrototypeCall(httpConnectionListener, this, socket);
3044+
return httpConnectionListener.call(this, socket);
30703045
}
30713046
// Let event handler deal with the socket
30723047
debug('Unknown protocol from %s:%s',
@@ -3164,7 +3139,7 @@ function initializeTLSOptions(options, servername) {
31643139
options = initializeOptions(options);
31653140
options.ALPNProtocols = ['h2'];
31663141
if (options.allowHTTP1 === true)
3167-
ArrayPrototypePush(options.ALPNProtocols, 'http/1.1');
3142+
options.ALPNProtocols.push('http/1.1');
31683143
if (servername !== undefined && !options.servername)
31693144
options.servername = servername;
31703145
return options;
@@ -3249,7 +3224,7 @@ class Http2Server extends NETServer {
32493224
}
32503225

32513226
async [SymbolAsyncDispose]() {
3252-
return FunctionPrototypeCall(promisify(super.close), this);
3227+
return promisify(super.close).call(this);
32533228
}
32543229
}
32553230

@@ -3284,7 +3259,7 @@ Http2Server.prototype[EventEmitter.captureRejectionSymbol] = function(
32843259
break;
32853260
}
32863261
default:
3287-
ArrayPrototypeUnshift(args, err, event);
3262+
args.unshift(err, event);
32883263
ReflectApply(net.Server.prototype[EventEmitter.captureRejectionSymbol],
32893264
this, args);
32903265
}
@@ -3293,11 +3268,8 @@ Http2Server.prototype[EventEmitter.captureRejectionSymbol] = function(
32933268
function setupCompat(ev) {
32943269
if (ev === 'request') {
32953270
this.removeListener('newListener', setupCompat);
3296-
this.on('stream', FunctionPrototypeBind(onServerStream,
3297-
this,
3298-
this[kOptions].Http2ServerRequest,
3299-
this[kOptions].Http2ServerResponse),
3300-
);
3271+
this.on('stream', onServerStream.bind(this, this[kOptions].Http2ServerRequest,
3272+
this[kOptions].Http2ServerResponse));
33013273
}
33023274
}
33033275

@@ -3344,7 +3316,7 @@ function connect(authority, options, listener) {
33443316
host = authority.hostname;
33453317

33463318
if (host[0] === '[')
3347-
host = StringPrototypeSlice(host, 1, -1);
3319+
host = host.slice(1, -1);
33483320
} else if (authority.host) {
33493321
host = authority.host;
33503322
}

‎lib/internal/http2/util.js

+5-12
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
const {
44
ArrayIsArray,
5-
ArrayPrototypeIncludes,
6-
ArrayPrototypeMap,
7-
ArrayPrototypePush,
85
Error,
96
MathMax,
107
Number,
@@ -13,8 +10,6 @@ const {
1310
SafeSet,
1411
String,
1512
StringFromCharCode,
16-
StringPrototypeIncludes,
17-
StringPrototypeToLowerCase,
1813
Symbol,
1914
} = primordials;
2015

@@ -602,15 +597,13 @@ function mapToHeaders(map,
602597
let value;
603598
let isSingleValueHeader;
604599
let err;
605-
const neverIndex =
606-
ArrayPrototypeMap(map[kSensitiveHeaders] || emptyArray,
607-
StringPrototypeToLowerCase);
600+
const neverIndex = (map[kSensitiveHeaders] || emptyArray).map((v) => v.toLowerCase());
608601
for (i = 0; i < keys.length; ++i) {
609602
key = keys[i];
610603
value = map[key];
611604
if (value === undefined || key === '')
612605
continue;
613-
key = StringPrototypeToLowerCase(key);
606+
key = key.toLowerCase();
614607
isSingleValueHeader = kSingleValueHeaders.has(key);
615608
isArray = ArrayIsArray(value);
616609
if (isArray) {
@@ -633,7 +626,7 @@ function mapToHeaders(map,
633626
throw new ERR_HTTP2_HEADER_SINGLE_VALUE(key);
634627
singles.add(key);
635628
}
636-
const flags = ArrayPrototypeIncludes(neverIndex, key) ?
629+
const flags = neverIndex.includes(key) ?
637630
kNeverIndexFlag :
638631
kNoHeaderFlags;
639632
if (key[0] === ':') {
@@ -644,7 +637,7 @@ function mapToHeaders(map,
644637
count++;
645638
continue;
646639
}
647-
if (StringPrototypeIncludes(key, ' ')) {
640+
if (key.includes(' ')) {
648641
throw new ERR_INVALID_HTTP_TOKEN('Header name', key);
649642
}
650643
if (isIllegalConnectionSpecificHeader(key, value)) {
@@ -738,7 +731,7 @@ function toHeaderObject(headers, sensitiveHeaders) {
738731
// fields with the same name. Since it cannot be combined into a
739732
// single field-value, recipients ought to handle "Set-Cookie" as a
740733
// special case while processing header fields."
741-
ArrayPrototypePush(existing, value);
734+
existing.push(value);
742735
break;
743736
default:
744737
// https://tools.ietf.org/html/rfc7230#section-3.2.2

0 commit comments

Comments
 (0)
Please sign in to comment.