Title: [281701] trunk
Revision
281701
Author
[email protected]
Date
2021-08-27 10:43:04 -0700 (Fri, 27 Aug 2021)

Log Message

[CSS Cascade Layers] Initial support
https://bugs.webkit.org/show_bug.cgi?id=229542

Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-cascade/layer-basic-expected.txt:

Source/WebCore:

https://www.w3.org/TR/css-cascade-5/#cascade-layers

This patch adds initial support for @layer rules, including both the block and the statement syntax.
No support for @import or CSSOM yet but basic functionality mostly works.

The feature is disabled by default.

* css/StyleRule.cpp:
(WebCore::StyleRuleBase::destroy):
(WebCore::StyleRuleBase::copy const):
(WebCore::StyleRuleBase::createCSSOMWrapper const):
(WebCore::StyleRuleLayer::StyleRuleLayer):
(WebCore::m_nameVariant):
(WebCore::StyleRuleLayer::create):
* css/StyleRule.h:
(WebCore::StyleRuleBase::isGroupRule const):

Add support for casting to StyleRuleGroup.

(WebCore::StyleRuleBase::isLayerRule const):
(isType):
* css/StyleRuleType.h:

Add subclass for layer.

* css/StyleSheetContents.cpp:
(WebCore::traverseRulesInVector):
(WebCore::StyleSheetContents::traverseSubresources const):

Traversal support. Also cover other missing group rules.

* css/parser/CSSAtRuleID.cpp:
(WebCore::cssAtRuleID):
* css/parser/CSSAtRuleID.h:
* css/parser/CSSParserContext.cpp:

Enable bit.

(WebCore::operator==):
(WebCore::add):
* css/parser/CSSParserContext.h:
* css/parser/CSSParserImpl.cpp:
(WebCore::CSSParserImpl::consumeAtRule):
(WebCore::CSSParserImpl::consumeLayerRule):

Parsing support.

* css/parser/CSSParserImpl.h:
* style/ElementRuleCollector.cpp:
(WebCore::Style::ElementRuleCollector::addMatchedRule):
(WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):

Save the layer order to MatchResult.

(WebCore::Style::compareRules):

Layer order has higher priority than specificity but lower than scope.

* style/ElementRuleCollector.h:
* style/RuleSet.cpp:
(WebCore::Style::RuleSet::addRule):
(WebCore::Style::RuleSet::addChildRules):
(WebCore::Style::RuleSet::pushCascadeLayer):
(WebCore::Style::RuleSet::popCascadeLayer):

Compute layer order when adding the rules to RuleSet.

* style/RuleSet.h:
(WebCore::Style::RuleSet::cascadeLayerOrderFor const):

Resolved order is kept in a side vector to avoid bloating RuleSet. The vector is initialized
only if cascade layers are being used.

Source/WTF:

* Scripts/Preferences/WebPreferencesExperimental.yaml:

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (281700 => 281701)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-08-27 17:43:04 UTC (rev 281701)
@@ -1,3 +1,12 @@
+2021-08-27  Antti Koivisto  <[email protected]>
+
+        [CSS Cascade Layers] Initial support
+        https://bugs.webkit.org/show_bug.cgi?id=229542
+
+        Reviewed by Simon Fraser.
+
+        * web-platform-tests/css/css-cascade/layer-basic-expected.txt:
+
 2021-08-27  Martin Robinson  <[email protected]>
 
         [css-position-sticky] createIndicatorForStickyElements testing function races with font loading

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/layer-basic-expected.txt (281700 => 281701)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/layer-basic-expected.txt	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/layer-basic-expected.txt	2021-08-27 17:43:04 UTC (rev 281701)
@@ -1,36 +1,36 @@
 
 PASS A1 Anonymous layers
-FAIL A2 Anonymous layers assert_equals: A2 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
-FAIL A3 Anonymous layers assert_equals: A3 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
-FAIL A4 Anonymous layers assert_equals: A4 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL A5 Anonymous layers assert_equals: A5 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
-FAIL A6 Anonymous layers assert_equals: A6 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
-FAIL A7 Anonymous layers assert_equals: A7 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL A8 Anonymous layers assert_equals: A8 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL A9 Anonymous layers assert_equals: A9 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
+PASS A2 Anonymous layers
+PASS A3 Anonymous layers
+PASS A4 Anonymous layers
+PASS A5 Anonymous layers
+PASS A6 Anonymous layers
+PASS A7 Anonymous layers
+PASS A8 Anonymous layers
+PASS A9 Anonymous layers
 PASS B1 Named layers
-FAIL B2 Named layers assert_equals: B2 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
-FAIL B3 Named layers assert_equals: B3 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
-FAIL B4 Named layers assert_equals: B4 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL B5 Named layers assert_equals: B5 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL B6 Named layers assert_equals: B6 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL B7 Named layers assert_equals: B7 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL B8 Named layers assert_equals: B8 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL B9 Named layers assert_equals: B9 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL B10 Named layers assert_equals: B10 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL C1 Named layers shorthand assert_equals: C1 Named layers shorthand, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL C2 Named layers shorthand assert_equals: C2 Named layers shorthand, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL C3 Named layers shorthand assert_equals: C3 Named layers shorthand, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL C4 Named layers shorthand assert_equals: C4 Named layers shorthand, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL C5 Named layers shorthand assert_equals: C5 Named layers shorthand, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL D1 Mixed named and anonymous layers assert_equals: D1 Mixed named and anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL D2 Mixed named and anonymous layers assert_equals: D2 Mixed named and anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL D3 Mixed named and anonymous layers assert_equals: D3 Mixed named and anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL D4 Mixed named and anonymous layers assert_equals: D4 Mixed named and anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL D5 Mixed named and anonymous layers assert_equals: D5 Mixed named and anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL E1 Statement syntax assert_equals: E1 Statement syntax, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL E2 Statement syntax assert_equals: E2 Statement syntax, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL E3 Statement syntax assert_equals: E3 Statement syntax, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL E4 Statement syntax assert_equals: E4 Statement syntax, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
-FAIL E5 Statement syntax assert_equals: E5 Statement syntax, target 'first' expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
+PASS B2 Named layers
+PASS B3 Named layers
+PASS B4 Named layers
+PASS B5 Named layers
+PASS B6 Named layers
+PASS B7 Named layers
+PASS B8 Named layers
+PASS B9 Named layers
+FAIL B10 Named layers assert_equals: B10 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+PASS C1 Named layers shorthand
+PASS C2 Named layers shorthand
+FAIL C3 Named layers shorthand assert_equals: C3 Named layers shorthand, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+PASS C4 Named layers shorthand
+FAIL C5 Named layers shorthand assert_equals: C5 Named layers shorthand, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+PASS D1 Mixed named and anonymous layers
+PASS D2 Mixed named and anonymous layers
+PASS D3 Mixed named and anonymous layers
+FAIL D4 Mixed named and anonymous layers assert_equals: D4 Mixed named and anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+PASS D5 Mixed named and anonymous layers
+PASS E1 Statement syntax
+PASS E2 Statement syntax
+PASS E3 Statement syntax
+PASS E4 Statement syntax
+FAIL E5 Statement syntax assert_equals: E5 Statement syntax, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
 

Modified: trunk/Source/WTF/ChangeLog (281700 => 281701)


--- trunk/Source/WTF/ChangeLog	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WTF/ChangeLog	2021-08-27 17:43:04 UTC (rev 281701)
@@ -1,3 +1,12 @@
+2021-08-27  Antti Koivisto  <[email protected]>
+
+        [CSS Cascade Layers] Initial support
+        https://bugs.webkit.org/show_bug.cgi?id=229542
+
+        Reviewed by Simon Fraser.
+
+        * Scripts/Preferences/WebPreferencesExperimental.yaml:
+
 2021-08-27  Mikhail R. Gadelha  <[email protected]>
 
         Avoid increasing required alignment of target type warning on ARM 32 bits

Modified: trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml (281700 => 281701)


--- trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml	2021-08-27 17:43:04 UTC (rev 281701)
@@ -111,6 +111,18 @@
     WebKit:
       default: false
 
+CSSCascadeLayersEnabled:
+  type: bool
+  humanReadableName: "CSS Cascade Layers"
+  humanReadableDescription: "Enable CSS Cascade Layers"
+  defaultValue:
+    WebKitLegacy:
+      default: false
+    WebKit:
+      default: false
+    WebCore:
+      default: false
+
 CSSColor4:
   type: bool
   humanReadableName: "CSS Color 4 Color Types"

Modified: trunk/Source/WebCore/ChangeLog (281700 => 281701)


--- trunk/Source/WebCore/ChangeLog	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/ChangeLog	2021-08-27 17:43:04 UTC (rev 281701)
@@ -1,5 +1,85 @@
 2021-08-27  Antti Koivisto  <[email protected]>
 
+        [CSS Cascade Layers] Initial support
+        https://bugs.webkit.org/show_bug.cgi?id=229542
+
+        Reviewed by Simon Fraser.
+
+        https://www.w3.org/TR/css-cascade-5/#cascade-layers
+
+        This patch adds initial support for @layer rules, including both the block and the statement syntax.
+        No support for @import or CSSOM yet but basic functionality mostly works.
+
+        The feature is disabled by default.
+
+        * css/StyleRule.cpp:
+        (WebCore::StyleRuleBase::destroy):
+        (WebCore::StyleRuleBase::copy const):
+        (WebCore::StyleRuleBase::createCSSOMWrapper const):
+        (WebCore::StyleRuleLayer::StyleRuleLayer):
+        (WebCore::m_nameVariant):
+        (WebCore::StyleRuleLayer::create):
+        * css/StyleRule.h:
+        (WebCore::StyleRuleBase::isGroupRule const):
+
+        Add support for casting to StyleRuleGroup.
+
+        (WebCore::StyleRuleBase::isLayerRule const):
+        (isType):
+        * css/StyleRuleType.h:
+
+        Add subclass for layer.
+
+        * css/StyleSheetContents.cpp:
+        (WebCore::traverseRulesInVector):
+        (WebCore::StyleSheetContents::traverseSubresources const):
+
+        Traversal support. Also cover other missing group rules.
+
+        * css/parser/CSSAtRuleID.cpp:
+        (WebCore::cssAtRuleID):
+        * css/parser/CSSAtRuleID.h:
+        * css/parser/CSSParserContext.cpp:
+
+        Enable bit.
+
+        (WebCore::operator==):
+        (WebCore::add):
+        * css/parser/CSSParserContext.h:
+        * css/parser/CSSParserImpl.cpp:
+        (WebCore::CSSParserImpl::consumeAtRule):
+        (WebCore::CSSParserImpl::consumeLayerRule):
+
+        Parsing support.
+
+        * css/parser/CSSParserImpl.h:
+        * style/ElementRuleCollector.cpp:
+        (WebCore::Style::ElementRuleCollector::addMatchedRule):
+        (WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):
+
+        Save the layer order to MatchResult.
+
+        (WebCore::Style::compareRules):
+
+        Layer order has higher priority than specificity but lower than scope.
+
+        * style/ElementRuleCollector.h:
+        * style/RuleSet.cpp:
+        (WebCore::Style::RuleSet::addRule):
+        (WebCore::Style::RuleSet::addChildRules):
+        (WebCore::Style::RuleSet::pushCascadeLayer):
+        (WebCore::Style::RuleSet::popCascadeLayer):
+
+        Compute layer order when adding the rules to RuleSet.
+
+        * style/RuleSet.h:
+        (WebCore::Style::RuleSet::cascadeLayerOrderFor const):
+
+        Resolved order is kept in a side vector to avoid bloating RuleSet. The vector is initialized
+        only if cascade layers are being used.
+
+2021-08-27  Antti Koivisto  <[email protected]>
+
         REGRESSION (r276882): Shadow trees may use stale style information after inline stylesheet is mutated via CSSOM
         https://bugs.webkit.org/show_bug.cgi?id=228917
         rdar://81483998

Modified: trunk/Source/WebCore/css/StyleRule.cpp (281700 => 281701)


--- trunk/Source/WebCore/css/StyleRule.cpp	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/StyleRule.cpp	2021-08-27 17:43:04 UTC (rev 281701)
@@ -94,6 +94,9 @@
     case StyleRuleType::CounterStyle:
         delete downcast<StyleRuleCounterStyle>(this);
         return;
+    case StyleRuleType::Layer:
+        delete downcast<StyleRuleLayer>(this);
+        return;
     case StyleRuleType::Unknown:
         ASSERT_NOT_REACHED();
         return;
@@ -118,6 +121,8 @@
         return downcast<StyleRuleKeyframes>(*this).copy();
     case StyleRuleType::CounterStyle:
         return downcast<StyleRuleCounterStyle>(*this).copy();
+    case StyleRuleType::Layer:
+        return downcast<StyleRuleLayer>(*this).copy();
     case StyleRuleType::Import:
     case StyleRuleType::Namespace:
         // FIXME: Copy import and namespace rules.
@@ -162,6 +167,8 @@
     case StyleRuleType::CounterStyle:
         rule = CSSCounterStyleRule::create(downcast<StyleRuleCounterStyle>(self), parentSheet);
         break;
+    case StyleRuleType::Layer:
+        // FIXME: Implement.
     case StyleRuleType::Unknown:
     case StyleRuleType::Charset:
     case StyleRuleType::Keyframe:
@@ -431,6 +438,7 @@
 {
 }
 
+
 Ref<StyleRuleSupports> StyleRuleSupports::create(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase>>&& rules)
 {
     return adoptRef(*new StyleRuleSupports(conditionText, conditionIsSupported, WTFMove(rules)));
@@ -441,6 +449,45 @@
     return adoptRef(*new StyleRuleSupports(conditionText, conditionIsSupported, WTFMove(rules)));
 }
 
+StyleRuleLayer::StyleRuleLayer(Vector<CascadeLayerName>&& nameList)
+    : StyleRuleGroup(StyleRuleType::Layer, Vector<RefPtr<StyleRuleBase>> { })
+    , m_nameVariant(WTFMove(nameList))
+{
+}
+
+StyleRuleLayer::StyleRuleLayer(CascadeLayerName&& name, Vector<RefPtr<StyleRuleBase>>&& rules)
+    : StyleRuleGroup(StyleRuleType::Layer, WTFMove(rules))
+    , m_nameVariant(WTFMove(name))
+{
+}
+
+StyleRuleLayer::StyleRuleLayer(CascadeLayerName&& name, std::unique_ptr<DeferredStyleGroupRuleList>&& rules)
+    : StyleRuleGroup(StyleRuleType::Layer, WTFMove(rules))
+    , m_nameVariant(WTFMove(name))
+{
+}
+
+StyleRuleLayer::StyleRuleLayer(const StyleRuleLayer& other)
+    : StyleRuleGroup(other)
+    , m_nameVariant(other.m_nameVariant)
+{
+}
+
+Ref<StyleRuleLayer> StyleRuleLayer::create(Vector<CascadeLayerName>&& nameList)
+{
+    return adoptRef(*new StyleRuleLayer(WTFMove(nameList)));
+}
+
+Ref<StyleRuleLayer> StyleRuleLayer::create(CascadeLayerName&& name, Vector<RefPtr<StyleRuleBase>>&& rules)
+{
+    return adoptRef(*new StyleRuleLayer(WTFMove(name), WTFMove(rules)));
+}
+
+Ref<StyleRuleLayer> StyleRuleLayer::create(CascadeLayerName&& name, std::unique_ptr<DeferredStyleGroupRuleList>&& rules)
+{
+    return adoptRef(*new StyleRuleLayer(WTFMove(name), WTFMove(rules)));
+}
+
 StyleRuleCharset::StyleRuleCharset()
     : StyleRuleBase(StyleRuleType::Charset)
 {

Modified: trunk/Source/WebCore/css/StyleRule.h (281700 => 281701)


--- trunk/Source/WebCore/css/StyleRule.h	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/StyleRule.h	2021-08-27 17:43:04 UTC (rev 281701)
@@ -28,6 +28,7 @@
 #include <wtf/RefPtr.h>
 #include <wtf/TypeCasts.h>
 #include <wtf/UniqueArray.h>
+#include <wtf/Variant.h>
 
 namespace WebCore {
 
@@ -39,6 +40,8 @@
 class StyleRuleKeyframe;
 class StyleProperties;
 class StyleRuleKeyframes;
+
+using CascadeLayerName = Vector<AtomString>;
     
 DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(StyleRuleBase);
 class StyleRuleBase : public WTF::RefCountedBase {
@@ -55,8 +58,10 @@
     bool isMediaRule() const { return type() == StyleRuleType::Media; }
     bool isPageRule() const { return type() == StyleRuleType::Page; }
     bool isStyleRule() const { return type() == StyleRuleType::Style; }
+    bool isGroupRule() const { return type() == StyleRuleType::Media || type() == StyleRuleType::Supports || type() == StyleRuleType::Layer; }
     bool isSupportsRule() const { return type() == StyleRuleType::Supports; }
     bool isImportRule() const { return type() == StyleRuleType::Import; }
+    bool isLayerRule() const { return type() == StyleRuleType::Layer; }
 
     Ref<StyleRuleBase> copy() const;
 
@@ -239,6 +244,27 @@
     bool m_conditionIsSupported;
 };
 
+class StyleRuleLayer final : public StyleRuleGroup {
+public:
+    static Ref<StyleRuleLayer> create(Vector<CascadeLayerName>&&);
+    static Ref<StyleRuleLayer> create(CascadeLayerName&&, Vector<RefPtr<StyleRuleBase>>&&);
+    static Ref<StyleRuleLayer> create(CascadeLayerName&&, std::unique_ptr<DeferredStyleGroupRuleList>&&);
+    Ref<StyleRuleLayer> copy() const { return adoptRef(*new StyleRuleLayer(*this)); }
+
+    bool isList() const { return WTF::holds_alternative<Vector<CascadeLayerName>>(m_nameVariant); }
+
+    auto& name() const { return WTF::get<CascadeLayerName>(m_nameVariant); }
+    auto& nameList() const { return WTF::get<Vector<CascadeLayerName>>(m_nameVariant); }
+
+private:
+    StyleRuleLayer(Vector<CascadeLayerName>&&);
+    StyleRuleLayer(CascadeLayerName&&, Vector<RefPtr<StyleRuleBase>>&&);
+    StyleRuleLayer(CascadeLayerName&&, std::unique_ptr<DeferredStyleGroupRuleList>&&);
+    StyleRuleLayer(const StyleRuleLayer&);
+
+    Variant<CascadeLayerName, Vector<CascadeLayerName>> m_nameVariant;
+};
+
 // This is only used by the CSS parser.
 class StyleRuleCharset final : public StyleRuleBase {
 public:
@@ -323,6 +349,10 @@
     static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isStyleRule(); }
 SPECIALIZE_TYPE_TRAITS_END()
 
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleGroup)
+    static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isGroupRule(); }
+SPECIALIZE_TYPE_TRAITS_END()
+
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleFontFace)
     static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isFontFaceRule(); }
 SPECIALIZE_TYPE_TRAITS_END()
@@ -350,3 +380,7 @@
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleCharset)
     static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isCharsetRule(); }
 SPECIALIZE_TYPE_TRAITS_END()
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleLayer)
+    static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isLayerRule(); }
+SPECIALIZE_TYPE_TRAITS_END()

Modified: trunk/Source/WebCore/css/StyleRuleType.h (281700 => 281701)


--- trunk/Source/WebCore/css/StyleRuleType.h	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/StyleRuleType.h	2021-08-27 17:43:04 UTC (rev 281701)
@@ -40,6 +40,7 @@
     Namespace = 10,
     CounterStyle = 11,
     Supports = 12,
+    Layer = 13,
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/css/StyleSheetContents.cpp (281700 => 281701)


--- trunk/Source/WebCore/css/StyleSheetContents.cpp	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/StyleSheetContents.cpp	2021-08-27 17:43:04 UTC (rev 281701)
@@ -423,8 +423,10 @@
         if (handler(*rule))
             return true;
         switch (rule->type()) {
-        case StyleRuleType::Media: {
-            auto* childRules = downcast<StyleRuleMedia>(*rule).childRulesWithoutDeferredParsing();
+        case StyleRuleType::Media:
+        case StyleRuleType::Supports:
+        case StyleRuleType::Layer: {
+            auto* childRules = downcast<StyleRuleGroup>(*rule).childRulesWithoutDeferredParsing();
             if (childRules && traverseRulesInVector(*childRules, handler))
                 return true;
             break;
@@ -441,7 +443,6 @@
         case StyleRuleType::Charset:
         case StyleRuleType::CounterStyle:
         case StyleRuleType::Keyframe:
-        case StyleRuleType::Supports:
             break;
         }
     }
@@ -484,6 +485,7 @@
         case StyleRuleType::Charset:
         case StyleRuleType::Keyframe:
         case StyleRuleType::Supports:
+        case StyleRuleType::Layer:
             return false;
         };
         ASSERT_NOT_REACHED();

Modified: trunk/Source/WebCore/css/parser/CSSAtRuleID.cpp (281700 => 281701)


--- trunk/Source/WebCore/css/parser/CSSAtRuleID.cpp	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/parser/CSSAtRuleID.cpp	2021-08-27 17:43:04 UTC (rev 281701)
@@ -58,6 +58,8 @@
         return CSSAtRuleApply;
     if (equalIgnoringASCIICase(name, "counter-style"))
         return CSSAtRuleCounterStyle;
+    if (equalIgnoringASCIICase(name, "layer"))
+        return CSSAtRuleLayer;
     return CSSAtRuleInvalid;
 }
 

Modified: trunk/Source/WebCore/css/parser/CSSAtRuleID.h (281700 => 281701)


--- trunk/Source/WebCore/css/parser/CSSAtRuleID.h	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/parser/CSSAtRuleID.h	2021-08-27 17:43:04 UTC (rev 281701)
@@ -48,6 +48,7 @@
     CSSAtRuleWebkitKeyframes = 10,
     CSSAtRuleApply = 11,
     CSSAtRuleCounterStyle = 12,
+    CSSAtRuleLayer = 13,
 };
 
 CSSAtRuleID cssAtRuleID(StringView name);

Modified: trunk/Source/WebCore/css/parser/CSSParserContext.cpp (281700 => 281701)


--- trunk/Source/WebCore/css/parser/CSSParserContext.cpp	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/parser/CSSParserContext.cpp	2021-08-27 17:43:04 UTC (rev 281701)
@@ -95,6 +95,7 @@
     , useLegacyBackgroundSizeShorthandBehavior { document.settings().useLegacyBackgroundSizeShorthandBehavior() }
     , focusVisibleEnabled { document.settings().focusVisibleEnabled() }
     , hasPseudoClassEnabled { document.settings().hasPseudoClassEnabled() }
+    , cascadeLayersEnabled { document.settings().cssCascadeLayersEnabled() }
 #if ENABLE(ATTACHMENT_ELEMENT)
     , attachmentEnabled { RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() }
 #endif
@@ -139,6 +140,7 @@
         && a.useLegacyBackgroundSizeShorthandBehavior == b.useLegacyBackgroundSizeShorthandBehavior
         && a.focusVisibleEnabled == b.focusVisibleEnabled
         && a.hasPseudoClassEnabled == b.hasPseudoClassEnabled
+        && a.cascadeLayersEnabled == b.cascadeLayersEnabled
 #if ENABLE(ATTACHMENT_ELEMENT)
         && a.attachmentEnabled == b.attachmentEnabled
 #endif
@@ -177,11 +179,12 @@
         | context.useLegacyBackgroundSizeShorthandBehavior  << 20
         | context.focusVisibleEnabled                       << 21
         | context.hasPseudoClassEnabled                     << 22
+        | context.cascadeLayersEnabled                      << 23
 #if ENABLE(ATTACHMENT_ELEMENT)
-        | context.attachmentEnabled                         << 23
+        | context.attachmentEnabled                         << 24
 #endif
-        | context.overflowClipEnabled                       << 24
-        | context.mode                                      << 25; // This is multiple bits, so keep it last.
+        | context.overflowClipEnabled                       << 25
+        | context.mode                                      << 26; // This is multiple bits, so keep it last.
     add(hasher, context.baseURL, context.charset, bits);
 }
 

Modified: trunk/Source/WebCore/css/parser/CSSParserContext.h (281700 => 281701)


--- trunk/Source/WebCore/css/parser/CSSParserContext.h	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/parser/CSSParserContext.h	2021-08-27 17:43:04 UTC (rev 281701)
@@ -82,6 +82,7 @@
     bool useLegacyBackgroundSizeShorthandBehavior { false };
     bool focusVisibleEnabled { false };
     bool hasPseudoClassEnabled { false };
+    bool cascadeLayersEnabled { false };
 
     // RuntimeEnabledFeatures.
 #if ENABLE(ATTACHMENT_ELEMENT)

Modified: trunk/Source/WebCore/css/parser/CSSParserImpl.cpp (281700 => 281701)


--- trunk/Source/WebCore/css/parser/CSSParserImpl.cpp	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/parser/CSSParserImpl.cpp	2021-08-27 17:43:04 UTC (rev 281701)
@@ -420,6 +420,8 @@
             return consumeImportRule(prelude);
         if (allowedRules <= AllowNamespaceRules && id == CSSAtRuleNamespace)
             return consumeNamespaceRule(prelude);
+        if (allowedRules <= RegularRules && id == CSSAtRuleLayer)
+            return consumeLayerRule(prelude, { });
         // FIXME-NEWPARSER: Support "apply"
         /*if (allowedRules == ApplyRules && id == CSSAtRuleApply) {
             consumeApplyRule(prelude);
@@ -451,6 +453,8 @@
         return consumePageRule(prelude, block);
     case CSSAtRuleCounterStyle:
         return consumeCounterStyleRule(prelude, block);
+    case CSSAtRuleLayer:
+        return consumeLayerRule(prelude, block);
     default:
         return nullptr; // Parse error, unrecognised at-rule with block
     }
@@ -676,6 +680,92 @@
     return StyleRuleCounterStyle::create(name, createStyleProperties(m_parsedProperties, m_context.mode));
 }
 
+RefPtr<StyleRuleLayer> CSSParserImpl::consumeLayerRule(CSSParserTokenRange prelude, std::optional<CSSParserTokenRange> block)
+{
+    if (!m_context.cascadeLayersEnabled)
+        return nullptr;
+
+    auto preludeCopy = prelude;
+
+    auto consumeName = [&]() -> std::optional<CascadeLayerName> {
+        CascadeLayerName name;
+        // Anonymous case.
+        if (prelude.atEnd())
+            return name;
+
+        while (true) {
+            auto nameToken = prelude.consume();
+            if (nameToken.type() != IdentToken)
+                return { };
+
+            name.append(nameToken.value().toAtomString());
+
+            if (prelude.peek().type() != DelimiterToken || prelude.peek().delimiter() != '.')
+                break;
+            prelude.consume();
+        }
+
+        prelude.consumeWhitespace();
+        return name;
+    };
+
+    if (!block) {
+        // List syntax.
+        Vector<CascadeLayerName> nameList;
+        while (true) {
+            auto name = consumeName();
+            if (!name)
+                return nullptr;
+            nameList.append(*name);
+
+            if (prelude.atEnd())
+                break;
+
+            auto commaToken = prelude.consumeIncludingWhitespace();
+            if (commaToken.type() != CommaToken)
+                return { };
+        }
+
+        if (m_observerWrapper) {
+            unsigned endOffset = m_observerWrapper->endOffset(preludeCopy);
+            m_observerWrapper->observer().startRuleHeader(StyleRuleType::Layer, m_observerWrapper->startOffset(preludeCopy));
+            m_observerWrapper->observer().endRuleHeader(endOffset);
+            m_observerWrapper->observer().startRuleBody(endOffset);
+            m_observerWrapper->observer().endRuleBody(endOffset);
+        }
+
+        return StyleRuleLayer::create(WTFMove(nameList));
+    }
+
+    auto name = consumeName();
+    if (!name)
+        return nullptr;
+
+    // No comma separated list when using the block syntax.
+    if (!prelude.atEnd())
+        return nullptr;
+
+    if (m_deferredParser)
+        return StyleRuleLayer::create(WTFMove(*name), makeUnique<DeferredStyleGroupRuleList>(*block, *m_deferredParser));
+
+    if (m_observerWrapper) {
+        m_observerWrapper->observer().startRuleHeader(StyleRuleType::Layer, m_observerWrapper->startOffset(preludeCopy));
+        m_observerWrapper->observer().endRuleHeader(m_observerWrapper->endOffset(preludeCopy));
+        m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousTokenStartOffset(*block));
+    }
+
+    Vector<RefPtr<StyleRuleBase>> rules;
+    consumeRuleList(*block, RegularRuleList, [&](RefPtr<StyleRuleBase> rule) {
+        rules.append(rule);
+    });
+    rules.shrinkToFit();
+
+    if (m_observerWrapper)
+        m_observerWrapper->observer().endRuleBody(m_observerWrapper->endOffset(*block));
+
+    return StyleRuleLayer::create(WTFMove(*name), WTFMove(rules));
+}
+
 // FIXME-NEWPARSER: Support "apply"
 /*void CSSParserImpl::consumeApplyRule(CSSParserTokenRange prelude)
 {

Modified: trunk/Source/WebCore/css/parser/CSSParserImpl.h (281700 => 281701)


--- trunk/Source/WebCore/css/parser/CSSParserImpl.h	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/css/parser/CSSParserImpl.h	2021-08-27 17:43:04 UTC (rev 281701)
@@ -53,6 +53,7 @@
 class StyleRuleFontFace;
 class StyleRuleImport;
 class StyleRuleKeyframes;
+class StyleRuleLayer;
 class StyleRuleMedia;
 class StyleRuleNamespace;
 class StyleRulePage;
@@ -135,7 +136,8 @@
     RefPtr<StyleRuleKeyframes> consumeKeyframesRule(bool webkitPrefixed, CSSParserTokenRange prelude, CSSParserTokenRange block);
     RefPtr<StyleRulePage> consumePageRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
     RefPtr<StyleRuleCounterStyle> consumeCounterStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
-    
+    RefPtr<StyleRuleLayer> consumeLayerRule(CSSParserTokenRange prelude, std::optional<CSSParserTokenRange> block);
+
     // FIXME-NEWPARSER: Support "apply"
     // void consumeApplyRule(CSSParserTokenRange prelude);
 

Modified: trunk/Source/WebCore/style/ElementRuleCollector.cpp (281700 => 281701)


--- trunk/Source/WebCore/style/ElementRuleCollector.cpp	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/style/ElementRuleCollector.cpp	2021-08-27 17:43:04 UTC (rev 281701)
@@ -111,9 +111,10 @@
     return m_matchedRuleList;
 }
 
-inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, ScopeOrdinal styleScopeOrdinal)
+inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, const MatchRequest& matchRequest)
 {
-    m_matchedRules.append({ &ruleData, specificity, styleScopeOrdinal });
+    auto cascadeLayerOrder = matchRequest.ruleSet ? matchRequest.ruleSet->cascadeLayerOrderFor(ruleData) : 0;
+    m_matchedRules.append({ &ruleData, specificity, matchRequest.styleScopeOrdinal, cascadeLayerOrder });
 }
 
 void ElementRuleCollector::clearMatchedRules()
@@ -535,7 +536,7 @@
 
         unsigned specificity;
         if (ruleMatches(ruleData, specificity))
-            addMatchedRule(ruleData, specificity, matchRequest.styleScopeOrdinal);
+            addMatchedRule(ruleData, specificity, matchRequest);
     }
 }
 
@@ -545,6 +546,9 @@
     if (r1.styleScopeOrdinal != r2.styleScopeOrdinal)
         return r1.styleScopeOrdinal > r2.styleScopeOrdinal;
 
+    if (r1.cascadeLayerOrder != r2.cascadeLayerOrder)
+        return r1.cascadeLayerOrder < r2.cascadeLayerOrder;
+
     if (r1.specificity != r2.specificity)
         return r1.specificity < r2.specificity;
 

Modified: trunk/Source/WebCore/style/ElementRuleCollector.h (281700 => 281701)


--- trunk/Source/WebCore/style/ElementRuleCollector.h	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/style/ElementRuleCollector.h	2021-08-27 17:43:04 UTC (rev 281701)
@@ -62,6 +62,7 @@
     const RuleData* ruleData;
     unsigned specificity;
     ScopeOrdinal styleScopeOrdinal;
+    unsigned cascadeLayerOrder;
 };
 
 struct MatchedProperties {
@@ -146,7 +147,7 @@
     void sortAndTransferMatchedRules(DeclarationOrigin);
     void transferMatchedRules(DeclarationOrigin, std::optional<ScopeOrdinal> forScope = { });
 
-    void addMatchedRule(const RuleData&, unsigned specificity, ScopeOrdinal);
+    void addMatchedRule(const RuleData&, unsigned specificity, const MatchRequest&);
     void addMatchedProperties(MatchedProperties&&, DeclarationOrigin);
 
     const Element& element() const { return m_element.get(); }

Modified: trunk/Source/WebCore/style/RuleSet.cpp (281700 => 281701)


--- trunk/Source/WebCore/style/RuleSet.cpp	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/style/RuleSet.cpp	2021-08-27 17:43:04 UTC (rev 281701)
@@ -87,6 +87,13 @@
 {
     RuleData ruleData(rule, selectorIndex, selectorListIndex, m_ruleCount++);
 
+    if (m_cascadeLayerOrder) {
+        auto oldSize = m_cascadeLayerOrderForPosition.size();
+        m_cascadeLayerOrderForPosition.grow(m_ruleCount);
+        std::fill(m_cascadeLayerOrderForPosition.begin() + oldSize, m_cascadeLayerOrderForPosition.end(), 0);
+        m_cascadeLayerOrderForPosition.last() = m_cascadeLayerOrder;
+    }
+
     m_features.collectFeatures(ruleData);
 
     if (mediaQueryCollector)
@@ -287,6 +294,22 @@
             mediaQueryCollector.pop(&mediaRule.mediaQueries());
             continue;
         }
+        if (is<StyleRuleLayer>(*rule)) {
+            auto& layerRule = downcast<StyleRuleLayer>(*rule);
+            if (layerRule.isList()) {
+                // List syntax that just registers the layers.
+                for (auto& name : layerRule.nameList()) {
+                    pushCascadeLayer(name);
+                    popCascadeLayer(name);
+                }
+                continue;
+            }
+            // Block syntax.
+            pushCascadeLayer(layerRule.name());
+            addChildRules(layerRule.childRules(), mediaQueryCollector, resolver, mode);
+            popCascadeLayer(layerRule.name());
+            continue;
+        }
         if (is<StyleRuleFontFace>(*rule)) {
             // Add this font face to our set.
             if (resolver) {
@@ -469,6 +492,34 @@
     return collectedChanges;
 }
 
+void RuleSet::pushCascadeLayer(const CascadeLayerName& name)
+{
+    auto nameResolvingAnonymous = [&] {
+        if (name.isEmpty()) {
+            // Make unique name for an anonymous layer.
+            unsigned long long random = randomNumber() * std::numeric_limits<unsigned long long>::max();
+            return CascadeLayerName { "anon_"_s + String::number(random) };
+        }
+        return name;
+    };
+
+    // For hierarchical names we register the containing layers individually first.
+    for (auto& nameSegment : nameResolvingAnonymous()) {
+        m_resolvedCascadeLayerName.append(nameSegment);
+        m_cascadeLayerOrder = m_cascadeLayerOrderMap.ensure(m_resolvedCascadeLayerName, [&] {
+            // FIXME: This is not correct when adding a sublayer to an already registered layer after it has gained siblings.
+            return m_cascadeLayerOrderMap.size() + 1;
+        }).iterator->value;
+    }
+}
+
+void RuleSet::popCascadeLayer(const CascadeLayerName& name)
+{
+    auto size = name.isEmpty() ? 1 : name.size();
+    m_resolvedCascadeLayerName.shrink(m_resolvedCascadeLayerName.size() - size);
+    m_cascadeLayerOrder = m_resolvedCascadeLayerName.isEmpty() ? 0 : m_cascadeLayerOrderMap.get(m_resolvedCascadeLayerName);
+}
+
 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
 {
     for (auto& vector : map.values())
@@ -505,6 +556,8 @@
     m_features.shrinkToFit();
 
     shrinkDynamicRules(m_dynamicMediaQueryRules);
+
+    m_cascadeLayerOrderForPosition.shrinkToFit();
 }
 
 RuleSet::MediaQueryCollector::~MediaQueryCollector() = default;
@@ -569,6 +622,5 @@
     context.ruleFeatures.append({ ruleData });
 }
 
-
 } // namespace Style
 } // namespace WebCore

Modified: trunk/Source/WebCore/style/RuleSet.h (281700 => 281701)


--- trunk/Source/WebCore/style/RuleSet.h	2021-08-27 17:12:41 UTC (rev 281700)
+++ trunk/Source/WebCore/style/RuleSet.h	2021-08-27 17:43:04 UTC (rev 281701)
@@ -145,6 +145,8 @@
     bool hasShadowPseudoElementRules() const { return !m_shadowPseudoElementRules.isEmpty(); }
     bool hasHostPseudoClassRulesMatchingInShadowTree() const { return m_hasHostPseudoClassRulesMatchingInShadowTree; }
 
+    unsigned cascadeLayerOrderFor(const RuleData&) const;
+
 private:
     RuleSet();
 
@@ -158,6 +160,9 @@
     };
     CollectedMediaQueryChanges evaluateDynamicMediaQueryRules(const MediaQueryEvaluator&, size_t startIndex);
 
+    void pushCascadeLayer(const CascadeLayerName&);
+    void popCascadeLayer(const CascadeLayerName&);
+
     template<typename Function> void traverseRuleDatas(Function&&);
 
     AtomRuleMap m_idRules;
@@ -179,9 +184,18 @@
     Vector<DynamicMediaQueryRules> m_dynamicMediaQueryRules;
     HashMap<Vector<size_t>, Ref<const RuleSet>> m_mediaQueryInvalidationRuleSetCache;
     unsigned m_ruleCount { 0 };
+
+    HashMap<CascadeLayerName, unsigned> m_cascadeLayerOrderMap;
+    // This is a side vector to hold layer order without bloating RuleData.
+    Vector<unsigned> m_cascadeLayerOrderForPosition;
+
     bool m_hasHostPseudoClassRulesMatchingInShadowTree { false };
     bool m_autoShrinkToFitEnabled { true };
     bool m_hasViewportDependentMediaQueries { false };
+
+    // FIXME: These should be in stack.
+    CascadeLayerName m_resolvedCascadeLayerName;
+    unsigned m_cascadeLayerOrder { 0 };
 };
 
 inline const RuleSet::RuleDataVector* RuleSet::tagRules(const AtomString& key, bool isHTMLName) const
@@ -194,5 +208,13 @@
     return tagRules->get(key);
 }
 
+inline unsigned RuleSet::cascadeLayerOrderFor(const RuleData& ruleData) const
+{
+    if (m_cascadeLayerOrderForPosition.size() > ruleData.position())
+        return m_cascadeLayerOrderForPosition[ruleData.position()];
+    return 0;
+}
+
+
 } // namespace Style
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to