From 63c49d320cac7bf08821dacbb041ed3b2cb9ea2c Mon Sep 17 00:00:00 2001 From: ldm0 Date: Fri, 17 Jul 2026 06:56:39 +0800 Subject: [PATCH] fix(dom): synchronize element reflection targets --- moli-dom/src/native/element/mod.rs | 3 ++ moli-dom/src/native/element/tests.rs | 10 +---- moli-renderer-v8/src/native_bridge/element.rs | 45 ++++++++++++++++--- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/moli-dom/src/native/element/mod.rs b/moli-dom/src/native/element/mod.rs index f72fa055f6..5320795a59 100644 --- a/moli-dom/src/native/element/mod.rs +++ b/moli-dom/src/native/element/mod.rs @@ -73,6 +73,9 @@ fn is_element_reference_attribute(name: &str) -> bool { | "aria-flowto" | "aria-labelledby" | "aria-owns" + | "commandfor" + | "interestfor" + | "popovertarget" ) } diff --git a/moli-dom/src/native/element/tests.rs b/moli-dom/src/native/element/tests.rs index 9e69117ae0..4d90133452 100644 --- a/moli-dom/src/native/element/tests.rs +++ b/moli-dom/src/native/element/tests.rs @@ -211,10 +211,7 @@ fn aria_element_reference_state_is_owned_by_the_content_attribute() { None, String::new(), )); - assert_eq!( - element.explicit_element_references("aria-controls"), - None - ); + assert_eq!(element.explicit_element_references("aria-controls"), None); element.set_explicit_element_references("aria-controls", vec![NativeNodeId::new(8)]); assert!(element.set_attribute_ns( @@ -229,10 +226,7 @@ fn aria_element_reference_state_is_owned_by_the_content_attribute() { ); assert!(element.remove_attribute("aria-controls")); - assert_eq!( - element.explicit_element_references("aria-controls"), - None - ); + assert_eq!(element.explicit_element_references("aria-controls"), None); } #[test] diff --git a/moli-renderer-v8/src/native_bridge/element.rs b/moli-renderer-v8/src/native_bridge/element.rs index dbbbb9f2fc..bfbc3f3538 100644 --- a/moli-renderer-v8/src/native_bridge/element.rs +++ b/moli-renderer-v8/src/native_bridge/element.rs @@ -1851,7 +1851,7 @@ fn aria_element_reference_handle_for_owner( .or_else(|| (reference.runtime_ptr == owner_runtime_ptr).then_some(reference.handle)) } -fn aria_element_reference_is_in_valid_scope( +fn element_reference_is_in_valid_scope( runtime: &JsContextHost, owner: DomHandle, candidate: DomHandle, @@ -1882,7 +1882,7 @@ fn aria_element_reference_is_in_valid_scope( } } -fn aria_element_by_id_including_disconnected( +fn element_by_id_including_disconnected( runtime: &JsContextHost, owner: DomHandle, id: &str, @@ -1906,6 +1906,39 @@ fn aria_element_by_id_including_disconnected( None } +pub(in crate::native_bridge::element) fn reflected_element_attribute_handle( + runtime: &JsContextHost, + owner: DomHandle, + attribute: &str, +) -> Option { + let candidate = match runtime + .dom_host() + .explicit_element_references(owner, attribute) + { + Some(references) => references.into_iter().next()?, + None => { + let id = runtime.dom_host().get_attribute(owner, attribute)?; + element_by_id_including_disconnected(runtime, owner, &id)? + } + }; + if !element_reference_is_in_valid_scope(runtime, owner, candidate) { + return None; + } + runtime + .dom_host() + .resolve_reference_target_chain(candidate) + .map(|_| candidate) +} + +pub(in crate::native_bridge::element) fn resolved_reflected_element_attribute_handle( + runtime: &JsContextHost, + owner: DomHandle, + attribute: &str, +) -> Option { + reflected_element_attribute_handle(runtime, owner, attribute) + .and_then(|candidate| runtime.dom_host().resolve_reference_target_chain(candidate)) +} + fn aria_element_reference_content_handles( runtime: &JsContextHost, owner: DomHandle, @@ -1914,7 +1947,7 @@ fn aria_element_reference_content_handles( let value = runtime.dom_host().get_attribute(owner, attribute)?; if aria_element_reference_is_singular(attribute) { return Some( - aria_element_by_id_including_disconnected(runtime, owner, &value) + element_by_id_including_disconnected(runtime, owner, &value) .into_iter() .collect(), ); @@ -1923,7 +1956,7 @@ fn aria_element_reference_content_handles( value .split([' ', '\t', '\n', '\r', '\u{000c}']) .filter(|token| !token.is_empty()) - .filter_map(|token| aria_element_by_id_including_disconnected(runtime, owner, token)) + .filter_map(|token| element_by_id_including_disconnected(runtime, owner, token)) .collect(), ) } @@ -1940,9 +1973,7 @@ fn aria_element_reference_handles( Some(references) => Some( references .into_iter() - .filter(|candidate| { - aria_element_reference_is_in_valid_scope(runtime, owner, *candidate) - }) + .filter(|candidate| element_reference_is_in_valid_scope(runtime, owner, *candidate)) .collect(), ), None => aria_element_reference_content_handles(runtime, owner, attribute),