diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 34791c3417c..5b7c9ecf4aa 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -119,6 +119,25 @@ pub enum ElementCreator { ScriptCreated, } +pub enum AdjacentPosition { + BeforeBegin, + AfterEnd, + AfterBegin, + BeforeEnd, +} + +impl AdjacentPosition { + pub fn parse(position: &str) -> Fallible { + match_ignore_ascii_case! { &*position, + "beforebegin" => Ok(AdjacentPosition::BeforeBegin), + "afterbegin" => Ok(AdjacentPosition::AfterBegin), + "beforeend" => Ok(AdjacentPosition::BeforeEnd), + "afterend" => Ok(AdjacentPosition::AfterEnd), + _ => Err(Error::Syntax) + } + } +} + // // Element methods // @@ -1252,31 +1271,30 @@ impl Element { } // https://dom.spec.whatwg.org/#insert-adjacent - pub fn insert_adjacent(&self, where_: DOMString, node: &Node) + pub fn insert_adjacent(&self, where_: AdjacentPosition, node: &Node) -> Fallible>> { let self_node = self.upcast::(); - match &*where_ { - "beforebegin" => { + match where_ { + AdjacentPosition::BeforeBegin => { if let Some(parent) = self_node.GetParentNode() { Node::pre_insert(node, &parent, Some(self_node)).map(Some) } else { Ok(None) } } - "afterbegin" => { + AdjacentPosition::AfterBegin => { Node::pre_insert(node, &self_node, self_node.GetFirstChild().r()).map(Some) } - "beforeend" => { + AdjacentPosition::BeforeEnd => { Node::pre_insert(node, &self_node, None).map(Some) } - "afterend" => { + AdjacentPosition::AfterEnd => { if let Some(parent) = self_node.GetParentNode() { Node::pre_insert(node, &parent, self_node.GetNextSibling().r()).map(Some) } else { Ok(None) } } - _ => Err(Error::Syntax) } } @@ -1995,6 +2013,7 @@ impl ElementMethods for Element { // https://dom.spec.whatwg.org/#dom-element-insertadjacentelement fn InsertAdjacentElement(&self, where_: DOMString, element: &Element) -> Fallible>> { + let where_ = try!(AdjacentPosition::parse(&*where_)); let inserted_node = try!(self.insert_adjacent(where_, element.upcast())); Ok(inserted_node.map(|node| Root::downcast(node).unwrap())) } @@ -2006,8 +2025,44 @@ impl ElementMethods for Element { let text = Text::new(data, &document_from_node(self)); // Step 2. + let where_ = try!(AdjacentPosition::parse(&*where_)); self.insert_adjacent(where_, text.upcast()).map(|_| ()) } + + // https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml + fn InsertAdjacentHTML(&self, position: DOMString, text: DOMString) + -> ErrorResult { + // Step 1. + let position = try!(AdjacentPosition::parse(&*position)); + + let context = match position { + AdjacentPosition::BeforeBegin | AdjacentPosition::AfterEnd => { + match self.upcast::().GetParentNode() { + Some(ref node) if node.is::() => { + return Err(Error::NoModificationAllowed) + } + None => return Err(Error::NoModificationAllowed), + Some(node) => node, + } + } + AdjacentPosition::AfterBegin | AdjacentPosition::BeforeEnd => { + Root::from_ref(self.upcast::()) + } + }; + + // Step 2. + let context = match context.downcast::() { + Some(elem) if elem.local_name() != &atom!("html") || + !elem.html_element_in_html_document() => Root::from_ref(elem), + _ => Root::upcast(HTMLBodyElement::new(atom!("body"), None, &*context.owner_doc())) + }; + + // Step 3. + let fragment = try!(context.upcast::().parse_fragment(text)); + + // Step 4. + context.insert_adjacent(position, fragment.upcast()).map(|_| ()) + } } pub fn fragment_affecting_attributes() -> [Atom; 3] { diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl index ee27b78d4e4..48aeed7fbbb 100644 --- a/components/script/dom/webidls/Element.webidl +++ b/components/script/dom/webidls/Element.webidl @@ -75,6 +75,8 @@ interface Element : Node { Element? insertAdjacentElement(DOMString where_, Element element); // historical [Throws] void insertAdjacentText(DOMString where_, DOMString data); + [Throws] + void insertAdjacentHTML(DOMString position, DOMString html); }; // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-element-interface diff --git a/components/script/lib.rs b/components/script/lib.rs index c2aa794719f..50b0c47ac6b 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -38,6 +38,7 @@ extern crate canvas; extern crate canvas_traits; extern crate caseless; extern crate core; +#[macro_use] extern crate cssparser; extern crate devtools_traits; extern crate encoding; diff --git a/tests/wpt/metadata/domparsing/insert-adjacent.html.ini b/tests/wpt/metadata/domparsing/insert-adjacent.html.ini index af6749ad7d2..10a4345eeb0 100644 --- a/tests/wpt/metadata/domparsing/insert-adjacent.html.ini +++ b/tests/wpt/metadata/domparsing/insert-adjacent.html.ini @@ -3,12 +3,6 @@ [insertAdjacentHTML(beforebegin,

beforebegin

)] expected: FAIL - [insertAdjacentHTML(afterbegin,

afterbegin

)] - expected: FAIL - - [insertAdjacentHTML(beforeend,

beforeend

)] - expected: FAIL - [insertAdjacentHTML(afterend,

afterend

)] expected: FAIL diff --git a/tests/wpt/metadata/domparsing/insert_adjacent_html.html.ini b/tests/wpt/metadata/domparsing/insert_adjacent_html.html.ini index a1028c07ebe..552aaec582f 100644 --- a/tests/wpt/metadata/domparsing/insert_adjacent_html.html.ini +++ b/tests/wpt/metadata/domparsing/insert_adjacent_html.html.ini @@ -3,87 +3,30 @@ [beforeBegin content without next sibling] expected: FAIL - [Afterbegin content without next sibling] - expected: FAIL - - [BeforeEnd content without next sibling] - expected: FAIL - [afterend content without next sibling] expected: FAIL [beforeBegin content again, with next sibling] expected: FAIL - [Afterbegin content again, with next sibling] - expected: FAIL - - [BeforeEnd content again, with next sibling] - expected: FAIL - [afterend content again, with next sibling] expected: FAIL - [Should throw when inserting with invalid position string] - expected: FAIL - - [When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (text)] - expected: FAIL - - [When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (comments)] - expected: FAIL - - [When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (elements)] - expected: FAIL - - [When the parent node is a document, insertAdjacentHTML should throw for beforebegin and afterend (text)] - expected: FAIL - - [When the parent node is a document, insertAdjacentHTML should throw for beforebegin and afterend (comments)] - expected: FAIL - - [When the parent node is a document, insertAdjacentHTML should throw for beforebegin and afterend (elements)] - expected: FAIL - - [Inserting after being and before end should order things correctly] - expected: FAIL - [beforeBegin child node not in tree but has parent] expected: FAIL - [Afterbegin child node not in tree but has parent] - expected: FAIL - - [BeforeEnd child node not in tree but has parent] - expected: FAIL - [afterend child node not in tree but has parent] expected: FAIL [beforeBegin content2 without next sibling] expected: FAIL - [Afterbegin content2 without next sibling] - expected: FAIL - - [BeforeEnd content2 without next sibling] - expected: FAIL - [afterend content2 without next sibling] expected: FAIL [beforeBegin content2 test again, now that there's a next sibling] expected: FAIL - [Afterbegin content2 test again, now that there's a next sibling] - expected: FAIL - - [BeforeEnd content2 test again, now that there's a next sibling] - expected: FAIL - [afterend content2 test again, now that there's a next sibling] expected: FAIL - [Inserting kids of the element should not do weird things with implied / tags] - expected: FAIL - diff --git a/tests/wpt/metadata/domparsing/insert_adjacent_html.xhtml.ini b/tests/wpt/metadata/domparsing/insert_adjacent_html.xhtml.ini index 5ceb4830cb7..9312a8de81a 100644 --- a/tests/wpt/metadata/domparsing/insert_adjacent_html.xhtml.ini +++ b/tests/wpt/metadata/domparsing/insert_adjacent_html.xhtml.ini @@ -3,84 +3,30 @@ [beforeBegin content without next sibling] expected: FAIL - [Afterbegin content without next sibling] - expected: FAIL - - [BeforeEnd content without next sibling] - expected: FAIL - [afterend content without next sibling] expected: FAIL [beforeBegin content again, with next sibling] expected: FAIL - [Afterbegin content again, with next sibling] - expected: FAIL - - [BeforeEnd content again, with next sibling] - expected: FAIL - [afterend content again, with next sibling] expected: FAIL - [Should throw when inserting with invalid position string] - expected: FAIL - - [When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (text)] - expected: FAIL - - [When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (comments)] - expected: FAIL - - [When the parent node is null, insertAdjacentHTML should throw for beforebegin and afterend (elements)] - expected: FAIL - - [When the parent node is a document, insertAdjacentHTML should throw for beforebegin and afterend (text)] - expected: FAIL - - [When the parent node is a document, insertAdjacentHTML should throw for beforebegin and afterend (comments)] - expected: FAIL - - [When the parent node is a document, insertAdjacentHTML should throw for beforebegin and afterend (elements)] - expected: FAIL - - [Inserting after being and before end should order things correctly] - expected: FAIL - [beforeBegin child node not in tree but has parent] expected: FAIL - [Afterbegin child node not in tree but has parent] - expected: FAIL - - [BeforeEnd child node not in tree but has parent] - expected: FAIL - [afterend child node not in tree but has parent] expected: FAIL [beforeBegin content2 without next sibling] expected: FAIL - [Afterbegin content2 without next sibling] - expected: FAIL - - [BeforeEnd content2 without next sibling] - expected: FAIL - [afterend content2 without next sibling] expected: FAIL [beforeBegin content2 test again, now that there's a next sibling] expected: FAIL - [Afterbegin content2 test again, now that there's a next sibling] - expected: FAIL - - [BeforeEnd content2 test again, now that there's a next sibling] - expected: FAIL - [afterend content2 test again, now that there's a next sibling] expected: FAIL