Format script component

This commit is contained in:
chansuke 2018-09-18 23:24:15 +09:00 committed by Josh Matthews
parent 2ca7a13473
commit c37a345dc9
357 changed files with 25485 additions and 18076 deletions

View file

@ -58,49 +58,77 @@ struct Attribute {
#[derive(JSTraceable, MallocSizeOf)]
enum ParseOperation {
GetTemplateContents { target: ParseNodeId, contents: ParseNodeId },
GetTemplateContents {
target: ParseNodeId,
contents: ParseNodeId,
},
CreateElement {
node: ParseNodeId,
name: QualName,
attrs: Vec<Attribute>,
current_line: u64
current_line: u64,
},
CreateComment { text: String, node: ParseNodeId },
AppendBeforeSibling { sibling: ParseNodeId, node: NodeOrText },
AppendBasedOnParentNode { element: ParseNodeId, prev_element: ParseNodeId, node: NodeOrText },
Append { parent: ParseNodeId, node: NodeOrText },
CreateComment {
text: String,
node: ParseNodeId,
},
AppendBeforeSibling {
sibling: ParseNodeId,
node: NodeOrText,
},
AppendBasedOnParentNode {
element: ParseNodeId,
prev_element: ParseNodeId,
node: NodeOrText,
},
Append {
parent: ParseNodeId,
node: NodeOrText,
},
AppendDoctypeToDocument {
name: String,
public_id: String,
system_id: String
system_id: String,
},
AddAttrsIfMissing { target: ParseNodeId, attrs: Vec<Attribute> },
RemoveFromParent { target: ParseNodeId },
MarkScriptAlreadyStarted { node: ParseNodeId },
ReparentChildren { parent: ParseNodeId, new_parent: ParseNodeId },
AddAttrsIfMissing {
target: ParseNodeId,
attrs: Vec<Attribute>,
},
RemoveFromParent {
target: ParseNodeId,
},
MarkScriptAlreadyStarted {
node: ParseNodeId,
},
ReparentChildren {
parent: ParseNodeId,
new_parent: ParseNodeId,
},
AssociateWithForm {
target: ParseNodeId,
form: ParseNodeId,
element: ParseNodeId,
prev_element: Option<ParseNodeId>
prev_element: Option<ParseNodeId>,
},
CreatePI {
node: ParseNodeId,
target: String,
data: String
data: String,
},
Pop { node: ParseNodeId },
Pop {
node: ParseNodeId,
},
SetQuirksMode {
#[ignore_malloc_size_of = "Defined in style"]
mode: ServoQuirksMode
mode: ServoQuirksMode,
},
}
@ -109,12 +137,12 @@ enum ToTokenizerMsg {
// From HtmlTokenizer
TokenizerResultDone {
#[ignore_malloc_size_of = "Defined in html5ever"]
updated_input: VecDeque<SendTendril<UTF8>>
updated_input: VecDeque<SendTendril<UTF8>>,
},
TokenizerResultScript {
script: ParseNode,
#[ignore_malloc_size_of = "Defined in html5ever"]
updated_input: VecDeque<SendTendril<UTF8>>
updated_input: VecDeque<SendTendril<UTF8>>,
},
End, // Sent to Tokenizer to signify HtmlTokenizer's end method has returned
@ -126,7 +154,7 @@ enum ToTokenizerMsg {
enum ToHtmlTokenizerMsg {
Feed {
#[ignore_malloc_size_of = "Defined in html5ever"]
input: VecDeque<SendTendril<UTF8>>
input: VecDeque<SendTendril<UTF8>>,
},
End,
SetPlainTextState,
@ -180,10 +208,10 @@ pub struct Tokenizer {
impl Tokenizer {
pub fn new(
document: &Document,
url: ServoUrl,
fragment_context: Option<super::FragmentContext>)
-> Self {
document: &Document,
url: ServoUrl,
fragment_context: Option<super::FragmentContext>,
) -> Self {
// Messages from the Tokenizer (main thread) to HtmlTokenizer (parser thread)
let (to_html_tokenizer_sender, html_tokenizer_receiver) = channel();
// Messages from HtmlTokenizer and Sink (parser thread) to Tokenizer (main thread)
@ -194,7 +222,7 @@ impl Tokenizer {
receiver: tokenizer_receiver,
html_tokenizer_sender: to_html_tokenizer_sender,
nodes: HashMap::new(),
url: url
url: url,
};
tokenizer.insert_node(0, Dom::from_ref(document.upcast()));
@ -218,14 +246,18 @@ impl Tokenizer {
// Create new thread for HtmlTokenizer. This is where parser actions
// will be generated from the input provided. These parser actions are then passed
// onto the main thread to be executed.
thread::Builder::new().name(String::from("HTML Parser")).spawn(move || {
run(sink,
fragment_context_is_some,
ctxt_parse_node,
form_parse_node,
to_tokenizer_sender,
html_tokenizer_receiver);
}).expect("HTML Parser thread spawning failed");
thread::Builder::new()
.name(String::from("HTML Parser"))
.spawn(move || {
run(
sink,
fragment_context_is_some,
ctxt_parse_node,
form_parse_node,
to_tokenizer_sender,
html_tokenizer_receiver,
);
}).expect("HTML Parser thread spawning failed");
tokenizer
}
@ -238,31 +270,47 @@ impl Tokenizer {
// Send message to parser thread, asking it to start reading from the input.
// Parser operation messages will be sent to main thread as they are evaluated.
self.html_tokenizer_sender.send(ToHtmlTokenizerMsg::Feed { input: send_tendrils }).unwrap();
self.html_tokenizer_sender
.send(ToHtmlTokenizerMsg::Feed {
input: send_tendrils,
}).unwrap();
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::TokenizerResultDone { updated_input } => {
let buffer_queue = create_buffer_queue(updated_input);
*input = buffer_queue;
return Ok(());
},
ToTokenizerMsg::TokenizerResultScript { script, updated_input } => {
ToTokenizerMsg::TokenizerResultScript {
script,
updated_input,
} => {
let buffer_queue = create_buffer_queue(updated_input);
*input = buffer_queue;
let script = self.get_node(&script.id);
return Err(DomRoot::from_ref(script.downcast().unwrap()));
}
},
ToTokenizerMsg::End => unreachable!(),
};
}
}
pub fn end(&mut self) {
self.html_tokenizer_sender.send(ToHtmlTokenizerMsg::End).unwrap();
self.html_tokenizer_sender
.send(ToHtmlTokenizerMsg::End)
.unwrap();
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::End => return,
_ => unreachable!(),
@ -275,7 +323,9 @@ impl Tokenizer {
}
pub fn set_plaintext_state(&mut self) {
self.html_tokenizer_sender.send(ToHtmlTokenizerMsg::SetPlainTextState).unwrap();
self.html_tokenizer_sender
.send(ToHtmlTokenizerMsg::SetPlainTextState)
.unwrap();
}
fn insert_node(&mut self, id: ParseNodeId, node: Dom<Node>) {
@ -286,26 +336,27 @@ impl Tokenizer {
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(Dom::from_ref(&**self.get_node(&n.id))),
NodeOrText::Text(text) => HtmlNodeOrText::AppendText(
Tendril::from(text)
)
NodeOrText::Node(n) => {
HtmlNodeOrText::AppendNode(Dom::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");
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(Dom::from_ref(&**self.get_node(&n.id))),
NodeOrText::Text(text) => HtmlNodeOrText::AppendText(
Tendril::from(text)
)
NodeOrText::Node(n) => {
HtmlNodeOrText::AppendNode(Dom::from_ref(&**self.get_node(&n.id)))
},
NodeOrText::Text(text) => HtmlNodeOrText::AppendText(Tendril::from(text)),
};
let parent = &**self.get_node(&parent);
@ -327,15 +378,23 @@ impl Tokenizer {
fn process_operation(&mut self, op: ParseOperation) {
let document = DomRoot::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!");
match op {
ParseOperation::GetTemplateContents { target, contents } => {
let target = DomRoot::from_ref(&**self.get_node(&target));
let template = target.downcast::<HTMLTemplateElement>().expect(
"Tried to extract contents from non-template element while parsing");
let template = target
.downcast::<HTMLTemplateElement>()
.expect("Tried to extract contents from non-template element while parsing");
self.insert_node(contents, Dom::from_ref(template.Content().upcast()));
}
ParseOperation::CreateElement { node, name, attrs, current_line } => {
},
ParseOperation::CreateElement {
node,
name,
attrs,
current_line,
} => {
let attrs = attrs
.into_iter()
.map(|attr| ElementAttribute::new(attr.name, DOMString::from(attr.value)))
@ -345,60 +404,85 @@ impl Tokenizer {
attrs,
&*self.document,
ElementCreator::ParserCreated(current_line),
ParsingAlgorithm::Normal
ParsingAlgorithm::Normal,
);
self.insert_node(node, Dom::from_ref(element.upcast()));
}
},
ParseOperation::CreateComment { text, node } => {
let comment = Comment::new(DOMString::from(text), document);
self.insert_node(node, Dom::from_ref(&comment.upcast()));
}
},
ParseOperation::AppendBeforeSibling { sibling, node } => {
self.append_before_sibling(sibling, node);
}
},
ParseOperation::Append { parent, node } => {
self.append(parent, node);
}
ParseOperation::AppendBasedOnParentNode { element, prev_element, node } => {
},
ParseOperation::AppendBasedOnParentNode {
element,
prev_element,
node,
} => {
if self.has_parent_node(element) {
self.append_before_sibling(element, node);
} else {
self.append(prev_element, node);
}
}
ParseOperation::AppendDoctypeToDocument { name, public_id, system_id } => {
},
ParseOperation::AppendDoctypeToDocument {
name,
public_id,
system_id,
} => {
let doctype = DocumentType::new(
DOMString::from(String::from(name)), Some(DOMString::from(public_id)),
Some(DOMString::from(system_id)), document);
DOMString::from(String::from(name)),
Some(DOMString::from(public_id)),
Some(DOMString::from(system_id)),
document,
);
document.upcast::<Node>().AppendChild(doctype.upcast()).expect("Appending failed");
}
document
.upcast::<Node>()
.AppendChild(doctype.upcast())
.expect("Appending failed");
},
ParseOperation::AddAttrsIfMissing { target, attrs } => {
let elem = self.get_node(&target).downcast::<Element>()
let elem = self
.get_node(&target)
.downcast::<Element>()
.expect("tried to set attrs on non-Element in HTML parsing");
for attr in attrs {
elem.set_attribute_from_parser(attr.name, DOMString::from(attr.value), None);
}
}
},
ParseOperation::RemoveFromParent { target } => {
if let Some(ref parent) = self.get_node(&target).GetParentNode() {
parent.RemoveChild(&**self.get_node(&target)).unwrap();
}
}
},
ParseOperation::MarkScriptAlreadyStarted { node } => {
let script = self.get_node(&node).downcast::<HTMLScriptElement>();
script.map(|script| script.set_already_started(true));
}
},
ParseOperation::ReparentChildren { parent, new_parent } => {
let parent = self.get_node(&parent);
let new_parent = self.get_node(&new_parent);
while let Some(child) = parent.GetFirstChild() {
new_parent.AppendChild(&child).unwrap();
}
}
ParseOperation::AssociateWithForm { target, form, element, prev_element } => {
},
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.has_parent_node(element) {
element
} else {
prev
}
});
if !self.same_tree(tree_node, form) {
@ -416,47 +500,51 @@ impl Tokenizer {
control.set_form_owner_from_parser(&form);
} else {
// TODO remove this code when keygen is implemented.
assert_eq!(node.NodeName(), "KEYGEN", "Unknown form-associatable element");
assert_eq!(
node.NodeName(),
"KEYGEN",
"Unknown form-associatable element"
);
}
}
},
ParseOperation::Pop { node } => {
vtable_for(self.get_node(&node)).pop();
}
},
ParseOperation::CreatePI { node, target, data } => {
let pi = ProcessingInstruction::new(
DOMString::from(target),
DOMString::from(data),
document);
document,
);
self.insert_node(node, Dom::from_ref(pi.upcast()));
}
},
ParseOperation::SetQuirksMode { mode } => {
document.set_quirks_mode(mode);
}
},
}
}
}
fn run(sink: Sink,
fragment_context_is_some: bool,
ctxt_parse_node: Option<ParseNode>,
form_parse_node: Option<ParseNode>,
sender: Sender<ToTokenizerMsg>,
receiver: Receiver<ToHtmlTokenizerMsg>) {
fn run(
sink: Sink,
fragment_context_is_some: bool,
ctxt_parse_node: Option<ParseNode>,
form_parse_node: Option<ParseNode>,
sender: Sender<ToTokenizerMsg>,
receiver: Receiver<ToHtmlTokenizerMsg>,
) {
let options = TreeBuilderOpts {
ignore_missing_rules: true,
.. Default::default()
..Default::default()
};
let mut html_tokenizer = if fragment_context_is_some {
let tb = TreeBuilder::new_for_fragment(
sink,
ctxt_parse_node.unwrap(),
form_parse_node,
options);
let tb =
TreeBuilder::new_for_fragment(sink, ctxt_parse_node.unwrap(), form_parse_node, options);
let tok_options = TokenizerOpts {
initial_state: Some(tb.tokenizer_state_for_context_elem()),
.. Default::default()
..Default::default()
};
HtmlTokenizer::new(tb, tok_options)
@ -465,7 +553,10 @@ fn run(sink: Sink,
};
loop {
match receiver.recv().expect("Unexpected channel panic in html parser thread") {
match receiver
.recv()
.expect("Unexpected channel panic in html parser thread")
{
ToHtmlTokenizerMsg::Feed { input } => {
let mut input = create_buffer_queue(input);
let res = html_tokenizer.feed(&mut input);
@ -479,7 +570,10 @@ fn run(sink: Sink,
let res = match res {
TokenizerResult::Done => ToTokenizerMsg::TokenizerResultDone { updated_input },
TokenizerResult::Script(script) => ToTokenizerMsg::TokenizerResultScript { script, updated_input }
TokenizerResult::Script(script) => ToTokenizerMsg::TokenizerResultScript {
script,
updated_input,
},
};
sender.send(res).unwrap();
},
@ -488,7 +582,7 @@ fn run(sink: Sink,
sender.send(ToTokenizerMsg::End).unwrap();
break;
},
ToHtmlTokenizerMsg::SetPlainTextState => html_tokenizer.set_plaintext_state()
ToHtmlTokenizerMsg::SetPlainTextState => html_tokenizer.set_plaintext_state(),
};
}
}
@ -517,7 +611,7 @@ impl Sink {
id: 0,
qual_name: None,
},
sender: sender
sender: sender,
};
let data = ParseNodeData::default();
sink.insert_parse_node_data(0, data);
@ -536,7 +630,9 @@ impl Sink {
}
fn send_op(&self, op: ParseOperation) {
self.sender.send(ToTokenizerMsg::ProcessOperation(op)).unwrap();
self.sender
.send(ToTokenizerMsg::ProcessOperation(op))
.unwrap();
}
fn insert_parse_node_data(&mut self, id: ParseNodeId, data: ParseNodeData) {
@ -544,18 +640,24 @@ impl Sink {
}
fn get_parse_node_data<'a>(&'a self, id: &'a ParseNodeId) -> &'a ParseNodeData {
self.parse_node_data.get(id).expect("Parse Node data not found!")
self.parse_node_data
.get(id)
.expect("Parse Node data not found!")
}
fn get_parse_node_data_mut<'a>(&'a mut self, id: &'a ParseNodeId) -> &'a mut ParseNodeData {
self.parse_node_data.get_mut(id).expect("Parse Node data not found!")
self.parse_node_data
.get_mut(id)
.expect("Parse Node data not found!")
}
}
#[allow(unrooted_must_root)]
impl TreeSink for Sink {
type Output = Self;
fn finish(self) -> Self { self }
fn finish(self) -> Self {
self
}
type Handle = ParseNode;
@ -572,7 +674,10 @@ impl TreeSink for Sink {
let data = self.get_parse_node_data_mut(&target.id);
data.contents = Some(node.clone());
}
self.send_op(ParseOperation::GetTemplateContents { target: target.id, contents: node.id });
self.send_op(ParseOperation::GetTemplateContents {
target: target.id,
contents: node.id,
});
node
}
@ -581,38 +686,52 @@ impl TreeSink for Sink {
}
fn elem_name<'a>(&self, target: &'a Self::Handle) -> ExpandedName<'a> {
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 create_element(&mut self, name: QualName, html_attrs: Vec<HtmlAttribute>, _flags: ElementFlags)
-> Self::Handle {
fn create_element(
&mut self,
name: QualName,
html_attrs: Vec<HtmlAttribute>,
_flags: ElementFlags,
) -> Self::Handle {
let mut node = self.new_parse_node();
node.qual_name = Some(name.clone());
{
let node_data = self.get_parse_node_data_mut(&node.id);
node_data.is_integration_point = html_attrs.iter()
.any(|attr| {
node_data.is_integration_point = html_attrs.iter().any(|attr| {
let attr_value = &String::from(attr.value.clone());
(attr.name.local == local_name!("encoding") && attr.name.ns == ns!()) &&
(attr_value.eq_ignore_ascii_case("text/html") ||
attr_value.eq_ignore_ascii_case("application/xhtml+xml"))
(attr_value.eq_ignore_ascii_case("text/html") ||
attr_value.eq_ignore_ascii_case("application/xhtml+xml"))
});
}
let attrs = html_attrs.into_iter()
.map(|attr| Attribute { name: attr.name, value: String::from(attr.value) }).collect();
let attrs = html_attrs
.into_iter()
.map(|attr| Attribute {
name: attr.name,
value: String::from(attr.value),
}).collect();
self.send_op(ParseOperation::CreateElement {
node: node.id,
name,
attrs,
current_line: self.current_line
current_line: self.current_line,
});
node
}
fn create_comment(&mut self, text: StrTendril) -> Self::Handle {
let node = self.new_parse_node();
self.send_op(ParseOperation::CreateComment { text: String::from(text), node: node.id });
self.send_op(ParseOperation::CreateComment {
text: String::from(text),
node: node.id,
});
node
}
@ -621,7 +740,7 @@ impl TreeSink for Sink {
self.send_op(ParseOperation::CreatePI {
node: node.id,
target: String::from(target),
data: String::from(data)
data: String::from(data),
});
node
}
@ -641,14 +760,19 @@ impl TreeSink for Sink {
});
}
fn append_before_sibling(&mut self,
sibling: &Self::Handle,
new_node: HtmlNodeOrText<Self::Handle>) {
fn append_before_sibling(
&mut self,
sibling: &Self::Handle,
new_node: HtmlNodeOrText<Self::Handle>,
) {
let new_node = match new_node {
HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text))
HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
};
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(
@ -659,12 +783,12 @@ impl TreeSink for Sink {
) {
let child = match child {
HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text))
HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
};
self.send_op(ParseOperation::AppendBasedOnParentNode {
element: elem.id,
prev_element: prev_elem.id,
node: child
node: child,
});
}
@ -684,24 +808,38 @@ impl TreeSink for Sink {
fn append(&mut self, parent: &Self::Handle, child: HtmlNodeOrText<Self::Handle>) {
let child = match child {
HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text))
HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
};
self.send_op(ParseOperation::Append { parent: parent.id, node: child });
self.send_op(ParseOperation::Append {
parent: parent.id,
node: child,
});
}
fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril,
system_id: StrTendril) {
fn append_doctype_to_document(
&mut self,
name: StrTendril,
public_id: StrTendril,
system_id: StrTendril,
) {
self.send_op(ParseOperation::AppendDoctypeToDocument {
name: String::from(name),
public_id: String::from(public_id),
system_id: String::from(system_id)
system_id: String::from(system_id),
});
}
fn add_attrs_if_missing(&mut self, target: &Self::Handle, html_attrs: Vec<HtmlAttribute>) {
let attrs = html_attrs.into_iter()
.map(|attr| Attribute { name: attr.name, value: String::from(attr.value) }).collect();
self.send_op(ParseOperation::AddAttrsIfMissing { target: target.id, attrs });
let attrs = html_attrs
.into_iter()
.map(|attr| Attribute {
name: attr.name,
value: String::from(attr.value),
}).collect();
self.send_op(ParseOperation::AddAttrsIfMissing {
target: target.id,
attrs,
});
}
fn remove_from_parent(&mut self, target: &Self::Handle) {
@ -717,7 +855,10 @@ impl TreeSink for Sink {
}
fn reparent_children(&mut self, parent: &Self::Handle, new_parent: &Self::Handle) {
self.send_op(ParseOperation::ReparentChildren { parent: parent.id, new_parent: new_parent.id });
self.send_op(ParseOperation::ReparentChildren {
parent: parent.id,
new_parent: new_parent.id,
});
}
/// <https://html.spec.whatwg.org/multipage/#html-integration-point>