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