mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
TreeSink impls do not explicitly rely on and methods anymore
This commit is contained in:
parent
99235c9201
commit
2cc7199f42
2 changed files with 129 additions and 88 deletions
|
@ -69,6 +69,7 @@ enum ParseOperation {
|
||||||
|
|
||||||
CreateComment { text: String, node: ParseNodeId },
|
CreateComment { text: String, node: ParseNodeId },
|
||||||
AppendBeforeSibling { sibling: ParseNodeId, node: NodeOrText },
|
AppendBeforeSibling { sibling: ParseNodeId, node: NodeOrText },
|
||||||
|
AppendBasedOnParentNode { element: ParseNodeId, prev_element: ParseNodeId, node: NodeOrText },
|
||||||
Append { parent: ParseNodeId, node: NodeOrText },
|
Append { parent: ParseNodeId, node: NodeOrText },
|
||||||
|
|
||||||
AppendDoctypeToDocument {
|
AppendDoctypeToDocument {
|
||||||
|
@ -81,7 +82,13 @@ enum ParseOperation {
|
||||||
RemoveFromParent { target: ParseNodeId },
|
RemoveFromParent { target: ParseNodeId },
|
||||||
MarkScriptAlreadyStarted { node: ParseNodeId },
|
MarkScriptAlreadyStarted { node: ParseNodeId },
|
||||||
ReparentChildren { parent: ParseNodeId, new_parent: ParseNodeId },
|
ReparentChildren { parent: ParseNodeId, new_parent: ParseNodeId },
|
||||||
AssociateWithForm { target: ParseNodeId, form: ParseNodeId },
|
|
||||||
|
AssociateWithForm {
|
||||||
|
target: ParseNodeId,
|
||||||
|
form: ParseNodeId,
|
||||||
|
element: ParseNodeId,
|
||||||
|
prev_element: Option<ParseNodeId>
|
||||||
|
},
|
||||||
|
|
||||||
CreatePI {
|
CreatePI {
|
||||||
node: ParseNodeId,
|
node: ParseNodeId,
|
||||||
|
@ -113,8 +120,6 @@ enum ToTokenizerMsg {
|
||||||
|
|
||||||
// From Sink
|
// From Sink
|
||||||
ProcessOperation(ParseOperation),
|
ProcessOperation(ParseOperation),
|
||||||
IsSameTree(ParseNodeId, ParseNodeId),
|
|
||||||
HasParentNode(ParseNodeId),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(HeapSizeOf)]
|
#[derive(HeapSizeOf)]
|
||||||
|
@ -127,14 +132,6 @@ enum ToHtmlTokenizerMsg {
|
||||||
SetPlainTextState,
|
SetPlainTextState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Responses to the queries asked by the the Sink to the Tokenizer,
|
|
||||||
// using the messages types in FromSinkMsg.
|
|
||||||
#[derive(HeapSizeOf)]
|
|
||||||
enum ToSinkMsg {
|
|
||||||
IsSameTree(bool),
|
|
||||||
HasParentNode(bool),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_buffer_queue(mut buffers: VecDeque<SendTendril<UTF8>>) -> BufferQueue {
|
fn create_buffer_queue(mut buffers: VecDeque<SendTendril<UTF8>>) -> BufferQueue {
|
||||||
let mut buffer_queue = BufferQueue::new();
|
let mut buffer_queue = BufferQueue::new();
|
||||||
while let Some(st) = buffers.pop_front() {
|
while let Some(st) = buffers.pop_front() {
|
||||||
|
@ -155,17 +152,17 @@ fn create_buffer_queue(mut buffers: VecDeque<SendTendril<UTF8>>) -> BufferQueue
|
||||||
// then executes the received actions.
|
// then executes the received actions.
|
||||||
//
|
//
|
||||||
// _____________ _______________
|
// _____________ _______________
|
||||||
// | | ToHtmlTokenizerMsg | |
|
|
||||||
// | |------------------------>| |
|
|
||||||
// | | | |
|
// | | | |
|
||||||
// | | ToTokenizerMsg | HtmlTokenizer |
|
// | | | |
|
||||||
// | |<------------------------| |
|
// | | ToHtmlTokenizerMsg | |
|
||||||
// | Tokenizer | | |
|
// | |------------------------>| HtmlTokenizer |
|
||||||
// | | ToTokenizerMsg | ________ |
|
// | | | |
|
||||||
|
// | Tokenizer | ToTokenizerMsg | |
|
||||||
|
// | |<------------------------| ________ |
|
||||||
|
// | | | | | |
|
||||||
|
// | | ToTokenizerMsg | | Sink | |
|
||||||
// | |<------------------------|---| | |
|
// | |<------------------------|---| | |
|
||||||
// | | | | Sink | |
|
// | | | |________| |
|
||||||
// | | ToSinkMsg | | | |
|
|
||||||
// | |-------------------------|-->|________| |
|
|
||||||
// |_____________| |_______________|
|
// |_____________| |_______________|
|
||||||
//
|
//
|
||||||
#[derive(HeapSizeOf, JSTraceable)]
|
#[derive(HeapSizeOf, JSTraceable)]
|
||||||
|
@ -177,7 +174,6 @@ pub struct Tokenizer {
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
html_tokenizer_sender: Sender<ToHtmlTokenizerMsg>,
|
html_tokenizer_sender: Sender<ToHtmlTokenizerMsg>,
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
sink_sender: Sender<ToSinkMsg>,
|
|
||||||
nodes: HashMap<ParseNodeId, JS<Node>>,
|
nodes: HashMap<ParseNodeId, JS<Node>>,
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
}
|
}
|
||||||
|
@ -190,8 +186,6 @@ impl Tokenizer {
|
||||||
-> Self {
|
-> Self {
|
||||||
// Messages from the Tokenizer (main thread) to HtmlTokenizer (parser thread)
|
// Messages from the Tokenizer (main thread) to HtmlTokenizer (parser thread)
|
||||||
let (to_html_tokenizer_sender, html_tokenizer_receiver) = channel();
|
let (to_html_tokenizer_sender, html_tokenizer_receiver) = channel();
|
||||||
// Messages from the Tokenizer (main thread) to Sink (parser thread)
|
|
||||||
let (to_sink_sender, sink_receiver) = channel();
|
|
||||||
// Messages from HtmlTokenizer and Sink (parser thread) to Tokenizer (main thread)
|
// Messages from HtmlTokenizer and Sink (parser thread) to Tokenizer (main thread)
|
||||||
let (to_tokenizer_sender, tokenizer_receiver) = channel();
|
let (to_tokenizer_sender, tokenizer_receiver) = channel();
|
||||||
|
|
||||||
|
@ -199,13 +193,12 @@ impl Tokenizer {
|
||||||
document: JS::from_ref(document),
|
document: JS::from_ref(document),
|
||||||
receiver: tokenizer_receiver,
|
receiver: tokenizer_receiver,
|
||||||
html_tokenizer_sender: to_html_tokenizer_sender,
|
html_tokenizer_sender: to_html_tokenizer_sender,
|
||||||
sink_sender: to_sink_sender,
|
|
||||||
nodes: HashMap::new(),
|
nodes: HashMap::new(),
|
||||||
url: url
|
url: url
|
||||||
};
|
};
|
||||||
tokenizer.insert_node(0, JS::from_ref(document.upcast()));
|
tokenizer.insert_node(0, JS::from_ref(document.upcast()));
|
||||||
|
|
||||||
let mut sink = Sink::new(to_tokenizer_sender.clone(), sink_receiver);
|
let mut sink = Sink::new(to_tokenizer_sender.clone());
|
||||||
let mut ctxt_parse_node = None;
|
let mut ctxt_parse_node = None;
|
||||||
let mut form_parse_node = None;
|
let mut form_parse_node = None;
|
||||||
let mut fragment_context_is_some = false;
|
let mut fragment_context_is_some = false;
|
||||||
|
@ -250,18 +243,6 @@ impl Tokenizer {
|
||||||
loop {
|
loop {
|
||||||
match self.receiver.recv().expect("Unexpected channel panic in main thread.") {
|
match self.receiver.recv().expect("Unexpected channel panic in main thread.") {
|
||||||
ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
|
ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
|
||||||
ToTokenizerMsg::IsSameTree(ref x_id, ref y_id) => {
|
|
||||||
let x = self.get_node(x_id);
|
|
||||||
let y = self.get_node(y_id);
|
|
||||||
|
|
||||||
let x = x.downcast::<Element>().expect("Element node expected");
|
|
||||||
let y = y.downcast::<Element>().expect("Element node expected");
|
|
||||||
self.sink_sender.send(ToSinkMsg::IsSameTree(x.is_in_same_home_subtree(y))).unwrap();
|
|
||||||
},
|
|
||||||
ToTokenizerMsg::HasParentNode(ref id) => {
|
|
||||||
let res = self.get_node(id).GetParentNode().is_some();
|
|
||||||
self.sink_sender.send(ToSinkMsg::HasParentNode(res)).unwrap();
|
|
||||||
},
|
|
||||||
ToTokenizerMsg::TokenizerResultDone { updated_input } => {
|
ToTokenizerMsg::TokenizerResultDone { updated_input } => {
|
||||||
let buffer_queue = create_buffer_queue(updated_input);
|
let buffer_queue = create_buffer_queue(updated_input);
|
||||||
*input = buffer_queue;
|
*input = buffer_queue;
|
||||||
|
@ -283,18 +264,6 @@ impl Tokenizer {
|
||||||
loop {
|
loop {
|
||||||
match self.receiver.recv().expect("Unexpected channel panic in main thread.") {
|
match self.receiver.recv().expect("Unexpected channel panic in main thread.") {
|
||||||
ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
|
ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
|
||||||
ToTokenizerMsg::IsSameTree(ref x_id, ref y_id) => {
|
|
||||||
let x = self.get_node(x_id);
|
|
||||||
let y = self.get_node(y_id);
|
|
||||||
|
|
||||||
let x = x.downcast::<Element>().expect("Element node expected");
|
|
||||||
let y = y.downcast::<Element>().expect("Element node expected");
|
|
||||||
self.sink_sender.send(ToSinkMsg::IsSameTree(x.is_in_same_home_subtree(y))).unwrap();
|
|
||||||
},
|
|
||||||
ToTokenizerMsg::HasParentNode(ref id) => {
|
|
||||||
let res = self.get_node(id).GetParentNode().is_some();
|
|
||||||
self.sink_sender.send(ToSinkMsg::HasParentNode(res)).unwrap();
|
|
||||||
},
|
|
||||||
ToTokenizerMsg::End => return,
|
ToTokenizerMsg::End => return,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -317,6 +286,45 @@ impl Tokenizer {
|
||||||
self.nodes.get(id).expect("Node not found!")
|
self.nodes.get(id).expect("Node not found!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn append_before_sibling(&mut self, sibling: ParseNodeId, node: NodeOrText) {
|
||||||
|
let node = match node {
|
||||||
|
NodeOrText::Node(n) => HtmlNodeOrText::AppendNode(JS::from_ref(&**self.get_node(&n.id))),
|
||||||
|
NodeOrText::Text(text) => HtmlNodeOrText::AppendText(
|
||||||
|
Tendril::from(text)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let sibling = &**self.get_node(&sibling);
|
||||||
|
let parent = &*sibling.GetParentNode().expect("append_before_sibling called on node without parent");
|
||||||
|
|
||||||
|
super::insert(parent, Some(sibling), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append(&mut self, parent: ParseNodeId, node: NodeOrText) {
|
||||||
|
let node = match node {
|
||||||
|
NodeOrText::Node(n) => HtmlNodeOrText::AppendNode(JS::from_ref(&**self.get_node(&n.id))),
|
||||||
|
NodeOrText::Text(text) => HtmlNodeOrText::AppendText(
|
||||||
|
Tendril::from(text)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let parent = &**self.get_node(&parent);
|
||||||
|
super::insert(parent, None, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_parent_node(&self, node: ParseNodeId) -> bool {
|
||||||
|
self.get_node(&node).GetParentNode().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn same_tree(&self, x: ParseNodeId, y: ParseNodeId) -> bool {
|
||||||
|
let x = self.get_node(&x);
|
||||||
|
let y = self.get_node(&y);
|
||||||
|
|
||||||
|
let x = x.downcast::<Element>().expect("Element node expected");
|
||||||
|
let y = y.downcast::<Element>().expect("Element node expected");
|
||||||
|
x.is_in_same_home_subtree(y)
|
||||||
|
}
|
||||||
|
|
||||||
fn process_operation(&mut self, op: ParseOperation) {
|
fn process_operation(&mut self, op: ParseOperation) {
|
||||||
let document = Root::from_ref(&**self.get_node(&0));
|
let document = Root::from_ref(&**self.get_node(&0));
|
||||||
let document = document.downcast::<Document>().expect("Document node should be downcasted!");
|
let document = document.downcast::<Document>().expect("Document node should be downcasted!");
|
||||||
|
@ -348,27 +356,17 @@ impl Tokenizer {
|
||||||
self.insert_node(node, JS::from_ref(&comment.upcast()));
|
self.insert_node(node, JS::from_ref(&comment.upcast()));
|
||||||
}
|
}
|
||||||
ParseOperation::AppendBeforeSibling { sibling, node } => {
|
ParseOperation::AppendBeforeSibling { sibling, node } => {
|
||||||
let node = match node {
|
self.append_before_sibling(sibling, node);
|
||||||
NodeOrText::Node(n) => HtmlNodeOrText::AppendNode(JS::from_ref(&**self.get_node(&n.id))),
|
|
||||||
NodeOrText::Text(text) => HtmlNodeOrText::AppendText(
|
|
||||||
Tendril::from(text)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let sibling = &**self.get_node(&sibling);
|
|
||||||
let parent = &*sibling.GetParentNode().expect("append_before_sibling called on node without parent");
|
|
||||||
|
|
||||||
super::insert(parent, Some(sibling), node);
|
|
||||||
}
|
}
|
||||||
ParseOperation::Append { parent, node } => {
|
ParseOperation::Append { parent, node } => {
|
||||||
let node = match node {
|
self.append(parent, node);
|
||||||
NodeOrText::Node(n) => HtmlNodeOrText::AppendNode(JS::from_ref(&**self.get_node(&n.id))),
|
}
|
||||||
NodeOrText::Text(text) => HtmlNodeOrText::AppendText(
|
ParseOperation::AppendBasedOnParentNode { element, prev_element, node } => {
|
||||||
Tendril::from(text)
|
if self.has_parent_node(element) {
|
||||||
)
|
self.append_before_sibling(element, node);
|
||||||
};
|
} else {
|
||||||
|
self.append(prev_element, node);
|
||||||
let parent = &**self.get_node(&parent);
|
}
|
||||||
super::insert(parent, None, node);
|
|
||||||
}
|
}
|
||||||
ParseOperation::AppendDoctypeToDocument { name, public_id, system_id } => {
|
ParseOperation::AppendDoctypeToDocument { name, public_id, system_id } => {
|
||||||
let doctype = DocumentType::new(
|
let doctype = DocumentType::new(
|
||||||
|
@ -400,7 +398,14 @@ impl Tokenizer {
|
||||||
new_parent.AppendChild(&child).unwrap();
|
new_parent.AppendChild(&child).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParseOperation::AssociateWithForm { target, form } => {
|
ParseOperation::AssociateWithForm { target, form, element, prev_element } => {
|
||||||
|
let tree_node = prev_element.map_or(element, |prev| {
|
||||||
|
if self.has_parent_node(element) { element } else { prev }
|
||||||
|
});
|
||||||
|
|
||||||
|
if !self.same_tree(tree_node, form) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let form = self.get_node(&form);
|
let form = self.get_node(&form);
|
||||||
let form = Root::downcast::<HTMLFormElement>(Root::from_ref(&**form))
|
let form = Root::downcast::<HTMLFormElement>(Root::from_ref(&**form))
|
||||||
.expect("Owner must be a form element");
|
.expect("Owner must be a form element");
|
||||||
|
@ -502,11 +507,10 @@ pub struct Sink {
|
||||||
next_parse_node_id: Cell<ParseNodeId>,
|
next_parse_node_id: Cell<ParseNodeId>,
|
||||||
document_node: ParseNode,
|
document_node: ParseNode,
|
||||||
sender: Sender<ToTokenizerMsg>,
|
sender: Sender<ToTokenizerMsg>,
|
||||||
receiver: Receiver<ToSinkMsg>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sink {
|
impl Sink {
|
||||||
fn new(sender: Sender<ToTokenizerMsg>, receiver: Receiver<ToSinkMsg>) -> Sink {
|
fn new(sender: Sender<ToTokenizerMsg>) -> Sink {
|
||||||
let mut sink = Sink {
|
let mut sink = Sink {
|
||||||
current_line: 1,
|
current_line: 1,
|
||||||
parse_node_data: HashMap::new(),
|
parse_node_data: HashMap::new(),
|
||||||
|
@ -515,8 +519,7 @@ impl Sink {
|
||||||
id: 0,
|
id: 0,
|
||||||
qual_name: None,
|
qual_name: None,
|
||||||
},
|
},
|
||||||
sender: sender,
|
sender: sender
|
||||||
receiver: receiver,
|
|
||||||
};
|
};
|
||||||
let data = ParseNodeData::default();
|
let data = ParseNodeData::default();
|
||||||
sink.insert_parse_node_data(0, data);
|
sink.insert_parse_node_data(0, data);
|
||||||
|
@ -583,12 +586,8 @@ impl TreeSink for Sink {
|
||||||
target.qual_name.as_ref().expect("Expected qual name of node!").expanded()
|
target.qual_name.as_ref().expect("Expected qual name of node!").expanded()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn same_tree(&self, x: &Self::Handle, y: &Self::Handle) -> bool {
|
fn same_tree(&self, _: &Self::Handle, _: &Self::Handle) -> bool {
|
||||||
self.sender.send(ToTokenizerMsg::IsSameTree(x.id, y.id)).unwrap();
|
unreachable!();
|
||||||
match self.receiver.recv().expect("Unexpected channel panic in html parser thread.") {
|
|
||||||
ToSinkMsg::IsSameTree(result) => result,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_element(&mut self, name: QualName, html_attrs: Vec<HtmlAttribute>, _flags: ElementFlags)
|
fn create_element(&mut self, name: QualName, html_attrs: Vec<HtmlAttribute>, _flags: ElementFlags)
|
||||||
|
@ -633,18 +632,22 @@ impl TreeSink for Sink {
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_parent_node(&self, node: &Self::Handle) -> bool {
|
fn has_parent_node(&self, _: &Self::Handle) -> bool {
|
||||||
self.sender.send(ToTokenizerMsg::HasParentNode(node.id)).unwrap();
|
unreachable!();
|
||||||
match self.receiver.recv().expect("Unexpected channel panic in html parser thread.") {
|
|
||||||
ToSinkMsg::HasParentNode(result) => result,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn associate_with_form(&mut self, target: &Self::Handle, form: &Self::Handle) {
|
fn associate_with_form(
|
||||||
|
&mut self,
|
||||||
|
target: &Self::Handle,
|
||||||
|
form: &Self::Handle,
|
||||||
|
nodes: (&Self::Handle, Option<&Self::Handle>),
|
||||||
|
) {
|
||||||
|
let (element, prev_element) = nodes;
|
||||||
self.send_op(ParseOperation::AssociateWithForm {
|
self.send_op(ParseOperation::AssociateWithForm {
|
||||||
target: target.id,
|
target: target.id,
|
||||||
form: form.id
|
form: form.id,
|
||||||
|
element: element.id,
|
||||||
|
prev_element: prev_element.map(|p| p.id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,6 +661,23 @@ impl TreeSink for Sink {
|
||||||
self.send_op(ParseOperation::AppendBeforeSibling { sibling: sibling.id, node: new_node });
|
self.send_op(ParseOperation::AppendBeforeSibling { sibling: sibling.id, node: new_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn append_based_on_parent_node(
|
||||||
|
&mut self,
|
||||||
|
elem: &Self::Handle,
|
||||||
|
prev_elem: &Self::Handle,
|
||||||
|
child: HtmlNodeOrText<Self::Handle>,
|
||||||
|
) {
|
||||||
|
let child = match child {
|
||||||
|
HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
|
||||||
|
HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text))
|
||||||
|
};
|
||||||
|
self.send_op(ParseOperation::AppendBasedOnParentNode {
|
||||||
|
element: elem.id,
|
||||||
|
prev_element: prev_elem.id,
|
||||||
|
node: child
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_error(&mut self, msg: Cow<'static, str>) {
|
fn parse_error(&mut self, msg: Cow<'static, str>) {
|
||||||
debug!("Parse error: {}", msg);
|
debug!("Parse error: {}", msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -820,7 +820,15 @@ impl TreeSink for Sink {
|
||||||
node.GetParentNode().is_some()
|
node.GetParentNode().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn associate_with_form(&mut self, target: &JS<Node>, form: &JS<Node>) {
|
fn associate_with_form(&mut self, target: &JS<Node>, form: &JS<Node>, nodes: (&JS<Node>, Option<&JS<Node>>)) {
|
||||||
|
let (element, prev_element) = nodes;
|
||||||
|
let tree_node = prev_element.map_or(element, |prev| {
|
||||||
|
if self.has_parent_node(element) { element } else { prev }
|
||||||
|
});
|
||||||
|
if !self.same_tree(tree_node, form) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let node = target;
|
let node = target;
|
||||||
let form = Root::downcast::<HTMLFormElement>(Root::from_ref(&**form))
|
let form = Root::downcast::<HTMLFormElement>(Root::from_ref(&**form))
|
||||||
.expect("Owner must be a form element");
|
.expect("Owner must be a form element");
|
||||||
|
@ -862,6 +870,19 @@ impl TreeSink for Sink {
|
||||||
insert(&parent, None, child);
|
insert(&parent, None, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn append_based_on_parent_node(
|
||||||
|
&mut self,
|
||||||
|
elem: &JS<Node>,
|
||||||
|
prev_elem: &JS<Node>,
|
||||||
|
child: NodeOrText<JS<Node>>,
|
||||||
|
) {
|
||||||
|
if self.has_parent_node(elem) {
|
||||||
|
self.append_before_sibling(elem, child);
|
||||||
|
} else {
|
||||||
|
self.append(prev_elem, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril,
|
fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril,
|
||||||
system_id: StrTendril) {
|
system_id: StrTendril) {
|
||||||
let doc = &*self.document;
|
let doc = &*self.document;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue