Title: [204591] trunk
Revision
204591
Author
[email protected]
Date
2016-08-17 23:22:40 -0700 (Wed, 17 Aug 2016)

Log Message

[CSS] The parser should not get rid of empty namespace specification in front of element name selectors
https://bugs.webkit.org/show_bug.cgi?id=160936

Reviewed by Chris Dumez.

LayoutTests/imported/w3c:

* web-platform-tests/dom/nodes/ParentNode-querySelector-All-expected.txt:
* web-platform-tests/dom/nodes/ParentNode-querySelector-All-xht-expected.txt:

Source/WebCore:

There are two places where you can specify an empty namespace
in selectors:
    - Element name (e.g. "|name")
    - Attribute name (e.g. "[|name]")
In the first case, if we have an empty namespace, the selector
should match that.
In the second case, the default namespace of attribute is already
empty so it is just the same as "[name]".

Our code was just discarding any empty namespace. This is fine
for attributes but for names that is transforming "|name" into "name"
which is invalid.

This patch updates those cases to differentiate:
- Null prefix -> There was no namespace specified.
- Empty prefix -> There was a namespace prefix and it is empty.

Test: fast/selectors/empty-namespace-with-element-selector.html

* css/CSSGrammar.y.in:
* css/CSSParser.cpp:
(WebCore::CSSParser::determineNameInNamespace):
(WebCore::CSSParser::rewriteSpecifiersWithNamespaceIfNeeded):
(WebCore::CSSParser::rewriteSpecifiersWithElementName):
* css/CSSParser.h:
* css/CSSSelector.cpp:
(WebCore::CSSSelector::selectorText):
* css/CSSSelectorList.cpp:
(WebCore::SelectorNeedsNamespaceResolutionFunctor::operator()):
* css/StyleSheetContents.cpp:
(WebCore::StyleSheetContents::determineNamespace): Deleted.

LayoutTests:

* fast/css/css-selector-text-expected.txt:
* fast/css/css-selector-text.html:
* fast/css/css-set-selector-text-expected.txt:
* fast/css/css-set-selector-text.html:
* fast/selectors/empty-namespace-with-element-selector-expected.txt: Added.
* fast/selectors/empty-namespace-with-element-selector.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (204590 => 204591)


--- trunk/LayoutTests/ChangeLog	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/ChangeLog	2016-08-18 06:22:40 UTC (rev 204591)
@@ -1,3 +1,17 @@
+2016-08-17  Benjamin Poulain  <[email protected]>
+
+        [CSS] The parser should not get rid of empty namespace specification in front of element name selectors
+        https://bugs.webkit.org/show_bug.cgi?id=160936
+
+        Reviewed by Chris Dumez.
+
+        * fast/css/css-selector-text-expected.txt:
+        * fast/css/css-selector-text.html:
+        * fast/css/css-set-selector-text-expected.txt:
+        * fast/css/css-set-selector-text.html:
+        * fast/selectors/empty-namespace-with-element-selector-expected.txt: Added.
+        * fast/selectors/empty-namespace-with-element-selector.html: Added.
+
 2016-08-17  Chris Fleizach  <[email protected]>
 
         AX: Support abbreviations in iOS

Modified: trunk/LayoutTests/fast/css/css-selector-text-expected.txt (204590 => 204591)


--- trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2016-08-18 06:22:40 UTC (rev 204591)
@@ -26,8 +26,11 @@
 PASS parseThenSerializeRule('n|a { }') is 'n|a { }'
 PASS parseThenSerializeRule('*|* { }') is '*|* { }'
 PASS parseThenSerializeRule('n|* { }') is 'n|* { }'
+PASS parseThenSerializeRule('|a { }') is '|a { }'
+PASS parseThenSerializeRule('|* { }') is '|* { }'
 PASS parseThenSerializeRule('[*|a] { }') is '[*|a] { }'
 PASS parseThenSerializeRule('[n|a] { }') is '[n|a] { }'
+PASS parseThenSerializeRule('[|a] { }') is '[a] { }'
 
 PASS parseThenSerializeRule('a:active { }') is 'a:active { }'
 PASS parseThenSerializeRule('a b { }') is 'a b { }'
@@ -253,7 +256,6 @@
 PASS parseThenSerializeRule(':not(:any-link) { }') is ':not(:any-link) { }'
 
 PASS parseThenSerializeRule('*:active { }') is ':active { }'
-PASS parseThenSerializeRule('|a { }') is 'a { }'
 
 PASS parseThenSerializeRule('input[type=file]:focus { }') is 'input[type="file"]:focus { }'
 

Modified: trunk/LayoutTests/fast/css/css-selector-text.html (204590 => 204591)


--- trunk/LayoutTests/fast/css/css-selector-text.html	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/fast/css/css-selector-text.html	2016-08-18 06:22:40 UTC (rev 204591)
@@ -77,8 +77,11 @@
 testSelectorRoundTrip('n|a');
 testSelectorRoundTrip('*|*');
 testSelectorRoundTrip('n|*');
+testSelectorRoundTrip('|a');
+testSelectorRoundTrip('|*');
 testSelectorRoundTrip('[*|a]');
 testSelectorRoundTrip('[n|a]');
+shouldBe("parseThenSerializeRule('[|a] { }')", "'[a] { }'");
 
 debug('');
 
@@ -354,7 +357,6 @@
 debug('');
 
 shouldBe("parseThenSerializeRule('*:active { }')", "':active { }'");
-shouldBe("parseThenSerializeRule('|a { }')", "'a { }'");
 
 debug('');
 

Modified: trunk/LayoutTests/fast/css/css-set-selector-text-expected.txt (204590 => 204591)


--- trunk/LayoutTests/fast/css/css-set-selector-text-expected.txt	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/fast/css/css-set-selector-text-expected.txt	2016-08-18 06:22:40 UTC (rev 204591)
@@ -38,6 +38,10 @@
 PASS setThenReadSelectorText('n|*') is 'n|*'
 PASS setThenReadSelectorText('[*|a]') is '[*|a]'
 PASS setThenReadSelectorText('[n|a]') is '[n|a]'
+PASS setThenReadSelectorText('|*') is '|*'
+PASS setThenReadSelectorText('[*|a]') is '[*|a]'
+PASS setThenReadSelectorText('[n|a]') is '[n|a]'
+PASS setThenReadSelectorText('[|a]') is '[a]'
 
 PASS setThenReadSelectorText('a:active') is 'a:active'
 PASS setThenReadSelectorText('a b') is 'a b'
@@ -248,7 +252,6 @@
 PASS setThenReadSelectorText(':-webkit-any(a.class1.class2.class3:hover)') is ':-webkit-any(a.class1.class2.class3:hover)'
 
 PASS setThenReadSelectorText('*:active') is ':active'
-PASS setThenReadSelectorText('|a') is 'a'
 
 PASS setThenReadSelectorText('input[type=file]:focus') is 'input[type="file"]:focus'
 

Modified: trunk/LayoutTests/fast/css/css-set-selector-text.html (204590 => 204591)


--- trunk/LayoutTests/fast/css/css-set-selector-text.html	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/fast/css/css-set-selector-text.html	2016-08-18 06:22:40 UTC (rev 204591)
@@ -96,6 +96,10 @@
 testSelectorRoundTrip('n|*');
 testSelectorRoundTrip('[*|a]');
 testSelectorRoundTrip('[n|a]');
+testSelectorRoundTrip('|*');
+testSelectorRoundTrip('[*|a]');
+testSelectorRoundTrip('[n|a]');
+shouldBe("setThenReadSelectorText('[|a]')", "'[a]'");
 
 debug('');
 
@@ -351,7 +355,6 @@
 debug('');
 
 shouldBe("setThenReadSelectorText('*:active')", "':active'");
-shouldBe("setThenReadSelectorText('|a')", "'a'");
 
 debug('');
 

Added: trunk/LayoutTests/fast/selectors/empty-namespace-with-element-selector-expected.txt (0 => 204591)


--- trunk/LayoutTests/fast/selectors/empty-namespace-with-element-selector-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/empty-namespace-with-element-selector-expected.txt	2016-08-18 06:22:40 UTC (rev 204591)
@@ -0,0 +1,22 @@
+Verify that "|name" matches the empty namespace while "*|name" and "name" match any namespace.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Trivial Selector used as rightmost
+PASS root.querySelectorAll("|div").length is 1
+PASS root.querySelectorAll("|div")[0].getAttribute("data-case") is "2"
+PASS root.querySelectorAll("*|div").length is 2
+PASS root.querySelectorAll("*|div")[0].getAttribute("data-case") is "1"
+PASS root.querySelectorAll("*|div")[1].getAttribute("data-case") is "2"
+PASS root.querySelectorAll("div").length is 2
+PASS root.querySelectorAll("div")[0].getAttribute("data-case") is "1"
+PASS root.querySelectorAll("div")[1].getAttribute("data-case") is "2"
+PASS getComputedStyle(document.querySelector("[|data-case='1' i]")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.querySelector("[|data-case='1' i]")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelector("[|data-case='2' i]")).color is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelector("[|data-case='2' i]")).backgroundColor is "rgb(4, 5, 6)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/empty-namespace-with-element-selector.html (0 => 204591)


--- trunk/LayoutTests/fast/selectors/empty-namespace-with-element-selector.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/empty-namespace-with-element-selector.html	2016-08-18 06:22:40 UTC (rev 204591)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <script src=""
+        <style>
+            @namespace uh url(http://www.w3.org/1999/xhtml);
+            #root div {
+                background-color: rgb(1, 2, 3);
+                color: rgb(1, 2, 3);
+            }
+            #root |div {
+                background-color: rgb(4, 5, 6);
+            }
+            #root uh|div {
+                color: rgb(4, 5, 6);
+            }
+        </style>
+    </head>
+    <body>
+        <div id="root" style="display:none;">
+            <div data-case="1">Default namespace</div>
+        </div>
+        <script>
+            description("Verify that \"|name\" matches the empty namespace while \"*|name\" and \"name\" match any namespace.");
+
+            var root = document.getElementById("root");
+            var elementWithoutNamespace = document.createElementNS("", "div");
+            elementWithoutNamespace.setAttribute("data-case", "2");
+            root.appendChild(elementWithoutNamespace);
+
+            function test(selector, expectedCases)
+            {
+                shouldBe('root.querySelectorAll("' + selector + '").length', '' + expectedCases.length);
+                let queryResult = root.querySelectorAll(selector);
+                for (let i = 0; i < queryResult.length; ++i) {
+                    shouldBeEqualToString('root.querySelectorAll("' + selector + '")[' + i + '].getAttribute("data-case")', '' + expectedCases[i]);
+                }
+            }
+
+            debug("Trivial Selector used as rightmost");
+            test("|div", [2]);
+            test("*|div", [1, 2]);
+            test("div", [1, 2]);
+
+            shouldBeEqualToString('getComputedStyle(document.querySelector("[|data-case=\'1\' i]")).color', 'rgb(4, 5, 6)');
+            shouldBeEqualToString('getComputedStyle(document.querySelector("[|data-case=\'1\' i]")).backgroundColor', 'rgb(1, 2, 3)');
+            shouldBeEqualToString('getComputedStyle(document.querySelector("[|data-case=\'2\' i]")).color', 'rgb(1, 2, 3)');
+            shouldBeEqualToString('getComputedStyle(document.querySelector("[|data-case=\'2\' i]")).backgroundColor', 'rgb(4, 5, 6)');
+        </script>
+        <script src=""
+    </body>
+</html>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (204590 => 204591)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2016-08-18 06:22:40 UTC (rev 204591)
@@ -1,3 +1,13 @@
+2016-08-17  Benjamin Poulain  <[email protected]>
+
+        [CSS] The parser should not get rid of empty namespace specification in front of element name selectors
+        https://bugs.webkit.org/show_bug.cgi?id=160936
+
+        Reviewed by Chris Dumez.
+
+        * web-platform-tests/dom/nodes/ParentNode-querySelector-All-expected.txt:
+        * web-platform-tests/dom/nodes/ParentNode-querySelector-All-xht-expected.txt:
+
 2016-08-16  Chris Dumez  <[email protected]>
 
         Add support for ShadowRoot.mode attribute

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-querySelector-All-expected.txt (204590 => 204591)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-querySelector-All-expected.txt	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-querySelector-All-expected.txt	2016-08-18 06:22:40 UTC (rev 204591)
@@ -603,10 +603,10 @@
 PASS Document.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS Document.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS Document.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL Document.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Document.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL Document.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Document.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS Document.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Document.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Document.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS Document.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS Document.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Document.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Document.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 
@@ -1021,10 +1021,10 @@
 PASS Detached Element.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS Detached Element.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS Detached Element.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL Detached Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Detached Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL Detached Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Detached Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS Detached Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Detached Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Detached Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS Detached Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS Detached Element.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Detached Element.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Detached Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 
@@ -1437,10 +1437,10 @@
 PASS Fragment.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS Fragment.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS Fragment.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL Fragment.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Fragment.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL Fragment.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Fragment.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS Fragment.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Fragment.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Fragment.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS Fragment.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS Fragment.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Fragment.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Fragment.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 
@@ -1853,10 +1853,10 @@
 PASS In-document Element.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS In-document Element.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS In-document Element.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL In-document Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL In-document Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL In-document Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL In-document Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS In-document Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS In-document Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS In-document Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS In-document Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS In-document Element.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS In-document Element.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-querySelector-All-xht-expected.txt (204590 => 204591)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-querySelector-All-xht-expected.txt	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/ParentNode-querySelector-All-xht-expected.txt	2016-08-18 06:22:40 UTC (rev 204591)
@@ -603,10 +603,10 @@
 PASS Document.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS Document.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS Document.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL Document.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Document.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL Document.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Document.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS Document.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Document.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Document.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS Document.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS Document.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Document.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Document.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 
@@ -1021,10 +1021,10 @@
 PASS Detached Element.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS Detached Element.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS Detached Element.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL Detached Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Detached Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL Detached Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Detached Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS Detached Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Detached Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Detached Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS Detached Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS Detached Element.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Detached Element.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Detached Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 
@@ -1437,10 +1437,10 @@
 PASS Fragment.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS Fragment.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS Fragment.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL Fragment.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Fragment.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL Fragment.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL Fragment.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS Fragment.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Fragment.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS Fragment.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS Fragment.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS Fragment.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Fragment.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS Fragment.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1 
@@ -1853,10 +1853,10 @@
 PASS In-document Element.querySelector: ID selector, matching element with id with escaped character: #test\.foo\[5\]bar 
 PASS In-document Element.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div 
 PASS In-document Element.querySelector: Namespace selector, matching element with any namespace: #any-namespace *|div 
-FAIL In-document Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL In-document Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
-FAIL In-document Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the expected number of matches. expected 1 but got 4
-FAIL In-document Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* assert_equals: The method should return the first match. expected "no-namespace-div3" but got "no-namespace-div1"
+PASS In-document Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS In-document Element.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div 
+PASS In-document Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
+PASS In-document Element.querySelector: Namespace selector, matching any elements in no namespace only: #no-namespace |* 
 PASS In-document Element.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS In-document Element.querySelector: Descendant combinator, matching element that is a descendant of an element with id: #descendant div 
 PASS In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1 

Modified: trunk/Source/WebCore/ChangeLog (204590 => 204591)


--- trunk/Source/WebCore/ChangeLog	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/Source/WebCore/ChangeLog	2016-08-18 06:22:40 UTC (rev 204591)
@@ -1,3 +1,42 @@
+2016-08-17  Benjamin Poulain  <[email protected]>
+
+        [CSS] The parser should not get rid of empty namespace specification in front of element name selectors
+        https://bugs.webkit.org/show_bug.cgi?id=160936
+
+        Reviewed by Chris Dumez.
+
+        There are two places where you can specify an empty namespace
+        in selectors:
+            - Element name (e.g. "|name")
+            - Attribute name (e.g. "[|name]")
+        In the first case, if we have an empty namespace, the selector
+        should match that.
+        In the second case, the default namespace of attribute is already
+        empty so it is just the same as "[name]".
+
+        Our code was just discarding any empty namespace. This is fine
+        for attributes but for names that is transforming "|name" into "name"
+        which is invalid.
+
+        This patch updates those cases to differentiate:
+        - Null prefix -> There was no namespace specified.
+        - Empty prefix -> There was a namespace prefix and it is empty.
+
+        Test: fast/selectors/empty-namespace-with-element-selector.html
+
+        * css/CSSGrammar.y.in:
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::determineNameInNamespace):
+        (WebCore::CSSParser::rewriteSpecifiersWithNamespaceIfNeeded):
+        (WebCore::CSSParser::rewriteSpecifiersWithElementName):
+        * css/CSSParser.h:
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::selectorText):
+        * css/CSSSelectorList.cpp:
+        (WebCore::SelectorNeedsNamespaceResolutionFunctor::operator()):
+        * css/StyleSheetContents.cpp:
+        (WebCore::StyleSheetContents::determineNamespace): Deleted.
+
 2016-08-17  Chris Dumez  <[email protected]>
 
         [Web IDL] Add support for dictionary members of dictionary types

Modified: trunk/Source/WebCore/css/CSSGrammar.y.in (204590 => 204591)


--- trunk/Source/WebCore/css/CSSGrammar.y.in	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/Source/WebCore/css/CSSGrammar.y.in	2016-08-18 06:22:40 UTC (rev 204591)
@@ -1165,7 +1165,10 @@
     ;
 
 namespace_selector:
-    '|' { $$.clear(); }
+    '|' {
+        static LChar emptyString = '\0';
+        $$.init(&emptyString, 0);
+    }
     | '*' '|' { static LChar star = '*'; $$.init(&star, 1); }
     | IDENT '|'
 ;
@@ -1176,8 +1179,10 @@
     }
     | element_name specifier_list {
         $$ = $2;
-        if ($$)
-            parser->rewriteSpecifiersWithElementName(nullAtom, $1, *$$);
+        if ($$) {
+            QualifiedName elementName(nullAtom, $1, parser->m_defaultNamespace);
+            parser->rewriteSpecifiersWithElementName(elementName, *$$);
+        }
     }
     | specifier_list {
         $$ = $1;

Modified: trunk/Source/WebCore/css/CSSParser.cpp (204590 => 204591)


--- trunk/Source/WebCore/css/CSSParser.cpp	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/Source/WebCore/css/CSSParser.cpp	2016-08-18 06:22:40 UTC (rev 204591)
@@ -13089,6 +13089,13 @@
 
 QualifiedName CSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
 {
+    if (prefix.isNull())
+        return QualifiedName(nullAtom, localName, nullAtom); // No namespace. If an element/attribute has a namespace, we won't match it.
+    if (prefix.isEmpty())
+        return QualifiedName(emptyAtom, localName, emptyAtom); // Empty namespace.
+    if (prefix == starAtom)
+        return QualifiedName(prefix, localName, starAtom); // We'll match any namespace.
+
     if (!m_styleSheet)
         return QualifiedName(prefix, localName, m_defaultNamespace);
     return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
@@ -13096,15 +13103,20 @@
 
 void CSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector& specifiers)
 {
-    if (m_defaultNamespace != starAtom || specifiers.isCustomPseudoElement())
-        rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
+    if (m_defaultNamespace != starAtom || specifiers.isCustomPseudoElement()) {
+        QualifiedName elementName(nullAtom, starAtom, m_defaultNamespace);
+        rewriteSpecifiersWithElementName(elementName, specifiers, /*tagIsForNamespaceRule*/true);
+    }
 }
 
-void CSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector& specifiers, bool tagIsForNamespaceRule)
+void CSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector& specifiers)
 {
-    AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
-    QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
+    QualifiedName tag(determineNameInNamespace(namespacePrefix, elementName));
+    rewriteSpecifiersWithElementName(tag, specifiers, false);
+}
 
+void CSSParser::rewriteSpecifiersWithElementName(const QualifiedName& tag, CSSParserSelector& specifiers, bool tagIsForNamespaceRule)
+{
     if (!specifiers.isCustomPseudoElement()) {
         if (tag == anyQName())
             return;

Modified: trunk/Source/WebCore/css/CSSParser.h (204590 => 204591)


--- trunk/Source/WebCore/css/CSSParser.h	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/Source/WebCore/css/CSSParser.h	2016-08-18 06:22:40 UTC (rev 204591)
@@ -403,7 +403,8 @@
     void addNamespace(const AtomicString& prefix, const AtomicString& uri);
     QualifiedName determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName);
 
-    void rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector&, bool isNamespacePlaceholder = false);
+    void rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector&);
+    void rewriteSpecifiersWithElementName(const QualifiedName& tagName, CSSParserSelector&, bool isNamespacePlaceholder = false);
     void rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector&);
     std::unique_ptr<CSSParserSelector> rewriteSpecifiers(std::unique_ptr<CSSParserSelector>, std::unique_ptr<CSSParserSelector>);
 

Modified: trunk/Source/WebCore/css/CSSSelector.cpp (204590 => 204591)


--- trunk/Source/WebCore/css/CSSSelector.cpp	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/Source/WebCore/css/CSSSelector.cpp	2016-08-18 06:22:40 UTC (rev 204591)
@@ -668,7 +668,7 @@
         } else if (cs->isAttributeSelector()) {
             str.append('[');
             const AtomicString& prefix = cs->attribute().prefix();
-            if (!prefix.isNull()) {
+            if (!prefix.isEmpty()) {
                 str.append(prefix);
                 str.append('|');
             }

Modified: trunk/Source/WebCore/css/CSSSelectorList.cpp (204590 => 204591)


--- trunk/Source/WebCore/css/CSSSelectorList.cpp	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/Source/WebCore/css/CSSSelectorList.cpp	2016-08-18 06:22:40 UTC (rev 204591)
@@ -173,9 +173,9 @@
 public:
     bool operator()(const CSSSelector* selector)
     {
-        if (selector->match() == CSSSelector::Tag && selector->tagQName().prefix() != nullAtom && selector->tagQName().prefix() != starAtom)
+        if (selector->match() == CSSSelector::Tag && !selector->tagQName().prefix().isEmpty() && selector->tagQName().prefix() != starAtom)
             return true;
-        if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
+        if (selector->isAttributeSelector() && !selector->attribute().prefix().isEmpty() && selector->attribute().prefix() != starAtom)
             return true;
         return false;
     }

Modified: trunk/Source/WebCore/css/StyleSheetContents.cpp (204590 => 204591)


--- trunk/Source/WebCore/css/StyleSheetContents.cpp	2016-08-18 05:37:34 UTC (rev 204590)
+++ trunk/Source/WebCore/css/StyleSheetContents.cpp	2016-08-18 06:22:40 UTC (rev 204591)
@@ -279,10 +279,6 @@
 
 const AtomicString& StyleSheetContents::determineNamespace(const AtomicString& prefix)
 {
-    if (prefix.isNull())
-        return nullAtom; // No namespace. If an element/attribute has a namespace, we won't match it.
-    if (prefix == starAtom)
-        return starAtom; // We'll match any namespace.
     PrefixNamespaceURIMap::const_iterator it = m_namespaces.find(prefix);
     if (it == m_namespaces.end())
         return nullAtom;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to