script/dom/
xpathexpression.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::rust::HandleObject;
7
8use crate::dom::bindings::codegen::Bindings::XPathExpressionBinding::XPathExpressionMethods;
9use crate::dom::bindings::error::{Error, Fallible};
10use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
11use crate::dom::bindings::root::{Dom, DomRoot};
12use crate::dom::node::Node;
13use crate::dom::window::Window;
14use crate::dom::xpathresult::{XPathResult, XPathResultType};
15use crate::script_runtime::CanGc;
16use crate::xpath::{Expr, evaluate_parsed_xpath};
17
18#[dom_struct]
19pub(crate) struct XPathExpression {
20    reflector_: Reflector,
21    window: Dom<Window>,
22    #[no_trace]
23    parsed_expression: Expr,
24}
25
26impl XPathExpression {
27    fn new_inherited(window: &Window, parsed_expression: Expr) -> XPathExpression {
28        XPathExpression {
29            reflector_: Reflector::new(),
30            window: Dom::from_ref(window),
31            parsed_expression,
32        }
33    }
34
35    pub(crate) fn new(
36        window: &Window,
37        proto: Option<HandleObject>,
38        can_gc: CanGc,
39        parsed_expression: Expr,
40    ) -> DomRoot<XPathExpression> {
41        reflect_dom_object_with_proto(
42            Box::new(XPathExpression::new_inherited(window, parsed_expression)),
43            window,
44            proto,
45            can_gc,
46        )
47    }
48}
49
50impl XPathExpressionMethods<crate::DomTypeHolder> for XPathExpression {
51    /// <https://dom.spec.whatwg.org/#dom-xpathexpression-evaluate>
52    fn Evaluate(
53        &self,
54        context_node: &Node,
55        result_type_num: u16,
56        _result: Option<&XPathResult>,
57        can_gc: CanGc,
58    ) -> Fallible<DomRoot<XPathResult>> {
59        let result_type = XPathResultType::try_from(result_type_num)
60            .map_err(|()| Error::Type("Invalid XPath result type".to_string()))?;
61
62        let global = self.global();
63        let window = global.as_window();
64
65        let result_value = evaluate_parsed_xpath(&self.parsed_expression, context_node)
66            .map_err(|_e| Error::Operation)?;
67
68        // TODO(vlindhol): support putting results into mutable `_result` as per the spec
69        Ok(XPathResult::new(
70            window,
71            None,
72            can_gc,
73            result_type,
74            result_value.into(),
75        ))
76    }
77}