From bb4f121bade2eed9b1eb74f26fd7d7407d02ac35 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Mon, 7 Sep 2026 12:51:15 +0800 Subject: [PATCH] fix(window): preserve dynamic child target names --- .../context_host/child_frames/registry.rs | 11 ++- .../tests/dom_elements/dom_surface.rs | 70 +++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/moli-renderer-v8/src/native_bridge/context_host/child_frames/registry.rs b/moli-renderer-v8/src/native_bridge/context_host/child_frames/registry.rs index 8ba6ee1465..c1ce4f35fa 100644 --- a/moli-renderer-v8/src/native_bridge/context_host/child_frames/registry.rs +++ b/moli-renderer-v8/src/native_bridge/context_host/child_frames/registry.rs @@ -192,7 +192,14 @@ impl JsContextHost { let existing_document_policy = existing .as_ref() .map(|entry| entry.document_policy_container_snapshot()); - let name = self.dom_host().get_attribute(handle, "name"); + // The owner element's `name` attribute seeds the navigable target name only + // when the child navigable is created. Preserve later `window.name` writes + // across ordinary DOM-to-runtime record refreshes. + let name = existing + .as_ref() + .map(|entry| entry.name.clone()) + .unwrap_or_else(|| self.dom_host().get_attribute(handle, "name")) + .filter(|value| !value.is_empty()); let id = self.dom_host().get_attribute(handle, "id"); let credentialless = self .dom_host() @@ -332,7 +339,7 @@ impl JsContextHost { current_document_loader_id: existing.as_ref().and_then(|entry| { entry.current_document_loader_id().map(ToOwned::to_owned) }), - name: name.filter(|value| !value.is_empty()), + name, id: id.filter(|value| !value.is_empty()), attribute_bootstrap, pending_attribute_bootstrap_commit: diff --git a/moli-renderer-v8/src/script_vm/tests/dom_elements/dom_surface.rs b/moli-renderer-v8/src/script_vm/tests/dom_elements/dom_surface.rs index 6724b1d6a2..2910982ff6 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_elements/dom_surface.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_elements/dom_surface.rs @@ -8828,6 +8828,76 @@ frame.name = 'target'; assert_eq!(result, "[object Window]|true|object"); } + +#[tokio::test] +async fn child_window_name_assignment_updates_parent_named_access() { + let mut vm = new_storage_test_vm("https://dynamic-frame-name.test/"); + + let initial = vm + .eval( + r#" +(() => { + const frame = document.createElement('iframe'); + frame.id = 'frame'; + frame.name = 'bar'; + (document.body || document.documentElement || document).appendChild(frame); + return [ + 'bar' in window, + window.bar === frame.contentWindow, + frame.contentWindow.name + ].join('|'); +})() +"#, + ) + .expect("initial iframe browsing-context name should evaluate"); + assert_eq!(initial, "true|true|bar"); + + vm.eval( + r#" +document.getElementById('frame').srcdoc = + "