fix(fetch): observe header mutations during forEach

Refresh the sorted, combined header pairs after each callback while keeping
the iteration index. Deletions, updates and additions made by script now
affect subsequent visits as required by WebIDL pair iteration.

Cover mutations, Set-Cookie entries, reentrancy, author iterator overrides,
callback Proxies and abrupt completion in Window and Worker contexts. Extend
the callback realm regression to append and visit a header from an iframe.
This commit is contained in:
ldm0
2026-09-23 09:17:25 +08:00
parent 24dce69d22
commit 7f54b2e5ea
3 changed files with 5 additions and 2 deletions
@@ -129,7 +129,7 @@ pub(in crate::network_host::headers) fn headers_for_each_callback<'s>(
let mut index = 0;
loop {
// Script can change both the values and the sorted pair order.
let entries = normalized_headers_entries(&headers_entries(scope, this));
let entries = headers_entries(scope, this);
let Some((name, value)) = entries.get(index) else {
break;
};
@@ -7694,7 +7694,7 @@ async fn headers_for_each_visits_live_entries_in_window_and_worker() {
.filter(|check| check["pass"] != true)
.collect();
assert_eq!(result["state"], "pass", "worker={worker}: {failures:?}");
assert_eq!(checks.len(), 34, "worker={worker}");
assert_eq!(checks.len(), 36, "worker={worker}");
}
}
+3
View File
@@ -39,6 +39,9 @@ async function headersForEachProbe() {
headers.append('e', '5');
}
}, [['a', '1'], ['e', '5']]],
['empty-fields', [['a', '1'], ['b', '2'], ['b', ''], ['c', '3']], (headers, key) => {
if (key === 'a') headers.append('b', '');
}, [['a', '1'], ['b', '2, , '], ['c', '3']]],
['append-cookie', [['Set-Cookie', 'a=1'], ['set-cookie', 'b=2'], ['x-tail', 'end']], (headers, key, value) => {
if (key === 'set-cookie' && value === 'a=1') headers.append('Set-Cookie', 'c=3');
}, [['set-cookie', 'a=1'], ['set-cookie', 'b=2'], ['set-cookie', 'c=3'], ['x-tail', 'end']]],