From a89bbc990674a64eb0a4e0648c3eafc0b9f36b02 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 6 Jan 2017 12:39:45 +0100 Subject: [PATCH 1/3] Update html5ever to 0.12.1 --- Cargo.lock | 6 +++--- components/script/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ed4633f743..8317631b3d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1103,7 +1103,7 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.10.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2263,7 +2263,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever-atoms 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3413,7 +3413,7 @@ dependencies = [ "checksum heartbeats-simple 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "78c0810722eacd0bdd3f1f691524bd9900bf8fed1947f6b883c10ddecd2560b1" "checksum heartbeats-simple-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53c4b67617665d7f4172f381f9843c1bec6a4fccc9a9226529e5b1be40dc1301" "checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58" -"checksum html5ever 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45815593feb142cf01121b9f413d8630c9902192d160e494a579c50628eef498" +"checksum html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a358fef34c3334e92cd34d83ce870a386334e605e7abe987a69a7078a4142c69" "checksum html5ever-atoms 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fd3fc831590ee7fcf693c673e4e3cbe14fbda44dc0f26d9bdc79cfc9f551dc05" "checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" "checksum hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb3fc65554155980167fb821d05c7c66177f92464976c0b676a19d9e03387a7" diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 4be7dff4a39..cd5750be9d4 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -38,7 +38,7 @@ fnv = "1.0" gfx_traits = {path = "../gfx_traits"} heapsize = "0.3.6" heapsize_derive = "0.1" -html5ever = {version = "0.10.2", features = ["heap_size", "unstable"]} +html5ever = {version = "0.12.1", features = ["heap_size", "unstable"]} html5ever-atoms = {version = "0.1", features = ["heap_size"]} hyper = "0.9.9" hyper_serde = "0.1.4" From 8caa56454002a66c7c73e7144da20731725b8edf Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 6 Jan 2017 12:55:16 +0100 Subject: [PATCH 2/3] Update xml5ever to 0.3.0 --- Cargo.lock | 6 +++--- components/script/Cargo.toml | 2 +- components/script/dom/servoparser/xml.rs | 9 +++++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8317631b3d7..c8186923756 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2308,7 +2308,7 @@ dependencies = [ "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_traits 0.11.0 (git+https://github.com/servo/webrender)", "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", - "xml5ever 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xml5ever 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3309,7 +3309,7 @@ dependencies = [ [[package]] name = "xml5ever" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "html5ever-atoms 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3581,4 +3581,4 @@ dependencies = [ "checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453" "checksum xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "315c4e158d7fa277e3ea35b32e50bc07e9a0c8de9130a7cc4bdeab42ddc7b442" "checksum xml-rs 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b15eed12692bd59d15e98ee7f8dc8408465b992d8ddb4d1672c24865132ec7" -"checksum xml5ever 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3aa816561c8d68419dec4c43df33974940cd6a03e376dfc497ec3e46fb7755" +"checksum xml5ever 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d3c01f8de37eb0e091996e9ecd23a4d6eefb821cd0e4d36c0e890343ddb1dd1e" diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index cd5750be9d4..10ea03bc548 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -81,7 +81,7 @@ time = "0.1.12" url = {version = "1.2", features = ["heap_size", "query_encoding"]} uuid = {version = "0.3.1", features = ["v4"]} websocket = "0.17" -xml5ever = {version = "0.2", features = ["unstable"]} +xml5ever = {version = "0.3.1", features = ["unstable"]} [dependencies.webrender_traits] git = "https://github.com/servo/webrender" diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs index 616263651c3..74b49fedd1c 100644 --- a/components/script/dom/servoparser/xml.rs +++ b/components/script/dom/servoparser/xml.rs @@ -42,7 +42,7 @@ impl Tokenizer { script: Default::default(), }; - let tb = XmlTreeBuilder::new(sink); + let tb = XmlTreeBuilder::new(sink, Default::default()); let tok = XmlTokenizer::new(tb, Default::default()); Tokenizer { @@ -100,9 +100,14 @@ struct Sink { script: MutNullableJS, } -impl<'a> TreeSink for Sink { +impl TreeSink for Sink { + type Output = Self; type Handle = JS; + fn finish(self) -> Self { + self + } + fn parse_error(&mut self, msg: Cow<'static, str>) { debug!("Parse error: {}", msg); } From 0cb09468a0e39b7797f3cd540b8d47e0e1ba55a0 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 6 Jan 2017 16:16:48 +0100 Subject: [PATCH 3/3] Properly insert text in document when parsing If the last child of a node is a Text child and we are inserting text in that node, we need to append it to that Text child. Doing that means that HTMLStyleElement::children_changed gets called less frequently, but that's not a problem during parsing thanks to the pop hook. --- components/script/dom/htmlstyleelement.rs | 36 ++++++++++++++----- components/script/dom/htmltextareaelement.rs | 7 ++++ components/script/dom/servoparser/html.rs | 18 +++++++--- components/script/dom/servoparser/xml.rs | 6 ++++ components/script/dom/virtualmethods.rs | 8 +++++ .../open-url-javascript-window-2.htm.ini | 2 +- .../open-url-javascript-window.htm.ini | 2 +- .../document-write/051.html.ini | 5 --- ...invoke-insert-source-networkState.html.ini | 2 +- ...oke-insert-source-not-in-document.html.ini | 2 +- ...ce-selection-invoke-insert-source.html.ini | 2 +- .../resource-selection-remove-source.html.ini | 2 +- .../resource-selection-source-media.html.ini | 2 +- .../html/syntax/parsing/math-parse01.html.ini | 3 -- .../compile-error-cross-origin.html.ini | 2 +- .../runtime-error-cross-origin.html.ini | 2 +- .../tests/mozilla/iframe_hierarchy.html | 2 +- 17 files changed, 72 insertions(+), 31 deletions(-) delete mode 100644 tests/wpt/metadata/html/dom/dynamic-markup-insertion/document-write/051.html.ini diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 2507f7bee35..97fd6591de8 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -36,6 +36,7 @@ pub struct HTMLStyleElement { cssom_stylesheet: MutNullableJS, /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts parser_inserted: Cell, + in_stack_of_open_elements: Cell, pending_loads: Cell, any_failed_load: Cell, } @@ -50,6 +51,7 @@ impl HTMLStyleElement { stylesheet: DOMRefCell::new(None), cssom_stylesheet: MutNullableJS::new(None), parser_inserted: Cell::new(creator == ElementCreator::ParserCreated), + in_stack_of_open_elements: Cell::new(creator == ElementCreator::ParserCreated), pending_loads: Cell::new(0), any_failed_load: Cell::new(false), } @@ -124,20 +126,38 @@ impl VirtualMethods for HTMLStyleElement { } fn children_changed(&self, mutation: &ChildrenMutation) { - if let Some(ref s) = self.super_type() { - s.children_changed(mutation); - } - if self.upcast::().is_in_doc() { + self.super_type().unwrap().children_changed(mutation); + + // https://html.spec.whatwg.org/multipage/#update-a-style-block + // Handles the case when: + // "The element is not on the stack of open elements of an HTML parser or XML parser, + // and one of its child nodes is modified by a script." + // TODO: Handle Text child contents being mutated. + if self.upcast::().is_in_doc() && !self.in_stack_of_open_elements.get() { self.parse_own_css(); } } fn bind_to_tree(&self, tree_in_doc: bool) { - if let Some(ref s) = self.super_type() { - s.bind_to_tree(tree_in_doc); - } + self.super_type().unwrap().bind_to_tree(tree_in_doc); - if tree_in_doc { + // https://html.spec.whatwg.org/multipage/#update-a-style-block + // Handles the case when: + // "The element is not on the stack of open elements of an HTML parser or XML parser, + // and it becomes connected or disconnected." + if tree_in_doc && !self.in_stack_of_open_elements.get() { + self.parse_own_css(); + } + } + + fn pop(&self) { + self.super_type().unwrap().pop(); + + // https://html.spec.whatwg.org/multipage/#update-a-style-block + // Handles the case when: + // "The element is popped off the stack of open elements of an HTML parser or XML parser." + self.in_stack_of_open_elements.set(false); + if self.upcast::().is_in_doc() { self.parse_own_css(); } } diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 2582b13514a..c6fd4d6b170 100755 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -425,6 +425,13 @@ impl VirtualMethods for HTMLTextAreaElement { } } } + + fn pop(&self) { + self.super_type().unwrap().pop(); + + // https://html.spec.whatwg.org/multipage/#the-textarea-element:stack-of-open-elements + self.reset(); + } } impl FormControl for HTMLTextAreaElement {} diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs index 28f8735891e..4a8f01d639e 100644 --- a/components/script/dom/servoparser/html.rs +++ b/components/script/dom/servoparser/html.rs @@ -20,6 +20,7 @@ use dom::htmltemplateelement::HTMLTemplateElement; use dom::node::Node; use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; +use dom::virtualmethods::vtable_for; use html5ever::Attribute; use html5ever::serialize::{AttrRef, Serializable, Serializer}; use html5ever::serialize::TraversalScope; @@ -124,7 +125,7 @@ struct Sink { document: JS, } -impl<'a> TreeSink for Sink { +impl TreeSink for Sink { type Output = Self; fn finish(self) -> Self { self } @@ -233,7 +234,11 @@ impl<'a> TreeSink for Sink { while let Some(ref child) = node.GetFirstChild() { new_parent.AppendChild(&child).unwrap(); } + } + fn pop(&mut self, node: JS) { + let node = Root::from_ref(&*node); + vtable_for(&node).pop(); } } @@ -243,10 +248,13 @@ fn insert(parent: &Node, reference_child: Option<&Node>, child: NodeOrText { - // FIXME(ajeffrey): convert directly from tendrils to DOMStrings - let s: String = t.into(); - let text = Text::new(DOMString::from(s), &parent.owner_doc()); - assert!(parent.InsertBefore(text.upcast(), reference_child).is_ok()); + if let Some(text) = parent.GetLastChild().and_then(Root::downcast::) { + text.upcast::().append_data(&t); + } else { + let s: String = t.into(); + let text = Text::new(DOMString::from(s), &parent.owner_doc()); + parent.InsertBefore(text.upcast(), reference_child).unwrap(); + } } } } diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs index 74b49fedd1c..6bab196d7ee 100644 --- a/components/script/dom/servoparser/xml.rs +++ b/components/script/dom/servoparser/xml.rs @@ -17,6 +17,7 @@ use dom::htmlscriptelement::HTMLScriptElement; use dom::node::Node; use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; +use dom::virtualmethods::vtable_for; use html5ever::tokenizer::buffer_queue::BufferQueue; use html5ever_atoms::{Prefix, QualName}; use js::jsapi::JSTracer; @@ -196,4 +197,9 @@ impl TreeSink for Sink { NextParserState::Continue } } + + fn pop(&mut self, node: Self::Handle) { + let node = Root::from_ref(&*node); + vtable_for(&node).pop(); + } } diff --git a/components/script/dom/virtualmethods.rs b/components/script/dom/virtualmethods.rs index e10e48e8ab8..d6b77b31256 100644 --- a/components/script/dom/virtualmethods.rs +++ b/components/script/dom/virtualmethods.rs @@ -124,6 +124,14 @@ pub trait VirtualMethods { s.cloning_steps(copy, maybe_doc, clone_children); } } + + /// Called on an element when it is popped off the stack of open elements + /// of a parser. + fn pop(&self) { + if let Some(ref s) = self.super_type() { + s.pop(); + } + } } /// Obtain a VirtualMethods instance for a given Node-derived object. Any diff --git a/tests/wpt/metadata/XMLHttpRequest/open-url-javascript-window-2.htm.ini b/tests/wpt/metadata/XMLHttpRequest/open-url-javascript-window-2.htm.ini index f48486261eb..8f9dc0ea819 100644 --- a/tests/wpt/metadata/XMLHttpRequest/open-url-javascript-window-2.htm.ini +++ b/tests/wpt/metadata/XMLHttpRequest/open-url-javascript-window-2.htm.ini @@ -1,6 +1,6 @@ [open-url-javascript-window-2.htm] type: testharness expected: TIMEOUT - [XMLHttpRequest: open() - resolving URLs (javascript: ] + [XMLHttpRequest: open() - resolving URLs (javascript: