script/dom/
documentfragment.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;
7use stylo_atoms::Atom;
8
9use super::bindings::trace::HashMapTracedValues;
10use crate::dom::bindings::cell::DomRefCell;
11use crate::dom::bindings::codegen::Bindings::DocumentFragmentBinding::DocumentFragmentMethods;
12use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
13use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
14use crate::dom::bindings::error::{ErrorResult, Fallible};
15use crate::dom::bindings::inheritance::Castable;
16use crate::dom::bindings::root::{Dom, DomRoot};
17use crate::dom::bindings::str::DOMString;
18use crate::dom::document::Document;
19use crate::dom::element::Element;
20use crate::dom::html::htmlcollection::HTMLCollection;
21use crate::dom::node::{Node, NodeTraits};
22use crate::dom::nodelist::NodeList;
23use crate::dom::virtualmethods::VirtualMethods;
24use crate::dom::window::Window;
25use crate::script_runtime::CanGc;
26
27// https://dom.spec.whatwg.org/#documentfragment
28#[dom_struct]
29pub(crate) struct DocumentFragment {
30    node: Node,
31    /// Caches for the getElement methods
32    id_map: DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>>,
33}
34
35impl DocumentFragment {
36    /// Creates a new DocumentFragment.
37    pub(crate) fn new_inherited(document: &Document) -> DocumentFragment {
38        DocumentFragment {
39            node: Node::new_inherited(document),
40            id_map: DomRefCell::new(HashMapTracedValues::new()),
41        }
42    }
43
44    pub(crate) fn new(document: &Document, can_gc: CanGc) -> DomRoot<DocumentFragment> {
45        Self::new_with_proto(document, None, can_gc)
46    }
47
48    fn new_with_proto(
49        document: &Document,
50        proto: Option<HandleObject>,
51        can_gc: CanGc,
52    ) -> DomRoot<DocumentFragment> {
53        Node::reflect_node_with_proto(
54            Box::new(DocumentFragment::new_inherited(document)),
55            document,
56            proto,
57            can_gc,
58        )
59    }
60
61    pub(crate) fn id_map(&self) -> &DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>> {
62        &self.id_map
63    }
64}
65
66impl DocumentFragmentMethods<crate::DomTypeHolder> for DocumentFragment {
67    // https://dom.spec.whatwg.org/#dom-documentfragment-documentfragment
68    fn Constructor(
69        window: &Window,
70        proto: Option<HandleObject>,
71        can_gc: CanGc,
72    ) -> Fallible<DomRoot<DocumentFragment>> {
73        let document = window.Document();
74
75        Ok(DocumentFragment::new_with_proto(&document, proto, can_gc))
76    }
77
78    // https://dom.spec.whatwg.org/#dom-parentnode-children
79    fn Children(&self, can_gc: CanGc) -> DomRoot<HTMLCollection> {
80        let window = self.owner_window();
81        HTMLCollection::children(&window, self.upcast(), can_gc)
82    }
83
84    // https://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid
85    fn GetElementById(&self, id: DOMString) -> Option<DomRoot<Element>> {
86        let id = Atom::from(id);
87        self.id_map
88            .borrow()
89            .get(&id)
90            .map(|elements| DomRoot::from_ref(&*elements[0]))
91    }
92
93    // https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
94    fn GetFirstElementChild(&self) -> Option<DomRoot<Element>> {
95        self.upcast::<Node>().child_elements().next()
96    }
97
98    // https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
99    fn GetLastElementChild(&self) -> Option<DomRoot<Element>> {
100        self.upcast::<Node>()
101            .rev_children()
102            .filter_map(DomRoot::downcast::<Element>)
103            .next()
104    }
105
106    // https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
107    fn ChildElementCount(&self) -> u32 {
108        self.upcast::<Node>().child_elements().count() as u32
109    }
110
111    // https://dom.spec.whatwg.org/#dom-parentnode-prepend
112    fn Prepend(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
113        self.upcast::<Node>().prepend(nodes, can_gc)
114    }
115
116    // https://dom.spec.whatwg.org/#dom-parentnode-append
117    fn Append(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
118        self.upcast::<Node>().append(nodes, can_gc)
119    }
120
121    // https://dom.spec.whatwg.org/#dom-parentnode-replacechildren
122    fn ReplaceChildren(&self, nodes: Vec<NodeOrString>, can_gc: CanGc) -> ErrorResult {
123        self.upcast::<Node>().replace_children(nodes, can_gc)
124    }
125
126    // https://dom.spec.whatwg.org/#dom-parentnode-queryselector
127    fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<DomRoot<Element>>> {
128        self.upcast::<Node>().query_selector(selectors)
129    }
130
131    // https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
132    fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<DomRoot<NodeList>> {
133        self.upcast::<Node>().query_selector_all(selectors)
134    }
135}
136
137impl VirtualMethods for DocumentFragment {
138    fn super_type(&self) -> Option<&dyn VirtualMethods> {
139        Some(self.upcast::<Node>() as &dyn VirtualMethods)
140    }
141}