From 650a15fa7e8a682efb3165835cb5d0ca30f612ac Mon Sep 17 00:00:00 2001 From: ldm0 Date: Wed, 7 Oct 2026 03:40:40 +0800 Subject: [PATCH] fix(streams): preserve stored errors across array prototype changes Create the internal error container with an own element directly. Setting index zero on an empty array could consult an author-defined inherited property and replace the original rejection value. Cover Response.clone().text() with a read-only inherited array index. Validation: cargo fmt --all; cargo clippy --workspace --all-targets --all-features -- -D warnings; cargo nextest run --no-fail-fast (19,655 passed, 16 skipped); cargo build --release -p moli. --- .../stream_adapter/readable_state.rs | 5 +++-- .../tests/extracted/realms_and_teardown.rs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/moli-renderer-v8/src/context_bootstrap/stream_adapter/readable_state.rs b/moli-renderer-v8/src/context_bootstrap/stream_adapter/readable_state.rs index 1115ea7c1c..212b24f8e4 100644 --- a/moli-renderer-v8/src/context_bootstrap/stream_adapter/readable_state.rs +++ b/moli-renderer-v8/src/context_bootstrap/stream_adapter/readable_state.rs @@ -197,8 +197,9 @@ pub(crate) fn error_stream<'s>( if readable_stream_is_byte_stream(scope, stream) { reset_byte_stream_pending_pull_intos(scope, stream); } - let error_entry = v8::Array::new(scope, 1); - let _ = error_entry.set_index(scope, 0, reason); + // Initialize an own element directly, without consulting author-modified + // Array.prototype indices. This also preserves an undefined rejection value. + let error_entry = v8::Array::new_with_elements(scope, &[reason]); set_stream_slot_value( scope, stream, diff --git a/moli-renderer-v8/src/script_vm/tests/extracted/realms_and_teardown.rs b/moli-renderer-v8/src/script_vm/tests/extracted/realms_and_teardown.rs index 78769afaea..98b32e13cc 100644 --- a/moli-renderer-v8/src/script_vm/tests/extracted/realms_and_teardown.rs +++ b/moli-renderer-v8/src/script_vm/tests/extracted/realms_and_teardown.rs @@ -373,6 +373,24 @@ fn response_body_and_clones_preserve_primitive_errors_after_gc() { } } +#[test] +fn response_body_preserves_error_with_an_inherited_read_only_array_index() { + let (mut vm, body_source_id) = new_vm_with_pending_response_for_teardown_test(); + vm.eval( + "Object.defineProperty(Array.prototype, '0', {\n\ + value: 'inherited value', writable: false, configurable: true\n\ + });", + ) + .unwrap(); + error_response_for_teardown_test(&mut vm, body_source_id); + vm.eval( + "globalThis.sameError = false;\n\ + response.clone().text().catch(error => { sameError = error === bodyFailure; });", + ) + .unwrap(); + assert_eq!(vm.eval("sameError").unwrap(), "true"); +} + fn new_vm_with_evaluated_module_for_teardown_test() -> StandaloneScriptVmHarness { let mut vm = new_storage_test_vm("https://module-teardown.test/"); let url = vm.document_runtime.document_url().clone();