diff --git a/components/script/dom/xpathresult.rs b/components/script/dom/xpathresult.rs index f4a9ae7a31b..a636419cf61 100644 --- a/components/script/dom/xpathresult.rs +++ b/components/script/dom/xpathresult.rs @@ -54,7 +54,7 @@ impl TryFrom for XPathResultType { } } -#[derive(JSTraceable, MallocSizeOf)] +#[derive(JSTraceable, MallocSizeOf, Debug)] pub(crate) enum XPathResultValue { Boolean(bool), /// A IEEE-754 double-precision floating point number diff --git a/components/script/xpath/eval_function.rs b/components/script/xpath/eval_function.rs index e6666713359..53c14944474 100644 --- a/components/script/xpath/eval_function.rs +++ b/components/script/xpath/eval_function.rs @@ -165,10 +165,13 @@ impl Evaluatable for CoreFunction { let args = args_normalized.split(' '); let document = context.context_node.owner_doc(); - let result = args - .flat_map(|arg| document.get_element_by_id(&Atom::from(arg))) - .map(|e| DomRoot::from_ref(e.upcast::())); - Ok(Value::Nodeset(result.collect())) + let mut result = Vec::new(); + for arg in args { + for element in document.get_elements_with_id(&Atom::from(arg)).iter() { + result.push(DomRoot::from_ref(element.upcast::())); + } + } + Ok(Value::Nodeset(result)) }, CoreFunction::LocalName(expr_opt) => { let node = match expr_opt { diff --git a/components/script/xpath/eval_value.rs b/components/script/xpath/eval_value.rs index de6c13e3454..66f1b92c6d4 100644 --- a/components/script/xpath/eval_value.rs +++ b/components/script/xpath/eval_value.rs @@ -8,7 +8,6 @@ use std::{fmt, string}; use crate::dom::bindings::codegen::Bindings::NodeBinding::Node_Binding::NodeMethods; use crate::dom::bindings::root::DomRoot; -use crate::dom::bindings::utils::AsVoidPtr; use crate::dom::node::Node; /// The primary types of values that an XPath expression returns as a result. @@ -216,7 +215,7 @@ impl NodesetHelpers for Vec> { } fn document_order(&self) -> Vec> { let mut nodes: Vec> = self.clone(); - if nodes.len() == 1 { + if nodes.len() <= 1 { return nodes; } @@ -233,10 +232,13 @@ impl NodesetHelpers for Vec> { nodes } fn document_order_unique(&self) -> Vec> { - let mut nodes: Vec> = self.document_order(); + let mut seen = HashSet::new(); + let unique_nodes: Vec> = self + .iter() + .filter(|node| seen.insert(node.to_opaque())) + .cloned() + .collect(); - nodes.dedup_by_key(|n| n.as_void_ptr()); - - nodes + unique_nodes.document_order() } } diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 3a7faebb345..60d4d4fbe97 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -630517,6 +630517,13 @@ {} ] ], + "fn-id.html": [ + "304d38985a0cf2df8b4365cae497292ef36d3599", + [ + null, + {} + ] + ], "fn-lang.html": [ "1fbd0a2ee4d419275c6d78f54e3425135cf838a1", [ diff --git a/tests/wpt/tests/domxpath/fn-id.html b/tests/wpt/tests/domxpath/fn-id.html new file mode 100644 index 00000000000..304d38985a0 --- /dev/null +++ b/tests/wpt/tests/domxpath/fn-id.html @@ -0,0 +1,48 @@ + + + + + + + \ No newline at end of file