Title: [290037] trunk
Revision
290037
Author
an...@apple.com
Date
2022-02-17 11:38:06 -0800 (Thu, 17 Feb 2022)

Log Message

[CSS Container Queries] Support full range notation in size queries
https://bugs.webkit.org/show_bug.cgi?id=236771

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt:

Source/WebCore:

Parse and evaluate notations like (100px < width) and (100px < width < 200px).

* css/ContainerQuery.h:

There are now optional left and right comparisons.

* css/ContainerQueryParser.cpp:
(WebCore::ContainerQueryParser::consumeSizeQuery):
(WebCore::ContainerQueryParser::consumeSizeFeature):
(WebCore::ContainerQueryParser::consumePlainSizeFeature):

Evaluate the plain (foo: value) notation.

(WebCore::ContainerQueryParser::consumeRangeSizeFeature):

Evaluate range notation.

(WebCore::ContainerQueryParser::consumeValue):
* css/ContainerQueryParser.h:
* style/ContainerQueryEvaluator.cpp:
(WebCore::Style::ContainerQueryEvaluator::evaluateSizeFeature const):

Evaluate both comparisons if they exist.

* style/ContainerQueryEvaluator.h:
(WebCore::Style::toEvaluationResult):
(WebCore::Style::operator|):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (290036 => 290037)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-02-17 19:38:06 UTC (rev 290037)
@@ -1,3 +1,12 @@
+2022-02-17  Antti Koivisto  <an...@apple.com>
+
+        [CSS Container Queries] Support full range notation in size queries
+        https://bugs.webkit.org/show_bug.cgi?id=236771
+
+        Reviewed by Dean Jackson.
+
+        * web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt:
+
 2022-02-17  Matt Woodrow  <mattwood...@apple.com>
 
         Fix abs-pos breadth issue when using 'auto'

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt (290036 => 290037)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/at-container-parsing-expected.txt	2022-02-17 19:38:06 UTC (rev 290037)
@@ -21,16 +21,16 @@
 PASS size((width: 100px) and (height: 100px))
 PASS size((width: 50px) or (height: 100px))
 PASS size(width < 100px)
-FAIL size(100px < width) assert_equals: expected 2 but got 0
-FAIL size(100px < width < 200px) assert_equals: expected 2 but got 0
+PASS size(100px < width)
+PASS size(100px < width < 200px)
 PASS foo(width)
 PASS size(asdf)
-FAIL size(resolution > 100dpi) assert_equals: expected 2 but got 0
-FAIL size(resolution: 150dpi) assert_equals: expected 2 but got 0
+PASS size(resolution > 100dpi)
+PASS size(resolution: 150dpi)
 PASS size(color)
-FAIL size(min-color: 1) assert_equals: expected 2 but got 0
-FAIL size(color-index >= 1) assert_equals: expected 2 but got 0
-FAIL (color-index >= 1) assert_equals: expected 2 but got 0
+PASS size(min-color: 1)
+PASS size(color-index >= 1)
+PASS (color-index >= 1)
 PASS size(grid)
 PASS (grid)
 PASS screen

Modified: trunk/Source/WebCore/ChangeLog (290036 => 290037)


--- trunk/Source/WebCore/ChangeLog	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/Source/WebCore/ChangeLog	2022-02-17 19:38:06 UTC (rev 290037)
@@ -1,3 +1,38 @@
+2022-02-17  Antti Koivisto  <an...@apple.com>
+
+        [CSS Container Queries] Support full range notation in size queries
+        https://bugs.webkit.org/show_bug.cgi?id=236771
+
+        Reviewed by Dean Jackson.
+
+        Parse and evaluate notations like (100px < width) and (100px < width < 200px).
+
+        * css/ContainerQuery.h:
+
+        There are now optional left and right comparisons.
+
+        * css/ContainerQueryParser.cpp:
+        (WebCore::ContainerQueryParser::consumeSizeQuery):
+        (WebCore::ContainerQueryParser::consumeSizeFeature):
+        (WebCore::ContainerQueryParser::consumePlainSizeFeature):
+
+        Evaluate the plain (foo: value) notation.
+
+        (WebCore::ContainerQueryParser::consumeRangeSizeFeature):
+
+        Evaluate range notation.
+
+        (WebCore::ContainerQueryParser::consumeValue):
+        * css/ContainerQueryParser.h:
+        * style/ContainerQueryEvaluator.cpp:
+        (WebCore::Style::ContainerQueryEvaluator::evaluateSizeFeature const):
+
+        Evaluate both comparisons if they exist.
+
+        * style/ContainerQueryEvaluator.h:
+        (WebCore::Style::toEvaluationResult):
+        (WebCore::Style::operator|):
+
 2022-02-17  Matt Woodrow  <mattwood...@apple.com>
 
         Fix abs-pos breadth issue when using 'auto'

Modified: trunk/Source/WebCore/css/ContainerQuery.h (290036 => 290037)


--- trunk/Source/WebCore/css/ContainerQuery.h	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/Source/WebCore/css/ContainerQuery.h	2022-02-17 19:38:06 UTC (rev 290037)
@@ -42,7 +42,7 @@
 using ContainerQuery = std::variant<ContainerCondition, SizeQuery, UnknownQuery>;
 
 enum class LogicalOperator : uint8_t { And, Or, Not };
-enum class ComparisonOperator : uint8_t { LessThan, LessThanOrEqual, Equal, GreaterThan, GreaterThanOrEqual, True };
+enum class ComparisonOperator : uint8_t { LessThan, LessThanOrEqual, Equal, GreaterThan, GreaterThanOrEqual };
 
 struct ContainerCondition {
     LogicalOperator logicalOperator { LogicalOperator::And };
@@ -54,10 +54,15 @@
     Vector<SizeQuery> queries;
 };
 
+struct Comparison {
+    ComparisonOperator op { ComparisonOperator::Equal };
+    RefPtr<CSSValue> value;
+};
+
 struct SizeFeature {
-    ComparisonOperator comparisonOperator { ComparisonOperator::Equal };
     AtomString name;
-    RefPtr<CSSValue> value;
+    std::optional<Comparison> leftComparison;
+    std::optional<Comparison> rightComparison;
 };
 
 namespace FeatureNames {

Modified: trunk/Source/WebCore/css/ContainerQueryParser.cpp (290036 => 290037)


--- trunk/Source/WebCore/css/ContainerQueryParser.cpp	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/Source/WebCore/css/ContainerQueryParser.cpp	2022-02-17 19:38:06 UTC (rev 290037)
@@ -136,7 +136,7 @@
 
 std::optional<CQ::SizeQuery> ContainerQueryParser::consumeSizeQuery(CSSParserTokenRange& range)
 {
-    if (range.peek().type() != IdentToken || range.peek().id() == CSSValueNot) {
+    if (range.peek().type() == LeftParenthesisToken || (range.peek().type() == IdentToken && range.peek().id() == CSSValueNot)) {
         auto sizeCondition = consumeCondition<CQ::SizeCondition>(range);
         if (!sizeCondition)
             return { };
@@ -147,82 +147,142 @@
     if (!sizeFeature)
         return { };
 
-    range.consumeWhitespace();
-    if (!range.atEnd())
-        return { };
-
     return { *sizeFeature };
 }
 
 std::optional<CQ::SizeFeature> ContainerQueryParser::consumeSizeFeature(CSSParserTokenRange& range)
 {
-    // FIXME: Support value-first (100px < width) and full range (100px < width < 200px) notations.
+    auto rangeCopy = range;
+    if (auto sizeFeature = consumePlainSizeFeature(range))
+        return sizeFeature;
 
-    auto nameToken = range.consumeIncludingWhitespace();
-    ASSERT(nameToken.type() == IdentToken);
+    range = rangeCopy;
+    return consumeRangeSizeFeature(range);
+}
 
-    auto name = nameToken.value();
+std::optional<CQ::SizeFeature> ContainerQueryParser::consumePlainSizeFeature(CSSParserTokenRange& range)
+{
+    auto consumePlainFeatureName = [&]() -> std::pair<AtomString, CQ::ComparisonOperator> {
+        if (range.peek().type() != IdentToken)
+            return { };
+        auto token = range.consumeIncludingWhitespace();
+        auto name = token.value();
+        if (name.startsWith("min-"))
+            return { name.substring(4).toAtomString(), CQ::ComparisonOperator::GreaterThanOrEqual };
+        if (name.startsWith("max-"))
+            return { name.substring(4).toAtomString(), CQ::ComparisonOperator::LessThanOrEqual };
 
+        return { name.toAtomString(), CQ::ComparisonOperator::Equal };
+    };
+
+    auto [featureName, op] = consumePlainFeatureName();
+    if (featureName.isEmpty())
+        return { };
+
+    range.consumeWhitespace();
+
+    if (range.atEnd()) {
+        if (op != CQ::ComparisonOperator::Equal)
+            return { };
+        return CQ::SizeFeature { featureName, { }, { } };
+    }
+
+    if (range.peek().type() != ColonToken)
+        return { };
+
+    range.consumeIncludingWhitespace();
     if (range.atEnd())
-        return CQ::SizeFeature { CQ::ComparisonOperator::True, name.toAtomString(), { } };
+        return { };
 
-    auto consumeOperator = [&]() -> std::optional<CQ::ComparisonOperator> {
-        auto opToken = range.consume();
+    auto value = consumeValue(range);
+    
+    return CQ::SizeFeature { featureName, { }, CQ::Comparison { op, WTFMove(value) } };
+}
+
+std::optional<CQ::SizeFeature> ContainerQueryParser::consumeRangeSizeFeature(CSSParserTokenRange& range)
+{
+    auto consumeFeatureName = [&]() -> AtomString {
+        if (range.peek().type() != IdentToken)
+            return { };
+        return range.consumeIncludingWhitespace().value().toAtomString();
+    };
+
+    auto consumeRangeOperator = [&]() -> std::optional<CQ::ComparisonOperator> {
         if (range.atEnd())
             return { };
-        if (opToken.type() == ColonToken) {
-            if (name.startsWith("min-")) {
-                name = name.substring(4);
-                return CQ::ComparisonOperator::GreaterThanOrEqual;
-            }
-            if (name.startsWith("max-")) {
-                name = name.substring(4);
+        auto opToken = range.consume();
+        if (range.atEnd() || opToken.type() != DelimiterToken)
+            return { };
+
+        switch (opToken.delimiter()) {
+        case '=':
+            range.consumeWhitespace();
+            return CQ::ComparisonOperator::Equal;
+        case '<':
+            if (range.peek().type() == DelimiterToken && range.peek().delimiter() == '=') {
+                range.consumeIncludingWhitespace();
                 return CQ::ComparisonOperator::LessThanOrEqual;
             }
-            return CQ::ComparisonOperator::Equal;
-        }
-        if (opToken.type() == DelimiterToken) {
-            switch (opToken.delimiter()) {
-            case '=':
-                return CQ::ComparisonOperator::Equal;
-            case '<':
-                if (range.peek().type() == DelimiterToken && range.peek().delimiter() == '=') {
-                    range.consume();
-                    return CQ::ComparisonOperator::LessThanOrEqual;
-                }
-                return CQ::ComparisonOperator::LessThan;
-            case '>':
-                if (range.peek().type() == DelimiterToken && range.peek().delimiter() == '=') {
-                    range.consume();
-                    return CQ::ComparisonOperator::GreaterThanOrEqual;
-                }
-                return CQ::ComparisonOperator::GreaterThan;
-            default:
-                return { };
+            range.consumeWhitespace();
+            return CQ::ComparisonOperator::LessThan;
+        case '>':
+            if (range.peek().type() == DelimiterToken && range.peek().delimiter() == '=') {
+                range.consumeIncludingWhitespace();
+                return CQ::ComparisonOperator::GreaterThanOrEqual;
             }
+            range.consumeWhitespace();
+            return CQ::ComparisonOperator::GreaterThan;
+        default:
+            return { };
         }
-        return { };
     };
 
-    auto op = consumeOperator();
-    if (!op)
-        return { };
+    auto consumeLeftComparison = [&]() -> std::optional<CQ::Comparison> {
+        if (range.peek().type() == IdentToken)
+            return { };
+        auto value = consumeValue(range);
+        auto op = consumeRangeOperator();
+        if (!op)
+            return { };
 
-    range.consumeWhitespace();
+        return CQ::Comparison { *op, WTFMove(value) };
+    };
 
-    auto featureName = name.toAtomString();
+    auto consumeRightComparison = [&]() -> std::optional<CQ::Comparison> {
+        auto op = consumeRangeOperator();
+        if (!op)
+            return { };
+        auto value = consumeValue(range);
 
-    auto consumeValue = [&]() -> RefPtr<CSSValue> {
-        if (featureName == CQ::FeatureNames::orientation())
-            return CSSPropertyParserHelpers::consumeIdent(range);
-        if (featureName == CQ::FeatureNames::aspectRatio())
-            return CSSPropertyParserHelpers::consumeAspectRatioValue(range);
-        return CSSPropertyParserHelpers::consumeLength(range, m_context.mode, ValueRange::All);
+        return CQ::Comparison { *op, WTFMove(value) };
     };
 
-    auto value = consumeValue();
+    auto leftComparison = consumeLeftComparison();
 
-    return CQ::SizeFeature { *op, WTFMove(featureName), WTFMove(value) };
+    auto featureName = consumeFeatureName();
+    if (featureName.isEmpty())
+        return { };
+
+    auto rightComparison = consumeRightComparison();
+
+    if (!leftComparison && !rightComparison)
+        return { };
+
+    return CQ::SizeFeature { WTFMove(featureName), WTFMove(leftComparison), WTFMove(rightComparison) };
 }
 
+RefPtr<CSSValue> ContainerQueryParser::consumeValue(CSSParserTokenRange& range)
+{
+    if (range.atEnd())
+        return nullptr;
+    if (auto value = CSSPropertyParserHelpers::consumeIdent(range))
+        return value;
+    if (auto value = CSSPropertyParserHelpers::consumeLength(range, m_context.mode, ValueRange::All))
+        return value;
+    if (auto value = CSSPropertyParserHelpers::consumeAspectRatioValue(range))
+        return value;
+    range.consumeIncludingWhitespace();
+    return nullptr;
 }
+
+}

Modified: trunk/Source/WebCore/css/ContainerQueryParser.h (290036 => 290037)


--- trunk/Source/WebCore/css/ContainerQueryParser.h	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/Source/WebCore/css/ContainerQueryParser.h	2022-02-17 19:38:06 UTC (rev 290037)
@@ -41,6 +41,9 @@
     std::optional<CQ::SizeQuery> consumeSizeQuery(CSSParserTokenRange&);
     template<typename ConditionType> std::optional<ConditionType> consumeCondition(CSSParserTokenRange&);
     std::optional<CQ::SizeFeature> consumeSizeFeature(CSSParserTokenRange&);
+    std::optional<CQ::SizeFeature> consumePlainSizeFeature(CSSParserTokenRange&);
+    std::optional<CQ::SizeFeature> consumeRangeSizeFeature(CSSParserTokenRange&);
+    RefPtr<CSSValue> consumeValue(CSSParserTokenRange&);
 
     ContainerQueryParser(const CSSParserContext& context)
         : m_context(context) { }

Modified: trunk/Source/WebCore/style/ContainerQueryEvaluator.cpp (290036 => 290037)


--- trunk/Source/WebCore/style/ContainerQueryEvaluator.cpp	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/Source/WebCore/style/ContainerQueryEvaluator.cpp	2022-02-17 19:38:06 UTC (rev 290037)
@@ -76,7 +76,7 @@
 
     auto container = resolveContainer();
     if (!container)
-        return { };
+        return false;
 
     return evaluateQuery(filteredContainerQuery.query, *container) == EvaluationResult::True;
 }
@@ -108,16 +108,8 @@
         return EvaluationResult::Unknown;
 
     switch (condition.logicalOperator) {
-    case CQ::LogicalOperator::Not: {
-        switch (evaluateQuery(condition.queries.first(), container)) {
-        case EvaluationResult::True:
-            return EvaluationResult::False;
-        case EvaluationResult::False:
-            return EvaluationResult::True;
-        case EvaluationResult::Unknown:
-            return EvaluationResult::Unknown;
-        }
-    }
+    case CQ::LogicalOperator::Not:
+        return !evaluateQuery(condition.queries.first(), container);
     case CQ::LogicalOperator::And: {
         auto result = EvaluationResult::True;
         for (auto query : condition.queries) {
@@ -162,12 +154,8 @@
 
 auto ContainerQueryEvaluator::evaluateSizeFeature(const CQ::SizeFeature& sizeFeature, const ResolvedContainer& container) const -> EvaluationResult
 {
-    auto toEvaluationResult = [](bool boolean) {
-        return boolean ? EvaluationResult::True : EvaluationResult::False;
-    };
-
-    auto compare = [&](auto left, auto right) {
-        switch (sizeFeature.comparisonOperator) {
+    auto compare = [](CQ::ComparisonOperator op, auto left, auto right) {
+        switch (op) {
         case CQ::ComparisonOperator::LessThan:
             return left < right;
         case CQ::ComparisonOperator::GreaterThan:
@@ -178,21 +166,55 @@
             return left >= right;
         case CQ::ComparisonOperator::Equal:
             return left == right;
-        case CQ::ComparisonOperator::True:
-            ASSERT_NOT_REACHED();
-            return false;
         }
     };
 
+    enum class Side : uint8_t { Left, Right };
+    auto evaluateSizeComparison = [&](LayoutUnit size, const std::optional<CQ::Comparison>& comparison, Side side) {
+        if (!comparison)
+            return EvaluationResult::True;
+        auto expressionSize = computeSize(comparison->value.get(), container.conversionData);
+        if (!expressionSize)
+            return EvaluationResult::Unknown;
+        auto left = side == Side::Left ? *expressionSize : size;
+        auto right = side == Side::Left ? size : *expressionSize;
+
+        return toEvaluationResult(compare(comparison->op, left, right));
+    };
+
     auto evaluateSize = [&](LayoutUnit size) {
-        if (sizeFeature.comparisonOperator == CQ::ComparisonOperator::True)
+        if (!sizeFeature.leftComparison && !sizeFeature.rightComparison)
             return toEvaluationResult(!!size);
 
-        auto expressionSize = computeSize(sizeFeature.value.get(), container.conversionData);
-        if (!expressionSize)
+        auto leftResult = evaluateSizeComparison(size, sizeFeature.leftComparison, Side::Left);
+        auto rightResult = evaluateSizeComparison(size, sizeFeature.rightComparison, Side::Right);
+
+        return leftResult & rightResult;
+    };
+
+    auto evaluateAspectRatioComparison = [&](double aspectRatio, const std::optional<CQ::Comparison>& comparison, Side side) {
+        if (!comparison)
+            return EvaluationResult::True;
+
+        if (!is<CSSValueList>(comparison->value))
             return EvaluationResult::Unknown;
 
-        return toEvaluationResult(compare(size, *expressionSize));
+        auto& ratioList = downcast<CSSValueList>(*comparison->value);
+        if (ratioList.length() != 2)
+            return EvaluationResult::Unknown;
+
+        auto first = dynamicDowncast<CSSPrimitiveValue>(ratioList.item(0));
+        auto second = dynamicDowncast<CSSPrimitiveValue>(ratioList.item(1));
+
+        if (!first || !second || !first->isNumberOrInteger() || !second->isNumberOrInteger())
+            return EvaluationResult::Unknown;
+
+        auto expressionRatio = first->doubleValue() / second->doubleValue();
+
+        auto left = side == Side::Left ? expressionRatio : aspectRatio;
+        auto right = side == Side::Left ? aspectRatio : expressionRatio;
+
+        return toEvaluationResult(compare(comparison->op, left, right));
     };
 
     enum class Axis : uint8_t { Both, Block, Inline, Width, Height };
@@ -245,25 +267,14 @@
             return EvaluationResult::Unknown;
 
         auto boxRatio = container.renderer.contentWidth().toDouble() / container.renderer.contentHeight().toDouble();
-        if (sizeFeature.comparisonOperator == CQ::ComparisonOperator::True)
+        
+        if (!sizeFeature.leftComparison && !sizeFeature.rightComparison)
             return toEvaluationResult(!!boxRatio);
 
-        if (!is<CSSValueList>(sizeFeature.value))
-            return EvaluationResult::Unknown;
+        auto leftResult = evaluateAspectRatioComparison(boxRatio, sizeFeature.leftComparison, Side::Left);
+        auto rightResult = evaluateAspectRatioComparison(boxRatio, sizeFeature.rightComparison, Side::Right);
 
-        auto& ratioList = downcast<CSSValueList>(*sizeFeature.value);
-        if (ratioList.length() != 2)
-            return EvaluationResult::Unknown;
-
-        auto first = dynamicDowncast<CSSPrimitiveValue>(ratioList.item(0));
-        auto second = dynamicDowncast<CSSPrimitiveValue>(ratioList.item(1));
-
-        if (!first || !second || !first->isNumberOrInteger() || !second->isNumberOrInteger())
-            return EvaluationResult::Unknown;
-
-        auto expressionRatio = first->doubleValue() / second->doubleValue();
-
-        return toEvaluationResult(compare(boxRatio, expressionRatio));
+        return leftResult & rightResult;
     }
 
     if (sizeFeature.name == CQ::FeatureNames::orientation()) {
@@ -270,11 +281,16 @@
         if (!containerSupportsRequiredAxis(Axis::Both))
             return EvaluationResult::Unknown;
 
-        if (!is<CSSPrimitiveValue>(sizeFeature.value) || sizeFeature.comparisonOperator != CQ::ComparisonOperator::Equal)
+        if (!sizeFeature.rightComparison)
             return EvaluationResult::Unknown;
 
-        auto& value = downcast<CSSPrimitiveValue>(*sizeFeature.value);
+        auto& comparison = *sizeFeature.rightComparison;
 
+        if (!is<CSSPrimitiveValue>(comparison.value) || comparison.op != CQ::ComparisonOperator::Equal)
+            return EvaluationResult::Unknown;
+
+        auto& value = downcast<CSSPrimitiveValue>(*sizeFeature.rightComparison->value);
+
         bool isPortrait = container.renderer.contentHeight() >= container.renderer.contentWidth();
         if (value.valueID() == CSSValuePortrait)
             return toEvaluationResult(isPortrait);

Modified: trunk/Source/WebCore/style/ContainerQueryEvaluator.h (290036 => 290037)


--- trunk/Source/WebCore/style/ContainerQueryEvaluator.h	2022-02-17 19:05:45 UTC (rev 290036)
+++ trunk/Source/WebCore/style/ContainerQueryEvaluator.h	2022-02-17 19:38:06 UTC (rev 290037)
@@ -33,6 +33,8 @@
 
 namespace Style {
 
+enum class EvaluationResult : uint8_t { False, True, Unknown };
+
 class ContainerQueryEvaluator {
 public:
     ContainerQueryEvaluator(const Vector<Ref<const Element>>& containers);
@@ -41,7 +43,6 @@
 
 private:
     struct ResolvedContainer;
-    enum class EvaluationResult : uint8_t { False, True, Unknown };
 
     EvaluationResult evaluateQuery(const CQ::ContainerQuery&, const ResolvedContainer&) const;
     EvaluationResult evaluateQuery(const CQ::SizeQuery&, const ResolvedContainer&) const;
@@ -51,5 +52,31 @@
     const Vector<Ref<const Element>>& m_containers;
 };
 
+inline EvaluationResult toEvaluationResult(bool boolean)
+{
+    return boolean ? EvaluationResult::True : EvaluationResult::False;
+};
+
+inline EvaluationResult operator&(EvaluationResult left, EvaluationResult right)
+{
+    if (left == EvaluationResult::Unknown || right == EvaluationResult::Unknown)
+        return EvaluationResult::Unknown;
+    if (left == EvaluationResult::True && right == EvaluationResult::True)
+        return EvaluationResult::True;
+    return EvaluationResult::False;
 }
+
+inline EvaluationResult operator!(EvaluationResult result)
+{
+    switch (result) {
+    case EvaluationResult::True:
+        return EvaluationResult::False;
+    case EvaluationResult::False:
+        return EvaluationResult::True;
+    case EvaluationResult::Unknown:
+        return EvaluationResult::Unknown;
+    }
 }
+
+}
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to