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_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, cx: &mut js::context::JSContext) -> DomRoot<DocumentFragment> {
102 self.contents.or_init(|| {
103 let doc = self.owner_document();
106 let document_fragment = doc
108 .appropriate_template_contents_owner_document(CanGc::from_cx(cx))
109 .CreateDocumentFragment(cx);
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, cx: &mut JSContext, old_doc: &Document) {
124 self.super_type().unwrap().adopting_steps(cx, old_doc);
125 let doc = self
127 .owner_document()
128 .appropriate_template_contents_owner_document(CanGc::from_cx(cx));
129 let content = self.Content(cx);
131 Node::adopt(cx, content.upcast(), &doc);
132 }
133
134 fn cloning_steps(
136 &self,
137 cx: &mut JSContext,
138 copy: &Node,
139 maybe_doc: Option<&Document>,
140 clone_children: CloneChildrenFlag,
141 ) {
142 self.super_type()
143 .unwrap()
144 .cloning_steps(cx, copy, maybe_doc, clone_children);
145 if clone_children == CloneChildrenFlag::DoNotCloneChildren {
146 return;
148 }
149 let copy = copy.downcast::<HTMLTemplateElement>().unwrap();
150 let copy_contents = DomRoot::upcast::<Node>(copy.Content(cx));
152 let copy_contents_doc = copy_contents.owner_doc();
153 for child in self.Content(cx).upcast::<Node>().children() {
154 let copy_child = Node::clone(
155 cx,
156 &child,
157 Some(©_contents_doc),
158 CloneChildrenFlag::CloneChildren,
159 None,
160 );
161 copy_contents.AppendChild(cx, ©_child).unwrap();
162 }
163 }
164}