LibWeb/CSS: Pass Length::ResolutionContext to resolve_integer

The length resolution context might be needed even when resolving an
integer value, since it might contain a sign() function with length
values inside. This fixes a WPT subtest.
This commit is contained in:
Milo van der Tier 2024-11-29 16:41:40 +01:00 committed by Sam Atkins
parent 8bec80ac47
commit 1882a2e19b
Notes: github-actions[bot] 2024-12-04 12:38:56 +00:00
7 changed files with 75 additions and 17 deletions

View file

@ -47,15 +47,15 @@ NonnullRefPtr<CSSStyleValue> FrequencyOrCalculated::create_style_value() const
return FrequencyStyleValue::create(value());
}
i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const&) const
i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const& layout_node) const
{
return calculated->resolve_integer().value();
return calculated->resolve_integer(layout_node).value();
}
i64 IntegerOrCalculated::resolved() const
i64 IntegerOrCalculated::resolved(Length::ResolutionContext const& context) const
{
if (is_calculated())
return calculated()->resolve_integer().value();
return calculated()->resolve_integer(context).value();
return value();
}
@ -81,9 +81,9 @@ NonnullRefPtr<CSSStyleValue> LengthOrCalculated::create_style_value() const
return LengthStyleValue::create(value());
}
double NumberOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const&) const
double NumberOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& calculated, Layout::Node const& layout_node) const
{
return calculated->resolve_number().value();
return calculated->resolve_number(layout_node).value();
}
NonnullRefPtr<CSSStyleValue> NumberOrCalculated::create_style_value() const

View file

@ -119,7 +119,7 @@ class IntegerOrCalculated : public CalculatedOr<i64> {
public:
using CalculatedOr<i64>::CalculatedOr;
[[nodiscard]] i64 resolved() const;
[[nodiscard]] i64 resolved(Length::ResolutionContext const&) const;
private:
virtual i64 resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;

View file

@ -90,12 +90,12 @@ bool MediaFeature::evaluate(HTML::Window const& window) const
return false;
auto queried_value = maybe_queried_value.release_value();
auto resolution_context = Length::ResolutionContext::for_window(window);
switch (m_type) {
case Type::IsTrue:
if (queried_value.is_integer())
return queried_value.integer().resolved() != 0;
return queried_value.integer().resolved(resolution_context) != 0;
if (queried_value.is_length()) {
auto resolution_context = Length::ResolutionContext::for_window(window);
auto length = queried_value.length().resolved(resolution_context);
return length.raw_value() != 0;
}
@ -149,17 +149,18 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
}
if (left.is_integer()) {
auto resolution_context = Length::ResolutionContext::for_window(window);
switch (comparison) {
case Comparison::Equal:
return left.integer().resolved() == right.integer().resolved();
return left.integer().resolved(resolution_context) == right.integer().resolved(resolution_context);
case Comparison::LessThan:
return left.integer().resolved() < right.integer().resolved();
return left.integer().resolved(resolution_context) < right.integer().resolved(resolution_context);
case Comparison::LessThanOrEqual:
return left.integer().resolved() <= right.integer().resolved();
return left.integer().resolved(resolution_context) <= right.integer().resolved(resolution_context);
case Comparison::GreaterThan:
return left.integer().resolved() > right.integer().resolved();
return left.integer().resolved(resolution_context) > right.integer().resolved(resolution_context);
case Comparison::GreaterThanOrEqual:
return left.integer().resolved() >= right.integer().resolved();
return left.integer().resolved(resolution_context) >= right.integer().resolved(resolution_context);
}
VERIFY_NOT_REACHED();
}

View file

@ -569,8 +569,7 @@ Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID med
auto transaction = tokens.begin_transaction();
tokens.discard_whitespace();
if (auto integer = parse_integer(tokens); integer.has_value()) {
auto integer_value = integer.value().resolved();
if (integer_value == 0 || integer_value == 1) {
if (integer.value().is_calculated() || integer->value() == 0 || integer->value() == 1) {
transaction.commit();
return MediaFeatureValue(integer.release_value());
}

View file

@ -2797,19 +2797,49 @@ Optional<Time> CSSMathValue::resolve_time_percentage(Time const& percentage_basi
Optional<double> CSSMathValue::resolve_number() const
{
auto result = m_calculation->resolve({}, {});
if (result.value().has<Number>())
return result.value().get<Number>().value();
return {};
}
Optional<double> CSSMathValue::resolve_number(Length::ResolutionContext const& context) const
{
auto result = m_calculation->resolve(context, {});
if (result.value().has<Number>())
return result.value().get<Number>().value();
return {};
}
Optional<double> CSSMathValue::resolve_number(Layout::Node const& layout_node) const
{
return resolve_number(Length::ResolutionContext::for_layout_node(layout_node));
}
Optional<i64> CSSMathValue::resolve_integer() const
{
auto result = m_calculation->resolve({}, {});
if (result.value().has<Number>())
return result.value().get<Number>().integer_value();
return {};
}
Optional<i64> CSSMathValue::resolve_integer(Length::ResolutionContext const& context) const
{
auto result = m_calculation->resolve(context, {});
if (result.value().has<Number>())
return result.value().get<Number>().integer_value();
return {};
}
Optional<i64> CSSMathValue::resolve_integer(Layout::Node const& layout_node) const
{
return resolve_integer(Length::ResolutionContext::for_layout_node(layout_node));
}
bool CSSMathValue::contains_percentage() const
{
return m_calculation->contains_percentage();

View file

@ -99,7 +99,7 @@ public:
bool resolves_to_length() const { return m_resolved_type.matches_length(); }
bool resolves_to_length_percentage() const { return m_resolved_type.matches_length_percentage(); }
[[nodiscard]] Optional<Length> resolve_length(Length::ResolutionContext const&) const;
Optional<Length> resolve_length(Length::ResolutionContext const&) const;
Optional<Length> resolve_length(Layout::Node const& layout_node) const;
Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
Optional<Length> resolve_length_percentage(Layout::Node const&, CSSPixels percentage_basis) const;
@ -119,7 +119,11 @@ public:
bool resolves_to_number() const { return m_resolved_type.matches_number(); }
bool resolves_to_number_percentage() const { return m_resolved_type.matches_number_percentage(); }
Optional<double> resolve_number() const;
Optional<double> resolve_number(Length::ResolutionContext const&) const;
Optional<double> resolve_number(Layout::Node const& layout_node) const;
Optional<i64> resolve_integer() const;
Optional<i64> resolve_integer(Length::ResolutionContext const&) const;
Optional<i64> resolve_integer(Layout::Node const& layout_node) const;
bool resolves_to_dimension() const { return m_resolved_type.matches_dimension(); }

View file

@ -0,0 +1,24 @@
<!doctype html>
<title>Test: support for calc with sign() in Media Queries</title>
<link rel="author" title="Daniil Sakhapov" href="mailto:sakhapov@chromium.org">
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
<style>
:root {
font-size: 16px;
}
div {
width: 100px;
height: 100px;
background-color: green;
}
@media (grid: calc(2 * sign(17px - 1rem))) {
div {
background-color: red;
}
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div></div>