fix(window): preserve dynamic child target names

This commit is contained in:
ldm0
2026-09-07 12:51:15 +08:00
parent db98c42087
commit bb4f121bad
2 changed files with 79 additions and 2 deletions
@@ -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:
@@ -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 =
"<script>window.name = 'foo'<\/script>";
"#,
)
.expect("child window.name assignment should queue through srcdoc navigation");
run_realm_prerequisite_then_expected_child_frame_semantic_turn_for_test(
&mut vm,
ChildFrameSemanticTurnKind::NavigationCommit,
"child window.name assignment srcdoc should commit before parser work",
)
.await;
run_realm_prerequisite_then_expected_child_frame_semantic_turn_for_test(
&mut vm,
ChildFrameSemanticTurnKind::DocumentScriptReady,
"child window.name assignment should run as parser script",
)
.await;
run_child_document_lifecycle_and_host_load_for_test(
&mut vm,
"child window.name assignment srcdoc",
)
.await;
let result = vm
.eval(
r#"
(() => {
const frame = document.getElementById('frame');
return [
'foo' in window,
window.foo === frame.contentWindow,
'bar' in window,
window.bar === undefined,
frame.name,
frame.contentWindow.name
].join('|');
})()
"#,
)
.expect("dynamic iframe browsing-context name should evaluate");
assert_eq!(result, "true|true|false|true|bar|foo");
}
#[test]
fn iframe_in_shadow_tree_is_not_a_named_window_property() {
let mut vm = new_storage_test_vm("https://shadow-iframe-named-property.test/");