perf(dom): avoid per-element node clone when serializing template contents
The template.content bridge (#463) routed every element through content_source(), which called get_node().clone() to read the Copy template_contents field. That deep-cloned each element's Node (its attrs Vec plus a String per attribute) on every innerHTML/outerHTML/dump-html serialization, once per non-void element. template_contents is already destructured from the node in the serialize loop, so read it there directly. content_source() (inner_html path) now reads it through with_node() by reference. Serialization output is byte-identical; ~10% faster on serialization-heavy pages.
This commit is contained in:
1 parent
98f4efae1c
commit
becb3d941f
1 file changed
+12
-7
@@ -30,10 +30,12 @@ impl DomTree {
|
||||
// there rather than under the element (issue #463); for everything else it
|
||||
// is the node itself.
|
||||
fn content_source(&self, node_id: NodeId) -> NodeId {
|
||||
match self.get_node(node_id).map(|n| n.data) {
|
||||
Some(NodeData::Element { template_contents: Some(contents), .. }) => contents,
|
||||
_ => node_id,
|
||||
}
|
||||
self.with_node(node_id, |n| match &n.data {
|
||||
NodeData::Element { template_contents: Some(contents), .. } => Some(*contents),
|
||||
_ => None,
|
||||
})
|
||||
.flatten()
|
||||
.unwrap_or(node_id)
|
||||
}
|
||||
|
||||
// Children as work items in document order (top of the LIFO stack first).
|
||||
@@ -90,7 +92,7 @@ impl DomTree {
|
||||
buf.push_str(name);
|
||||
buf.push('>');
|
||||
}
|
||||
NodeData::Element { name, attrs, .. } => {
|
||||
NodeData::Element { name, attrs, template_contents, .. } => {
|
||||
let tag = name.local.as_ref();
|
||||
if include_self {
|
||||
buf.push('<');
|
||||
@@ -113,8 +115,11 @@ impl DomTree {
|
||||
stack.push(SerializeWork::CloseTag(tag.to_string()));
|
||||
}
|
||||
// A <template> serializes its contents document, not its
|
||||
// own (always empty) children — issue #463.
|
||||
for w in self.child_work(self.content_source(node_id)) {
|
||||
// own (always empty) children (issue #463). template_contents
|
||||
// is already in hand from this node, so read it directly
|
||||
// rather than re-fetching and cloning the node.
|
||||
let source = template_contents.unwrap_or(node_id);
|
||||
for w in self.child_work(source) {
|
||||
stack.push(w);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user