Skip to content

Commit f54a307

Browse files
committed
Avoid dropping template contents nodes recursively.
1 parent 3e9fe22 commit f54a307

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

rcdom/lib.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub enum NodeData {
8989
/// For HTML \<template\> elements, the [template contents].
9090
///
9191
/// [template contents]: https://html.spec.whatwg.org/multipage/#template-contents
92-
template_contents: Option<Handle>,
92+
template_contents: RefCell<Option<Handle>>,
9393

9494
/// Whether the node is a [HTML integration point].
9595
///
@@ -131,6 +131,11 @@ impl Drop for Node {
131131
while let Some(node) = nodes.pop() {
132132
let children = mem::replace(&mut *node.children.borrow_mut(), vec![]);
133133
nodes.extend(children.into_iter());
134+
if let NodeData::Element { ref template_contents, .. } = node.data {
135+
if let Some(template_contents) = template_contents.borrow_mut().take() {
136+
nodes.push(template_contents);
137+
}
138+
}
134139
}
135140
}
136141
}
@@ -226,11 +231,11 @@ impl TreeSink for RcDom {
226231

227232
fn get_template_contents(&mut self, target: &Handle) -> Handle {
228233
if let NodeData::Element {
229-
template_contents: Some(ref contents),
234+
ref template_contents,
230235
..
231236
} = target.data
232237
{
233-
contents.clone()
238+
template_contents.borrow().as_ref().expect("not a template element!").clone()
234239
} else {
235240
panic!("not a template element!")
236241
}
@@ -260,11 +265,11 @@ impl TreeSink for RcDom {
260265
Node::new(NodeData::Element {
261266
name: name,
262267
attrs: RefCell::new(attrs),
263-
template_contents: if flags.template {
268+
template_contents: RefCell::new(if flags.template {
264269
Some(Node::new(NodeData::Document))
265270
} else {
266271
None
267-
},
272+
}),
268273
mathml_annotation_xml_integration_point: flags.mathml_annotation_xml_integration_point,
269274
})
270275
}

rcdom/tests/html-driver.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,14 @@ fn from_utf8() {
1616
"<html><head><title>Test</title></head><body></body></html>"
1717
);
1818
}
19+
20+
#[test]
21+
fn many_templates() {
22+
let mut body = String::new();
23+
for _ in 1..10000 {
24+
body.push_str("<template>");
25+
}
26+
let _ = driver::parse_document(RcDom::default(), Default::default())
27+
.from_utf8()
28+
.one(body.as_bytes());
29+
}

rcdom/tests/html-tree-builder.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,17 @@ fn serialize(buf: &mut String, indent: usize, handle: Handle) {
146146
}
147147

148148
if let NodeData::Element {
149-
template_contents: Some(ref content),
149+
ref template_contents,
150150
..
151151
} = node.data
152152
{
153-
buf.push_str("|");
154-
buf.push_str(&repeat(" ").take(indent + 2).collect::<String>());
155-
buf.push_str("content\n");
156-
for child in content.children.borrow().iter() {
157-
serialize(buf, indent + 4, child.clone());
153+
if let Some(ref content) = &*template_contents.borrow() {
154+
buf.push_str("|");
155+
buf.push_str(&repeat(" ").take(indent + 2).collect::<String>());
156+
buf.push_str("content\n");
157+
for child in content.children.borrow().iter() {
158+
serialize(buf, indent + 4, child.clone());
159+
}
158160
}
159161
}
160162
}

0 commit comments

Comments
 (0)