[CSS Container Queries] Parsing support for container-name property
https://bugs.webkit.org/show_bug.cgi?id=235564

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-contain/container-queries/container-inheritance-expected.txt:
* web-platform-tests/css/css-contain/container-queries/container-name-computed-expected.txt:
* web-platform-tests/css/css-contain/container-queries/container-name-parsing-expected.txt:
* web-platform-tests/css/cssom/getComputedStyle-detached-subtree-expected.txt:

Source/WebCore:

Parse 'container-name' and map it to style.

https://drafts.csswg.org/css-contain-3/#container-name

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::ComputedStyleExtractor::valueForPropertyInStyle):
* css/CSSProperties.json:
* css/parser/CSSPropertyParser.cpp:
(WebCore::consumeContainerName):
(WebCore::CSSPropertyParser::parseSingleValue):
* rendering/style/RenderStyle.h:
(WebCore::RenderStyle::containerNames const):
(WebCore::RenderStyle::setContainerNames):
(WebCore::RenderStyle::initialContainerNames):

'container-name' is actually a list of names, that's why the plural.

* rendering/style/StyleRareNonInheritedData.cpp:
(WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
(WebCore::StyleRareNonInheritedData::operator== const):
* rendering/style/StyleRareNonInheritedData.h:
* style/StyleBuilderConverter.h:
(WebCore::Style::BuilderConverter::convertContainerName):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@288556 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog
index 5b42c09..e818519 100644
--- a/LayoutTests/imported/w3c/ChangeLog
+++ b/LayoutTests/imported/w3c/ChangeLog
@@ -1,3 +1,15 @@
+2022-01-25  Antti Koivisto  <antti@apple.com>
+
+        [CSS Container Queries] Parsing support for container-name property
+        https://bugs.webkit.org/show_bug.cgi?id=235564
+
+        Reviewed by Dean Jackson.
+
+        * web-platform-tests/css/css-contain/container-queries/container-inheritance-expected.txt:
+        * web-platform-tests/css/css-contain/container-queries/container-name-computed-expected.txt:
+        * web-platform-tests/css/css-contain/container-queries/container-name-parsing-expected.txt:
+        * web-platform-tests/css/cssom/getComputedStyle-detached-subtree-expected.txt:
+
 2022-01-25  Ziran Sun  <zsun@igalia.com>
 
         [css-grid] Fix grid shorthand expansion of initial values
diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt
index 0748e77..0cefe67 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt
@@ -97,6 +97,7 @@
 PASS column-span
 PASS column-width
 PASS contain
+PASS container-name
 PASS container-type
 PASS content
 PASS counter-increment
diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-inheritance-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-inheritance-expected.txt
index 3f72cf6..3ce3267 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-inheritance-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-inheritance-expected.txt
@@ -1,6 +1,6 @@
 
-FAIL Property container-name has initial value none assert_true: container-name doesn't seem to be supported in the computed style expected true got false
-FAIL Property container-name does not inherit assert_true: expected true got false
+PASS Property container-name has initial value none
+PASS Property container-name does not inherit
 PASS Property container-type has initial value none
 PASS Property container-type does not inherit
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-computed-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-computed-expected.txt
index 0601e10..c0f3b0c 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-computed-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-computed-expected.txt
@@ -1,6 +1,6 @@
 
-FAIL Property container-name value 'initial' assert_true: container-name doesn't seem to be supported in the computed style expected true got false
-FAIL Property container-name value 'unset' assert_true: container-name doesn't seem to be supported in the computed style expected true got false
-FAIL Property container-name value 'foo' assert_true: container-name doesn't seem to be supported in the computed style expected true got false
-FAIL Property container-name value 'FoO' assert_true: container-name doesn't seem to be supported in the computed style expected true got false
+PASS Property container-name value 'initial'
+PASS Property container-name value 'unset'
+PASS Property container-name value 'foo'
+PASS Property container-name value 'FoO'
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-parsing-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-parsing-expected.txt
index 11c83a1..93eed90 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-parsing-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-name-parsing-expected.txt
@@ -1,12 +1,12 @@
 
-FAIL e.style['container-name'] = "initial" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['container-name'] = "inherit" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['container-name'] = "unset" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['container-name'] = "revert" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['container-name'] = "none" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['container-name'] = "foo" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['container-name'] = "BAR" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['container-name'] = "foo bar" should set the property value assert_not_equals: property should be set got disallowed value ""
+PASS e.style['container-name'] = "initial" should set the property value
+PASS e.style['container-name'] = "inherit" should set the property value
+PASS e.style['container-name'] = "unset" should set the property value
+PASS e.style['container-name'] = "revert" should set the property value
+PASS e.style['container-name'] = "none" should set the property value
+PASS e.style['container-name'] = "foo" should set the property value
+PASS e.style['container-name'] = "BAR" should set the property value
+PASS e.style['container-name'] = "foo bar" should set the property value
 PASS e.style['container-name'] = "none none" should not set the property value
 PASS e.style['container-name'] = "foo, bar" should not set the property value
 PASS e.style['container-name'] = "#fff" should not set the property value
diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/cssom/getComputedStyle-detached-subtree-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/cssom/getComputedStyle-detached-subtree-expected.txt
index 9c6c2d6..a2b849e 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/css/cssom/getComputedStyle-detached-subtree-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/css/cssom/getComputedStyle-detached-subtree-expected.txt
@@ -1,8 +1,8 @@
 
 PASS getComputedStyle returns no style for detached element
-FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) assert_equals: expected 0 but got 397
-FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) from iframe's window assert_equals: expected 0 but got 397
-FAIL getComputedStyle returns no style for element outside the flat tree assert_equals: expected 0 but got 397
-FAIL getComputedStyle returns no style for descendant outside the flat tree assert_equals: expected 0 but got 397
+FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) assert_equals: expected 0 but got 398
+FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) from iframe's window assert_equals: expected 0 but got 398
+FAIL getComputedStyle returns no style for element outside the flat tree assert_equals: expected 0 but got 398
+FAIL getComputedStyle returns no style for descendant outside the flat tree assert_equals: expected 0 but got 398
 PASS getComputedStyle returns no style for shadow tree outside of flattened tree
 
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 6b072e4..4094826 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,34 @@
+2022-01-25  Antti Koivisto  <antti@apple.com>
+
+        [CSS Container Queries] Parsing support for container-name property
+        https://bugs.webkit.org/show_bug.cgi?id=235564
+
+        Reviewed by Dean Jackson.
+
+        Parse 'container-name' and map it to style.
+
+        https://drafts.csswg.org/css-contain-3/#container-name
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::ComputedStyleExtractor::valueForPropertyInStyle):
+        * css/CSSProperties.json:
+        * css/parser/CSSPropertyParser.cpp:
+        (WebCore::consumeContainerName):
+        (WebCore::CSSPropertyParser::parseSingleValue):
+        * rendering/style/RenderStyle.h:
+        (WebCore::RenderStyle::containerNames const):
+        (WebCore::RenderStyle::setContainerNames):
+        (WebCore::RenderStyle::initialContainerNames):
+
+        'container-name' is actually a list of names, that's why the plural.
+
+        * rendering/style/StyleRareNonInheritedData.cpp:
+        (WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
+        (WebCore::StyleRareNonInheritedData::operator== const):
+        * rendering/style/StyleRareNonInheritedData.h:
+        * style/StyleBuilderConverter.h:
+        (WebCore::Style::BuilderConverter::convertContainerName):
+
 2022-01-25  Sam Sneddon  <gsnedders@apple.com>
 
         Missing EnabledBySetting=WebXREnabled where Conditional=WEBXR exists
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
index 6784778..15557ab 100644
--- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
+++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
@@ -3627,6 +3627,14 @@
         }
         case CSSPropertyContainerType:
             return CSSPrimitiveValue::create(style.containerType());
+        case CSSPropertyContainerName: {
+            if (style.containerNames().isEmpty())
+                return cssValuePool.createIdentifierValue(CSSValueNone);
+            auto list = CSSValueList::createSpaceSeparated();
+            for (auto& name : style.containerNames())
+                list->append(cssValuePool.createCustomIdent(name));
+            return list;
+        }
         case CSSPropertyBackfaceVisibility:
             return cssValuePool.createIdentifierValue((style.backfaceVisibility() == BackfaceVisibility::Hidden) ? CSSValueHidden : CSSValueVisible);
         case CSSPropertyWebkitBorderImage:
diff --git a/Source/WebCore/css/CSSProperties.json b/Source/WebCore/css/CSSProperties.json
index a3fae27..1fd441b 100644
--- a/Source/WebCore/css/CSSProperties.json
+++ b/Source/WebCore/css/CSSProperties.json
@@ -5221,6 +5221,20 @@
                 "url": "https://drafts.csswg.org/css-contain-1/"
             }
         },
+        "container-name": {
+            "codegen-properties": {
+                "settings-flag": "cssContainerQueriesEnabled",
+                "converter": "ContainerName",
+                "name-for-methods": "ContainerNames"
+            },
+            "status": {
+                "status": "experimental"
+            },
+            "specification": {
+                "category": "css-contain",
+                "url": "https://drafts.csswg.org/css-contain-3/#container-queries"
+            }
+        },
         "container-type": {
             "codegen-properties": {
                 "settings-flag": "cssContainerQueriesEnabled"
diff --git a/Source/WebCore/css/parser/CSSPropertyParser.cpp b/Source/WebCore/css/parser/CSSPropertyParser.cpp
index 7dc1a2e..28ed1b2 100644
--- a/Source/WebCore/css/parser/CSSPropertyParser.cpp
+++ b/Source/WebCore/css/parser/CSSPropertyParser.cpp
@@ -3801,6 +3801,32 @@
     return consumeCustomIdent(range);
 }
 
+static RefPtr<CSSValue> consumeContainerName(CSSParserTokenRange& range)
+{
+    if (range.peek().id() == CSSValueNone)
+        return consumeIdent(range);
+
+    auto consumeName = [&]() -> RefPtr<CSSValue> {
+        if (range.peek().id() == CSSValueNone)
+            return nullptr;
+        if (auto ident = consumeCustomIdent(range))
+            return ident;
+        if (auto string = consumeString(range))
+            return string;
+        return nullptr;
+    };
+
+    auto list = CSSValueList::createSpaceSeparated();
+    do {
+        auto name = consumeName();
+        if (!name)
+            return nullptr;
+        list->append(name.releaseNonNull());
+    } while (!range.atEnd());
+
+    return list;
+}
+
 static RefPtr<CSSValue> consumeInitialLetter(CSSParserTokenRange& range)
 {
     RefPtr<CSSValue> ident = consumeIdent<CSSValueNormal>(range);
@@ -4654,6 +4680,8 @@
     case CSSPropertyListStyleType:
         // All the keyword values for the list-style-type property are handled by the CSSParserFastPaths.
         return consumeString(m_range);
+    case CSSPropertyContainerName:
+        return consumeContainerName(m_range);
     default:
         return nullptr;
     }
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index 4f2135e..7324469 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -533,6 +533,7 @@
     bool containsStyle() const { return m_rareNonInheritedData->contain.contains(Containment::Style); }
     bool containsPaint() const { return m_rareNonInheritedData->contain.contains(Containment::Paint); }
     ContainerType containerType() const { return static_cast<ContainerType>(m_rareNonInheritedData->containerType); }
+    const Vector<AtomString>& containerNames() const { return m_rareNonInheritedData->containerNames; }
     BoxAlignment boxAlign() const { return static_cast<BoxAlignment>(m_rareNonInheritedData->deprecatedFlexibleBox->align); }
     BoxDirection boxDirection() const { return static_cast<BoxDirection>(m_inheritedFlags.boxDirection); }
     float boxFlex() const { return m_rareNonInheritedData->deprecatedFlexibleBox->flex; }
@@ -1059,6 +1060,7 @@
 
     void setContain(OptionSet<Containment> containment) { SET_VAR(m_rareNonInheritedData, contain, containment); }
     void setContainerType(ContainerType containerType) { SET_VAR(m_rareNonInheritedData, containerType, static_cast<unsigned>(containerType)); }
+    void setContainerNames(const Vector<AtomString>& names) { SET_VAR(m_rareNonInheritedData, containerNames, names); }
 
     void setListStyleStringValue(const AtomString& value) { SET_VAR(m_rareInheritedData, listStyleStringValue, value); }
     void setListStyleType(ListStyleType v) { m_inheritedFlags.listStyleType = static_cast<unsigned>(v); }
@@ -1674,6 +1676,7 @@
     static OptionSet<Containment> strictContainment() { return OptionSet<Containment> { Containment::Size, Containment::Layout, Containment::Paint, Containment::Style }; }
     static OptionSet<Containment> contentContainment() { return OptionSet<Containment> { Containment::Layout, Containment::Paint, Containment::Style }; }
     static ContainerType initialContainerType() { return ContainerType::None; }
+    static Vector<AtomString> initialContainerNames() { return { }; }
     static double initialAspectRatioWidth() { return 1.0; }
     static double initialAspectRatioHeight() { return 1.0; }
     static Order initialRTLOrdering() { return Order::Logical; }
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index aaae2e9..19249ef 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -216,6 +216,7 @@
     , hasAttrContent(o.hasAttrContent)
     , isNotFinal(o.isNotFinal)
     , containerType(o.containerType)
+    , containerNames(o.containerNames)
     , columnGap(o.columnGap)
     , rowGap(o.rowGap)
     , offsetDistance(o.offsetDistance)
@@ -328,6 +329,7 @@
         && hasAttrContent == o.hasAttrContent
         && isNotFinal == o.isNotFinal
         && containerType == o.containerType
+        && containerNames == o.containerNames
         && columnGap == o.columnGap
         && rowGap == o.rowGap
         && offsetDistance == o.offsetDistance
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
index 2e62c09..ca157f8 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -235,6 +235,8 @@
 
     unsigned containerType : 2; // ContainerType
 
+    Vector<AtomString> containerNames;
+
     GapLength columnGap;
     GapLength rowGap;
 
diff --git a/Source/WebCore/style/StyleBuilderConverter.h b/Source/WebCore/style/StyleBuilderConverter.h
index fb9c548..0f90bc2 100644
--- a/Source/WebCore/style/StyleBuilderConverter.h
+++ b/Source/WebCore/style/StyleBuilderConverter.h
@@ -172,6 +172,7 @@
     static GapLength convertGapLength(BuilderState&, const CSSValue&);
 
     static OffsetRotation convertOffsetRotate(BuilderState&, const CSSValue&);
+    static Vector<AtomString> convertContainerName(BuilderState&, const CSSValue&);
     
 private:
     friend class BuilderCustom;
@@ -1675,5 +1676,20 @@
     return OffsetRotation(hasAuto, angleInDegrees);
 }
 
+inline Vector<AtomString> BuilderConverter::convertContainerName(BuilderState&, const CSSValue& value)
+{
+    if (is<CSSPrimitiveValue>(value)) {
+        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
+        return { };
+    }
+
+    Vector<AtomString> result;
+    if (is<CSSValueList>(value)) {
+        for (auto& item : downcast<CSSValueList>(value))
+            result.append(downcast<CSSPrimitiveValue>(item.get()).stringValue());
+    }
+    return result;
+}
+
 }
 }