Implement Element.matches(selectors)
http://dom.spec.whatwg.org/#dom-element-matches
No tested browser (Firefox Nightly, IE11 Release Preview, Opera 12.16)
has implemented the unprefixed API yet.
Having verified that the other browsers throw an exception for
*MatchesSelector(), make the argument to webkitMatchesSelector()
non-optional to align with them and the unprefixed API.
The spec requires throwing a TypeError when parsing the selectors
fails, but we currently throw a SyntaxError. So do the other browsers
for *MatchesSelector(), so file a spec bug instead of changing it:
https://www.w3.org/Bugs/Public/show_bug.cgi?id=24028
BUG=326652
Review URL: https://codereview.chromium.org/106983004
git-svn-id: svn://svn.chromium.org/blink/trunk@163442 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/fast/dom/Element/matches-expected.txt b/LayoutTests/fast/dom/Element/matches-expected.txt
new file mode 100644
index 0000000..5f31448
--- /dev/null
+++ b/LayoutTests/fast/dom/Element/matches-expected.txt
@@ -0,0 +1,18 @@
+PASS element.matches() threw exception TypeError: Failed to execute 'matches' on 'Element': 1 argument required, but only 0 present..
+PASS element.matches('body') is true
+PASS element.matches('html > .foo') is true
+PASS element.matches('html') is false
+PASS element.matches('html > .bar') is false
+PASS element.matches('') threw exception SyntaxError: Failed to execute 'matches' on 'Element': '' is not a valid selector..
+PASS element.matches('!invalid!') threw exception SyntaxError: Failed to execute 'matches' on 'Element': '!invalid!' is not a valid selector..
+PASS element.webkitMatchesSelector() threw exception TypeError: Failed to execute 'webkitMatchesSelector' on 'Element': 1 argument required, but only 0 present..
+PASS element.webkitMatchesSelector('body') is true
+PASS element.webkitMatchesSelector('html > .foo') is true
+PASS element.webkitMatchesSelector('html') is false
+PASS element.webkitMatchesSelector('html > .bar') is false
+PASS element.webkitMatchesSelector('') threw exception SyntaxError: Failed to execute 'webkitMatchesSelector' on 'Element': '' is not a valid selector..
+PASS element.webkitMatchesSelector('!invalid!') threw exception SyntaxError: Failed to execute 'webkitMatchesSelector' on 'Element': '!invalid!' is not a valid selector..
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Element/matches.html b/LayoutTests/fast/dom/Element/matches.html
new file mode 100644
index 0000000..88eb7e7
--- /dev/null
+++ b/LayoutTests/fast/dom/Element/matches.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+</head>
+<body class="foo">
+<script>
+var element = document.body;
+["matches", "webkitMatchesSelector"].forEach(function(func)
+{
+ shouldThrow("element." + func + "()");
+ shouldBeTrue("element." + func + "('body')");
+ shouldBeTrue("element." + func + "('html > .foo')");
+ shouldBeFalse("element." + func + "('html')");
+ shouldBeFalse("element." + func + "('html > .bar')");
+ shouldThrow("element." + func + "('')");
+ shouldThrow("element." + func + "('!invalid!')");
+});
+</script>
+</body>
+</html>
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index f0b7b12..f1c68f7 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -2690,14 +2690,9 @@
return 0;
}
-bool Element::webkitMatchesSelector(const String& selector, ExceptionState& exceptionState)
+bool Element::matches(const String& selectors, ExceptionState& exceptionState)
{
- if (selector.isEmpty()) {
- exceptionState.throwUninformativeAndGenericDOMException(SyntaxError);
- return false;
- }
-
- SelectorQuery* selectorQuery = document().selectorQueryCache().add(selector, document(), exceptionState);
+ SelectorQuery* selectorQuery = document().selectorQueryCache().add(selectors, document(), exceptionState);
if (!selectorQuery)
return false;
return selectorQuery->matches(*this);
diff --git a/Source/core/dom/Element.h b/Source/core/dom/Element.h
index 2ff1f47..a95423c 100644
--- a/Source/core/dom/Element.h
+++ b/Source/core/dom/Element.h
@@ -421,7 +421,7 @@
virtual bool matchesReadOnlyPseudoClass() const { return false; }
virtual bool matchesReadWritePseudoClass() const { return false; }
- bool webkitMatchesSelector(const String& selectors, ExceptionState&);
+ bool matches(const String& selectors, ExceptionState&);
virtual bool shouldAppearIndeterminate() const { return false; }
DOMTokenList* classList();
diff --git a/Source/core/dom/Element.idl b/Source/core/dom/Element.idl
index 807ed3b..cbfd8ae 100644
--- a/Source/core/dom/Element.idl
+++ b/Source/core/dom/Element.idl
@@ -62,6 +62,8 @@
[TreatReturnedNullStringAs=Null, TreatNullAs=NullString, PerWorldBindings, RaisesException=Setter] attribute DOMString prefix;
[TreatReturnedNullStringAs=Null, PerWorldBindings] readonly attribute DOMString localName;
+ [RaisesException] boolean matches(DOMString selectors);
+
// Common extensions
[PerWorldBindings] readonly attribute long offsetLeft;
@@ -103,7 +105,7 @@
[RaisesException] NodeList querySelectorAll(DOMString selectors);
// WebKit extension
- [RaisesException, MeasureAs=ElementPrefixedMatchesSelector] boolean webkitMatchesSelector([Default=Undefined] optional DOMString selectors);
+ [RaisesException, ImplementedAs=matches, MeasureAs=ElementPrefixedMatchesSelector] boolean webkitMatchesSelector(DOMString selectors);
// Shadow DOM API
[RuntimeEnabled=ShadowDOM, Reflect, TreatNullAs=NullString, PerWorldBindings] attribute DOMString pseudo;
diff --git a/Source/core/inspector/InspectorCSSAgent.cpp b/Source/core/inspector/InspectorCSSAgent.cpp
index b369361..da2d87a 100644
--- a/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/Source/core/inspector/InspectorCSSAgent.cpp
@@ -1622,7 +1622,7 @@
bool matched = false;
if (elementPseudoId)
matched = matchesPseudoElement(selector, elementPseudoId); // Modifies |selector|.
- matched |= element->webkitMatchesSelector(firstTagHistorySelector->selectorText(), IGNORE_EXCEPTION);
+ matched |= element->matches(firstTagHistorySelector->selectorText(), IGNORE_EXCEPTION);
if (matched)
matchingSelectors->addItem(index);
++index;