script/dom/html/
htmltemplateelement.rs1use dom_struct::dom_struct;
6use html5ever::{LocalName, Prefix};
7use js::context::JSContext;
8use js::rust::HandleObject;
9
10use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
11use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
12use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
13use crate::dom::bindings::inheritance::Castable;
14use crate::dom::bindings::root::{DomRoot, MutNullableDom};
15use crate::dom::bindings::str::DOMString;
16use crate::dom::document::Document;
17use crate::dom::documentfragment::DocumentFragment;
18use crate::dom::html::htmlelement::HTMLElement;
19use crate::dom::node::{CloneChildrenFlag, Node, NodeTraits};
20use crate::dom::virtualmethods::VirtualMethods;
21use crate::script_runtime::CanGc;
22
23#[dom_struct]
24pub(crate) struct HTMLTemplateElement {
25 htmlelement: HTMLElement,
26
27 contents: MutNullableDom<DocumentFragment>,
29}
30
31impl HTMLTemplateElement {
32 fn new_inherited(
33 local_name: LocalName,
34 prefix: Option<Prefix>,
35 document: &Document,
36 ) -> HTMLTemplateElement {
37 HTMLTemplateElement {
38 htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
39 contents: MutNullableDom::new(None),
40 }
41 }
42
43 pub(crate) fn new(
44 local_name: LocalName,
45 prefix: Option<Prefix>,
46 document: &Document,
47 proto: Option<HandleObject>,
48 can_gc: CanGc,
49 ) -> DomRoot<HTMLTemplateElement> {
50 let n = Node::reflect_node_with_proto(
51 Box::new(HTMLTemplateElement::new_inherited(
52 local_name, prefix, document,
53 )),
54 document,
55 proto,
56 can_gc,
57 );
58
59 n.upcast::<Node>().set_weird_parser_insertion_mode();
60 n
61 }
62
63 pub(crate) fn set_contents(&self, document_fragment: Option<&DocumentFragment>) {
64 self.contents.set(document_fragment);
65 }
66}
67
68#[expect(unused_doc_comments)]
69impl HTMLTemplateElementMethods<crate::DomTypeHolder> for HTMLTemplateElement {
70 make_enumerated_getter!(
72 ShadowRootMode,
73 "shadowrootmode",
74 "open" | "closed",
75 missing => "",
76 invalid => ""
77 );
78
79 make_atomic_setter!(SetShadowRootMode, "shadowrootmode");
81
82 make_bool_getter!(ShadowRootDelegatesFocus, "shadowrootdelegatesfocus");
84
85 make_bool_setter!(SetShadowRootDelegatesFocus, "shadowrootdelegatesfocus");
87
88 make_bool_getter!(ShadowRootClonable, "shadowrootclonable");
90
91 make_bool_setter!(SetShadowRootClonable, "shadowrootclonable");
93
94 make_bool_getter!(ShadowRootSerializable, "shadowrootserializable");
96
97 make_bool_setter!(SetShadowRootSerializable, "shadowrootserializable");
99
100 fn Content(&self, can_gc: CanGc) -> DomRoot<DocumentFragment> {
102 self.contents.or_init(|| {
103 let doc = self.owner_document();
106 let document_fragment = doc
108 .appropriate_template_contents_owner_document(can_gc)
109 .CreateDocumentFragment(can_gc);
110 document_fragment.set_host(self.upcast());
111 document_fragment
113 })
114 }
115}
116
117impl VirtualMethods for HTMLTemplateElement {
118 fn super_type(&self) -> Option<&dyn VirtualMethods> {
119 Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
120 }
121
122 fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
124 self.super_type().unwrap().adopting_steps(old_doc, can_gc);
125 let doc = self
127 .owner_document()
128 .appropriate_template_contents_owner_document(CanGc::note());
129 Node::adopt(self.Content(CanGc::note()).upcast(), &doc, can_gc);
131 }
132
133 fn cloning_steps(
135 &self,
136 cx: &mut JSContext,
137 copy: &Node,
138 maybe_doc: Option<&Document>,
139 clone_children: CloneChildrenFlag,
140 ) {
141 self.super_type()
142 .unwrap()
143 .cloning_steps(cx, copy, maybe_doc, clone_children);
144 if clone_children == CloneChildrenFlag::DoNotCloneChildren {
145 return;
147 }
148 let copy = copy.downcast::<HTMLTemplateElement>().unwrap();
149 let copy_contents = DomRoot::upcast::<Node>(copy.Content(CanGc::from_cx(cx)));
151 let copy_contents_doc = copy_contents.owner_doc();
152 for child in self.Content(CanGc::from_cx(cx)).upcast::<Node>().children() {
153 let copy_child = Node::clone(
154 cx,
155 &child,
156 Some(©_contents_doc),
157 CloneChildrenFlag::CloneChildren,
158 None,
159 );
160 copy_contents
161 .AppendChild(©_child, CanGc::from_cx(cx))
162 .unwrap();
163 }
164 }
165}