script/dom/
xpathexpression.rs1use std::rc::Rc;
6
7use dom_struct::dom_struct;
8use js::rust::HandleObject;
9use xpath::{Error as XPathError, Expression, evaluate_parsed_xpath};
10
11use crate::dom::bindings::codegen::Bindings::XPathExpressionBinding::XPathExpressionMethods;
12use crate::dom::bindings::codegen::Bindings::XPathNSResolverBinding::XPathNSResolver;
13use crate::dom::bindings::error::{Error, Fallible};
14use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
15use crate::dom::bindings::root::{Dom, DomRoot};
16use crate::dom::node::Node;
17use crate::dom::window::Window;
18use crate::dom::xpathresult::{XPathResult, XPathResultType};
19use crate::script_runtime::CanGc;
20use crate::xpath::{XPathImplementation, XPathWrapper};
21
22#[dom_struct]
23pub(crate) struct XPathExpression {
24 reflector_: Reflector,
25 window: Dom<Window>,
26 #[no_trace]
27 parsed_expression: Expression,
28}
29
30impl XPathExpression {
31 fn new_inherited(window: &Window, parsed_expression: Expression) -> XPathExpression {
32 XPathExpression {
33 reflector_: Reflector::new(),
34 window: Dom::from_ref(window),
35 parsed_expression,
36 }
37 }
38
39 pub(crate) fn new(
40 window: &Window,
41 proto: Option<HandleObject>,
42 can_gc: CanGc,
43 parsed_expression: Expression,
44 ) -> DomRoot<XPathExpression> {
45 reflect_dom_object_with_proto(
46 Box::new(XPathExpression::new_inherited(window, parsed_expression)),
47 window,
48 proto,
49 can_gc,
50 )
51 }
52
53 pub(crate) fn evaluate_internal(
54 &self,
55 context_node: &Node,
56 result_type_num: u16,
57 result: Option<&XPathResult>,
58 resolver: Option<Rc<XPathNSResolver>>,
59 can_gc: CanGc,
60 ) -> Fallible<DomRoot<XPathResult>> {
61 let result_type = XPathResultType::try_from(result_type_num)
62 .map_err(|()| Error::Type("Invalid XPath result type".to_string()))?;
63
64 let global = self.global();
65 let window = global.as_window();
66
67 let result_value = evaluate_parsed_xpath::<XPathImplementation>(
68 &self.parsed_expression,
69 DomRoot::from_ref(context_node).into(),
70 resolver.map(XPathWrapper),
71 )
72 .map_err(|error| match error {
73 XPathError::JsException(exception) => exception,
74 _ => Error::Operation,
75 })?
76 .into();
77
78 if let Some(result) = result {
79 result.reinitialize_with(result_type, result_value);
82 Ok(DomRoot::from_ref(result))
83 } else {
84 Ok(XPathResult::new(
85 window,
86 None,
87 can_gc,
88 result_type,
89 result_value,
90 ))
91 }
92 }
93}
94
95impl XPathExpressionMethods<crate::DomTypeHolder> for XPathExpression {
96 fn Evaluate(
98 &self,
99 context_node: &Node,
100 result_type_num: u16,
101 result: Option<&XPathResult>,
102 can_gc: CanGc,
103 ) -> Fallible<DomRoot<XPathResult>> {
104 self.evaluate_internal(context_node, result_type_num, result, None, can_gc)
105 }
106}