Changeset 289742 in webkit


Ignore:
Timestamp:
Feb 14, 2022 11:05:56 AM (5 months ago)
Author:
Antti Koivisto
Message:

[CSS Container Queries] Implement full query parser and evaluator
https://bugs.webkit.org/show_bug.cgi?id=236580

Reviewed by Sam Weinig.

LayoutTests/imported/w3c:

  • web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt:
  • web-platform-tests/css/css-contain/container-queries/container-for-shadow-dom.tentative-expected.txt:
  • web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt:
  • web-platform-tests/css/css-contain/container-queries/query-evaluation-expected.txt:
  • web-platform-tests/css/css-contain/container-queries/size-feature-evaluation-expected.txt:

Source/WebCore:

So far we have been using the media query parser to parse container queries.
It does not support nesting and other necessary features. Also the produced data
structures are awkward to evaluate.

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

This patch supports size queries but not style queries. It supports both the current spec
size query syntax "size(foo)" (used in WPTs), and the non-function POR syntax from
https://github.com/w3c/csswg-drafts/issues/6870#issuecomment-1022430911.

  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • css/ContainerQuery.h:
  • css/ContainerQueryParser.cpp: Added.

(WebCore::ContainerQueryParser::parse):
(WebCore::ContainerQueryParser::consumeContainerQuery):
(WebCore::ContainerQueryParser::consumeCondition):
(WebCore::ContainerQueryParser::consumeSizeQuery):

No support for range operators ('<' etc) yet.

  • css/ContainerQueryParser.h: Copied from Source/WebCore/css/ContainerQuery.h.

(WebCore::ContainerQueryParser::ContainerQueryParser):

  • css/parser/CSSParserImpl.cpp:

(WebCore::CSSParserImpl::consumeContainerRule):

  • style/ContainerQueryEvaluator.cpp:

(WebCore::Style::computeSize):
(WebCore::Style::ContainerQueryEvaluator::evaluate const):
(WebCore::Style::ContainerQueryEvaluator::evaluateQuery const):
(WebCore::Style::ContainerQueryEvaluator::evaluateCondition const):
(WebCore::Style::ContainerQueryEvaluator::evaluateSizeFeature const):

Just 'width' and 'height' for now, no new size features yet.

  • style/ContainerQueryEvaluator.h:

LayoutTests:

Location:
trunk
Files:
1 added
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r289736 r289742  
     12022-02-14  Antti Koivisto  <antti@apple.com>
     2
     3        [CSS Container Queries] Implement full query parser and evaluator
     4        https://bugs.webkit.org/show_bug.cgi?id=236580
     5
     6        Reviewed by Sam Weinig.
     7
     8        * TestExpectations:
     9
    1102022-02-14  Frédéric Wang  <fwang@igalia.com>
    211
  • trunk/LayoutTests/TestExpectations

    r289722 r289742  
    47584758webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/pseudo-elements-002.tentative.html [ ImageOnlyFailure ]
    47594759webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/multicol-inside-container.html [ ImageOnlyFailure ]
     4760webkit.org/b/229659 imported/w3c/web-platform-tests/css/css-contain/container-queries/inline-size-bfc-floats.html [ ImageOnlyFailure ]
    47604761
    47614762# Flaky css-contain test
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r289732 r289742  
     12022-02-14  Antti Koivisto  <antti@apple.com>
     2
     3        [CSS Container Queries] Implement full query parser and evaluator
     4        https://bugs.webkit.org/show_bug.cgi?id=236580
     5
     6        Reviewed by Sam Weinig.
     7
     8        * web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt:
     9        * web-platform-tests/css/css-contain/container-queries/container-for-shadow-dom.tentative-expected.txt:
     10        * web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt:
     11        * web-platform-tests/css/css-contain/container-queries/query-evaluation-expected.txt:
     12        * web-platform-tests/css/css-contain/container-queries/size-feature-evaluation-expected.txt:
     13
    1142022-02-14  Martin Robinson  <mrobinson@webkit.org>
    215
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt

    r289222 r289742  
    11
    2 FAIL size(width) assert_equals: expected "true" but got ""
    3 FAIL size(min-width: 0px) assert_equals: expected "true" but got ""
    4 FAIL size(max-width: 0px) assert_equals: expected "true" but got ""
    5 FAIL size(height) assert_equals: expected "true" but got ""
    6 FAIL size(min-height: 0px) assert_equals: expected "true" but got ""
    7 FAIL size(max-height: 0px) assert_equals: expected "true" but got ""
     2PASS size(width)
     3PASS size(min-width: 0px)
     4PASS size(max-width: 0px)
     5PASS size(height)
     6PASS size(min-height: 0px)
     7PASS size(max-height: 0px)
    88FAIL size(aspect-ratio) assert_equals: expected "true" but got ""
    9 FAIL size(min-aspect-ratio: 1/2) assert_equals: expected "true" but got ""
    10 FAIL size(max-aspect-ratio: 1/2) assert_equals: expected "true" but got ""
    11 FAIL size(orientation: portrait) assert_equals: expected "true" but got ""
     9FAIL size(min-aspect-ratio: 1/2) assert_equals: expected 2 but got 0
     10FAIL size(max-aspect-ratio: 1/2) assert_equals: expected 2 but got 0
     11FAIL size(orientation: portrait) assert_equals: expected 2 but got 0
    1212FAIL size(inline-size) assert_equals: expected "true" but got ""
    1313FAIL size(min-inline-size: 0px) assert_equals: expected "true" but got ""
     
    1616FAIL size(min-block-size: 0px) assert_equals: expected "true" but got ""
    1717FAIL size(max-block-size: 0px) assert_equals: expected "true" but got ""
    18 FAIL size(width: 100px) assert_equals: expected "true" but got ""
    19 FAIL size((width: 100px)) assert_equals: expected "true" but got ""
    20 FAIL size(not (width: 100px)) assert_equals: expected "true" but got ""
    21 FAIL size((width: 100px) and (height: 100px)) assert_equals: expected "true" but got ""
    22 FAIL size((width: 50px) or (height: 100px)) assert_equals: expected "true" but got ""
    23 FAIL size(width < 100px) assert_equals: expected "true" but got ""
    24 FAIL size(100px < width) assert_equals: expected "true" but got ""
    25 FAIL size(100px < width < 200px) assert_equals: expected "true" but got ""
     18PASS size(width: 100px)
     19PASS size((width: 100px))
     20PASS size(not (width: 100px))
     21PASS size((width: 100px) and (height: 100px))
     22PASS size((width: 50px) or (height: 100px))
     23PASS size(width < 100px)
     24FAIL size(100px < width) assert_equals: expected 2 but got 0
     25FAIL size(100px < width < 200px) assert_equals: expected 2 but got 0
    2626PASS foo(width)
    2727PASS size(asdf)
    28 PASS size(resolution > 100dpi)
    29 PASS size(resolution: 150dpi)
     28FAIL size(resolution > 100dpi) assert_equals: expected 2 but got 0
     29FAIL size(resolution: 150dpi) assert_equals: expected 2 but got 0
    3030PASS size(color)
    31 PASS size(min-color: 1)
    32 PASS size(color-index >= 1)
    33 PASS (color-index >= 1)
     31FAIL size(min-color: 1) assert_equals: expected 2 but got 0
     32FAIL size(color-index >= 1) assert_equals: expected 2 but got 0
     33FAIL (color-index >= 1) assert_equals: expected 2 but got 0
    3434PASS size(grid)
    3535PASS (grid)
     
    4242PASS not screen and (width: 100px)
    4343PASS not screen or (width: 100px)
    44 FAIL (width: 100px), (height: 100px) assert_equals: expected 0 but got 1
     44PASS (width: 100px), (height: 100px)
    4545PASS Container selector:  foo
    4646PASS Container selector:  foo
    47 PASS Container selector: name(foo)
    48 PASS Container selector: name( foo )
    49 PASS Container selector: type(size)
    50 PASS Container selector: type( size )
    51 PASS Container selector: type(inline-size)
    52 PASS Container selector: type(block-size)
    53 PASS Container selector: name(bar) type(block-size)
    54 PASS Container selector: type(block-size) name(bar)
     47FAIL Container selector: name(foo) assert_equals: expected 1 but got 0
     48FAIL Container selector: name( foo ) assert_equals: expected 1 but got 0
     49FAIL Container selector: type(size) assert_equals: expected 1 but got 0
     50FAIL Container selector: type( size ) assert_equals: expected 1 but got 0
     51FAIL Container selector: type(inline-size) assert_equals: expected 1 but got 0
     52FAIL Container selector: type(block-size) assert_equals: expected 1 but got 0
     53FAIL Container selector: name(bar) type(block-size) assert_equals: expected 1 but got 0
     54FAIL Container selector: type(block-size) name(bar) assert_equals: expected 1 but got 0
    5555PASS Container selector: foo foo
    5656PASS Container selector: 1px
    5757PASS Container selector: 50gil
    58 FAIL Container selector: name(1px) assert_equals: expected 0 but got 1
    59 FAIL Container selector: type(1px) assert_equals: expected 0 but got 1
    60 FAIL Container selector: type(red) assert_equals: expected 0 but got 1
    61 FAIL Container selector: type(size) type(size) assert_equals: expected 0 but got 1
    62 FAIL Container selector: type(inline-size) type(block-size) assert_equals: expected 0 but got 1
    63 FAIL Container selector: name(foo) name(bar) assert_equals: expected 0 but got 1
    64 FAIL Container selector: type(inline-size) name(foo) type(block-size) assert_equals: expected 0 but got 1
    65 FAIL Container selector: name(foo) type(size) name(bar) assert_equals: expected 0 but got 1
    66 FAIL Container selector: name(type(size)) assert_equals: expected 0 but got 1
    67 FAIL Container selector: type(name(bar)) assert_equals: expected 0 but got 1
     58PASS Container selector: name(1px)
     59PASS Container selector: type(1px)
     60PASS Container selector: type(red)
     61PASS Container selector: type(size) type(size)
     62PASS Container selector: type(inline-size) type(block-size)
     63PASS Container selector: name(foo) name(bar)
     64PASS Container selector: type(inline-size) name(foo) type(block-size)
     65PASS Container selector: name(foo) type(size) name(bar)
     66PASS Container selector: name(type(size))
     67PASS Container selector: type(name(bar))
    6868
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-for-shadow-dom.tentative-expected.txt

    r289222 r289742  
    11
    22FAIL Match container in outer tree null is not an object (evaluating 'document.querySelector("#inclusive-ancestor-across-root > div").shadowRoot.querySelector')
    3 FAIL Match container in same tree, not walking flat tree ancestors assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
     3PASS Match container in same tree, not walking flat tree ancestors
    44FAIL Match container in ::slotted selector's originating element tree assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
    55FAIL Match container in outer tree for :host assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt

    r289222 r289742  
    11Test
    22
    3 FAIL Changing the container type invalidates relevant descendants assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
     3FAIL Changing the container type invalidates relevant descendants assert_equals: expected "rgb(0, 0, 0)" but got "rgb(0, 128, 0)"
    44
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/query-evaluation-expected.txt

    r289222 r289742  
    44PASS size(unknown)
    55PASS unknown(width)
    6 FAIL (size(width)) assert_equals: expected "true" but got "false"
     6PASS (size(width))
    77PASS (size(height))
    88PASS (size(unknown))
    9 FAIL (((size(width)))) assert_equals: expected "true" but got "false"
     9PASS (((size(width))))
    1010PASS (((size(height))))
    1111PASS (((size(unknown))))
    1212PASS (not size(width))
    13 FAIL (not size(height)) assert_equals: expected "true" but got "false"
     13PASS (not size(height))
    1414PASS (not size(unknown))
    1515PASS (not unknown(width))
    16 FAIL (size(width) and size(width)) assert_equals: expected "true" but got "false"
    17 FAIL (size(width) and size(width) and size(width)) assert_equals: expected "true" but got "false"
     16PASS (size(width) and size(width))
     17PASS (size(width) and size(width) and size(width))
    1818PASS (size(height) and size(height))
    1919PASS (size(height) and size(width) and size(width))
     
    2323PASS (size(width) and size(unknown) and size(width))
    2424PASS (size(width) and size(width) and size(unknown))
    25 FAIL (size(width) or size(width)) assert_equals: expected "true" but got "false"
    26 FAIL (size(width) or size(width) or size(width)) assert_equals: expected "true" but got "false"
     25PASS (size(width) or size(width))
     26PASS (size(width) or size(width) or size(width))
    2727PASS (size(height) or size(height))
    28 FAIL (size(height) or size(width) or size(width)) assert_equals: expected "true" but got "false"
    29 FAIL (size(width) or size(height) or size(width)) assert_equals: expected "true" but got "false"
    30 FAIL (size(width) or size(width) or size(height)) assert_equals: expected "true" but got "false"
    31 FAIL (size(unknown) or size(width) or size(width)) assert_equals: expected "true" but got "false"
    32 FAIL (size(width) or size(unknown) or size(width)) assert_equals: expected "true" but got "false"
    33 FAIL (size(width) or size(width) or size(unknown)) assert_equals: expected "true" but got "false"
    34 FAIL (size(unknown) or size(height) or size(width)) assert_equals: expected "true" but got "false"
     28PASS (size(height) or size(width) or size(width))
     29PASS (size(width) or size(height) or size(width))
     30PASS (size(width) or size(width) or size(height))
     31PASS (size(unknown) or size(width) or size(width))
     32PASS (size(width) or size(unknown) or size(width))
     33PASS (size(width) or size(width) or size(unknown))
     34PASS (size(unknown) or size(height) or size(width))
    3535PASS (not (size(width) and size(width)))
    36 FAIL (not (size(width) and size(height))) assert_equals: expected "true" but got "false"
     36PASS (not (size(width) and size(height)))
    3737PASS (size(width) and (not (size(height) or size(width))))
    38 FAIL (size(height) or (not (size(height) and size(width)))) assert_equals: expected "true" but got "false"
     38PASS (size(height) or (not (size(height) and size(width))))
    3939PASS (size(height) or (size(height) and size(width)))
    40 FAIL size((width)) assert_equals: expected "true" but got "false"
     40PASS size((width))
    4141PASS size((height))
    4242PASS size((unknown))
    4343PASS unknown((width))
    4444PASS size(not (width))
    45 FAIL size(not (height)) assert_equals: expected "true" but got "false"
     45PASS size(not (height))
    4646PASS size(not (unknown))
    47 FAIL size((width) and (width)) assert_equals: expected "true" but got "false"
    48 FAIL size((width) and (width) and (width)) assert_equals: expected "true" but got "false"
     47PASS size((width) and (width))
     48PASS size((width) and (width) and (width))
    4949PASS size((height) and (height))
    5050PASS size((height) and (width) and (width))
     
    5454PASS size((width) and (unknown) and (width))
    5555PASS size((width) and (width) and (unknown))
    56 FAIL size((width) or (width)) assert_equals: expected "true" but got "false"
    57 FAIL size((width) or (width) or (width)) assert_equals: expected "true" but got "false"
     56PASS size((width) or (width))
     57PASS size((width) or (width) or (width))
    5858PASS size((height) or (height))
    59 FAIL size((height) or (width) or (width)) assert_equals: expected "true" but got "false"
    60 FAIL size((width) or (height) or (width)) assert_equals: expected "true" but got "false"
    61 FAIL size((width) or (width) or (height)) assert_equals: expected "true" but got "false"
    62 FAIL size((unknown) or (width) or (width)) assert_equals: expected "true" but got "false"
    63 FAIL size((width) or (unknown) or (width)) assert_equals: expected "true" but got "false"
    64 FAIL size((width) or (width) or (unknown)) assert_equals: expected "true" but got "false"
    65 FAIL size((unknown) or (height) or (width)) assert_equals: expected "true" but got "false"
     59PASS size((height) or (width) or (width))
     60PASS size((width) or (height) or (width))
     61PASS size((width) or (width) or (height))
     62PASS size((unknown) or (width) or (width))
     63PASS size((width) or (unknown) or (width))
     64PASS size((width) or (width) or (unknown))
     65PASS size((unknown) or (height) or (width))
    6666PASS size(not ((width) and (width)))
    67 FAIL size(not ((width) and (height))) assert_equals: expected "true" but got "false"
     67PASS size(not ((width) and (height)))
    6868PASS size((width) and (not ((height) or (width))))
    69 FAIL size((height) or (not ((height) and (width)))) assert_equals: expected "true" but got "false"
     69PASS size((height) or (not ((height) and (width))))
    7070PASS size((height) or ((height) and (width)))
    7171
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/size-feature-evaluation-expected.txt

    r289222 r289742  
    11Test
    22
    3 PASS size(width < 100px) (.horizontal)
     3FAIL size(width < 100px) (.horizontal) assert_equals: expected "" but got "true"
    44FAIL size(width >= 100px) (.horizontal) assert_equals: expected "true" but got ""
    55PASS size(min-width: 100px) (.horizontal)
     
    77PASS size(max-width: 100px) (.horizontal)
    88PASS size(max-width: 99px) (.horizontal)
    9 PASS size(height < 200px) (.horizontal)
     9FAIL size(height < 200px) (.horizontal) assert_equals: expected "" but got "true"
    1010FAIL size(height >= 200px) (.horizontal) assert_equals: expected "true" but got ""
    1111PASS size(min-height: 200px) (.horizontal)
     
    2929FAIL size(aspect-ratio: 1/2) (.horizontal) assert_equals: expected "true" but got ""
    3030PASS size(aspect-ratio: 2/1) (.horizontal)
    31 PASS size(width < 100px) (.vertical)
     31FAIL size(width < 100px) (.vertical) assert_equals: expected "" but got "true"
    3232FAIL size(width >= 100px) (.vertical) assert_equals: expected "true" but got ""
    3333PASS size(min-width: 100px) (.vertical)
     
    3535PASS size(max-width: 100px) (.vertical)
    3636PASS size(max-width: 99px) (.vertical)
    37 PASS size(height < 200px) (.vertical)
     37FAIL size(height < 200px) (.vertical) assert_equals: expected "" but got "true"
    3838FAIL size(height >= 200px) (.vertical) assert_equals: expected "true" but got ""
    3939PASS size(min-height: 200px) (.vertical)
  • trunk/Source/WebCore/ChangeLog

    r289739 r289742  
     12022-02-14  Antti Koivisto  <antti@apple.com>
     2
     3        [CSS Container Queries] Implement full query parser and evaluator
     4        https://bugs.webkit.org/show_bug.cgi?id=236580
     5
     6        Reviewed by Sam Weinig.
     7
     8        So far we have been using the media query parser to parse container queries.
     9        It does not support nesting and other necessary features. Also the produced data
     10        structures are awkward to evaluate.
     11
     12        https://drafts.csswg.org/css-contain-3/#container-rule
     13
     14        This patch supports size queries but not style queries. It supports both the current spec
     15        size query syntax "size(foo)" (used in WPTs), and the non-function POR syntax from
     16        https://github.com/w3c/csswg-drafts/issues/6870#issuecomment-1022430911.
     17
     18        * Sources.txt:
     19        * WebCore.xcodeproj/project.pbxproj:
     20        * css/ContainerQuery.h:
     21        * css/ContainerQueryParser.cpp: Added.
     22        (WebCore::ContainerQueryParser::parse):
     23        (WebCore::ContainerQueryParser::consumeContainerQuery):
     24        (WebCore::ContainerQueryParser::consumeCondition):
     25        (WebCore::ContainerQueryParser::consumeSizeQuery):
     26
     27        No support for range operators ('<' etc) yet.
     28
     29        * css/ContainerQueryParser.h: Copied from Source/WebCore/css/ContainerQuery.h.
     30        (WebCore::ContainerQueryParser::ContainerQueryParser):
     31        * css/parser/CSSParserImpl.cpp:
     32        (WebCore::CSSParserImpl::consumeContainerRule):
     33        * style/ContainerQueryEvaluator.cpp:
     34        (WebCore::Style::computeSize):
     35        (WebCore::Style::ContainerQueryEvaluator::evaluate const):
     36        (WebCore::Style::ContainerQueryEvaluator::evaluateQuery const):
     37        (WebCore::Style::ContainerQueryEvaluator::evaluateCondition const):
     38        (WebCore::Style::ContainerQueryEvaluator::evaluateSizeFeature const):
     39
     40        Just 'width' and 'height' for now, no new size features yet.
     41
     42        * style/ContainerQueryEvaluator.h:
     43
    1442022-02-14  J Pascoe  <j_pascoe@apple.com>
    245
  • trunk/Source/WebCore/Sources.txt

    r289722 r289742  
    705705crypto/keys/CryptoKeyRaw.cpp
    706706css/BasicShapeFunctions.cpp
     707css/ContainerQueryParser.cpp
    707708css/CSSAspectRatioValue.cpp
    708709css/CSSBasicShapes.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r289722 r289742  
    54315431                E4F0BE3125712F6E009E7431 /* CaretRectComputation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F0BE2E25710A75009E7431 /* CaretRectComputation.h */; };
    54325432                E4F1573927B9261500B330D8 /* ContainerQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F1573227B6991F00B330D8 /* ContainerQuery.h */; settings = {ATTRIBUTES = (Private, ); }; };
     5433                E4F1574127B93B7700B330D8 /* ContainerQueryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F1573D27B93B4C00B330D8 /* ContainerQueryParser.h */; };
    54335434                E4F38D1B2626F13B007B1064 /* DefaultResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F38D192626F13B007B1064 /* DefaultResourceLoadPriority.h */; };
    54345435                E4F819C626FB4EBF0094E162 /* InlineBoxPainter.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F819C526FB4EBF0094E162 /* InlineBoxPainter.h */; };
     
    1761517616                E4F0BE3025710A76009E7431 /* CaretRectComputation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CaretRectComputation.cpp; sourceTree = "<group>"; };
    1761617617                E4F1573227B6991F00B330D8 /* ContainerQuery.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContainerQuery.h; sourceTree = "<group>"; };
     17618                E4F1573D27B93B4C00B330D8 /* ContainerQueryParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContainerQueryParser.h; sourceTree = "<group>"; };
     17619                E4F1573F27B93B5800B330D8 /* ContainerQueryParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ContainerQueryParser.cpp; sourceTree = "<group>"; };
    1761717620                E4F38D192626F13B007B1064 /* DefaultResourceLoadPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultResourceLoadPriority.h; sourceTree = "<group>"; };
    1761817621                E4F38D1C2626F144007B1064 /* DefaultResourceLoadPriority.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DefaultResourceLoadPriority.cpp; sourceTree = "<group>"; };
     
    3160031603                                FBD6AF8515EF21D4008B7110 /* BasicShapeFunctions.h */,
    3160131604                                E4F1573227B6991F00B330D8 /* ContainerQuery.h */,
     31605                                E4F1573F27B93B5800B330D8 /* ContainerQueryParser.cpp */,
     31606                                E4F1573D27B93B4C00B330D8 /* ContainerQueryParser.h */,
    3160231607                                A80E6CDA0A1989CA007FB8C5 /* Counter.h */,
    3160331608                                CAE9F90D146441F000C245B0 /* CSSAspectRatioValue.cpp */,
     
    3387733882                                A818721C0977D3C0005826D9 /* ContainerNode.h in Headers */,
    3387833883                                E1A1470811102B1500EEC0F3 /* ContainerNodeAlgorithms.h in Headers */,
     33884                                E4F1573927B9261500B330D8 /* ContainerQuery.h in Headers */,
    3387933885                                E4AAB38727AA95D7009F5899 /* ContainerQueryEvaluator.h in Headers */,
     33886                                E4F1574127B93B7700B330D8 /* ContainerQueryParser.h in Headers */,
    3388033887                                6FB5E214221F2453003989CF /* ContentChangeObserver.h in Headers */,
    3388133888                                BC5EB9810E82072500B25965 /* ContentData.h in Headers */,
     
    3719537202                                F4D43D662188038B00ECECAC /* SerializedAttachmentData.h in Headers */,
    3719637203                                E18DF33518AAF12C00773E59 /* SerializedCryptoKeyWrap.h in Headers */,
    37197                                 E4F1573927B9261500B330D8 /* ContainerQuery.h in Headers */,
    3719837204                                077AF14018F4AE400001ED61 /* SerializedPlatformDataCue.h in Headers */,
    3719937205                                077AF14318F4B1BB0001ED61 /* SerializedPlatformDataCueMac.h in Headers */,
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r289722 r289742  
    16431643sides
    16441644// contain
     1645
     1646// for @media/@supports/@container
     1647and
     1648or
     1649not
  • trunk/Source/WebCore/css/ContainerQuery.h

    r289706 r289742  
    2929namespace WebCore {
    3030
    31 class MediaQuerySet;
     31class CSSPrimitiveValue;
    3232
    33 using ContainerQuery = MediaQuerySet;
     33namespace CQ {
     34
     35struct ContainerCondition;
     36struct SizeCondition;
     37struct SizeFeature;
     38
     39struct UnknownQuery { };
     40
     41using SizeQuery = std::variant<SizeCondition, SizeFeature>;
     42using ContainerQuery = std::variant<ContainerCondition, SizeQuery, UnknownQuery>;
     43
     44enum class LogicalOperator : uint8_t { And, Or, Not };
     45enum class ComparisonOperator : uint8_t { LessThan, LessThanOrEqual, Equal, GreaterThan, GreaterThanOrEqual, True };
     46
     47struct ContainerCondition {
     48    LogicalOperator logicalOperator { LogicalOperator::And };
     49    Vector<ContainerQuery> queries;
     50};
     51
     52struct SizeCondition {
     53    LogicalOperator logicalOperator { LogicalOperator::And };
     54    Vector<SizeQuery> queries;
     55};
     56
     57struct SizeFeature {
     58    ComparisonOperator comparisonOperator { ComparisonOperator::Equal };
     59    AtomString name;
     60    RefPtr<CSSPrimitiveValue> value;
     61};
     62
     63}
     64
     65using ContainerQuery = CQ::ContainerQuery;
    3466
    3567struct FilteredContainerQuery {
    3668    AtomString nameFilter;
    37     Ref<ContainerQuery> query;
     69    ContainerQuery query;
    3870};
    3971
  • trunk/Source/WebCore/css/ContainerQueryParser.h

    r289740 r289742  
    2525#pragma once
    2626
    27 #include <wtf/text/AtomString.h>
     27#include "CSSParserToken.h"
     28#include "ContainerQuery.h"
    2829
    2930namespace WebCore {
    3031
    31 class MediaQuerySet;
     32class ContainerQueryParser {
     33public:
     34    static std::optional<ContainerQuery> consumeContainerQuery(CSSParserTokenRange&, const CSSParserContext&);
    3235
    33 using ContainerQuery = MediaQuerySet;
     36private:
     37    std::optional<CQ::ContainerQuery> consumeContainerQuery(CSSParserTokenRange&);
     38    std::optional<CQ::SizeQuery> consumeSizeQuery(CSSParserTokenRange&);
     39    template<typename ConditionType> std::optional<ConditionType> consumeCondition(CSSParserTokenRange&);
    3440
    35 struct FilteredContainerQuery {
    36     AtomString nameFilter;
    37     Ref<ContainerQuery> query;
     41    ContainerQueryParser(const CSSParserContext& context)
     42        : m_context(context) { }
     43
     44    const CSSParserContext m_context;
    3845};
    3946
  • trunk/Source/WebCore/css/parser/CSSParserImpl.cpp

    r288675 r289742  
    4848#include "CSSTokenizer.h"
    4949#include "CSSVariableParser.h"
     50#include "ContainerQueryParser.h"
    5051#include "Document.h"
    5152#include "Element.h"
     
    866867    auto name = consumeName();
    867868
    868     auto query = MediaQueryParser::parseContainerQuery(prelude, MediaQueryParserContext(m_context));
     869    auto query = ContainerQueryParser::consumeContainerQuery(prelude, m_context);
    869870    if (!query)
    870871        return nullptr;
    871872
     873    prelude.consumeWhitespace();
     874    if (!prelude.atEnd())
     875        return nullptr;
     876
    872877    if (m_deferredParser)
    873         return StyleRuleContainer::create({ name, query.releaseNonNull() }, makeUnique<DeferredStyleGroupRuleList>(block, *m_deferredParser));
     878        return StyleRuleContainer::create({ name, *query }, makeUnique<DeferredStyleGroupRuleList>(block, *m_deferredParser));
    874879
    875880    Vector<RefPtr<StyleRuleBase>> rules;
     
    889894        m_observerWrapper->observer().endRuleBody(m_observerWrapper->endOffset(block));
    890895
    891     return StyleRuleContainer::create({ name, query.releaseNonNull() }, WTFMove(rules));
     896    return StyleRuleContainer::create({ name, *query }, WTFMove(rules));
    892897}
    893898   
  • trunk/Source/WebCore/style/ContainerQueryEvaluator.cpp

    r289706 r289742  
    3636namespace WebCore::Style {
    3737
     38struct ContainerQueryEvaluator::EvaluationContext {
     39    RenderBox& renderer;
     40    CSSToLengthConversionData conversionData;
     41};
     42
    3843ContainerQueryEvaluator::ContainerQueryEvaluator(const Vector<Ref<const Element>>& containers)
    3944    : m_containers(containers)
     
    4146}
    4247
    43 static std::optional<LayoutUnit> computeSize(CSSValue* value, const CSSToLengthConversionData& conversionData)
     48static std::optional<LayoutUnit> computeSize(const CSSPrimitiveValue& value, const CSSToLengthConversionData& conversionData)
    4449{
    45     if (!is<CSSPrimitiveValue>(value))
    46         return { };
    47 
    48     auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
    49     if (primitiveValue.isNumberOrInteger()) {
    50         if (primitiveValue.doubleValue())
     50    if (value.isNumberOrInteger()) {
     51        if (value.doubleValue())
    5152            return { };
    5253        return 0_lu;
    5354    }
    5455
    55     if (!primitiveValue.isLength())
     56    if (!value.isLength())
    5657        return { };
    57     return primitiveValue.computeLength<LayoutUnit>(conversionData);
     58    return value.computeLength<LayoutUnit>(conversionData);
    5859}
    59 
    60 enum class Comparator { Lesser, Greater, LesserOrEqual, GreaterOrEqual, Equal, True };
    6160
    6261bool ContainerQueryEvaluator::evaluate(const FilteredContainerQuery& filteredContainerQuery) const
     
    8483
    8584    auto& view = renderer->view();
    86     CSSToLengthConversionData conversionData { &renderer->style(), &view.style(), nullptr, &view, 1 };
     85    CSSToLengthConversionData { &renderer->style(), &view.style(), nullptr, &view, 1 };
    8786
    88     auto evaluateSize = [&](const MediaQueryExpression& expression, Comparator comparator, auto&& sizeGetter)
    89     {
     87    EvaluationContext evaluationContext {
     88        *renderer,
     89        CSSToLengthConversionData { &renderer->style(), &view.style(), nullptr, &view, 1 }
     90    };
     91
     92    return evaluateQuery(filteredContainerQuery.query, evaluationContext) == EvaluationResult::True;
     93}
     94
     95auto ContainerQueryEvaluator::evaluateQuery(const CQ::ContainerQuery& containerQuery, const EvaluationContext& context) const -> EvaluationResult
     96{
     97    return WTF::switchOn(containerQuery, [&](const CQ::ContainerCondition& containerCondition) {
     98        return evaluateCondition(containerCondition, context);
     99    }, [&](const CQ::SizeQuery& sizeQuery) {
     100        return evaluateQuery(sizeQuery, context);
     101    }, [&](const CQ::UnknownQuery&) {
     102        return EvaluationResult::Unknown;
     103    });
     104}
     105
     106auto ContainerQueryEvaluator::evaluateQuery(const CQ::SizeQuery& sizeQuery, const EvaluationContext& context) const -> EvaluationResult
     107{
     108    return WTF::switchOn(sizeQuery, [&](const CQ::SizeCondition& sizeCondition) {
     109        return evaluateCondition(sizeCondition, context);
     110    }, [&](const CQ::SizeFeature& sizeFeature) {
     111        return evaluateSizeFeature(sizeFeature, context);
     112    });
     113}
     114
     115template<typename ConditionType>
     116auto ContainerQueryEvaluator::evaluateCondition(const ConditionType& condition, const EvaluationContext& context) const -> EvaluationResult
     117{
     118    if (condition.queries.isEmpty())
     119        return EvaluationResult::Unknown;
     120
     121    switch (condition.logicalOperator) {
     122    case CQ::LogicalOperator::Not: {
     123        switch (evaluateQuery(condition.queries.first(), context)) {
     124        case EvaluationResult::True:
     125            return EvaluationResult::False;
     126        case EvaluationResult::False:
     127            return EvaluationResult::True;
     128        case EvaluationResult::Unknown:
     129            return EvaluationResult::Unknown;
     130        }
     131    }
     132    case CQ::LogicalOperator::And: {
     133        auto result = EvaluationResult::True;
     134        for (auto query : condition.queries) {
     135            auto queryResult = evaluateQuery(query, context);
     136            if (queryResult == EvaluationResult::False)
     137                return EvaluationResult::False;
     138            if (queryResult == EvaluationResult::Unknown)
     139                result = EvaluationResult::Unknown;
     140        }
     141        return result;
     142    }
     143    case CQ::LogicalOperator::Or: {
     144        auto result = EvaluationResult::False;
     145        for (auto query : condition.queries) {
     146            auto queryResult = evaluateQuery(query, context);
     147            if (queryResult == EvaluationResult::True)
     148                return EvaluationResult::True;
     149            if (queryResult == EvaluationResult::Unknown)
     150                result = EvaluationResult::Unknown;
     151        }
     152        return result;
     153    }
     154    }
     155}
     156
     157auto ContainerQueryEvaluator::evaluateSizeFeature(const CQ::SizeFeature& sizeFeature, const EvaluationContext& context) const -> EvaluationResult
     158{
     159    auto evaluateSize = [&](LayoutUnit size) {
    90160        std::optional<LayoutUnit> expressionSize;
    91161
    92         if (comparator != Comparator::True) {
    93             expressionSize = computeSize(expression.value(), conversionData);
     162        if (sizeFeature.comparisonOperator != CQ::ComparisonOperator::True) {
     163            if (!sizeFeature.value)
     164                return false;
     165            expressionSize = computeSize(*sizeFeature.value, context.conversionData);
    94166            if (!expressionSize)
    95167                return false;
    96168        }
    97169
    98         auto size = sizeGetter(*renderer);
    99 
    100         switch (comparator) {
    101         case Comparator::Lesser:
     170        switch (sizeFeature.comparisonOperator) {
     171        case CQ::ComparisonOperator::LessThan:
    102172            return size < *expressionSize;
    103         case Comparator::Greater:
     173        case CQ::ComparisonOperator::GreaterThan:
    104174            return size > *expressionSize;
    105         case Comparator::LesserOrEqual:
     175        case CQ::ComparisonOperator::LessThanOrEqual:
    106176            return size <= *expressionSize;
    107         case Comparator::GreaterOrEqual:
     177        case CQ::ComparisonOperator::GreaterThanOrEqual:
    108178            return size >= *expressionSize;
    109         case Comparator::Equal:
     179        case CQ::ComparisonOperator::Equal:
    110180            return size == *expressionSize;
    111         case Comparator::True:
     181        case CQ::ComparisonOperator::True:
    112182            return !!size;
    113183        }
    114184    };
    115185
    116     auto evaluateWidth = [&](const MediaQueryExpression& expression, Comparator comparator)
    117     {
    118         return evaluateSize(expression, comparator, [&](const RenderBox& renderer) {
    119             return renderer.width();
    120         });
    121     };
     186    // FIXME: Support all features.
     187    if (sizeFeature.name == MediaFeatureNames::width)
     188        return evaluateSize(context.renderer.width()) ? EvaluationResult::True : EvaluationResult::False;
     189    if (sizeFeature.name == MediaFeatureNames::height)
     190        return evaluateSize(context.renderer.height()) ? EvaluationResult::True : EvaluationResult::False;
    122191
    123     auto evaluateHeight = [&](const MediaQueryExpression& expression, Comparator comparator)
    124     {
    125         return evaluateSize(expression, comparator, [&](const RenderBox& renderer) {
    126             return renderer.height();
    127         });
    128     };
    129 
    130     bool result = false;
    131 
    132     // FIXME: This is very rudimentary.
    133     auto& queries = filteredContainerQuery.query->queryVector();
    134     for (auto& query : queries) {
    135         for (auto& expression : query.expressions()) {
    136             if (expression.mediaFeature() == MediaFeatureNames::minWidth) {
    137                 if (evaluateWidth(expression, Comparator::GreaterOrEqual))
    138                     result = true;
    139                 continue;
    140             }
    141             if (expression.mediaFeature() == MediaFeatureNames::maxWidth) {
    142                 if (evaluateWidth(expression, Comparator::LesserOrEqual))
    143                     result = true;
    144                 continue;
    145             }
    146             if (expression.mediaFeature() == MediaFeatureNames::width) {
    147                 if (evaluateWidth(expression, expression.value() ? Comparator::Equal : Comparator::True))
    148                     result = true;
    149                 continue;
    150             }
    151             if (expression.mediaFeature() == MediaFeatureNames::minHeight) {
    152                 if (evaluateHeight(expression, Comparator::GreaterOrEqual))
    153                     result = true;
    154                 continue;
    155             }
    156             if (expression.mediaFeature() == MediaFeatureNames::maxHeight) {
    157                 if (evaluateHeight(expression, Comparator::LesserOrEqual))
    158                     result = true;
    159                 continue;
    160             }
    161             if (expression.mediaFeature() == MediaFeatureNames::height) {
    162                 if (evaluateHeight(expression, expression.value() ? Comparator::Equal : Comparator::True))
    163                     result = true;
    164                 continue;
    165             }
    166         }
    167     }
    168 
    169     return result;
     192    return EvaluationResult::Unknown;
    170193}
    171194
  • trunk/Source/WebCore/style/ContainerQueryEvaluator.h

    r289706 r289742  
    2525#pragma once
    2626
     27#include "ContainerQuery.h"
    2728#include <wtf/Ref.h>
    2829
    2930namespace WebCore {
    3031
    31 struct FilteredContainerQuery;
    3232class Element;
    3333
     
    4141
    4242private:
     43    struct EvaluationContext;
     44    enum class EvaluationResult : uint8_t { False, True, Unknown };
     45
     46    EvaluationResult evaluateQuery(const CQ::ContainerQuery&, const EvaluationContext&) const;
     47    EvaluationResult evaluateQuery(const CQ::SizeQuery&, const EvaluationContext&) const;
     48    template<typename ConditionType> EvaluationResult evaluateCondition(const ConditionType&, const EvaluationContext&) const;
     49    EvaluationResult evaluateSizeFeature(const CQ::SizeFeature&, const EvaluationContext&) const;
     50
    4351    const Vector<Ref<const Element>>& m_containers;
    4452};
Note: See TracChangeset for help on using the changeset viewer.