Auto merge of #11668 - GuillaumeGomez:insert_adjacent, r=nox

Insert adjacent

Fixes #11622.

r? @nox

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11668)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-06-08 08:29:42 -05:00
commit da5007ef1c
6 changed files with 65 additions and 124 deletions

View file

@ -119,6 +119,25 @@ pub enum ElementCreator {
ScriptCreated,
}
pub enum AdjacentPosition {
BeforeBegin,
AfterEnd,
AfterBegin,
BeforeEnd,
}
impl AdjacentPosition {
pub fn parse(position: &str) -> Fallible<AdjacentPosition> {
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<Option<Root<Node>>> {
let self_node = self.upcast::<Node>();
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<Option<Root<Element>>> {
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::<Node>().GetParentNode() {
Some(ref node) if node.is::<Document>() => {
return Err(Error::NoModificationAllowed)
}
None => return Err(Error::NoModificationAllowed),
Some(node) => node,
}
}
AdjacentPosition::AfterBegin | AdjacentPosition::BeforeEnd => {
Root::from_ref(self.upcast::<Node>())
}
};
// Step 2.
let context = match context.downcast::<Element>() {
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::<Node>().parse_fragment(text));
// Step 4.
context.insert_adjacent(position, fragment.upcast()).map(|_| ())
}
}
pub fn fragment_affecting_attributes() -> [Atom; 3] {

View file

@ -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

View file

@ -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;

View file

@ -3,12 +3,6 @@
[insertAdjacentHTML(beforebegin, <h3>beforebegin</h3> )]
expected: FAIL
[insertAdjacentHTML(afterbegin, <h3>afterbegin</h3> )]
expected: FAIL
[insertAdjacentHTML(beforeend, <h3>beforeend</h3> )]
expected: FAIL
[insertAdjacentHTML(afterend, <h3>afterend</h3> )]
expected: FAIL

View file

@ -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 <html> element should not do weird things with implied <body>/<head> tags]
expected: FAIL

View file

@ -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