| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/dom/SelectorQuery.h" | 5 #include "core/dom/SelectorQuery.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include "core/css/parser/CSSParser.h" | 8 #include "core/css/parser/CSSParser.h" |
| 9 #include "core/css/parser/CSSParserContext.h" | 9 #include "core/css/parser/CSSParserContext.h" |
| 10 #include "core/dom/Document.h" | 10 #include "core/dom/Document.h" |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 // Id in right most selector fast path. | 132 // Id in right most selector fast path. |
| 133 {"#A", false, 1, {1, 1, 0, 0, 0, 0, 0}}, | 133 {"#A", false, 1, {1, 1, 0, 0, 0, 0, 0}}, |
| 134 {"#multiple", false, 1, {1, 1, 0, 0, 0, 0, 0}}, | 134 {"#multiple", false, 1, {1, 1, 0, 0, 0, 0, 0}}, |
| 135 {"#multiple.two", false, 1, {1, 1, 0, 0, 0, 0, 0}}, | 135 {"#multiple.two", false, 1, {1, 1, 0, 0, 0, 0, 0}}, |
| 136 {"#multiple", true, 2, {2, 2, 0, 0, 0, 0, 0}}, | 136 {"#multiple", true, 2, {2, 2, 0, 0, 0, 0, 0}}, |
| 137 {"span#multiple", true, 1, {2, 2, 0, 0, 0, 0, 0}}, | 137 {"span#multiple", true, 1, {2, 2, 0, 0, 0, 0, 0}}, |
| 138 {"#multiple.two", true, 2, {2, 2, 0, 0, 0, 0, 0}}, | 138 {"#multiple.two", true, 2, {2, 2, 0, 0, 0, 0, 0}}, |
| 139 {"body #multiple", false, 1, {1, 1, 0, 0, 0, 0, 0}}, | 139 {"body #multiple", false, 1, {1, 1, 0, 0, 0, 0, 0}}, |
| 140 {"body span#multiple", false, 1, {2, 2, 0, 0, 0, 0, 0}}, | 140 {"body span#multiple", false, 1, {2, 2, 0, 0, 0, 0, 0}}, |
| 141 {"body #multiple", true, 2, {2, 2, 0, 0, 0, 0, 0}}, | 141 {"body #multiple", true, 2, {2, 2, 0, 0, 0, 0, 0}}, |
| 142 {"[id=multiple]", true, 2, {2, 2, 0, 0, 0, 0, 0}}, |
| 143 {"body [id=multiple]", true, 2, {2, 2, 0, 0, 0, 0, 0}}, |
| 142 | 144 |
| 143 // Single selector tag fast path. | 145 // Single selector tag fast path. |
| 144 {"span", false, 1, {4, 0, 0, 4, 0, 0, 0}}, | 146 {"span", false, 1, {4, 0, 0, 4, 0, 0, 0}}, |
| 145 {"span", true, 9, {14, 0, 0, 14, 0, 0, 0}}, | 147 {"span", true, 9, {14, 0, 0, 14, 0, 0, 0}}, |
| 146 | 148 |
| 147 // Single selector class fast path. | 149 // Single selector class fast path. |
| 148 {".two", false, 1, {6, 0, 6, 0, 0, 0, 0}}, | 150 {".two", false, 1, {6, 0, 6, 0, 0, 0, 0}}, |
| 149 {".two", true, 4, {14, 0, 14, 0, 0, 0, 0}}, | 151 {".two", true, 4, {14, 0, 14, 0, 0, 0, 0}}, |
| 150 | 152 |
| 151 // Class in the right most selector fast path. | 153 // Class in the right most selector fast path. |
| 152 {"body .two", false, 1, {6, 0, 0, 0, 6, 0, 0}}, | 154 {"body .two", false, 1, {6, 0, 6, 0, 0, 0, 0}}, |
| 153 {"div .two", false, 1, {12, 0, 0, 0, 12, 0, 0}}, | 155 {"div .two", false, 1, {12, 0, 12, 0, 0, 0, 0}}, |
| 154 | 156 |
| 155 // Classes in the right most selector for querySelectorAll use a fast | 157 // Classes in the right most selector for querySelectorAll use a fast |
| 156 // path. | 158 // path. |
| 157 {"body .two", true, 4, {14, 0, 14, 0, 0, 0, 0}}, | 159 {"body .two", true, 4, {14, 0, 14, 0, 0, 0, 0}}, |
| 158 {"div .two", true, 2, {14, 0, 14, 0, 0, 0, 0}}, | 160 {"div .two", true, 2, {14, 0, 14, 0, 0, 0, 0}}, |
| 159 | 161 |
| 160 // TODO: querySelector disables the class fast path to favor the id, but | 162 // TODO: We could use the fast class path to find the elements inside |
| 161 // this means some selectors always end up doing fastScan. | 163 // the id scope instead of the fast scan. |
| 162 {"#second .two", false, 1, {2, 0, 0, 0, 2, 0, 0}}, | 164 {"#second .two", false, 1, {3, 1, 0, 0, 2, 0, 0}}, |
| 163 | 165 {"#second .two", true, 2, {5, 1, 0, 0, 4, 0, 0}}, |
| 164 // TODO(esprehn): This should have used getElementById instead of doing | |
| 165 // a fastClass scan. It could have looked at 4 elements instead. | |
| 166 {"#second .two", true, 2, {14, 0, 14, 0, 0, 0, 0}}, | |
| 167 | 166 |
| 168 // We combine the class fast path with the fast scan mode when possible. | 167 // We combine the class fast path with the fast scan mode when possible. |
| 169 {".B span", false, 1, {11, 0, 0, 0, 11, 0, 0}}, | 168 {".B span", false, 1, {11, 0, 10, 0, 1, 0, 0}}, |
| 170 {".B span", true, 4, {14, 0, 10, 0, 4, 0, 0}}, | 169 {".B span", true, 4, {14, 0, 10, 0, 4, 0, 0}}, |
| 171 | 170 |
| 172 // We expand the scope of id selectors when affected by an adjectent | 171 // We expand the scope of id selectors when affected by an adjectent |
| 173 // combinator. | 172 // combinator. |
| 174 {"#c + :last-child", false, 1, {4, 0, 0, 0, 4, 0, 0}}, | 173 {"#c + :last-child", false, 1, {5, 1, 0, 0, 4, 0, 0}}, |
| 175 {"#a ~ :last-child", false, 1, {4, 0, 0, 0, 4, 0, 0}}, | 174 {"#a ~ :last-child", false, 1, {5, 1, 0, 0, 4, 0, 0}}, |
| 176 {"#c + div", true, 1, {4, 0, 0, 0, 4, 0, 0}}, | 175 {"#c + div", true, 1, {5, 1, 0, 0, 4, 0, 0}}, |
| 177 {"#a ~ span", true, 2, {4, 0, 0, 0, 4, 0, 0}}, | 176 {"#a ~ span", true, 2, {5, 1, 0, 0, 4, 0, 0}}, |
| 178 | 177 |
| 179 // We only expand the scope for id selectors if they're directly affected | 178 // We only expand the scope for id selectors if they're directly affected |
| 180 // the adjacent combinator. | 179 // the adjacent combinator. |
| 181 {"#first span + span", false, 1, {2, 0, 0, 0, 2, 0, 0}}, | 180 {"#first span + span", false, 1, {3, 1, 0, 0, 2, 0, 0}}, |
| 182 {"#first span ~ span", false, 1, {2, 0, 0, 0, 2, 0, 0}}, | 181 {"#first span ~ span", false, 1, {3, 1, 0, 0, 2, 0, 0}}, |
| 183 {"#second span + span", true, 3, {4, 0, 0, 0, 4, 0, 0}}, | 182 {"#second span + span", true, 3, {5, 1, 0, 0, 4, 0, 0}}, |
| 184 {"#second span ~ span", true, 3, {4, 0, 0, 0, 4, 0, 0}}, | 183 {"#second span ~ span", true, 3, {5, 1, 0, 0, 4, 0, 0}}, |
| 185 | 184 |
| 186 // We disable the fast path for class selectors when affected by adjacent | 185 // We disable the fast path for class selectors when affected by adjacent |
| 187 // combinator. | 186 // combinator. |
| 188 {".one + :last-child", false, 1, {8, 0, 0, 0, 8, 0, 0}}, | 187 {".one + :last-child", false, 1, {8, 0, 0, 0, 8, 0, 0}}, |
| 189 {".A ~ :last-child", false, 1, {9, 0, 0, 0, 9, 0, 0}}, | 188 {".A ~ :last-child", false, 1, {9, 0, 0, 0, 9, 0, 0}}, |
| 190 {".A + div", true, 1, {14, 0, 0, 0, 14, 0, 0}}, | 189 {".A + div", true, 1, {14, 0, 0, 0, 14, 0, 0}}, |
| 191 {".one ~ span", true, 5, {14, 0, 0, 0, 14, 0, 0}}, | 190 {".one ~ span", true, 5, {14, 0, 0, 0, 14, 0, 0}}, |
| 192 | 191 |
| 193 // We re-enable the fast path for classes once past the selector directly | 192 // We re-enable the fast path for classes once past the selector directly |
| 194 // affected by the adjacent combinator. | 193 // affected by the adjacent combinator. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 // If an ancestor has the class name we fast scan all the descendants of | 260 // If an ancestor has the class name we fast scan all the descendants of |
| 262 // the scope. | 261 // the scope. |
| 263 {".root-class span", true, 4, {7, 0, 0, 0, 7, 0, 0}}, | 262 {".root-class span", true, 4, {7, 0, 0, 0, 7, 0, 0}}, |
| 264 | 263 |
| 265 // If an ancestor has the class name in the middle of the selector we fast | 264 // If an ancestor has the class name in the middle of the selector we fast |
| 266 // scan all the descendants of the scope. | 265 // scan all the descendants of the scope. |
| 267 {".root-class span:nth-child(2)", false, 1, {2, 0, 0, 0, 2, 0, 0}}, | 266 {".root-class span:nth-child(2)", false, 1, {2, 0, 0, 0, 2, 0, 0}}, |
| 268 {".root-class span:nth-child(2)", true, 1, {7, 0, 0, 0, 7, 0, 0}}, | 267 {".root-class span:nth-child(2)", true, 1, {7, 0, 0, 0, 7, 0, 0}}, |
| 269 | 268 |
| 270 // If the id is an ancestor we scan all the descendants. | 269 // If the id is an ancestor we scan all the descendants. |
| 271 {"#root-id span", true, 4, {7, 0, 0, 0, 7, 0, 0}}, | 270 {"#root-id span", true, 4, {8, 1, 0, 0, 7, 0, 0}}, |
| 272 }; | 271 }; |
| 273 | 272 |
| 274 { | 273 { |
| 275 SCOPED_TRACE("Inside document"); | 274 SCOPED_TRACE("Inside document"); |
| 276 RunTests(*scope, kTestCases); | 275 RunTests(*scope, kTestCases); |
| 277 } | 276 } |
| 278 | 277 |
| 279 { | 278 { |
| 280 // Run all the tests a second time but with a scope inside a shadow root, | 279 // Run all the tests a second time but with a scope inside a shadow root, |
| 281 // all the fast paths should behave the same. | 280 // all the fast paths should behave the same. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 297 " <span id=one class=tWo></span>" | 296 " <span id=one class=tWo></span>" |
| 298 " </span>" | 297 " </span>" |
| 299 " </body>" | 298 " </body>" |
| 300 "</html>"); | 299 "</html>"); |
| 301 static const struct QueryTest kTestCases[] = { | 300 static const struct QueryTest kTestCases[] = { |
| 302 // Quirks mode always uses the slow path. | 301 // Quirks mode always uses the slow path. |
| 303 {"#one", false, 1, {5, 0, 0, 0, 0, 5, 0}}, | 302 {"#one", false, 1, {5, 0, 0, 0, 0, 5, 0}}, |
| 304 {"#One", false, 1, {5, 0, 0, 0, 0, 5, 0}}, | 303 {"#One", false, 1, {5, 0, 0, 0, 0, 5, 0}}, |
| 305 {"#ONE", false, 1, {5, 0, 0, 0, 0, 5, 0}}, | 304 {"#ONE", false, 1, {5, 0, 0, 0, 0, 5, 0}}, |
| 306 {"#ONE", true, 2, {6, 0, 0, 0, 0, 6, 0}}, | 305 {"#ONE", true, 2, {6, 0, 0, 0, 0, 6, 0}}, |
| 306 {"[id=One]", false, 1, {5, 0, 0, 0, 0, 5, 0}}, |
| 307 {"[id=One]", true, 1, {6, 0, 0, 0, 0, 6, 0}}, |
| 307 {"span", false, 1, {4, 0, 0, 0, 0, 4, 0}}, | 308 {"span", false, 1, {4, 0, 0, 0, 0, 4, 0}}, |
| 308 {"span", true, 3, {6, 0, 0, 0, 0, 6, 0}}, | 309 {"span", true, 3, {6, 0, 0, 0, 0, 6, 0}}, |
| 309 {".two", false, 1, {5, 0, 0, 0, 0, 5, 0}}, | 310 {".two", false, 1, {5, 0, 0, 0, 0, 5, 0}}, |
| 310 {".two", true, 2, {6, 0, 0, 0, 0, 6, 0}}, | 311 {".two", true, 2, {6, 0, 0, 0, 0, 6, 0}}, |
| 311 {"body #first", false, 1, {4, 0, 0, 0, 0, 4, 0}}, | 312 {"body #first", false, 1, {4, 0, 0, 0, 0, 4, 0}}, |
| 312 {"body #one", true, 2, {6, 0, 0, 0, 0, 6, 0}}, | 313 {"body #one", true, 2, {6, 0, 0, 0, 0, 6, 0}}, |
| 313 }; | 314 }; |
| 314 RunTests(*document, kTestCases); | 315 RunTests(*document, kTestCases); |
| 315 } | 316 } |
| 316 | 317 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 { | 355 { |
| 355 // Run all the tests a second time but with a scope inside a shadow root, | 356 // Run all the tests a second time but with a scope inside a shadow root, |
| 356 // this tests for cases where we could have used the id map the ShadowRoot | 357 // this tests for cases where we could have used the id map the ShadowRoot |
| 357 // is keeping track of. | 358 // is keeping track of. |
| 358 SCOPED_TRACE("Inside disconnected shadow root subtree"); | 359 SCOPED_TRACE("Inside disconnected shadow root subtree"); |
| 359 RunTests(shadowRoot, kTestCases); | 360 RunTests(shadowRoot, kTestCases); |
| 360 } | 361 } |
| 361 } | 362 } |
| 362 | 363 |
| 363 } // namespace blink | 364 } // namespace blink |
| OLD | NEW |