Files
servo/components/script/dom/html/htmltemplateelement.rs
Tim van der Lippe 5b6509f279 script: Implement customElementRegistry support for document.importNode (#41385)
This method now allows you to pass in a custom registry. The registry
isn't used yet for callers, since we don't support scoped registries.
However, as we now pass in the registry to `Node::clone`, we set the
registry when creating elements and cloning them.

As such, various tests start passing where we set the registry. Some
tests started failing, but they rely on scoped registries which we don't
support yet. These tests thus flipped: those that were erroneously
failing are now passing and vice versa.

Part of #34319

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
2025-12-19 09:01:08 +00:00

157 lines
5.7 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix};
use js::rust::HandleObject;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::document::Document;
use crate::dom::documentfragment::DocumentFragment;
use crate::dom::html::htmlelement::HTMLElement;
use crate::dom::node::{CloneChildrenFlag, Node, NodeTraits};
use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;
#[dom_struct]
pub(crate) struct HTMLTemplateElement {
htmlelement: HTMLElement,
/// <https://html.spec.whatwg.org/multipage/#template-contents>
contents: MutNullableDom<DocumentFragment>,
}
impl HTMLTemplateElement {
fn new_inherited(
local_name: LocalName,
prefix: Option<Prefix>,
document: &Document,
) -> HTMLTemplateElement {
HTMLTemplateElement {
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
contents: MutNullableDom::new(None),
}
}
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn new(
local_name: LocalName,
prefix: Option<Prefix>,
document: &Document,
proto: Option<HandleObject>,
can_gc: CanGc,
) -> DomRoot<HTMLTemplateElement> {
let n = Node::reflect_node_with_proto(
Box::new(HTMLTemplateElement::new_inherited(
local_name, prefix, document,
)),
document,
proto,
can_gc,
);
n.upcast::<Node>().set_weird_parser_insertion_mode();
n
}
pub(crate) fn set_contents(&self, document_fragment: Option<&DocumentFragment>) {
self.contents.set(document_fragment);
}
}
#[expect(unused_doc_comments)]
impl HTMLTemplateElementMethods<crate::DomTypeHolder> for HTMLTemplateElement {
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootmode>
make_enumerated_getter!(
ShadowRootMode,
"shadowrootmode",
"open" | "closed",
missing => "",
invalid => ""
);
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootmode>
make_atomic_setter!(SetShadowRootMode, "shadowrootmode");
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootdelegatesfocus>
make_bool_getter!(ShadowRootDelegatesFocus, "shadowrootdelegatesfocus");
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootdelegatesfocus>
make_bool_setter!(SetShadowRootDelegatesFocus, "shadowrootdelegatesfocus");
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootclonable>
make_bool_getter!(ShadowRootClonable, "shadowrootclonable");
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootclonable>
make_bool_setter!(SetShadowRootClonable, "shadowrootclonable");
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootserializable>
make_bool_getter!(ShadowRootSerializable, "shadowrootserializable");
/// <https://html.spec.whatwg.org/multipage/#dom-template-shadowrootserializable>
make_bool_setter!(SetShadowRootSerializable, "shadowrootserializable");
/// <https://html.spec.whatwg.org/multipage/#dom-template-content>
fn Content(&self, can_gc: CanGc) -> DomRoot<DocumentFragment> {
self.contents.or_init(|| {
let doc = self.owner_document();
doc.appropriate_template_contents_owner_document(can_gc)
.CreateDocumentFragment(can_gc)
})
}
}
impl VirtualMethods for HTMLTemplateElement {
fn super_type(&self) -> Option<&dyn VirtualMethods> {
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
/// <https://html.spec.whatwg.org/multipage/#template-adopting-steps>
fn adopting_steps(&self, old_doc: &Document, can_gc: CanGc) {
self.super_type().unwrap().adopting_steps(old_doc, can_gc);
// Step 1.
let doc = self
.owner_document()
.appropriate_template_contents_owner_document(CanGc::note());
// Step 2.
Node::adopt(self.Content(CanGc::note()).upcast(), &doc, can_gc);
}
/// <https://html.spec.whatwg.org/multipage/#the-template-element:concept-node-clone-ext>
fn cloning_steps(
&self,
copy: &Node,
maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag,
can_gc: CanGc,
) {
self.super_type()
.unwrap()
.cloning_steps(copy, maybe_doc, clone_children, can_gc);
if clone_children == CloneChildrenFlag::DoNotCloneChildren {
// Step 1.
return;
}
let copy = copy.downcast::<HTMLTemplateElement>().unwrap();
// Steps 2-3.
let copy_contents = DomRoot::upcast::<Node>(copy.Content(CanGc::note()));
let copy_contents_doc = copy_contents.owner_doc();
for child in self.Content(CanGc::note()).upcast::<Node>().children() {
let copy_child = Node::clone(
&child,
Some(&copy_contents_doc),
CloneChildrenFlag::CloneChildren,
None,
CanGc::note(),
);
copy_contents.AppendChild(&copy_child, can_gc).unwrap();
}
}
}