Title: [203439] trunk
Revision
203439
Author
[email protected]
Date
2016-07-19 18:29:25 -0700 (Tue, 19 Jul 2016)

Log Message

Use getElementById for attribute matching if the attribute name is html's id
https://bugs.webkit.org/show_bug.cgi?id=159960

Patch by Benjamin Poulain <[email protected]> on 2016-07-19
Reviewed by Chris Dumez.

Source/WebCore:

Elliott Sprehn discovered YUI makes heavy uses of querySelector with [id=value]
(https://bugs.chromium.org/p/chromium/issues/detail?id=627242).

If we are not in quirks mode, IdForStyleResolution has the same value
as the Id attribute. We can use the same optimization for both cases.

Tests: fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks.html
       fast/selectors/id-attribute-querySelector-used-as-id-selector.html

* dom/SelectorQuery.cpp:
(WebCore::canBeUsedForIdFastPath):
(WebCore::findIdMatchingType):
(WebCore::SelectorDataList::SelectorDataList):
(WebCore::selectorForIdLookup):
(WebCore::filterRootById):

LayoutTests:

* fast/selectors/id-attribute-querySelector-used-as-id-selector-expected.txt: Added.
* fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks-expected.txt: Added.
* fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks.html: Added.
* fast/selectors/id-attribute-querySelector-used-as-id-selector.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (203438 => 203439)


--- trunk/LayoutTests/ChangeLog	2016-07-20 01:27:24 UTC (rev 203438)
+++ trunk/LayoutTests/ChangeLog	2016-07-20 01:29:25 UTC (rev 203439)
@@ -1,3 +1,15 @@
+2016-07-19  Benjamin Poulain  <[email protected]>
+
+        Use getElementById for attribute matching if the attribute name is html's id
+        https://bugs.webkit.org/show_bug.cgi?id=159960
+
+        Reviewed by Chris Dumez.
+
+        * fast/selectors/id-attribute-querySelector-used-as-id-selector-expected.txt: Added.
+        * fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks-expected.txt: Added.
+        * fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks.html: Added.
+        * fast/selectors/id-attribute-querySelector-used-as-id-selector.html: Added.
+
 2016-07-19  Chris Dumez  <[email protected]>
 
         Drop SVGElement.xmlbase attribute

Added: trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-expected.txt (0 => 203439)


--- trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-expected.txt	2016-07-20 01:29:25 UTC (rev 203439)
@@ -0,0 +1,57 @@
+Verify the optimization transforming [id=value] into #value for querySelector.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Trivial Selector used as rightmost
+PASS document.querySelectorAll("[id=simple_unique]").length is 1
+PASS document.querySelectorAll("[id=simple_Duplicated]").length is 3
+PASS document.querySelectorAll("[id=simple_duplicated]").length is 0
+Non-Trivial Selector used as rightmost
+PASS document.querySelectorAll("div[id=simple_unique][data-case]").length is 1
+PASS document.querySelectorAll("div[id=simple_Duplicated][data-case]").length is 3
+PASS document.querySelectorAll("div[id=simple_duplicated][data-case]").length is 0
+Trivial Selector used as ancestor filter
+PASS document.querySelectorAll("[id=Ancestor_Unique] >> *").length is 4
+PASS document.querySelectorAll("[id=Ancestor_Unique] > * >> *").length is 2
+PASS document.querySelectorAll("[id=Ancestor_Unique] >> * > *").length is 2
+PASS document.querySelectorAll("[id=ancestor_unique] >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_unique] > * >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_unique] >> * > *").length is 0
+PASS document.querySelectorAll("[id=ANCESTOR_DUPLICATED] >> *").length is 5
+PASS document.querySelectorAll("[id=ANCESTOR_DUPLICATED] > * >> *").length is 2
+PASS document.querySelectorAll("[id=ANCESTOR_DUPLICATED] >> * > *").length is 2
+PASS document.querySelectorAll("[id=ancestor_duplicated] >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_duplicated] > * >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_duplicated] >> * > *").length is 0
+Non-Trivial Selector used as ancestor filter
+PASS document.querySelectorAll("div[id=Ancestor_Unique][data-case] >> *").length is 4
+PASS document.querySelectorAll("div[id=Ancestor_Unique][data-case] > * >> *").length is 2
+PASS document.querySelectorAll("div[id=Ancestor_Unique][data-case] >> * > *").length is 2
+PASS document.querySelectorAll("div[id=ancestor_unique][data-case] >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_unique][data-case] > * >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_unique][data-case] >> * > *").length is 0
+PASS document.querySelectorAll("div[id=ANCESTOR_DUPLICATED][data-case] >> *").length is 5
+PASS document.querySelectorAll("div[id=ANCESTOR_DUPLICATED][data-case] > * >> *").length is 2
+PASS document.querySelectorAll("div[id=ANCESTOR_DUPLICATED][data-case] >> * > *").length is 2
+PASS document.querySelectorAll("div[id=ancestor_duplicated][data-case] >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_duplicated][data-case] > * >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_duplicated][data-case] >> * > *").length is 0
+Trivial Selector used as sibling filter
+PASS document.querySelectorAll("[id=simple_unique] + *").length is 1
+PASS document.querySelectorAll("[id=simple_unique] ~ *").length is 5
+PASS document.querySelectorAll("[id=simple_Duplicated] + *").length is 3
+PASS document.querySelectorAll("[id=simple_Duplicated] ~ *").length is 4
+PASS document.querySelectorAll("[id=simple_duplicated] + *").length is 0
+PASS document.querySelectorAll("[id=simple_duplicated] ~ *").length is 0
+Trivial Selector used as sibling of ancestor filter
+PASS document.querySelectorAll("[id=simple_unique] + * > *").length is 0
+PASS document.querySelectorAll("[id=simple_unique] ~ * > *").length is 4
+PASS document.querySelectorAll("[id=simple_Duplicated] + * > *").length is 2
+PASS document.querySelectorAll("[id=simple_Duplicated] ~ * > *").length is 4
+PASS document.querySelectorAll("[id=simple_duplicated] + * > *").length is 0
+PASS document.querySelectorAll("[id=simple_duplicated] ~ * > *").length is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks-expected.txt (0 => 203439)


--- trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks-expected.txt	2016-07-20 01:29:25 UTC (rev 203439)
@@ -0,0 +1,57 @@
+Verify the optimization transforming [id=value] into #value for querySelector.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Trivial Selector used as rightmost
+PASS document.querySelectorAll("[id=simple_unique]").length is 1
+PASS document.querySelectorAll("[id=simple_Duplicated]").length is 3
+PASS document.querySelectorAll("[id=simple_duplicated]").length is 0
+Non-Trivial Selector used as rightmost
+PASS document.querySelectorAll("div[id=simple_unique][data-case]").length is 1
+PASS document.querySelectorAll("div[id=simple_Duplicated][data-case]").length is 3
+PASS document.querySelectorAll("div[id=simple_duplicated][data-case]").length is 0
+Trivial Selector used as ancestor filter
+PASS document.querySelectorAll("[id=Ancestor_Unique] >> *").length is 4
+PASS document.querySelectorAll("[id=Ancestor_Unique] > * >> *").length is 2
+PASS document.querySelectorAll("[id=Ancestor_Unique] >> * > *").length is 2
+PASS document.querySelectorAll("[id=ancestor_unique] >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_unique] > * >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_unique] >> * > *").length is 0
+PASS document.querySelectorAll("[id=ANCESTOR_DUPLICATED] >> *").length is 5
+PASS document.querySelectorAll("[id=ANCESTOR_DUPLICATED] > * >> *").length is 2
+PASS document.querySelectorAll("[id=ANCESTOR_DUPLICATED] >> * > *").length is 2
+PASS document.querySelectorAll("[id=ancestor_duplicated] >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_duplicated] > * >> *").length is 0
+PASS document.querySelectorAll("[id=ancestor_duplicated] >> * > *").length is 0
+Non-Trivial Selector used as ancestor filter
+PASS document.querySelectorAll("div[id=Ancestor_Unique][data-case] >> *").length is 4
+PASS document.querySelectorAll("div[id=Ancestor_Unique][data-case] > * >> *").length is 2
+PASS document.querySelectorAll("div[id=Ancestor_Unique][data-case] >> * > *").length is 2
+PASS document.querySelectorAll("div[id=ancestor_unique][data-case] >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_unique][data-case] > * >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_unique][data-case] >> * > *").length is 0
+PASS document.querySelectorAll("div[id=ANCESTOR_DUPLICATED][data-case] >> *").length is 5
+PASS document.querySelectorAll("div[id=ANCESTOR_DUPLICATED][data-case] > * >> *").length is 2
+PASS document.querySelectorAll("div[id=ANCESTOR_DUPLICATED][data-case] >> * > *").length is 2
+PASS document.querySelectorAll("div[id=ancestor_duplicated][data-case] >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_duplicated][data-case] > * >> *").length is 0
+PASS document.querySelectorAll("div[id=ancestor_duplicated][data-case] >> * > *").length is 0
+Trivial Selector used as sibling filter
+PASS document.querySelectorAll("[id=simple_unique] + *").length is 1
+PASS document.querySelectorAll("[id=simple_unique] ~ *").length is 5
+PASS document.querySelectorAll("[id=simple_Duplicated] + *").length is 3
+PASS document.querySelectorAll("[id=simple_Duplicated] ~ *").length is 4
+PASS document.querySelectorAll("[id=simple_duplicated] + *").length is 0
+PASS document.querySelectorAll("[id=simple_duplicated] ~ *").length is 0
+Trivial Selector used as sibling of ancestor filter
+PASS document.querySelectorAll("[id=simple_unique] + * > *").length is 0
+PASS document.querySelectorAll("[id=simple_unique] ~ * > *").length is 4
+PASS document.querySelectorAll("[id=simple_Duplicated] + * > *").length is 2
+PASS document.querySelectorAll("[id=simple_Duplicated] ~ * > *").length is 4
+PASS document.querySelectorAll("[id=simple_duplicated] + * > *").length is 0
+PASS document.querySelectorAll("[id=simple_duplicated] ~ * > *").length is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks.html (0 => 203439)


--- trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks.html	2016-07-20 01:29:25 UTC (rev 203439)
@@ -0,0 +1,101 @@
+<html>
+    <head>
+        <script src=""
+    </head>
+    <body>
+        <div class="display:none;">
+            <div id="simple_unique" data-case="1"></div>
+            <div id="simple_Duplicated" data-case="2"></div>
+            <div id="simple_Duplicated" data-case="3"></div>
+            <div id="simple_Duplicated" data-case="4"></div>
+
+            <div id="Ancestor_Unique" data-case="5">
+                <div data-case="6">
+                    <div data-case="7">
+                    </div>
+                </div>
+                <div id="ANCESTOR_DUPLICATED" data-case="8">
+                    <div data-case="9">
+                    </div>
+                </div>
+            </div>
+            <div id="ANCESTOR_DUPLICATED" data-case="10">
+                <div data-case="11">
+                    <div data-case="12">
+                    </div>
+                </div>
+                <div id="ANCESTOR_DUPLICATED" data-case="13">
+                    <div data-case="14">
+                    </div>
+                </div>
+            </div>
+        </div>
+        <script>
+            description("Verify the optimization transforming [id=value] into #value for querySelector.");
+
+            function test(selector, expectedCases)
+            {
+                shouldBe('document.querySelectorAll("' + selector + '").length', '' + expectedCases.length);
+                /*let queryResult = document.querySelectorAll(selector);
+                for (let i = 0; i < queryResult.length; ++i) {
+                    shouldBeEqualToString('document.querySelectorAll("' + selector + '")[' + i + '].dataset.case', '' + expectedCases[i]);
+                }*/
+            }
+
+            debug("Trivial Selector used as rightmost");
+            test("[id=simple_unique]", [1]);
+            test("[id=simple_Duplicated]", [2, 3, 4]);
+            test("[id=simple_duplicated]", []);
+
+            debug("Non-Trivial Selector used as rightmost");
+            test("div[id=simple_unique][data-case]", [1]);
+            test("div[id=simple_Duplicated][data-case]", [2, 3, 4]);
+            test("div[id=simple_duplicated][data-case]", []);
+
+            debug("Trivial Selector used as ancestor filter");
+            test("[id=Ancestor_Unique] >> *", [6, 7, 8, 9]);
+            test("[id=Ancestor_Unique] > * >> *", [7, 9]);
+            test("[id=Ancestor_Unique] >> * > *", [7, 9]);
+            test("[id=ancestor_unique] >> *", []);
+            test("[id=ancestor_unique] > * >> *", []);
+            test("[id=ancestor_unique] >> * > *", []);
+            test("[id=ANCESTOR_DUPLICATED] >> *", [9, 11, 12, 13, 14]);
+            test("[id=ANCESTOR_DUPLICATED] > * >> *", [12, 14]);
+            test("[id=ANCESTOR_DUPLICATED] >> * > *", [12, 14]);
+            test("[id=ancestor_duplicated] >> *", []);
+            test("[id=ancestor_duplicated] > * >> *", []);
+            test("[id=ancestor_duplicated] >> * > *", []);
+
+            debug("Non-Trivial Selector used as ancestor filter");
+            test("div[id=Ancestor_Unique][data-case] >> *", [6, 7, 8, 9]);
+            test("div[id=Ancestor_Unique][data-case] > * >> *", [7, 9]);
+            test("div[id=Ancestor_Unique][data-case] >> * > *", [7, 9]);
+            test("div[id=ancestor_unique][data-case] >> *", []);
+            test("div[id=ancestor_unique][data-case] > * >> *", []);
+            test("div[id=ancestor_unique][data-case] >> * > *", []);
+            test("div[id=ANCESTOR_DUPLICATED][data-case] >> *", [9, 11, 12, 13, 14]);
+            test("div[id=ANCESTOR_DUPLICATED][data-case] > * >> *", [12, 14]);
+            test("div[id=ANCESTOR_DUPLICATED][data-case] >> * > *", [12, 14]);
+            test("div[id=ancestor_duplicated][data-case] >> *", []);
+            test("div[id=ancestor_duplicated][data-case] > * >> *", []);
+            test("div[id=ancestor_duplicated][data-case] >> * > *", []);
+
+            debug("Trivial Selector used as sibling filter");
+            test("[id=simple_unique] + *", [2]);
+            test("[id=simple_unique] ~ *", [2, 3, 4, 5, 10]);
+            test("[id=simple_Duplicated] + *", [3, 4, 5]);
+            test("[id=simple_Duplicated] ~ *", [3, 4, 5, 10]);
+            test("[id=simple_duplicated] + *", []);
+            test("[id=simple_duplicated] ~ *", []);
+
+            debug("Trivial Selector used as sibling of ancestor filter");
+            test("[id=simple_unique] + * > *", []);
+            test("[id=simple_unique] ~ * > *", [6, 8, 11, 13]);
+            test("[id=simple_Duplicated] + * > *", [6, 8]);
+            test("[id=simple_Duplicated] ~ * > *", [6, 8, 11, 13]);
+            test("[id=simple_duplicated] + * > *", []);
+            test("[id=simple_duplicated] ~ * > *", []);
+        </script>
+        <script src=""
+    </body>
+</html>

Added: trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector.html (0 => 203439)


--- trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-attribute-querySelector-used-as-id-selector.html	2016-07-20 01:29:25 UTC (rev 203439)
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <script src=""
+    </head>
+    <body>
+        <div class="display:none;">
+            <div id="simple_unique" data-case="1"></div>
+            <div id="simple_Duplicated" data-case="2"></div>
+            <div id="simple_Duplicated" data-case="3"></div>
+            <div id="simple_Duplicated" data-case="4"></div>
+
+            <div id="Ancestor_Unique" data-case="5">
+                <div data-case="6">
+                    <div data-case="7">
+                    </div>
+                </div>
+                <div id="ANCESTOR_DUPLICATED" data-case="8">
+                    <div data-case="9">
+                    </div>
+                </div>
+            </div>
+            <div id="ANCESTOR_DUPLICATED" data-case="10">
+                <div data-case="11">
+                    <div data-case="12">
+                    </div>
+                </div>
+                <div id="ANCESTOR_DUPLICATED" data-case="13">
+                    <div data-case="14">
+                    </div>
+                </div>
+            </div>
+        </div>
+        <script>
+            description("Verify the optimization transforming [id=value] into #value for querySelector.");
+
+            function test(selector, expectedCases)
+            {
+                shouldBe('document.querySelectorAll("' + selector + '").length', '' + expectedCases.length);
+                /*let queryResult = document.querySelectorAll(selector);
+                for (let i = 0; i < queryResult.length; ++i) {
+                    shouldBeEqualToString('document.querySelectorAll("' + selector + '")[' + i + '].dataset.case', '' + expectedCases[i]);
+                }*/
+            }
+
+            debug("Trivial Selector used as rightmost");
+            test("[id=simple_unique]", [1]);
+            test("[id=simple_Duplicated]", [2, 3, 4]);
+            test("[id=simple_duplicated]", []);
+
+            debug("Non-Trivial Selector used as rightmost");
+            test("div[id=simple_unique][data-case]", [1]);
+            test("div[id=simple_Duplicated][data-case]", [2, 3, 4]);
+            test("div[id=simple_duplicated][data-case]", []);
+
+            debug("Trivial Selector used as ancestor filter");
+            test("[id=Ancestor_Unique] >> *", [6, 7, 8, 9]);
+            test("[id=Ancestor_Unique] > * >> *", [7, 9]);
+            test("[id=Ancestor_Unique] >> * > *", [7, 9]);
+            test("[id=ancestor_unique] >> *", []);
+            test("[id=ancestor_unique] > * >> *", []);
+            test("[id=ancestor_unique] >> * > *", []);
+            test("[id=ANCESTOR_DUPLICATED] >> *", [9, 11, 12, 13, 14]);
+            test("[id=ANCESTOR_DUPLICATED] > * >> *", [12, 14]);
+            test("[id=ANCESTOR_DUPLICATED] >> * > *", [12, 14]);
+            test("[id=ancestor_duplicated] >> *", []);
+            test("[id=ancestor_duplicated] > * >> *", []);
+            test("[id=ancestor_duplicated] >> * > *", []);
+
+            debug("Non-Trivial Selector used as ancestor filter");
+            test("div[id=Ancestor_Unique][data-case] >> *", [6, 7, 8, 9]);
+            test("div[id=Ancestor_Unique][data-case] > * >> *", [7, 9]);
+            test("div[id=Ancestor_Unique][data-case] >> * > *", [7, 9]);
+            test("div[id=ancestor_unique][data-case] >> *", []);
+            test("div[id=ancestor_unique][data-case] > * >> *", []);
+            test("div[id=ancestor_unique][data-case] >> * > *", []);
+            test("div[id=ANCESTOR_DUPLICATED][data-case] >> *", [9, 11, 12, 13, 14]);
+            test("div[id=ANCESTOR_DUPLICATED][data-case] > * >> *", [12, 14]);
+            test("div[id=ANCESTOR_DUPLICATED][data-case] >> * > *", [12, 14]);
+            test("div[id=ancestor_duplicated][data-case] >> *", []);
+            test("div[id=ancestor_duplicated][data-case] > * >> *", []);
+            test("div[id=ancestor_duplicated][data-case] >> * > *", []);
+
+            debug("Trivial Selector used as sibling filter");
+            test("[id=simple_unique] + *", [2]);
+            test("[id=simple_unique] ~ *", [2, 3, 4, 5, 10]);
+            test("[id=simple_Duplicated] + *", [3, 4, 5]);
+            test("[id=simple_Duplicated] ~ *", [3, 4, 5, 10]);
+            test("[id=simple_duplicated] + *", []);
+            test("[id=simple_duplicated] ~ *", []);
+
+            debug("Trivial Selector used as sibling of ancestor filter");
+            test("[id=simple_unique] + * > *", []);
+            test("[id=simple_unique] ~ * > *", [6, 8, 11, 13]);
+            test("[id=simple_Duplicated] + * > *", [6, 8]);
+            test("[id=simple_Duplicated] ~ * > *", [6, 8, 11, 13]);
+            test("[id=simple_duplicated] + * > *", []);
+            test("[id=simple_duplicated] ~ * > *", []);
+        </script>
+        <script src=""
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (203438 => 203439)


--- trunk/Source/WebCore/ChangeLog	2016-07-20 01:27:24 UTC (rev 203438)
+++ trunk/Source/WebCore/ChangeLog	2016-07-20 01:29:25 UTC (rev 203439)
@@ -1,3 +1,26 @@
+2016-07-19  Benjamin Poulain  <[email protected]>
+
+        Use getElementById for attribute matching if the attribute name is html's id
+        https://bugs.webkit.org/show_bug.cgi?id=159960
+
+        Reviewed by Chris Dumez.
+
+        Elliott Sprehn discovered YUI makes heavy uses of querySelector with [id=value]
+        (https://bugs.chromium.org/p/chromium/issues/detail?id=627242).
+
+        If we are not in quirks mode, IdForStyleResolution has the same value
+        as the Id attribute. We can use the same optimization for both cases.
+
+        Tests: fast/selectors/id-attribute-querySelector-used-as-id-selector-quirks.html
+               fast/selectors/id-attribute-querySelector-used-as-id-selector.html
+
+        * dom/SelectorQuery.cpp:
+        (WebCore::canBeUsedForIdFastPath):
+        (WebCore::findIdMatchingType):
+        (WebCore::SelectorDataList::SelectorDataList):
+        (WebCore::selectorForIdLookup):
+        (WebCore::filterRootById):
+
 2016-07-19  Chris Dumez  <[email protected]>
 
         Drop SVGElement.xmlbase attribute

Modified: trunk/Source/WebCore/dom/SelectorQuery.cpp (203438 => 203439)


--- trunk/Source/WebCore/dom/SelectorQuery.cpp	2016-07-20 01:27:24 UTC (rev 203438)
+++ trunk/Source/WebCore/dom/SelectorQuery.cpp	2016-07-20 01:29:25 UTC (rev 203439)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013, 2014, 2016 Apple Inc. All rights reserved.
  * Copyright (C) 2014 Yusuke Suzuki <[email protected]>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
 
 #include "CSSParser.h"
 #include "ElementDescendantIterator.h"
+#include "HTMLNames.h"
 #include "SelectorChecker.h"
 #include "StaticNodeList.h"
 #include "StyledElement.h"
@@ -53,11 +54,17 @@
     Filter
 };
 
+static bool canBeUsedForIdFastPath(const CSSSelector& selector)
+{
+    return selector.match() == CSSSelector::Id
+        || (selector.match() == CSSSelector::Exact && selector.attribute() == HTMLNames::idAttr && !selector.attributeValueMatchingIsCaseInsensitive());
+}
+
 static IdMatchingType findIdMatchingType(const CSSSelector& firstSelector)
 {
     bool inRightmost = true;
     for (const CSSSelector* selector = &firstSelector; selector; selector = selector->tagHistory()) {
-        if (selector->match() == CSSSelector::Id) {
+        if (canBeUsedForIdFastPath(*selector)) {
             if (inRightmost)
                 return IdMatchingType::Rightmost;
             return IdMatchingType::Filter;
@@ -88,11 +95,11 @@
             case CSSSelector::Class:
                 m_matchType = ClassNameMatch;
                 break;
-            case CSSSelector::Id:
-                m_matchType = RightMostWithIdMatch;
-                break;
             default:
-                m_matchType = CompilableSingle;
+                if (canBeUsedForIdFastPath(selector))
+                    m_matchType = RightMostWithIdMatch;
+                else
+                    m_matchType = CompilableSingle;
                 break;
             }
         } else {
@@ -194,7 +201,7 @@
         return nullptr;
 
     for (const CSSSelector* selector = &firstSelector; selector; selector = selector->tagHistory()) {
-        if (selector->match() == CSSSelector::Id)
+        if (canBeUsedForIdFastPath(*selector))
             return selector;
         if (selector->relation() != CSSSelector::SubSelector)
             break;
@@ -247,7 +254,7 @@
     // Thus we can skip the rightmost match.
     const CSSSelector* selector = &firstSelector;
     do {
-        ASSERT(selector->match() != CSSSelector::Id);
+        ASSERT(!canBeUsedForIdFastPath(*selector));
         if (selector->relation() != CSSSelector::SubSelector)
             break;
         selector = selector->tagHistory();
@@ -255,7 +262,7 @@
 
     bool inAdjacentChain = false;
     for (; selector; selector = selector->tagHistory()) {
-        if (selector->match() == CSSSelector::Id) {
+        if (canBeUsedForIdFastPath(*selector)) {
             const AtomicString& idToMatch = selector->value();
             if (ContainerNode* searchRoot = rootNode.treeScope().getElementById(idToMatch)) {
                 if (LIKELY(!rootNode.treeScope().containsMultipleElementsWithId(idToMatch))) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to