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 cx: &mut js::context::JSContext,
45 local_name: LocalName,
46 prefix: Option<Prefix>,
47 document: &Document,
48 proto: Option<HandleObject>,
49 ) -> DomRoot<HTMLTemplateElement> {
50 let n = Node::reflect_node_with_proto(
51 cx,
52 Box::new(HTMLTemplateElement::new_inherited(
53 local_name, prefix, document,
54 )),
55 document,
56 proto,
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_enumerated_getter!(
90 ShadowRootSlotAssignment,
91 "shadowrootslotassignment",
92 "named" | "manual",
93 missing => "named",
94 invalid => "named"
95 );
96
97 make_atomic_setter!(SetShadowRootSlotAssignment, "shadowrootslotassignment");
99
100 make_bool_getter!(ShadowRootClonable, "shadowrootclonable");
102
103 make_bool_setter!(SetShadowRootClonable, "shadowrootclonable");
105
106 make_bool_getter!(ShadowRootSerializable, "shadowrootserializable");
108
109 make_bool_setter!(SetShadowRootSerializable, "shadowrootserializable");
111
112 fn Content(&self, cx: &mut js::context::JSContext) -> DomRoot<DocumentFragment> {
114 self.contents.or_init(|| {
115 let doc = self.owner_document();
118 let document_fragment = doc
120 .appropriate_template_contents_owner_document(CanGc::from_cx(cx))
121 .CreateDocumentFragment(cx);
122 document_fragment.set_host(self.upcast());
123 document_fragment
125 })
126 }
127}
128
129impl VirtualMethods for HTMLTemplateElement {
130 fn super_type(&self) -> Option<&dyn VirtualMethods> {
131 Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
132 }
133
134 fn adopting_steps(&self, cx: &mut JSContext, old_doc: &Document) {
136 self.super_type().unwrap().adopting_steps(cx, old_doc);
137 let doc = self
139 .owner_document()
140 .appropriate_template_contents_owner_document(CanGc::from_cx(cx));
141 let content = self.Content(cx);
143 Node::adopt(cx, content.upcast(), &doc);
144 }
145
146 fn cloning_steps(
148 &self,
149 cx: &mut JSContext,
150 copy: &Node,
151 maybe_doc: Option<&Document>,
152 clone_children: CloneChildrenFlag,
153 ) {
154 self.super_type()
155 .unwrap()
156 .cloning_steps(cx, copy, maybe_doc, clone_children);
157 if clone_children == CloneChildrenFlag::DoNotCloneChildren {
158 return;
160 }
161 let copy = copy.downcast::<HTMLTemplateElement>().unwrap();
162 let copy_contents = DomRoot::upcast::<Node>(copy.Content(cx));
164 let copy_contents_doc = copy_contents.owner_doc();
165 for child in self.Content(cx).upcast::<Node>().children() {
166 let copy_child = Node::clone(
167 cx,
168 &child,
169 Some(©_contents_doc),
170 CloneChildrenFlag::CloneChildren,
171 None,
172 );
173 copy_contents.AppendChild(cx, ©_child).unwrap();
174 }
175 }
176}