Diff
Modified: trunk/LayoutTests/ChangeLog (284972 => 284973)
--- trunk/LayoutTests/ChangeLog 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/ChangeLog 2021-10-28 08:59:03 UTC (rev 284973)
@@ -1,3 +1,12 @@
+2021-10-28 Antti Koivisto <an...@apple.com>
+
+ Support ::before and ::after pseudo elements after ::slotted
+ https://bugs.webkit.org/show_bug.cgi?id=178237
+
+ Reviewed by Ryosuke Niwa.
+
+ * TestExpectations:
+
2021-10-28 Carlos Garcia Campos <cgar...@igalia.com>
AX: AXValueChanged is only sent for range elements when value is changed with the keyboard
Modified: trunk/LayoutTests/TestExpectations (284972 => 284973)
--- trunk/LayoutTests/TestExpectations 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/TestExpectations 2021-10-28 08:59:03 UTC (rev 284973)
@@ -3097,7 +3097,6 @@
imported/w3c/web-platform-tests/css/css-display/run-in/run-in-text-between-004.xht [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-display/run-in/run-in-text-between-005.xht [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-pseudo/placeholder-input-number.html [ ImageOnlyFailure ]
-imported/w3c/web-platform-tests/css/css-scoping/slotted-with-pseudo-element.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-color-001.xht [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-position-above-left-001.xht [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-position-above-left-002.xht [ ImageOnlyFailure ]
@@ -3208,7 +3207,6 @@
webkit.org/b/190032 compositing/layer-creation/translate-scale-transition-overlap.html [ Failure ]
webkit.org/b/190032 compositing/layer-creation/translate-transition-overlap.html [ Failure ]
webkit.org/b/190032 imported/w3c/web-platform-tests/css/css-logical/animation-003.tentative.html [ Failure ]
-webkit.org/b/190032 imported/w3c/web-platform-tests/css/css-scoping/keyframes-001.html [ Failure ]
# FIXME: Need to implement MediaRecorder dataavailable event to support these testcases
fast/mediacapturefromelement/CanvasCaptureMediaStream-imagebitmaprenderingcontext.html [ Skip ]
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (284972 => 284973)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2021-10-28 08:59:03 UTC (rev 284973)
@@ -1,3 +1,24 @@
+2021-10-28 Antti Koivisto <an...@apple.com>
+
+ Support ::before and ::after pseudo elements after ::slotted
+ https://bugs.webkit.org/show_bug.cgi?id=178237
+
+ Reviewed by Ryosuke Niwa.
+
+ Update the tests from WPT repo.
+
+ * web-platform-tests/css/css-scoping/host-context-parsing-expected.txt: Added.
+ * web-platform-tests/css/css-scoping/host-context-parsing.html: Added.
+ * web-platform-tests/css/css-scoping/host-parsing-expected.txt: Added.
+ * web-platform-tests/css/css-scoping/host-parsing.html: Added.
+ * web-platform-tests/css/css-scoping/keyframes-001-expected.txt:
+ * web-platform-tests/css/css-scoping/shadow-shared-style-cache-001-expected.txt: Added.
+ * web-platform-tests/css/css-scoping/shadow-shared-style-cache-001.html: Added.
+ * web-platform-tests/css/css-scoping/slotted-link-expected.txt:
+ * web-platform-tests/css/css-scoping/slotted-parsing-expected.txt:
+ * web-platform-tests/css/css-scoping/slotted-parsing.html:
+ * web-platform-tests/css/css-scoping/w3c-import.log:
+
2021-10-27 Kiet Ho <th...@apple.com>
Add discrete animation support between PathOperations
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-parsing-expected.txt (0 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-parsing-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-parsing-expected.txt 2021-10-28 08:59:03 UTC (rev 284973)
@@ -0,0 +1,9 @@
+
+FAIL ":host-context(.a)" should be a valid selector The string did not match the expected pattern.
+FAIL ":host-context(div.a)" should be a valid selector The string did not match the expected pattern.
+PASS ":host-context" should be an invalid selector
+PASS ":host-context()" should be an invalid selector
+PASS ":host-context(.a, .b)" should be an invalid selector
+PASS ":host-context(.a + .b)" should be an invalid selector
+PASS ":host-context(.a + .b, #c > #d)" should be an invalid selector
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-parsing.html (0 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-parsing.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-parsing.html 2021-10-28 08:59:03 UTC (rev 284973)
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Test parsing of the host-context() pseudo-classes</title>
+<link rel="help" href=""
+<script src=""
+<script src=""
+<script src=""
+<script>
+ test_valid_selector(':host-context(.a)');
+ test_valid_selector(':host-context(div.a)');
+
+ test_invalid_selector(':host-context');
+ test_invalid_selector(':host-context()');
+ test_invalid_selector(':host-context(.a, .b)');
+ test_invalid_selector(':host-context(.a + .b)');
+ test_invalid_selector(':host-context(.a + .b, #c > #d)');
+</script>
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-parsing-expected.txt (0 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-parsing-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-parsing-expected.txt 2021-10-28 08:59:03 UTC (rev 284973)
@@ -0,0 +1,9 @@
+
+PASS ":host" should be a valid selector
+PASS ":host(.a)" should be a valid selector
+PASS ":host(div.a)" should be a valid selector
+PASS ":host()" should be an invalid selector
+FAIL ":host(.a, .b)" should be an invalid selector assert_throws_dom: ":host(.a, .b)" should throw in querySelector function "() => document.querySelector(selector)" did not throw
+PASS ":host(.a + .b)" should be an invalid selector
+PASS ":host(.a + .b, #c > #d)" should be an invalid selector
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-parsing.html (0 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-parsing.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-parsing.html 2021-10-28 08:59:03 UTC (rev 284973)
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Test parsing of the :host/host() pseudo-classes</title>
+<link rel="help" href=""
+<script src=""
+<script src=""
+<script src=""
+<script>
+ test_valid_selector(':host');
+ test_valid_selector(':host(.a)');
+ test_valid_selector(':host(div.a)');
+
+ test_invalid_selector(':host()');
+ test_invalid_selector(':host(.a, .b)');
+ test_invalid_selector(':host(.a + .b)');
+ test_invalid_selector(':host(.a + .b, #c > #d)');
+</script>
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/keyframes-001-expected.txt (284972 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/keyframes-001-expected.txt 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/keyframes-001-expected.txt 2021-10-28 08:59:03 UTC (rev 284973)
@@ -1,3 +1,3 @@
-FAIL @keyframes applies in the shadow tree assert_equals: expected 1 but got 0
+PASS @keyframes applies in the shadow tree
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-shared-style-cache-001-expected.txt (0 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-shared-style-cache-001-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-shared-style-cache-001-expected.txt 2021-10-28 08:59:03 UTC (rev 284973)
@@ -0,0 +1,3 @@
+
+PASS Shared style invalidation with removals
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-shared-style-cache-001.html (0 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-shared-style-cache-001.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-shared-style-cache-001.html 2021-10-28 08:59:03 UTC (rev 284973)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Shared style invalidation with removals</title>
+<link rel="help" href=""
+<link rel="help" href=""
+<link rel="author" href="" title="Emilio Cobos Álvarez">
+<link rel="author" href="" title="Mozilla">
+<script src=""
+<script src=""
+<div id="host-1"></div>
+<div id="host-2"></div>
+<script>
+const INITIALLY_COMMON_STYLE = `<style>:host { background-color: red !important }</style>`;
+let helper = document.querySelector("#host-1");
+let host = document.querySelector("#host-2");
+
+test(function() {
+ helper.attachShadow({ mode: "open" }).innerHTML = INITIALLY_COMMON_STYLE;
+ assert_equals(getComputedStyle(helper).backgroundColor, "rgb(255, 0, 0)", "Common style should apply to helper");
+
+ host.attachShadow({ mode: "open" }).innerHTML = INITIALLY_COMMON_STYLE;
+ assert_equals(getComputedStyle(host).backgroundColor, "rgb(255, 0, 0)", "Common style should apply to host");
+
+ host.shadowRoot.innerHTML = `<style>:host { background-color: lime; width: 100px; height: 100px; }</style>`;
+ assert_equals(getComputedStyle(host).backgroundColor, "rgb(0, 255, 0)", "Common style should no longer apply to host");
+});
+</script>
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-link-expected.txt (284972 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-link-expected.txt 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-link-expected.txt 2021-10-28 08:59:03 UTC (rev 284973)
@@ -1,4 +1,4 @@
This link should be green.
-FAIL Check that we match :link and not :visited for slotted anchor. assert_equals: Unvisited link should be green. expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+PASS Check that we match :link and not :visited for slotted anchor.
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing-expected.txt (284972 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing-expected.txt 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing-expected.txt 2021-10-28 08:59:03 UTC (rev 284973)
@@ -7,10 +7,6 @@
PASS "::slotted(*):host" should be an invalid selector
PASS "::slotted(*):host(div)" should be an invalid selector
PASS "::slotted(*):hover" should be an invalid selector
-PASS "::slotted(*):is(:hover)" should be an invalid selector
-PASS "::slotted(*):where(:hover)" should be an invalid selector
-PASS "::slotted(*):is(#id)" should be an invalid selector
-PASS "::slotted(*):where(#id)" should be an invalid selector
PASS "::slotted(*):read-only" should be an invalid selector
PASS "::slotted(*)::slotted(*)" should be an invalid selector
PASS "::slotted(*)::before::slotted(*)" should be an invalid selector
@@ -19,10 +15,16 @@
PASS "::slotted(div)" should be a valid selector
PASS "::slotted([attr]:hover)" should be a valid selector
PASS "::slotted(:not(.a))" should be a valid selector
-FAIL "::slotted(*)::before" should be a valid selector The string did not match the expected pattern.
-FAIL "::slotted(*)::after" should be a valid selector The string did not match the expected pattern.
+FAIL "::slotted(*):is()" should be a valid selector The string did not match the expected pattern.
+FAIL "::slotted(*):is(:hover)" should be a valid selector The string did not match the expected pattern.
+FAIL "::slotted(*):is(#id)" should be a valid selector The string did not match the expected pattern.
+FAIL "::slotted(*):where()" should be a valid selector The string did not match the expected pattern.
+FAIL "::slotted(*):where(:hover)" should be a valid selector The string did not match the expected pattern.
+FAIL "::slotted(*):where(#id)" should be a valid selector The string did not match the expected pattern.
+PASS "::slotted(*)::before" should be a valid selector
+PASS "::slotted(*)::after" should be a valid selector
FAIL "::slotted(*)::placeholder" should be a valid selector The string did not match the expected pattern.
-FAIL "::slotted(*)::marker" should be a valid selector The string did not match the expected pattern.
+PASS "::slotted(*)::marker" should be a valid selector
PASS "::slotted(*)::first-line" should be an invalid selector
PASS "::slotted(*)::first-letter" should be an invalid selector
PASS "::slotted(*)::selection" should be an invalid selector
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing.html (284972 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing.html 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing.html 2021-10-28 08:59:03 UTC (rev 284973)
@@ -17,10 +17,6 @@
test_invalid_selector("::slotted(*):host");
test_invalid_selector("::slotted(*):host(div)");
test_invalid_selector("::slotted(*):hover");
- test_invalid_selector("::slotted(*):is(:hover)");
- test_invalid_selector("::slotted(*):where(:hover)");
- test_invalid_selector("::slotted(*):is(#id)");
- test_invalid_selector("::slotted(*):where(#id)");
test_invalid_selector("::slotted(*):read-only");
test_invalid_selector("::slotted(*)::slotted(*)");
test_invalid_selector("::slotted(*)::before::slotted(*)");
@@ -31,6 +27,14 @@
test_valid_selector("::slotted([attr]:hover)");
test_valid_selector("::slotted(:not(.a))");
+ test_valid_selector("::slotted(*):is()");
+ test_valid_selector("::slotted(*):is(:hover)", "::slotted(*):is()");
+ test_valid_selector("::slotted(*):is(#id)", "::slotted(*):is()");
+
+ test_valid_selector("::slotted(*):where()");
+ test_valid_selector("::slotted(*):where(:hover)", "::slotted(*):where()");
+ test_valid_selector("::slotted(*):where(#id)", "::slotted(*):where()");
+
// Allow tree-abiding pseudo elements after ::slotted
test_valid_selector("::slotted(*)::before");
test_valid_selector("::slotted(*)::after");
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/w3c-import.log (284972 => 284973)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/w3c-import.log 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/w3c-import.log 2021-10-28 08:59:03 UTC (rev 284973)
@@ -52,6 +52,7 @@
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/css-scoping-shadow-with-rules-no-style-leak-expected.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/css-scoping-shadow-with-rules-no-style-leak.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/css-scoping-shadow-with-rules.html
+/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-parsing.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-specificity-001-expected.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-specificity-001.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-context-specificity-002-expected.html
@@ -69,6 +70,7 @@
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-multiple-001.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-nested-001-expected.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-nested-001.html
+/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-parsing.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-slotted-001-expected.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-slotted-001.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/host-specificity-002-expected.html
@@ -125,6 +127,7 @@
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-reassign-dynamic-004.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-root-insert-into-document-expected.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-root-insert-into-document.html
+/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/shadow-shared-style-cache-001.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slot-non-html-display-value.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-invalidation.html
/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-link.html
Modified: trunk/Source/WebCore/ChangeLog (284972 => 284973)
--- trunk/Source/WebCore/ChangeLog 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/ChangeLog 2021-10-28 08:59:03 UTC (rev 284973)
@@ -1,3 +1,66 @@
+2021-10-28 Antti Koivisto <an...@apple.com>
+
+ Support ::before and ::after pseudo elements after ::slotted
+ https://bugs.webkit.org/show_bug.cgi?id=178237
+
+ Reviewed by Ryosuke Niwa.
+
+ Change the way we resolve ::slotted to improve compatibility. We now traverse through the assigned slot chain in
+ a single pass, similar to ::part matching.
+
+ * css/CSSSelector.cpp:
+ (WebCore::CSSSelector::selectorText const):
+ * css/CSSSelector.h:
+
+ Add a new selection relation ShadowSlotted, similar to the existing ShadowDescendant and ShadowPartDescendant,
+ for switching scopes during selector matching.
+
+ * css/SelectorChecker.cpp:
+ (WebCore::SelectorChecker::matchRecursively const):
+
+ Find the right scope to continue matching on ShadowSlotted relation. Pass in the scope ordinal to find the scope.
+
+ (WebCore::SelectorChecker::checkOne const):
+
+ Match the ::slotted() element.
+
+ * css/SelectorChecker.h:
+ * css/SelectorFilter.cpp:
+ (WebCore::collectSelectorHashes):
+ * css/parser/CSSParserSelector.h:
+ (WebCore::CSSParserSelector::needsImplicitShadowCombinatorForMatching const):
+ * css/parser/CSSSelectorParser.cpp:
+ (WebCore::isPseudoClassValidAfterPseudoElement):
+ (WebCore::isTreeAbidingPseudoElement):
+
+ Add a spec-termed helper.
+
+ (WebCore::isSimpleSelectorValidAfterPseudoElement):
+ (WebCore::CSSSelectorParser::splitCompoundAtImplicitShadowCrossingCombinator):
+
+ Insert ShadowSlotted relation for ::slotted().
+
+ * cssjit/SelectorCompiler.cpp:
+ (WebCore::SelectorCompiler::fragmentRelationForSelectorRelation):
+ (WebCore::SelectorCompiler::constructFragmentsInternal):
+ * style/ElementRuleCollector.cpp:
+ (WebCore::Style::ElementRuleCollector::clearMatchedRules):
+ (WebCore::Style::ElementRuleCollector::matchSlottedPseudoElementRules):
+
+ Simply get the rules from scopes in the assinged slot chaing and match against them.
+ No need for two passes.
+
+ (WebCore::Style::ElementRuleCollector::ruleMatches):
+ (WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):
+ (WebCore::Style::ElementRuleCollector::collectSlottedPseudoElementRulesForSlot): Deleted.
+
+ Not needed anymore.
+
+ (WebCore::Style::findSlottedPseudoElementSelector): Deleted.
+ * style/ElementRuleCollector.h:
+ * style/RuleFeature.cpp:
+ (WebCore::Style::RuleFeatureSet::computeNextMatchElement):
+
2021-10-28 Carlos Garcia Campos <cgar...@igalia.com>
AX: AXValueChanged is only sent for range elements when value is changed with the keyboard
Modified: trunk/Source/WebCore/css/CSSSelector.cpp (284972 => 284973)
--- trunk/Source/WebCore/css/CSSSelector.cpp 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/css/CSSSelector.cpp 2021-10-28 08:59:03 UTC (rev 284973)
@@ -823,6 +823,7 @@
#endif
case CSSSelector::ShadowDescendant:
case CSSSelector::ShadowPartDescendant:
+ case CSSSelector::ShadowSlotted:
builder.append(rightSide);
return tagHistory->selectorText(builder.toString());
}
Modified: trunk/Source/WebCore/css/CSSSelector.h (284972 => 284973)
--- trunk/Source/WebCore/css/CSSSelector.h 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/css/CSSSelector.h 2021-10-28 08:59:03 UTC (rev 284973)
@@ -87,7 +87,8 @@
DirectAdjacent,
IndirectAdjacent,
ShadowDescendant,
- ShadowPartDescendant
+ ShadowPartDescendant,
+ ShadowSlotted
};
enum PseudoClassType {
Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (284972 => 284973)
--- trunk/Source/WebCore/css/SelectorChecker.cpp 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp 2021-10-28 08:59:03 UTC (rev 284973)
@@ -408,22 +408,40 @@
return MatchResult::updateWithMatchType(result, matchType);
}
case CSSSelector::ShadowDescendant:
- case CSSSelector::ShadowPartDescendant:
- {
- // When matching foo::part(bar) we skip directly to the tree of element 'foo'.
- auto* shadowHost = relation == CSSSelector::ShadowPartDescendant ? checkingContext.shadowHostInPartRuleScope : context.element->shadowHost();
- if (!shadowHost)
- return MatchResult::fails(Match::SelectorFailsCompletely);
- nextContext.element = shadowHost;
- nextContext.firstSelectorOfTheFragment = nextContext.selector;
- nextContext.isSubjectOrAdjacentElement = false;
- PseudoIdSet ignoreDynamicPseudo;
- MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
+ case CSSSelector::ShadowPartDescendant: {
+ // When matching foo::part(bar) we skip directly to the tree of element 'foo'.
+ auto* shadowHost = relation == CSSSelector::ShadowPartDescendant ? checkingContext.shadowHostInPartRuleScope : context.element->shadowHost();
+ if (!shadowHost)
+ return MatchResult::fails(Match::SelectorFailsCompletely);
+ nextContext.element = shadowHost;
+ nextContext.firstSelectorOfTheFragment = nextContext.selector;
+ nextContext.isSubjectOrAdjacentElement = false;
+ PseudoIdSet ignoreDynamicPseudo;
+ MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
- return MatchResult::updateWithMatchType(result, matchType);
- }
+ return MatchResult::updateWithMatchType(result, matchType);
}
+ case CSSSelector::ShadowSlotted: {
+ auto* slot = context.element->assignedSlot();
+ if (!slot)
+ return MatchResult::fails(Match::SelectorFailsCompletely);
+ // We continue matching in the scope where this rule came from.
+ auto scopeDepth = static_cast<int>(checkingContext.styleScopeOrdinal);
+ while (--scopeDepth && slot->assignedSlot())
+ slot = slot->assignedSlot();
+ if (scopeDepth)
+ return MatchResult::fails(Match::SelectorFailsCompletely);
+ nextContext.element = slot;
+ nextContext.firstSelectorOfTheFragment = nextContext.selector;
+ nextContext.isSubjectOrAdjacentElement = false;
+ PseudoIdSet ignoreDynamicPseudo;
+ MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
+
+ return MatchResult::updateWithMatchType(result, matchType);
+ }
+ }
+
ASSERT_NOT_REACHED();
return MatchResult::fails(Match::SelectorFailsCompletely);
}
@@ -1150,11 +1168,18 @@
return false;
}
#endif
- case CSSSelector::PseudoElementSlotted:
- // We see ::slotted() pseudo elements when collecting slotted rules from the slot shadow tree only.
- ASSERT(checkingContext.resolvingMode == Mode::CollectingRules);
- return is<HTMLSlotElement>(element);
-
+ case CSSSelector::PseudoElementSlotted: {
+ if (!context.element->assignedSlot())
+ return false;
+ auto* subselector = context.selector->selectorList()->first();
+ LocalContext subcontext(context);
+ subcontext.selector = subselector;
+ subcontext.firstSelectorOfTheFragment = subselector;
+ subcontext.pseudoElementEffective = false;
+ subcontext.inFunctionalPseudoClass = true;
+ PseudoIdSet ignoredDynamicPseudo;
+ return matchRecursively(checkingContext, subcontext, ignoredDynamicPseudo).match == Match::SelectorMatches;
+ }
case CSSSelector::PseudoElementPart: {
auto translatePartNameToRuleScope = [&](AtomString partName) {
Vector<AtomString, 1> mappedNames { partName };
Modified: trunk/Source/WebCore/css/SelectorChecker.h (284972 => 284973)
--- trunk/Source/WebCore/css/SelectorChecker.h 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/css/SelectorChecker.h 2021-10-28 08:59:03 UTC (rev 284973)
@@ -30,6 +30,7 @@
#include "CSSSelector.h"
#include "Element.h"
#include "StyleRelations.h"
+#include "StyleScopeOrdinal.h"
namespace WebCore {
@@ -95,6 +96,7 @@
const ContainerNode* scope { nullptr };
bool isMatchingHostPseudoClass { false };
const Element* shadowHostInPartRuleScope { nullptr };
+ Style::ScopeOrdinal styleScopeOrdinal { Style::ScopeOrdinal::Element };
// FIXME: It would be nicer to have a separate object for return values. This requires some more work in the selector compiler.
Style::Relations styleRelations;
Modified: trunk/Source/WebCore/css/SelectorFilter.cpp (284972 => 284973)
--- trunk/Source/WebCore/css/SelectorFilter.cpp 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/css/SelectorFilter.cpp 2021-10-28 08:59:03 UTC (rev 284973)
@@ -195,6 +195,7 @@
case CSSSelector::IndirectAdjacent:
case CSSSelector::ShadowDescendant:
case CSSSelector::ShadowPartDescendant:
+ case CSSSelector::ShadowSlotted:
skipOverSubselectors = true;
break;
case CSSSelector::DescendantSpace:
Modified: trunk/Source/WebCore/css/parser/CSSParserSelector.h (284972 => 284973)
--- trunk/Source/WebCore/css/parser/CSSParserSelector.h 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/css/parser/CSSParserSelector.h 2021-10-28 08:59:03 UTC (rev 284973)
@@ -103,6 +103,7 @@
|| pseudoElementType() == CSSSelector::PseudoElementCue
#endif
|| pseudoElementType() == CSSSelector::PseudoElementPart
+ || pseudoElementType() == CSSSelector::PseudoElementSlotted
|| pseudoElementType() == CSSSelector::PseudoElementWebKitCustomLegacyPrefixed);
}
Modified: trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp (284972 => 284973)
--- trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp 2021-10-28 08:59:03 UTC (rev 284973)
@@ -343,6 +343,9 @@
switch (compoundPseudoElement) {
case CSSSelector::PseudoElementPart:
return !isTreeStructuralPseudoClass(pseudoClass);
+ case CSSSelector::PseudoElementSlotted:
+ // FIXME: A WPT indicates :is/:where should be parsed but reduce to nothing as their content is not legal in the context.
+ return false;
case CSSSelector::PseudoElementResizer:
case CSSSelector::PseudoElementScrollbar:
case CSSSelector::PseudoElementScrollbarCorner:
@@ -361,6 +364,19 @@
}
}
+static bool isTreeAbidingPseudoElement(CSSSelector::PseudoElementType pseudoElementType)
+{
+ switch (pseudoElementType) {
+ // FIXME: This list should also include ::placeholder and ::file-selector-button
+ case CSSSelector::PseudoElementBefore:
+ case CSSSelector::PseudoElementAfter:
+ case CSSSelector::PseudoElementMarker:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool isSimpleSelectorValidAfterPseudoElement(const CSSParserSelector& simpleSelector, CSSSelector::PseudoElementType compoundPseudoElement)
{
if (compoundPseudoElement == CSSSelector::PseudoElementUnknown)
@@ -369,6 +385,10 @@
if (simpleSelector.match() == CSSSelector::PseudoElement && simpleSelector.pseudoElementType() != CSSSelector::PseudoElementPart)
return true;
}
+ if (compoundPseudoElement == CSSSelector::PseudoElementSlotted) {
+ if (simpleSelector.match() == CSSSelector::PseudoElement && isTreeAbidingPseudoElement(simpleSelector.pseudoElementType()))
+ return true;
+ }
if (simpleSelector.match() != CSSSelector::PseudoClass)
return false;
CSSSelector::PseudoClassType pseudo = simpleSelector.pseudoClassType();
@@ -1059,6 +1079,9 @@
// ::part() combines with other pseudo elements.
bool isPart = splitAfter->tagHistory()->match() == CSSSelector::PseudoElement && splitAfter->tagHistory()->pseudoElementType() == CSSSelector::PseudoElementPart;
+ // ::slotted() combines with other pseudo elements.
+ bool isSlotted = splitAfter->tagHistory()->match() == CSSSelector::PseudoElement && splitAfter->tagHistory()->pseudoElementType() == CSSSelector::PseudoElementSlotted;
+
std::unique_ptr<CSSParserSelector> secondCompound;
if (context.mode == UASheetMode || isPart) {
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=161747
@@ -1068,7 +1091,14 @@
} else
secondCompound = splitAfter->releaseTagHistory();
- secondCompound->appendTagHistory(isPart ? CSSSelector::ShadowPartDescendant : CSSSelector::ShadowDescendant, WTFMove(compoundSelector));
+ auto relation = [&] {
+ if (isSlotted)
+ return CSSSelector::ShadowSlotted;
+ if (isPart)
+ return CSSSelector::ShadowPartDescendant;
+ return CSSSelector::ShadowDescendant;
+ }();
+ secondCompound->appendTagHistory(relation, WTFMove(compoundSelector));
return secondCompound;
}
Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (284972 => 284973)
--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp 2021-10-28 08:59:03 UTC (rev 284973)
@@ -501,6 +501,7 @@
case CSSSelector::Subselector:
case CSSSelector::ShadowDescendant:
case CSSSelector::ShadowPartDescendant:
+ case CSSSelector::ShadowSlotted:
ASSERT_NOT_REACHED();
}
ASSERT_NOT_REACHED();
@@ -1326,6 +1327,9 @@
if ((relation == CSSSelector::ShadowDescendant || relation == CSSSelector::ShadowPartDescendant) && !selector->isLastInTagHistory())
return FunctionType::CannotCompile;
+ if (relation == CSSSelector::ShadowSlotted)
+ return FunctionType::CannotCompile;
+
if (relation == CSSSelector::DirectAdjacent || relation == CSSSelector::IndirectAdjacent) {
FunctionType relationFunctionType = FunctionType::SelectorCheckerWithCheckingContext;
if (selectorContext == SelectorContext::QuerySelector)
Modified: trunk/Source/WebCore/style/ElementRuleCollector.cpp (284972 => 284973)
--- trunk/Source/WebCore/style/ElementRuleCollector.cpp 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/style/ElementRuleCollector.cpp 2021-10-28 08:59:03 UTC (rev 284973)
@@ -120,7 +120,6 @@
void ElementRuleCollector::clearMatchedRules()
{
m_matchedRules.clear();
- m_keepAliveSlottedPseudoElementRules.clear();
m_matchedRuleTransferIndex = 0;
}
@@ -283,19 +282,11 @@
auto& styleScope = Scope::forNode(*slot);
if (!styleScope.resolver().ruleSets().isAuthorStyleDefined())
continue;
- // Find out if there are any ::slotted rules in the shadow tree matching the current slot.
- // FIXME: This is really part of the slot style and could be cached when resolving it.
- ElementRuleCollector collector(*slot, styleScope.resolver().ruleSets().authorStyle(), nullptr);
- auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot();
- if (!slottedPseudoElementRules)
- continue;
- // Match in the current scope.
- SetForScope<bool> change(m_isMatchingSlottedPseudoElements, true);
- MatchRequest scopeMatchRequest(nullptr, styleScopeOrdinal);
- collectMatchingRulesForList(slottedPseudoElementRules.get(), scopeMatchRequest);
+ auto& scopeAuthorRules = styleScope.resolver().ruleSets().authorStyle();
- m_keepAliveSlottedPseudoElementRules.append(WTFMove(slottedPseudoElementRules));
+ MatchRequest scopeMatchRequest(&scopeAuthorRules, styleScopeOrdinal);
+ collectMatchingRulesForList(&scopeAuthorRules.slottedPseudoElementRules(), scopeMatchRequest);
}
}
@@ -347,29 +338,6 @@
collectMatchingRulesForList(rules.shadowPseudoElementRules(pseudoId), matchRequest);
}
-std::unique_ptr<RuleSet::RuleDataVector> ElementRuleCollector::collectSlottedPseudoElementRulesForSlot()
-{
- ASSERT(is<HTMLSlotElement>(element()));
-
- clearMatchedRules();
-
- m_mode = SelectorChecker::Mode::CollectingRules;
-
- // Match global author rules.
- MatchRequest matchRequest(m_authorStyle.ptr());
- collectMatchingRulesForList(&m_authorStyle->slottedPseudoElementRules(), matchRequest);
-
- if (m_matchedRules.isEmpty())
- return { };
-
- auto ruleDataVector = makeUnique<RuleSet::RuleDataVector>();
- ruleDataVector->reserveInitialCapacity(m_matchedRules.size());
- for (auto& matchedRule : m_matchedRules)
- ruleDataVector->uncheckedAppend(*matchedRule.ruleData);
-
- return ruleDataVector;
-}
-
void ElementRuleCollector::matchUserRules()
{
if (!m_userStyle)
@@ -407,20 +375,8 @@
sortAndTransferMatchedRules(DeclarationOrigin::UserAgent);
}
-static const CSSSelector* findSlottedPseudoElementSelector(const CSSSelector* selector)
+inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned& specificity, ScopeOrdinal styleScopeOrdinal)
{
- for (; selector; selector = selector->tagHistory()) {
- if (selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementSlotted) {
- if (auto* list = selector->selectorList())
- return list->first();
- break;
- }
- };
- return nullptr;
-}
-
-inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned& specificity)
-{
// We know a sufficiently simple single part selector matches simply because we found it from the rule hash when filtering the RuleSet.
// This is limited to HTML only so we don't need to check the namespace (because of tag name match).
auto matchBasedOnRuleHash = ruleData.matchBasedOnRuleHash();
@@ -475,6 +431,7 @@
context.nameForHightlightPseudoElement = m_pseudoElementRequest.highlightName;
context.isMatchingHostPseudoClass = m_isMatchingHostPseudoClass;
context.shadowHostInPartRuleScope = m_shadowHostInPartRuleScope.get();
+ context.styleScopeOrdinal = styleScopeOrdinal;
bool selectorMatches;
#if ENABLE(CSS_SELECTOR_JIT)
@@ -485,15 +442,9 @@
#endif // ENABLE(CSS_SELECTOR_JIT)
{
auto* selector = ruleData.selector();
- auto* selectorForMatching = selector;
- if (m_isMatchingSlottedPseudoElements) {
- selectorForMatching = findSlottedPseudoElementSelector(ruleData.selector());
- if (!selectorForMatching)
- return false;
- }
// Slow path.
SelectorChecker selectorChecker(element().document());
- selectorMatches = selectorChecker.match(*selectorForMatching, element(), context);
+ selectorMatches = selectorChecker.match(*selector, element(), context);
if (selectorMatches)
specificity = selector->computeSpecificity();
}
@@ -535,7 +486,7 @@
continue;
unsigned specificity;
- if (ruleMatches(ruleData, specificity))
+ if (ruleMatches(ruleData, specificity, matchRequest.styleScopeOrdinal))
addMatchedRule(ruleData, specificity, matchRequest);
}
}
Modified: trunk/Source/WebCore/style/ElementRuleCollector.h (284972 => 284973)
--- trunk/Source/WebCore/style/ElementRuleCollector.h 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/style/ElementRuleCollector.h 2021-10-28 08:59:03 UTC (rev 284973)
@@ -135,11 +135,10 @@
void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot);
void collectMatchingShadowPseudoElementRules(const MatchRequest&);
- std::unique_ptr<RuleSet::RuleDataVector> collectSlottedPseudoElementRulesForSlot();
void collectMatchingRules(const MatchRequest&);
void collectMatchingRulesForList(const RuleSet::RuleDataVector*, const MatchRequest&);
- bool ruleMatches(const RuleData&, unsigned& specificity);
+ bool ruleMatches(const RuleData&, unsigned& specificity, ScopeOrdinal);
void sortMatchedRules();
@@ -163,10 +162,8 @@
bool m_isPrintStyle { false };
PseudoElementRequest m_pseudoElementRequest { PseudoId::None };
SelectorChecker::Mode m_mode { SelectorChecker::Mode::ResolvingStyle };
- bool m_isMatchingSlottedPseudoElements { false };
bool m_isMatchingHostPseudoClass { false };
RefPtr<const Element> m_shadowHostInPartRuleScope;
- Vector<std::unique_ptr<RuleSet::RuleDataVector>> m_keepAliveSlottedPseudoElementRules;
Vector<MatchedRule, 64> m_matchedRules;
size_t m_matchedRuleTransferIndex { 0 };
Modified: trunk/Source/WebCore/style/RuleFeature.cpp (284972 => 284973)
--- trunk/Source/WebCore/style/RuleFeature.cpp 2021-10-28 08:36:34 UTC (rev 284972)
+++ trunk/Source/WebCore/style/RuleFeature.cpp 2021-10-28 08:59:03 UTC (rev 284973)
@@ -86,6 +86,9 @@
case CSSSelector::ShadowDescendant:
case CSSSelector::ShadowPartDescendant:
return MatchElement::Host;
+ case CSSSelector::ShadowSlotted:
+ // FIXME: Implement accurate invalidation.
+ return matchElement;
};
}
switch (relation) {
@@ -100,6 +103,9 @@
case CSSSelector::ShadowDescendant:
case CSSSelector::ShadowPartDescendant:
return MatchElement::Host;
+ case CSSSelector::ShadowSlotted:
+ // FIXME: Implement accurate invalidation.
+ return matchElement;
};
ASSERT_NOT_REACHED();
return matchElement;