Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7a89dbd

Browse files
committedNov 24, 2022
perf(fetch): simplify url serializer
1 parent 93f150f commit 7a89dbd

File tree

3 files changed

+16
-89
lines changed

3 files changed

+16
-89
lines changed
 

‎lib/fetch/dataURL.js

+2-67
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const assert = require('assert')
22
const { atob } = require('buffer')
3+
const { format } = require('url')
34
const { isValidHTTPToken, isomorphicDecode } = require('./util')
45

56
const encoder = new TextEncoder()
@@ -111,73 +112,7 @@ function dataURLProcessor (dataURL) {
111112
* @param {boolean} excludeFragment
112113
*/
113114
function URLSerializer (url, excludeFragment = false) {
114-
// 1. Let output be url’s scheme and U+003A (:) concatenated.
115-
let output = url.protocol
116-
117-
// 2. If url’s host is non-null:
118-
if (url.host.length > 0) {
119-
// 1. Append "//" to output.
120-
output += '//'
121-
122-
// 2. If url includes credentials, then:
123-
if (url.username.length > 0 || url.password.length > 0) {
124-
// 1. Append url’s username to output.
125-
output += url.username
126-
127-
// 2. If url’s password is not the empty string, then append U+003A (:),
128-
// followed by url’s password, to output.
129-
if (url.password.length > 0) {
130-
output += ':' + url.password
131-
}
132-
133-
// 3. Append U+0040 (@) to output.
134-
output += '@'
135-
}
136-
137-
// 3. Append url’s host, serialized, to output.
138-
output += decodeURIComponent(url.hostname)
139-
140-
// 4. If url’s port is non-null, append U+003A (:) followed by url’s port,
141-
// serialized, to output.
142-
if (url.port.length > 0) {
143-
output += ':' + url.port
144-
}
145-
}
146-
147-
// 3. If url’s host is null, url does not have an opaque path,
148-
// url’s path’s size is greater than 1, and url’s path[0]
149-
// is the empty string, then append U+002F (/) followed by
150-
// U+002E (.) to output.
151-
// Note: This prevents web+demo:/.//not-a-host/ or web+demo:/path/..//not-a-host/,
152-
// when parsed and then serialized, from ending up as web+demo://not-a-host/
153-
// (they end up as web+demo:/.//not-a-host/).
154-
// Undici implementation note: url's path[0] can never be an
155-
// empty string, so we have to slightly alter what the spec says.
156-
if (
157-
url.host.length === 0 &&
158-
url.pathname.length > 1 &&
159-
url.href.slice(url.protocol.length + 1)[0] === '.'
160-
) {
161-
output += '/.'
162-
}
163-
164-
// 4. Append the result of URL path serializing url to output.
165-
output += url.pathname
166-
167-
// 5. If url’s query is non-null, append U+003F (?),
168-
// followed by url’s query, to output.
169-
if (url.search.length > 0) {
170-
output += url.search
171-
}
172-
173-
// 6. If exclude fragment is false and url’s fragment is non-null,
174-
// then append U+0023 (#), followed by url’s fragment, to output.
175-
if (excludeFragment === false && url.hash.length > 0) {
176-
output += url.hash
177-
}
178-
179-
// 7. Return output.
180-
return output
115+
return format(url, { fragment: !excludeFragment })
181116
}
182117

183118
// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points

‎test/fetch/data-uri.js

+14
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,17 @@ test('too long base64 url', async (t) => {
177177
t.fail(`failed to fetch ${dataURL}`)
178178
}
179179
})
180+
181+
test('https://domain.com/#', (t) => {
182+
t.plan(1)
183+
const domain = 'https://domain.com/#'
184+
const serialized = URLSerializer(new URL(domain))
185+
t.equal(serialized, domain)
186+
})
187+
188+
test('https://domain.com/?', (t) => {
189+
t.plan(1)
190+
const domain = 'https://domain.com/?'
191+
const serialized = URLSerializer(new URL(domain))
192+
t.equal(serialized, domain)
193+
})

‎test/node-fetch/main.js

-22
Original file line numberDiff line numberDiff line change
@@ -1532,17 +1532,6 @@ describe('node-fetch', () => {
15321532
})
15331533
})
15341534

1535-
it('should NOT keep `?` sign in URL when no params are given', () => {
1536-
const url = `${base}question?`
1537-
const urlObject = new URL(url)
1538-
const request = new Request(urlObject)
1539-
return fetch(request).then(res => {
1540-
expect(res.url).to.equal(url.slice(0, -1))
1541-
expect(res.ok).to.be.true
1542-
expect(res.status).to.equal(200)
1543-
})
1544-
})
1545-
15461535
it('if params are given, do not modify anything', () => {
15471536
const url = `${base}question?a=1`
15481537
const urlObject = new URL(url)
@@ -1554,17 +1543,6 @@ describe('node-fetch', () => {
15541543
})
15551544
})
15561545

1557-
it('should NOT preserve the hash (#) symbol', () => {
1558-
const url = `${base}question?#`
1559-
const urlObject = new URL(url)
1560-
const request = new Request(urlObject)
1561-
return fetch(request).then(res => {
1562-
expect(res.url).to.equal(url.slice(0, -2))
1563-
expect(res.ok).to.be.true
1564-
expect(res.status).to.equal(200)
1565-
})
1566-
})
1567-
15681546
it('should support reading blob as text', () => {
15691547
return new Response('hello')
15701548
.blob()

0 commit comments

Comments
 (0)
Please sign in to comment.