Skip to content

Commit 51a8973

Browse files
committed
perf(fetch): avoid redundant conversion
1 parent 825e6e1 commit 51a8973

File tree

6 files changed

+37
-18
lines changed

6 files changed

+37
-18
lines changed

lib/web/fetch/body.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,21 @@ function extractBody (object, keepalive = false) {
121121

122122
for (const [name, value] of object) {
123123
if (typeof value === 'string') {
124-
const chunk = textEncoder.encode(prefix +
125-
`; name="${escape(normalizeLinefeeds(name))}"` +
126-
`\r\n\r\n${normalizeLinefeeds(value)}\r\n`)
124+
const chunk = textEncoder.encode(
125+
`${prefix}; name="${escape(
126+
normalizeLinefeeds(name)
127+
)}"\r\n\r\n${normalizeLinefeeds(value)}\r\n`
128+
)
127129
blobParts.push(chunk)
128130
length += chunk.byteLength
129131
} else {
130-
const chunk = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` +
131-
(value.name ? `; filename="${escape(value.name)}"` : '') + '\r\n' +
132-
`Content-Type: ${
132+
const chunk = textEncoder.encode(
133+
`${prefix}; name="${escape(normalizeLinefeeds(name))}"${
134+
value.name ? `; filename="${escape(value.name)}"` : ''
135+
}\r\nContent-Type: ${
133136
value.type || 'application/octet-stream'
134-
}\r\n\r\n`)
137+
}\r\n\r\n`
138+
)
135139
blobParts.push(chunk, value, rn)
136140
if (typeof value.size === 'number') {
137141
length += chunk.byteLength + value.size + rn.byteLength

lib/web/fetch/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1475,7 +1475,7 @@ async function httpNetworkOrCacheFetch (
14751475
// user agents should append `User-Agent`/default `User-Agent` value to
14761476
// httpRequest’s header list.
14771477
if (!httpRequest.headersList.contains('user-agent', true)) {
1478-
httpRequest.headersList.append('user-agent', defaultUserAgent)
1478+
httpRequest.headersList.append('user-agent', defaultUserAgent, true)
14791479
}
14801480

14811481
// 15. If httpRequest’s cache mode is "default" and httpRequest’s header

lib/web/fetch/request.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,8 @@ class Request {
467467
// list, append header’s name/header’s value to this’s headers.
468468
if (headers instanceof HeadersList) {
469469
for (const [key, val] of headers) {
470-
headersList.append(key, val)
470+
// Note: The header names are already in lowercase.
471+
headersList.append(key, val, true)
471472
}
472473
// Note: Copy the `set-cookie` meta-data.
473474
headersList.cookies = headers.cookies
@@ -892,16 +893,18 @@ webidl.converters.Request = webidl.interfaceConverter(
892893
)
893894

894895
// https://fetch.spec.whatwg.org/#requestinfo
896+
897+
// DOMString is used because the value is converted to a USVString in `new URL()`.
895898
webidl.converters.RequestInfo = function (V) {
896899
if (typeof V === 'string') {
897-
return webidl.converters.USVString(V)
900+
return webidl.converters.DOMString(V)
898901
}
899902

900903
if (V instanceof Request) {
901904
return webidl.converters.Request(V)
902905
}
903906

904-
return webidl.converters.USVString(V)
907+
return webidl.converters.DOMString(V)
905908
}
906909

907910
webidl.converters.AbortSignal = webidl.interfaceConverter(
@@ -921,7 +924,7 @@ webidl.converters.RequestInit = webidl.dictionaryConverter([
921924
{
922925
key: 'body',
923926
converter: webidl.nullableConverter(
924-
webidl.converters.BodyInit
927+
webidl.converters.BodyInit_DOMString
925928
)
926929
},
927930
{

lib/web/fetch/response.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ class Response {
7777

7878
webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' })
7979

80-
url = webidl.converters.USVString(url)
80+
// DOMString is used because the value is converted to a USVString in `new URL()`.
81+
url = webidl.converters.DOMString(url)
8182
status = webidl.converters['unsigned short'](status)
8283

8384
// 1. Let parsedURL be the result of parsing url with current settings
@@ -120,7 +121,7 @@ class Response {
120121
}
121122

122123
if (body !== null) {
123-
body = webidl.converters.BodyInit(body)
124+
body = webidl.converters.BodyInit_DOMString(body)
124125
}
125126

126127
init = webidl.converters.ResponseInit(init)
@@ -516,9 +517,10 @@ webidl.converters.URLSearchParams = webidl.interfaceConverter(
516517
)
517518

518519
// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit
519-
webidl.converters.XMLHttpRequestBodyInit = function (V) {
520+
521+
webidl.converters.XMLHttpRequestBodyInit_DOMString = function (V) {
520522
if (typeof V === 'string') {
521-
return webidl.converters.USVString(V)
523+
return webidl.converters.DOMString(V)
522524
}
523525

524526
if (isBlobLike(V)) {
@@ -541,7 +543,7 @@ webidl.converters.XMLHttpRequestBodyInit = function (V) {
541543
}
542544

543545
// https://fetch.spec.whatwg.org/#bodyinit
544-
webidl.converters.BodyInit = function (V) {
546+
webidl.converters.BodyInit_DOMString = function (V) {
545547
if (V instanceof ReadableStream) {
546548
return webidl.converters.ReadableStream(V)
547549
}
@@ -552,7 +554,7 @@ webidl.converters.BodyInit = function (V) {
552554
return V
553555
}
554556

555-
return webidl.converters.XMLHttpRequestBodyInit(V)
557+
return webidl.converters.XMLHttpRequestBodyInit_DOMString(V)
556558
}
557559

558560
webidl.converters.ResponseInit = webidl.dictionaryConverter([

test/fetch/request.js

+5
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,8 @@ test('fromInnerRequest', () => {
504504
assert.strictEqual(request[kHeaders][kGuard], 'immutable')
505505
assert.strictEqual(request[kHeaders][kRealm], realm)
506506
})
507+
508+
test('surrogate pair url', async () => {
509+
const request = new Request('https://asd/\ud801')
510+
assert.deepStrictEqual(request.url, 'https://asd/%EF%BF%BD')
511+
})

test/fetch/response.js

+5
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,8 @@ test('fromInnerResponse', () => {
288288
assert.strictEqual(response[kHeaders][kGuard], 'immutable')
289289
assert.strictEqual(response[kHeaders][kRealm], realm)
290290
})
291+
292+
test('surrogate pair', async () => {
293+
const response = new Response('\ud801')
294+
assert.deepStrictEqual(await response.text(), '\ufffd')
295+
})

0 commit comments

Comments
 (0)