Skip to content

Commit af14557

Browse files
committed
fix(fetch): default Request priority on the inner request
Move the "auto" default from the RequestInit WebIDL converter to makeRequest so an omitted init stays empty after conversion. Restores the Object.keys empty-init check. Assisted by Cursor Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
1 parent d7f3fac commit af14557

2 files changed

Lines changed: 9 additions & 42 deletions

File tree

‎lib/web/fetch/request.js‎

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,6 @@ const { getMaxListeners, setMaxListeners, defaultMaxListeners } = require('node:
3030

3131
const kAbortController = Symbol('abortController')
3232

33-
/**
34-
* Fetch's "If init is not empty" check is based on user-specified
35-
* RequestInit members, not dictionary defaults. undici's `priority`
36-
* member defaults to `"auto"`, so `Object.keys(convertedInit)` is
37-
* never empty and would otherwise force the expensive header
38-
* clone/clear/re-append path on every `fetch(url)` / `new Request(url)`.
39-
*
40-
* Matches the spec / Servo / Chromium "any members present" test.
41-
*
42-
* @param {object | null | undefined} init
43-
* @returns {boolean}
44-
*/
45-
function requestInitHasUserMembers (init) {
46-
return init != null && (
47-
init.method !== undefined ||
48-
init.headers !== undefined ||
49-
init.body !== undefined ||
50-
init.referrer !== undefined ||
51-
init.referrerPolicy !== undefined ||
52-
init.mode !== undefined ||
53-
init.credentials !== undefined ||
54-
init.cache !== undefined ||
55-
init.redirect !== undefined ||
56-
init.integrity !== undefined ||
57-
init.keepalive !== undefined ||
58-
init.signal !== undefined ||
59-
'window' in init ||
60-
init.duplex !== undefined ||
61-
init.dispatcher !== undefined ||
62-
init.priority !== undefined
63-
)
64-
}
65-
6633
const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => {
6734
signal.removeEventListener('abort', abort)
6835
})
@@ -149,8 +116,6 @@ class Request {
149116
webidl.argumentLengthCheck(arguments, 1, prefix)
150117

151118
input = webidl.converters.RequestInfo(input)
152-
// Capture this before WebIDL conversion fills dictionary defaults.
153-
const initHasKey = requestInitHasUserMembers(init)
154119
init = webidl.converters.RequestInit(init)
155120

156121
// 1. Let request be null.
@@ -276,6 +241,8 @@ class Request {
276241
urlList: [...request.urlList]
277242
})
278243

244+
const initHasKey = Object.keys(init).length !== 0
245+
279246
// 13. If init is not empty, then:
280247
if (initHasKey) {
281248
// 1. If request’s mode is "navigate", then set it to "same-origin".
@@ -956,7 +923,7 @@ function makeRequest (init) {
956923
serviceWorkers: init.serviceWorkers ?? 'all',
957924
initiator: init.initiator ?? '',
958925
destination: init.destination ?? '',
959-
priority: init.priority ?? null,
926+
priority: init.priority ?? 'auto',
960927
origin: init.origin ?? 'client',
961928
policyContainer: init.policyContainer ?? 'client',
962929
referrer: init.referrer ?? 'client',
@@ -1162,8 +1129,7 @@ webidl.converters.RequestInit = webidl.dictionaryConverter([
11621129
{
11631130
key: 'priority',
11641131
converter: webidl.converters.DOMString,
1165-
allowedValues: ['high', 'low', 'auto'],
1166-
defaultValue: () => 'auto'
1132+
allowedValues: ['high', 'low', 'auto']
11671133
}
11681134
])
11691135

‎test/fetch/request.js‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,10 +420,11 @@ test('request.referrer', (t) => {
420420
}
421421
})
422422

423-
// Dictionary defaults (undici's priority: "auto") must not make an omitted
424-
// RequestInit count as non-empty. That used to force a header clone/clear
425-
// on every fetch(url) / new Request(url) and reset copied request state.
426-
test('omitted RequestInit is empty even though priority defaults to auto', (t) => {
423+
// RequestInit.priority must not have a WebIDL default. A converter default
424+
// of "auto" made every omitted init non-empty (Object.keys never empty),
425+
// which cloned/cleared headers on fetch(url) / new Request(url) and reset
426+
// copied request state.
427+
test('omitted RequestInit is empty', (t) => {
427428
const parent = new Request('http://localhost/a', {
428429
method: 'POST',
429430
body: 'hi',

0 commit comments

Comments
 (0)