Bug 1639533 - Fix a case where we'd allow parsing functional :host incorrectly. r=heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 20 May 2020 23:54:16 +0000
changeset 531356 7b87e7b47c38348c3c6bf99c19e77e95b00a680c
parent 531355 1afd7205a9f3d9c61ba847dd7769543ad8befeaa
child 531357 23ddff9da376923836d2e66e9aa71191a065ca7c
push id37438
push userabutkovits@mozilla.com
push dateThu, 21 May 2020 09:36:57 +0000
treeherdermozilla-central@2d00a1a6495c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1639533, 1632647
milestone78.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1639533 - Fix a case where we'd allow parsing functional :host incorrectly. r=heycam This is a missing check I should've introduced in bug 1632647. Differential Revision: https://phabricator.services.mozilla.com/D76161
layout/style/test/test_selectors.html
servo/components/selectors/parser.rs
testing/web-platform/tests/css/css-scoping/slotted-parsing.html
--- a/layout/style/test/test_selectors.html
+++ b/layout/style/test/test_selectors.html
@@ -1305,16 +1305,19 @@ function runTests() {
     // using a pseudo-element that supports a user-action pseudo-class
     // after it, so we need to use the prefixed ::-moz-color-swatch,
     // which is one of the ones with
     // CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE (none of which are
     // unprefixed).
     test_parseable("::-moz-color-swatch:hover");
     test_balanced_unparseable("::-moz-color-swatch:not(.foo)");
     test_balanced_unparseable("::-moz-color-swatch:first-child");
+    test_balanced_unparseable("::-moz-color-swatch:host");
+    test_balanced_unparseable("::-moz-color-swatch:host(div)");
+    test_balanced_unparseable("::-moz-color-swatch:nth-child(1)");
     test_balanced_unparseable("::-moz-color-swatch:hover#foo");
     test_balanced_unparseable(".foo::after:not(.bar) ~ h3");
 
     test_parseable(":-moz-broken");
     test_parseable(":-moz-loading");
 
     run_deferred_tests();
 }
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -2202,17 +2202,22 @@ where
 {
     match_ignore_ascii_case! { &name,
         "nth-child" => return parse_nth_pseudo_class(parser, input, state, Component::NthChild),
         "nth-of-type" => return parse_nth_pseudo_class(parser, input, state, Component::NthOfType),
         "nth-last-child" => return parse_nth_pseudo_class(parser, input, state, Component::NthLastChild),
         "nth-last-of-type" => return parse_nth_pseudo_class(parser, input, state, Component::NthLastOfType),
         "is" if parser.parse_is_and_where() => return parse_is_or_where(parser, input, state, Component::Is),
         "where" if parser.parse_is_and_where() => return parse_is_or_where(parser, input, state, Component::Where),
-        "host" => return Ok(Component::Host(Some(parse_inner_compound_selector(parser, input, state)?))),
+        "host" => {
+            if !state.allows_tree_structural_pseudo_classes() {
+                return Err(input.new_custom_error(SelectorParseErrorKind::InvalidState));
+            }
+            return Ok(Component::Host(Some(parse_inner_compound_selector(parser, input, state)?)));
+        },
         "not" => {
             if state.intersects(SelectorParsingState::INSIDE_NEGATION) {
                 return Err(input.new_custom_error(
                     SelectorParseErrorKind::UnexpectedIdent("not".into())
                 ));
             }
             return parse_negation(parser, input, state)
         },
--- a/testing/web-platform/tests/css/css-scoping/slotted-parsing.html
+++ b/testing/web-platform/tests/css/css-scoping/slotted-parsing.html
@@ -9,16 +9,18 @@
 <style id="styleElm">
 </style>
 <script>
   test_invalid_selector("::slotted");
   test_invalid_selector("::slotted()");
   test_invalid_selector("::slotted(*).class");
   test_invalid_selector("::slotted(*)#id {}");
   test_invalid_selector("::slotted(*)[attr]");
+  test_invalid_selector("::slotted(*):host");
+  test_invalid_selector("::slotted(*):host(div)");
   test_invalid_selector("::slotted(*):hover");
   test_invalid_selector("::slotted(*):read-only");
   test_invalid_selector("::slotted(*)::slotted(*)");
   test_invalid_selector("::slotted(*)::before::slotted(*)");
   test_invalid_selector("::slotted(*) span");
 
   test_valid_selector("::slotted(*)");
   test_valid_selector("::slotted(div)");