Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up the parsers into a single interface #13675

Merged
merged 9 commits into from Oct 11, 2016
@@ -138,6 +138,7 @@ impl Formattable for ProfilerCategory {
ProfilerCategory::ScriptInputEvent => "Script Input Event",
ProfilerCategory::ScriptNetworkEvent => "Script Network Event",
ProfilerCategory::ScriptParseHTML => "Script Parse HTML",
ProfilerCategory::ScriptParseXML => "Script Parse XML",
ProfilerCategory::ScriptPlannedNavigation => "Script Planned Navigation",
ProfilerCategory::ScriptResize => "Script Resize",
ProfilerCategory::ScriptEvent => "Script Event",
@@ -83,6 +83,7 @@ pub enum ProfilerCategory {
ScriptWebSocketEvent = 0x73,
ScriptWorkerEvent = 0x74,
ScriptServiceWorkerEvent = 0x75,
ScriptParseXML = 0x76,
ApplicationHeartbeat = 0x90,
}

@@ -2748,7 +2748,8 @@ def definition_body(self):
interface.get());
""" % {"id": name, "name": str_to_const_array(name)})

if len(self.descriptor.prototypeChain) == 1:
parentName = self.descriptor.getParentName()
if not parentName:
if self.descriptor.interface.getExtendedAttribute("ExceptionClass"):
getPrototypeProto = "prototype_proto.set(JS_GetErrorPrototype(cx))"
elif self.descriptor.interface.isIteratorInterface():
@@ -2757,7 +2758,7 @@ def definition_body(self):
getPrototypeProto = "prototype_proto.set(JS_GetObjectPrototype(cx, global))"
else:
getPrototypeProto = ("%s::GetProtoObject(cx, global, prototype_proto.handle_mut())" %
toBindingNamespace(self.descriptor.getParentName()))
toBindingNamespace(parentName))

code = [CGGeneric("""\
rooted!(in(cx) let mut prototype_proto = ptr::null_mut());
@@ -76,6 +76,7 @@ use dom::popstateevent::PopStateEvent;
use dom::processinginstruction::ProcessingInstruction;
use dom::progressevent::ProgressEvent;
use dom::range::Range;
use dom::servoparser::ServoParser;
use dom::storageevent::StorageEvent;
use dom::stylesheetlist::StyleSheetList;
use dom::text::Text;
@@ -103,7 +104,6 @@ use net_traits::request::RequestInit;
use net_traits::response::HttpsState;
use num_traits::ToPrimitive;
use origin::Origin;
use parse::{MutNullableParserField, ParserRef, ParserRoot};
use script_layout_interface::message::{Msg, ReflowQueryType};
use script_thread::{MainThreadScriptMsg, Runnable};
use script_traits::{AnimationState, CompositorEvent, MouseButton, MouseEventType, MozBrowserEvent};
@@ -226,7 +226,7 @@ pub struct Document {
/// Tracks all outstanding loads related to this document.
loader: DOMRefCell<DocumentLoader>,
/// The current active HTML parser, to allow resuming after interruptions.
current_parser: MutNullableParserField,
current_parser: MutNullableHeap<JS<ServoParser>>,
/// When we should kick off a reflow. This happens during parsing.
reflow_timeout: Cell<Option<u64>>,
/// The cached first `base` element with an `href` attribute.
@@ -1627,11 +1627,11 @@ impl Document {
global_scope.constellation_chan().send(load_event).unwrap();
}

pub fn set_current_parser(&self, script: Option<ParserRef>) {
pub fn set_current_parser(&self, script: Option<&ServoParser>) {
self.current_parser.set(script);
}

pub fn get_current_parser(&self) -> Option<ParserRoot> {
pub fn get_current_parser(&self) -> Option<Root<ServoParser>> {
self.current_parser.get()
}

@@ -18,9 +18,9 @@ use dom::bindings::str::DOMString;
use dom::document::{Document, IsHTMLDocument};
use dom::document::DocumentSource;
use dom::globalscope::GlobalScope;
use dom::servoparser::html::{ParseContext, parse_html};
use dom::servoparser::xml::{self, parse_xml};
use dom::window::Window;
use parse::html::{ParseContext, parse_html};
use parse::xml::{self, parse_xml};

#[dom_struct]
pub struct DOMParser {
@@ -386,8 +386,7 @@ pub mod serviceworker;
pub mod serviceworkercontainer;
pub mod serviceworkerglobalscope;
pub mod serviceworkerregistration;
pub mod servohtmlparser;
pub mod servoxmlparser;
pub mod servoparser;
pub mod storage;
pub mod storageevent;
pub mod stylesheet;
@@ -47,6 +47,7 @@ use dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHel
use dom::nodelist::NodeList;
use dom::processinginstruction::ProcessingInstruction;
use dom::range::WeakRangeVec;
use dom::servoparser::html::parse_html_fragment;
use dom::svgsvgelement::{SVGSVGElement, LayoutSVGSVGElementHelpers};
use dom::text::Text;
use dom::virtualmethods::{VirtualMethods, vtable_for};
@@ -59,7 +60,6 @@ use html5ever::tree_builder::QuirksMode;
use js::jsapi::{JSContext, JSObject, JSRuntime};
use libc::{self, c_void, uintptr_t};
use msg::constellation_msg::PipelineId;
use parse::html::parse_html_fragment;
use ref_slice::ref_slice;
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
@@ -23,20 +23,20 @@ use dom::htmltemplateelement::HTMLTemplateElement;
use dom::node::{document_from_node, window_from_node};
use dom::node::Node;
use dom::processinginstruction::ProcessingInstruction;
use dom::servohtmlparser;
use dom::servohtmlparser::{FragmentContext, ServoHTMLParser};
use dom::text::Text;
use html5ever::Attribute;
use html5ever::serialize::{AttrRef, Serializable, Serializer};
use html5ever::serialize::TraversalScope;
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
use html5ever::tendril::StrTendril;
use html5ever::tree_builder::{NextParserState, NodeOrText, QuirksMode, TreeSink};
use html5ever::tokenizer::{Tokenizer as HtmlTokenizer, TokenizerOpts};
use html5ever::tree_builder::{NextParserState, NodeOrText, QuirksMode};
use html5ever::tree_builder::{TreeBuilder, TreeBuilderOpts, TreeSink};
use msg::constellation_msg::PipelineId;
use parse::Parser;
use std::borrow::Cow;
use std::io::{self, Write};
use string_cache::QualName;
use super::{LastChunkState, ServoParser, Sink, Tokenizer};
use url::Url;

fn insert(parent: &Node, reference_child: Option<&Node>, child: NodeOrText<JS<Node>>) {
@@ -53,7 +53,7 @@ fn insert(parent: &Node, reference_child: Option<&Node>, child: NodeOrText<JS<No
}
}

impl<'a> TreeSink for servohtmlparser::Sink {
impl<'a> TreeSink for Sink {
type Output = Self;
fn finish(self) -> Self { self }

@@ -246,6 +246,14 @@ impl<'a> Serializable for &'a Node {
}
}

/// FragmentContext is used only to pass this group of related values
/// into functions.
#[derive(Copy, Clone)]
pub struct FragmentContext<'a> {
pub context_elem: &'a Node,
pub form_elem: Option<&'a Node>,
}

pub enum ParseContext<'a> {
Fragment(FragmentContext<'a>),
Owner(Option<PipelineId>),
@@ -255,11 +263,40 @@ pub fn parse_html(document: &Document,
input: DOMString,
url: Url,
context: ParseContext) {
let sink = Sink {
base_url: url,
document: JS::from_ref(document),
};

let options = TreeBuilderOpts {
ignore_missing_rules: true,
.. Default::default()
};

let parser = match context {
ParseContext::Owner(owner) =>
ServoHTMLParser::new(Some(url), document, owner),
ParseContext::Fragment(fc) =>
ServoHTMLParser::new_for_fragment(Some(url), document, fc),
ParseContext::Owner(owner) => {
let tb = TreeBuilder::new(sink, options);
let tok = HtmlTokenizer::new(tb, Default::default());

ServoParser::new(
document, owner, Tokenizer::HTML(tok), LastChunkState::NotReceived)
},
ParseContext::Fragment(fc) => {
let tb = TreeBuilder::new_for_fragment(
sink,
JS::from_ref(fc.context_elem),
fc.form_elem.map(|n| JS::from_ref(n)),
options);

let tok_options = TokenizerOpts {
initial_state: Some(tb.tokenizer_state_for_context_elem()),
.. Default::default()
};
let tok = HtmlTokenizer::new(tb, tok_options);

ServoParser::new(
document, None, Tokenizer::HTML(tok), LastChunkState::Received)
}
};
parser.parse_chunk(String::from(input));
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.