From 7f54b2e5ea0c41864dc4178eddbb35abdf0703ff Mon Sep 17 00:00:00 2001 From: ldm0 Date: Fri, 18 Sep 2026 03:43:37 +0800 Subject: [PATCH] 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. --- moli-renderer-v8/src/network_host/headers/methods/iteration.rs | 2 +- moli-renderer-v8/src/script_vm/tests/webidl_fetch.rs | 2 +- moli-renderer-v8/tests/fixtures/headers-foreach.js | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/moli-renderer-v8/src/network_host/headers/methods/iteration.rs b/moli-renderer-v8/src/network_host/headers/methods/iteration.rs index 282c0b025..8d2acab1f 100644 --- a/moli-renderer-v8/src/network_host/headers/methods/iteration.rs +++ b/moli-renderer-v8/src/network_host/headers/methods/iteration.rs @@ -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; }; diff --git a/moli-renderer-v8/src/script_vm/tests/webidl_fetch.rs b/moli-renderer-v8/src/script_vm/tests/webidl_fetch.rs index 3accf3ad1..37cc945c9 100644 --- a/moli-renderer-v8/src/script_vm/tests/webidl_fetch.rs +++ b/moli-renderer-v8/src/script_vm/tests/webidl_fetch.rs @@ -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}"); } } diff --git a/moli-renderer-v8/tests/fixtures/headers-foreach.js b/moli-renderer-v8/tests/fixtures/headers-foreach.js index 427101326..9cba8cccb 100644 --- a/moli-renderer-v8/tests/fixtures/headers-foreach.js +++ b/moli-renderer-v8/tests/fixtures/headers-foreach.js @@ -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']]],