Skip to content

Commit d3fde7e

Browse files
committed
[css-nesting] CSSNestedDeclarations inside @scope should resolve to :where(:scope)
https://bugs.webkit.org/show_bug.cgi?id=280544 rdar://136856371 Reviewed by NOBODY (OOPS!). w3c/csswg-drafts#10431 This patch maintains a stack during rule set building to be able to determine whether the closest ancestor rule is a style rule or a scope rule, and to resolve the nesting parent selector & appropriately (:is(<parent>) or :where(:scope)). * LayoutTests/imported/w3c/web-platform-tests/css/css-nesting/nested-declarations-matching-expected.txt: * Source/WebCore/style/RuleSetBuilder.cpp: (WebCore::Style::RuleSetBuilder::addChildRule): (WebCore::Style::RuleSetBuilder::resolveSelectorListWithNesting): (WebCore::Style::RuleSetBuilder::addStyleRule): * Source/WebCore/style/RuleSetBuilder.h:
1 parent 4978759 commit d3fde7e

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

Diff for: LayoutTests/imported/w3c/web-platform-tests/css/css-nesting/nested-declarations-matching-expected.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ PASS Nested declarations rule has top-level specificity behavior
99
PASS Nested declarations rule has top-level specificity behavior (max matching)
1010
PASS Bare declartaion in nested grouping rule can match pseudo-element
1111
PASS Nested group rules have top-level specificity behavior
12-
FAIL Nested @scope rules behave like :where(:scope) assert_equals: expected "PASS" but got "FAIL"
13-
FAIL Nested @scope rules behave like :where(:scope) (trailing) assert_equals: expected "PASS" but got "FAIL"
12+
PASS Nested @scope rules behave like :where(:scope)
13+
PASS Nested @scope rules behave like :where(:scope) (trailing)
1414
PASS Nested declarations rule responds to parent selector text change
1515

Diff for: Source/WebCore/style/RuleSetBuilder.cpp

+27-5
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@
3939
#include "Document.h"
4040
#include "DocumentInlines.h"
4141
#include "MediaQueryEvaluator.h"
42+
#include "MutableCSSSelector.h"
4243
#include "StyleResolver.h"
4344
#include "StyleRuleImport.h"
4445
#include "StyleScope.h"
4546
#include "StyleSheetContents.h"
46-
#include "css/CSSSelectorList.h"
4747
#include <wtf/CryptographicallyRandomNumber.h>
4848

4949
namespace WebCore {
@@ -149,7 +149,9 @@ void RuleSetBuilder::addChildRule(Ref<StyleRuleBase> rule)
149149
// If <scope-start> is empty, it doesn't create a nesting context (the nesting selector might eventually be replaced by :scope)
150150
if (!scopeStart.isEmpty())
151151
m_selectorListStack.append(&scopeStart);
152+
m_ancestorStack.append(CSSParserEnum::NestedContextType::Scope);
152153
addChildRules(scopeRule->childRules());
154+
m_ancestorStack.removeLast();
153155
if (!scopeStart.isEmpty())
154156
m_selectorListStack.removeLast();
155157

@@ -275,7 +277,7 @@ void RuleSetBuilder::resolveSelectorListWithNesting(StyleRuleWithNesting& rule)
275277
{
276278
const CSSSelectorList* parentResolvedSelectorList = nullptr;
277279
if (m_selectorListStack.size())
278-
parentResolvedSelectorList = m_selectorListStack.last();
280+
parentResolvedSelectorList = m_selectorListStack.last();
279281

280282
// If it's a top-level rule without a nesting parent selector, keep the selector list as is.
281283
if (!rule.originalSelectorList().hasExplicitNestingParent() && !parentResolvedSelectorList)
@@ -303,13 +305,15 @@ void RuleSetBuilder::addStyleRule(StyleRuleWithNesting& rule)
303305
if (m_shouldResolveNesting == ShouldResolveNesting::Yes)
304306
resolveSelectorListWithNesting(rule);
305307

306-
auto& selectorList = rule.selectorList();
308+
const auto& selectorList = rule.selectorList();
307309
addStyleRuleWithSelectorList(selectorList, rule);
308310

309311
// Process nested rules
310312
m_selectorListStack.append(&selectorList);
313+
m_ancestorStack.append(CSSParserEnum::NestedContextType::Style);
311314
for (auto& nestedRule : rule.nestedRules())
312315
addChildRule(nestedRule);
316+
m_ancestorStack.removeLast();
313317
m_selectorListStack.removeLast();
314318
}
315319

@@ -320,8 +324,26 @@ void RuleSetBuilder::addStyleRule(const StyleRule& rule)
320324

321325
void RuleSetBuilder::addStyleRule(StyleRuleNestedDeclarations& rule)
322326
{
323-
ASSERT(m_selectorListStack.size());
324-
auto selectorList = *m_selectorListStack.last();
327+
auto whereScopeSelector = [] {
328+
auto scopeSelector = makeUnique<MutableCSSSelector>();
329+
scopeSelector->setMatch(CSSSelector::Match::PseudoClass);
330+
scopeSelector->setPseudoClass(CSSSelector::PseudoClass::Scope);
331+
auto whereSelector = makeUnique<MutableCSSSelector>();
332+
whereSelector->setMatch(CSSSelector::Match::PseudoClass);
333+
whereSelector->setPseudoClass(CSSSelector::PseudoClass::Where);
334+
whereSelector->setSelectorList(makeUnique<CSSSelectorList>(MutableCSSSelectorList::from(WTFMove(scopeSelector))));
335+
return whereSelector;
336+
};
337+
338+
auto selectorList = [&] {
339+
ASSERT(m_selectorListStack.size());
340+
ASSERT(m_ancestorStack.size());
341+
if (m_ancestorStack.last() == CSSParserEnum::NestedContextType::Style)
342+
return *m_selectorListStack.last();
343+
ASSERT(m_ancestorStack.last() == CSSParserEnum::NestedContextType::Scope);
344+
return CSSSelectorList { MutableCSSSelectorList::from(whereScopeSelector()) };
345+
}();
346+
325347
rule.wrapperAdoptSelectorList(WTFMove(selectorList));
326348
addStyleRuleWithSelectorList(rule.selectorList(), rule);
327349
}

Diff for: Source/WebCore/style/RuleSetBuilder.h

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#pragma once
2323

24+
#include "CSSParserEnum.h"
2425
#include "MediaQuery.h"
2526
#include "RuleSet.h"
2627

@@ -87,6 +88,7 @@ class RuleSetBuilder {
8788
HashMap<CascadeLayerName, RuleSet::CascadeLayerIdentifier> m_cascadeLayerIdentifierMap;
8889
RuleSet::CascadeLayerIdentifier m_currentCascadeLayerIdentifier { 0 };
8990
Vector<const CSSSelectorList*> m_selectorListStack;
91+
Vector<CSSParserEnum::NestedContextType> m_ancestorStack;
9092
const ShouldResolveNesting m_shouldResolveNesting { ShouldResolveNesting::No };
9193

9294
RuleSet::ContainerQueryIdentifier m_currentContainerQueryIdentifier { 0 };

0 commit comments

Comments
 (0)