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: