mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Implement Element#closest
fixes #4603 - Add definition to the Element.webidl and implementation to element.rs. - Create inclusive_ancestors helper in NodeHelpers - Update test expectations
This commit is contained in:
parent
2a9acdcb73
commit
7759358e09
6 changed files with 27 additions and 83 deletions
|
@ -1120,6 +1120,23 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#dom-element-closest
|
||||||
|
fn Closest(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> {
|
||||||
|
let parser_context = ParserContext {
|
||||||
|
origin: StylesheetOrigin::Author,
|
||||||
|
};
|
||||||
|
match style::parse_selector_list_from_str(&parser_context, selectors.as_slice()) {
|
||||||
|
Err(()) => Err(Syntax),
|
||||||
|
Ok(ref selectors) => {
|
||||||
|
let root: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
Ok(root.inclusive_ancestors()
|
||||||
|
.filter_map(ElementCast::to_ref)
|
||||||
|
.find(|element| matches(selectors, &NodeCast::from_ref(*element), &mut None))
|
||||||
|
.map(Temporary::from_rooted))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_attribute_parts<'a>(name: &'a str) -> (Option<&'a str>, &'a str) {
|
pub fn get_attribute_parts<'a>(name: &'a str) -> (Option<&'a str>, &'a str) {
|
||||||
|
|
|
@ -397,6 +397,7 @@ impl<'a> Iterator<JSRef<'a, Node>> for QuerySelectorIterator<'a> {
|
||||||
|
|
||||||
pub trait NodeHelpers<'a> {
|
pub trait NodeHelpers<'a> {
|
||||||
fn ancestors(self) -> AncestorIterator<'a>;
|
fn ancestors(self) -> AncestorIterator<'a>;
|
||||||
|
fn inclusive_ancestors(self) -> AncestorIterator<'a>;
|
||||||
fn children(self) -> NodeChildrenIterator<'a>;
|
fn children(self) -> NodeChildrenIterator<'a>;
|
||||||
fn rev_children(self) -> ReverseChildrenIterator;
|
fn rev_children(self) -> ReverseChildrenIterator;
|
||||||
fn child_elements(self) -> ChildElementIterator<'a>;
|
fn child_elements(self) -> ChildElementIterator<'a>;
|
||||||
|
@ -798,6 +799,12 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inclusive_ancestors(self) -> AncestorIterator<'a> {
|
||||||
|
AncestorIterator {
|
||||||
|
current: Some(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn owner_doc(self) -> Temporary<Document> {
|
fn owner_doc(self) -> Temporary<Document> {
|
||||||
self.owner_doc.get().unwrap()
|
self.owner_doc.get().unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,9 @@ interface Element : Node {
|
||||||
boolean hasAttribute(DOMString name);
|
boolean hasAttribute(DOMString name);
|
||||||
boolean hasAttributeNS(DOMString? namespace, DOMString localName);
|
boolean hasAttributeNS(DOMString? namespace, DOMString localName);
|
||||||
|
|
||||||
|
[Throws]
|
||||||
|
Element? closest(DOMString selectors);
|
||||||
|
|
||||||
[Throws]
|
[Throws]
|
||||||
boolean matches(DOMString selectors);
|
boolean matches(DOMString selectors);
|
||||||
|
|
||||||
|
|
|
@ -285,9 +285,6 @@
|
||||||
[Element interface: operation removeAttributeNode(Attr)]
|
[Element interface: operation removeAttributeNode(Attr)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Element interface: operation closest(DOMString)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element interface: attribute firstElementChild]
|
[Element interface: attribute firstElementChild]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -357,12 +354,6 @@
|
||||||
[Element interface: calling removeAttributeNode(Attr) on element with too few arguments must throw TypeError]
|
[Element interface: calling removeAttributeNode(Attr) on element with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Element interface: element must inherit property "closest" with the proper type (22)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element interface: calling closest(DOMString) on element with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element interface: element must inherit property "firstElementChild" with the proper type (28)]
|
[Element interface: element must inherit property "firstElementChild" with the proper type (28)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,77 +1,9 @@
|
||||||
[Element-closest.html]
|
[Element-closest.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[Element.closest with context node \'test12\' and selector \'select\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test13\' and selector \'fieldset\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test13\' and selector \'div\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test3\' and selector \'body\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test4\' and selector \'[default\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test4\' and selector \'[selected\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test11\' and selector \'[selected\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test12\' and selector \'[name="form-a"\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test13\' and selector \'form[name="form-a"\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test9\' and selector \'input[required\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test9\' and selector \'select[required\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test13\' and selector \'div:not(.div1)\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test6\' and selector \'div.div3\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test1\' and selector \'div#test7\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test12\' and selector \'.div3 > .div2\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test12\' and selector \'.div3 > .div1\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test9\' and selector \'form > input[required\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test12\' and selector \'fieldset > select[required\]\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test6\' and selector \'input + fieldset\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test3\' and selector \'form + form\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test5\' and selector \'form + form\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test10\' and selector \':empty\']
|
[Element.closest with context node \'test10\' and selector \':empty\']
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Element.closest with context node \'test11\' and selector \':last-child\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test12\' and selector \':first-child\']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element.closest with context node \'test11\' and selector \':invalid\']
|
[Element.closest with context node \'test11\' and selector \':invalid\']
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1488,12 +1488,6 @@
|
||||||
[Element interface: calling removeAttributeNode(Attr) on document.createElement("noscript") with too few arguments must throw TypeError]
|
[Element interface: calling removeAttributeNode(Attr) on document.createElement("noscript") with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Element interface: document.createElement("noscript") must inherit property "closest" with the proper type (22)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element interface: calling closest(DOMString) on document.createElement("noscript") with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Element interface: document.createElement("noscript") must inherit property "firstElementChild" with the proper type (28)]
|
[Element interface: document.createElement("noscript") must inherit property "firstElementChild" with the proper type (28)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue