LibWeb/CSS: Simplify calculations after parsing them

If a calculation was simplified down to a single numeric node, then most
of the time we can instead return a regular StyleValue, for example
`calc(2px + 3px)` would be simplified down to a `5px` LengthStyleValue.
This means that parse_calculated_value() can't return a
CalculatedStyleValue directly, and its callers all have to handle
non-calculated values as well as calculated ones.

This simplification is reflected in the new test results. Serialization
is not yet correct in all cases but we're closer than we were. :^)
This commit is contained in:
Sam Atkins 2025-01-28 16:24:39 +00:00 committed by Andreas Kling
commit ee712bd98f
Notes: github-actions[bot] 2025-01-30 18:32:52 +00:00
15 changed files with 295 additions and 228 deletions

View file

@ -1912,7 +1912,7 @@ RefPtr<CustomIdentStyleValue> Parser::parse_custom_ident_value(TokenStream<Compo
return CustomIdentStyleValue::create(custom_ident);
}
RefPtr<CalculatedStyleValue> Parser::parse_calculated_value(ComponentValue const& component_value)
RefPtr<CSSStyleValue> Parser::parse_calculated_value(ComponentValue const& component_value)
{
if (!component_value.is_function())
return nullptr;
@ -1949,6 +1949,12 @@ RefPtr<CalculatedStyleValue> Parser::parse_calculated_value(ComponentValue const
if (!function_node)
return nullptr;
// If the calculation got simplified down to a single value, return that instead.
if (function_node->type() == CalculationNode::Type::Numeric) {
if (auto number_value = as<NumericCalculationNode>(*function_node).to_style_value(context))
return number_value.release_nonnull();
}
auto function_type = function_node->numeric_type();
if (!function_type.has_value())
return nullptr;
@ -2182,13 +2188,18 @@ Optional<Ratio> Parser::parse_ratio(TokenStream<ComponentValue>& tokens)
// Still, we should probably support it. That means not assuming we can resolve the calculation immediately.
auto read_number_value = [this](ComponentValue const& component_value) -> Optional<double> {
if (component_value.is(Token::Type::Number)) {
if (component_value.is(Token::Type::Number))
return component_value.token().number_value();
} else if (component_value.is_function()) {
if (component_value.is_function()) {
auto maybe_calc = parse_calculated_value(component_value);
if (!maybe_calc || !maybe_calc->resolves_to_number())
if (!maybe_calc)
return {};
if (auto resolved_number = maybe_calc->resolve_number({}); resolved_number.has_value() && resolved_number.value() >= 0) {
if (maybe_calc->is_number())
return maybe_calc->as_number().value();
if (!maybe_calc->is_calculated() || !maybe_calc->as_calculated().resolves_to_number())
return {};
if (auto resolved_number = maybe_calc->as_calculated().resolve_number({}); resolved_number.has_value() && resolved_number.value() >= 0) {
return resolved_number.value();
}
}
@ -2490,7 +2501,9 @@ RefPtr<CSSStyleValue> Parser::parse_integer_value(TokenStream<ComponentValue>& t
tokens.discard_a_token(); // integer
return IntegerStyleValue::create(peek_token.token().number().integer_value());
}
if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_number()) {
if (auto calc = parse_calculated_value(peek_token); calc
&& (calc->is_integer() || (calc->is_calculated() && calc->as_calculated().resolves_to_number()))) {
tokens.discard_a_token(); // calc
return calc;
}
@ -2505,7 +2518,9 @@ RefPtr<CSSStyleValue> Parser::parse_number_value(TokenStream<ComponentValue>& to
tokens.discard_a_token(); // number
return NumberStyleValue::create(peek_token.token().number().value());
}
if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_number()) {
if (auto calc = parse_calculated_value(peek_token); calc
&& (calc->is_number() || (calc->is_calculated() && calc->as_calculated().resolves_to_number()))) {
tokens.discard_a_token(); // calc
return calc;
}
@ -2546,7 +2561,9 @@ RefPtr<CSSStyleValue> Parser::parse_percentage_value(TokenStream<ComponentValue>
tokens.discard_a_token(); // percentage
return PercentageStyleValue::create(Percentage(peek_token.token().percentage()));
}
if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_percentage()) {
if (auto calc = parse_calculated_value(peek_token); calc
&& (calc->is_percentage() || (calc->is_calculated() && calc->as_calculated().resolves_to_percentage()))) {
tokens.discard_a_token(); // calc
return calc;
}
@ -2576,11 +2593,11 @@ RefPtr<CSSStyleValue> Parser::parse_angle_value(TokenStream<ComponentValue>& tok
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_angle()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_angle() || (calc->is_calculated() && calc->as_calculated().resolves_to_angle()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2610,11 +2627,11 @@ RefPtr<CSSStyleValue> Parser::parse_angle_percentage_value(TokenStream<Component
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_angle_percentage()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_angle() || calc->is_percentage() || (calc->is_calculated() && calc->as_calculated().resolves_to_angle_percentage()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2632,11 +2649,11 @@ RefPtr<CSSStyleValue> Parser::parse_flex_value(TokenStream<ComponentValue>& toke
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_flex()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_flex() || (calc->is_calculated() && calc->as_calculated().resolves_to_flex()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2654,11 +2671,11 @@ RefPtr<CSSStyleValue> Parser::parse_frequency_value(TokenStream<ComponentValue>&
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_frequency()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_frequency() || (calc->is_calculated() && calc->as_calculated().resolves_to_frequency()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2679,11 +2696,11 @@ RefPtr<CSSStyleValue> Parser::parse_frequency_percentage_value(TokenStream<Compo
return PercentageStyleValue::create(Percentage { tokens.consume_a_token().token().percentage() });
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_frequency_percentage()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_frequency() || calc->is_percentage() || (calc->is_calculated() && calc->as_calculated().resolves_to_frequency_percentage()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2755,11 +2772,11 @@ RefPtr<CSSStyleValue> Parser::parse_length_value(TokenStream<ComponentValue>& to
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_length()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_length() || (calc->is_calculated() && calc->as_calculated().resolves_to_length()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2802,11 +2819,11 @@ RefPtr<CSSStyleValue> Parser::parse_length_percentage_value(TokenStream<Componen
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_length_percentage()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_length() || calc->is_percentage() || (calc->is_calculated() && calc->as_calculated().resolves_to_length_percentage()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2824,11 +2841,11 @@ RefPtr<CSSStyleValue> Parser::parse_resolution_value(TokenStream<ComponentValue>
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_resolution()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_resolution() || (calc->is_calculated() && calc->as_calculated().resolves_to_resolution()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2846,11 +2863,11 @@ RefPtr<CSSStyleValue> Parser::parse_time_value(TokenStream<ComponentValue>& toke
}
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_time()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_time() || (calc->is_calculated() && calc->as_calculated().resolves_to_time()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -2871,11 +2888,11 @@ RefPtr<CSSStyleValue> Parser::parse_time_percentage_value(TokenStream<ComponentV
return PercentageStyleValue::create(Percentage { tokens.consume_a_token().token().percentage() });
auto transaction = tokens.begin_transaction();
if (auto calculated_value = parse_calculated_value(tokens.consume_a_token());
calculated_value && calculated_value->resolves_to_time_percentage()) {
if (auto calc = parse_calculated_value(tokens.consume_a_token()); calc
&& (calc->is_time() || calc->is_percentage() || (calc->is_calculated() && calc->as_calculated().resolves_to_time_percentage()))) {
transaction.commit();
return calculated_value;
return calc;
}
return nullptr;
}
@ -7630,8 +7647,12 @@ Optional<CSS::GridSize> Parser::parse_grid_size(ComponentValue const& component_
{
if (component_value.is_function()) {
if (auto maybe_calculated = parse_calculated_value(component_value)) {
if (maybe_calculated->resolves_to_length_percentage())
return GridSize(LengthPercentage(maybe_calculated.release_nonnull()));
if (maybe_calculated->is_length())
return GridSize(maybe_calculated->as_length().length());
if (maybe_calculated->is_percentage())
return GridSize(maybe_calculated->as_percentage().percentage());
if (maybe_calculated->is_calculated() && maybe_calculated->as_calculated().resolves_to_length_percentage())
return GridSize(LengthPercentage(maybe_calculated->as_calculated()));
// FIXME: Support calculated <flex>
}
@ -7889,7 +7910,12 @@ Optional<CSS::ExplicitGridTrack> Parser::parse_track_sizing_function(ComponentVa
return CSS::ExplicitGridTrack(maybe_fit_content_value.value());
return {};
} else if (auto maybe_calculated = parse_calculated_value(token)) {
return CSS::ExplicitGridTrack(GridSize(LengthPercentage(maybe_calculated.release_nonnull())));
if (maybe_calculated->is_length())
return ExplicitGridTrack(GridSize(maybe_calculated->as_length().length()));
if (maybe_calculated->is_percentage())
return ExplicitGridTrack(GridSize(maybe_calculated->as_percentage().percentage()));
if (maybe_calculated->is_calculated() && maybe_calculated->as_calculated().resolves_to_length_percentage())
return ExplicitGridTrack(GridSize(LengthPercentage(maybe_calculated->as_calculated())));
}
return {};
} else if (token.is_ident("auto"sv)) {
@ -8123,9 +8149,15 @@ RefPtr<GridTrackPlacementStyleValue> Parser::parse_grid_track_placement(TokenStr
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line({}, custom_ident->custom_ident().to_string()));
}
auto const& token = tokens.consume_a_token();
if (auto maybe_calculated = parse_calculated_value(token); maybe_calculated && maybe_calculated->resolves_to_number()) {
if (auto maybe_calculated = parse_calculated_value(token)) {
if (maybe_calculated->is_number()) {
transaction.commit();
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(maybe_calculated->resolve_integer({}).value()), {}));
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(maybe_calculated->as_number().number()), {}));
}
if (maybe_calculated->is_calculated() && maybe_calculated->as_calculated().resolves_to_number()) {
transaction.commit();
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(maybe_calculated->as_calculated().resolve_integer({}).value()), {}));
}
}
if (token.is_ident("auto"sv)) {
transaction.commit();
@ -9491,8 +9523,8 @@ RefPtr<CalculationNode> Parser::parse_a_calculation(Vector<ComponentValue> const
if (!calculation_tree)
return nullptr;
// FIXME: 6. Return the result of simplifying a calculation tree from values.
return calculation_tree.release_nonnull();
// 6. Return the result of simplifying a calculation tree from values.
return simplify_a_calculation_tree(*calculation_tree, context, CalculationResolutionContext {});
}
bool Parser::has_ignored_vendor_prefix(StringView string)

View file

@ -273,7 +273,7 @@ private:
};
Optional<PropertyAndValue> parse_css_value_for_properties(ReadonlySpan<PropertyID>, TokenStream<ComponentValue>&);
RefPtr<CSSStyleValue> parse_builtin_value(TokenStream<ComponentValue>&);
RefPtr<CalculatedStyleValue> parse_calculated_value(ComponentValue const&);
RefPtr<CSSStyleValue> parse_calculated_value(ComponentValue const&);
RefPtr<CustomIdentStyleValue> parse_custom_ident_value(TokenStream<ComponentValue>&, std::initializer_list<StringView> blacklist);
// NOTE: Implemented in generated code. (GenerateCSSMathFunctions.cpp)
RefPtr<CalculationNode> parse_math_function(Function const&, CalculationContext const&);

View file

@ -11,6 +11,15 @@
#include <AK/TypeCasts.h>
#include <LibWeb/CSS/Percentage.h>
#include <LibWeb/CSS/PropertyID.h>
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
#include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
#include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
#include <LibWeb/CSS/StyleValues/ResolutionStyleValue.h>
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
namespace Web::CSS {
@ -298,6 +307,30 @@ CalculatedStyleValue::CalculationResult NumericCalculationNode::resolve(Calculat
return CalculatedStyleValue::CalculationResult::from_value(m_value, context, numeric_type());
}
RefPtr<CSSStyleValue> NumericCalculationNode::to_style_value(CalculationContext const& context) const
{
// TODO: Clamp values to the range allowed by the context.
return m_value.visit(
[&](Number const& number) -> RefPtr<CSSStyleValue> {
// FIXME: Returning infinity or NaN as a NumberStyleValue isn't valid.
// This is a temporary fix until value-clamping is implemented here.
// In future, we can remove these two lines and return NonnullRefPtr again.
if (!isfinite(number.value()))
return nullptr;
if (context.resolve_numbers_as_integers)
return IntegerStyleValue::create(llround(number.value()));
return NumberStyleValue::create(number.value());
},
[](Angle const& angle) -> RefPtr<CSSStyleValue> { return AngleStyleValue::create(angle); },
[](Flex const& flex) -> RefPtr<CSSStyleValue> { return FlexStyleValue::create(flex); },
[](Frequency const& frequency) -> RefPtr<CSSStyleValue> { return FrequencyStyleValue::create(frequency); },
[](Length const& length) -> RefPtr<CSSStyleValue> { return LengthStyleValue::create(length); },
[](Percentage const& percentage) -> RefPtr<CSSStyleValue> { return PercentageStyleValue::create(percentage); },
[](Resolution const& resolution) -> RefPtr<CSSStyleValue> { return ResolutionStyleValue::create(resolution); },
[](Time const& time) -> RefPtr<CSSStyleValue> { return TimeStyleValue::create(time); });
}
void NumericCalculationNode::dump(StringBuilder& builder, int indent) const
{
builder.appendff("{: >{}}NUMERIC({})\n", "", indent, m_value.visit([](auto& it) { return it.to_string(); }));

View file

@ -268,6 +268,8 @@ public:
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual NonnullRefPtr<CalculationNode> with_simplified_children(CalculationContext const&, CalculationResolutionContext const&) const override { return *this; }
RefPtr<CSSStyleValue> to_style_value(CalculationContext const&) const;
NumericValue const& value() const { return m_value; }
virtual void dump(StringBuilder&, int indent) const override;

View file

@ -1,80 +1,80 @@
animation-delay: 'calc(2s)' -> 'calc(2s)'
animation-delay: 'calc(2s)' -> '2s'
animation-delay: 'calc(2s * var(--n))' -> '4s'
animation-duration: 'calc(2s)' -> 'calc(2s)'
animation-duration: 'calc(2s)' -> '2s'
animation-duration: 'calc(2s * var(--n))' -> '4s'
animation-iteration-count: 'calc(2)' -> 'calc(2)'
animation-iteration-count: 'calc(2)' -> '2'
animation-iteration-count: 'calc(2 * var(--n))' -> '4'
backdrop-filter: 'grayscale(calc(2%))' -> 'grayscale(calc(2%))'
backdrop-filter: 'grayscale(calc(2% * var(--n)))' -> 'grayscale(calc(2% * 2))'
backdrop-filter: 'grayscale(calc(0.02))' -> 'grayscale(calc(0.02))'
backdrop-filter: 'grayscale(calc(0.02 * var(--n)))' -> 'grayscale(calc(0.02 * 2))'
background-position-x: 'calc(2px)' -> 'calc(2px)'
background-position-x: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
background-position-y: 'calc(2%)' -> 'calc(2%)'
background-position-y: 'calc(2% * var(--n))' -> '4%'
background-size: 'calc(2px * var(--n)) calc(2%)' -> 'calc(2px * 2) 2%'
background-size: 'calc(2px * var(--n)) calc(2% * var(--n))' -> 'calc(2px * 2) 4%'
border-bottom-left-radius: 'calc(2px)' -> 'calc(2px)'
border-bottom-left-radius: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
border-bottom-right-radius: 'calc(2%)' -> 'calc(2%)'
border-bottom-right-radius: 'calc(2% * var(--n))' -> '4%'
border-bottom-width: 'calc(2px)' -> 'calc(2px)'
border-bottom-width: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
border-left-width: 'calc(2px)' -> 'calc(2px)'
border-left-width: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
border-right-width: 'calc(2px)' -> 'calc(2px)'
border-right-width: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
border-spacing: 'calc(2px)' -> 'calc(2px)'
border-spacing: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
border-top-left-radius: 'calc(2px)' -> 'calc(2px)'
border-top-left-radius: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
border-top-right-radius: 'calc(2%)' -> 'calc(2%)'
border-top-right-radius: 'calc(2% * var(--n))' -> '4%'
border-top-width: 'calc(2px)' -> 'calc(2px)'
border-top-width: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
bottom: 'calc(2px)' -> 'calc(2px)'
bottom: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
clip-path: 'polygon(calc(0px) calc(2px), calc(2px) calc(0px), calc(2px) calc(2px))' -> 'polygon(nonzero, calc(0px) calc(2px), calc(2px) calc(0px), calc(2px) calc(2px))'
clip-path: 'polygon(calc(0px * var(--n)) calc(2px * var(--n)), calc(2px * var(--n)) calc(0px * var(--n)), calc(2px * var(--n)) calc(2px * var(--n)))' -> 'polygon(nonzero, calc(0px * 2) calc(2px * 2), calc(2px * 2) calc(0px * 2), calc(2px * 2) calc(2px * 2))'
clip-path: 'polygon(calc(0%) calc(2%), calc(2%) calc(0%), calc(2%) calc(2%))' -> 'polygon(nonzero, calc(0%) calc(2%), calc(2%) calc(0%), calc(2%) calc(2%))'
clip-path: 'polygon(calc(0% * var(--n)) calc(2% * var(--n)), calc(2% * var(--n)) calc(0% * var(--n)), calc(2% * var(--n)) calc(2% * var(--n)))' -> 'polygon(nonzero, calc(0% * 2) calc(2% * 2), calc(2% * 2) calc(0% * 2), calc(2% * 2) calc(2% * 2))'
column-count: 'calc(2)' -> 'calc(2)'
backdrop-filter: 'grayscale(calc(2%))' -> 'grayscale(2%)'
backdrop-filter: 'grayscale(calc(2% * var(--n)))' -> 'grayscale(4%)'
backdrop-filter: 'grayscale(calc(0.02))' -> 'grayscale(0.02)'
backdrop-filter: 'grayscale(calc(0.02 * var(--n)))' -> 'grayscale(0.04)'
background-position-x: 'calc(2px)' -> '2px'
background-position-x: 'calc(2px * var(--n))' -> '4px'
background-position-y: 'calc(2%)' -> '2%'
background-position-y: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
background-size: 'calc(2px * var(--n)) calc(2%)' -> '4px 2%'
background-size: 'calc(2px * var(--n)) calc(2% * var(--n))' -> '4px calc(2% * 2)'
border-bottom-left-radius: 'calc(2px)' -> '2px'
border-bottom-left-radius: 'calc(2px * var(--n))' -> '4px'
border-bottom-right-radius: 'calc(2%)' -> '2%'
border-bottom-right-radius: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
border-bottom-width: 'calc(2px)' -> '2px'
border-bottom-width: 'calc(2px * var(--n))' -> '4px'
border-left-width: 'calc(2px)' -> '2px'
border-left-width: 'calc(2px * var(--n))' -> '4px'
border-right-width: 'calc(2px)' -> '2px'
border-right-width: 'calc(2px * var(--n))' -> '4px'
border-spacing: 'calc(2px)' -> '2px'
border-spacing: 'calc(2px * var(--n))' -> '4px'
border-top-left-radius: 'calc(2px)' -> '2px'
border-top-left-radius: 'calc(2px * var(--n))' -> '4px'
border-top-right-radius: 'calc(2%)' -> '2%'
border-top-right-radius: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
border-top-width: 'calc(2px)' -> '2px'
border-top-width: 'calc(2px * var(--n))' -> '4px'
bottom: 'calc(2px)' -> '2px'
bottom: 'calc(2px * var(--n))' -> '4px'
clip-path: 'polygon(calc(0px) calc(2px), calc(2px) calc(0px), calc(2px) calc(2px))' -> 'polygon(nonzero, 0px 2px, 2px 0px, 2px 2px)'
clip-path: 'polygon(calc(0px * var(--n)) calc(2px * var(--n)), calc(2px * var(--n)) calc(0px * var(--n)), calc(2px * var(--n)) calc(2px * var(--n)))' -> 'polygon(nonzero, 0px 4px, 4px 0px, 4px 4px)'
clip-path: 'polygon(calc(0%) calc(2%), calc(2%) calc(0%), calc(2%) calc(2%))' -> 'polygon(nonzero, 0% 2%, 2% 0%, 2% 2%)'
clip-path: 'polygon(calc(0% * var(--n)) calc(2% * var(--n)), calc(2% * var(--n)) calc(0% * var(--n)), calc(2% * var(--n)) calc(2% * var(--n)))' -> 'polygon(nonzero, 0% 4%, 4% 0%, 4% 4%)'
column-count: 'calc(2)' -> '2'
column-count: 'calc(2 * var(--n))' -> '4'
column-gap: 'calc(2px)' -> 'calc(2px)'
column-gap: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
column-width: 'calc(2px)' -> 'calc(2px)'
column-width: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
counter-increment: 'foo calc(2)' -> 'foo calc(2)'
column-gap: 'calc(2px)' -> '2px'
column-gap: 'calc(2px * var(--n))' -> '4px'
column-width: 'calc(2px)' -> '2px'
column-width: 'calc(2px * var(--n))' -> '4px'
counter-increment: 'foo calc(2)' -> 'foo 2'
counter-increment: 'foo calc(2 * var(--n))' -> 'foo 4'
counter-reset: 'foo calc(2)' -> 'foo calc(2)'
counter-reset: 'foo calc(2)' -> 'foo 2'
counter-reset: 'foo calc(2 * var(--n))' -> 'foo 4'
counter-set: 'foo calc(2)' -> 'foo calc(2)'
counter-set: 'foo calc(2)' -> 'foo 2'
counter-set: 'foo calc(2 * var(--n))' -> 'foo 4'
cx: 'calc(2px)' -> 'calc(2px)'
cx: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
cy: 'calc(2%)' -> 'calc(2%)'
cy: 'calc(2% * var(--n))' -> '4%'
fill-opacity: 'calc(2)' -> 'calc(2)'
cx: 'calc(2px)' -> '2px'
cx: 'calc(2px * var(--n))' -> '4px'
cy: 'calc(2%)' -> '2%'
cy: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
fill-opacity: 'calc(2)' -> '2'
fill-opacity: 'calc(2 * var(--n))' -> '4'
filter: 'grayscale(calc(2%))' -> 'grayscale(calc(2%))'
filter: 'grayscale(calc(2% * var(--n)))' -> 'grayscale(calc(2% * 2))'
filter: 'grayscale(calc(0.02))' -> 'grayscale(calc(0.02))'
filter: 'grayscale(calc(0.02 * var(--n)))' -> 'grayscale(calc(0.02 * 2))'
flex-basis: 'calc(2px)' -> 'calc(2px)'
flex-basis: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
flex-grow: 'calc(2)' -> 'calc(2)'
filter: 'grayscale(calc(2%))' -> 'grayscale(2%)'
filter: 'grayscale(calc(2% * var(--n)))' -> 'grayscale(4%)'
filter: 'grayscale(calc(0.02))' -> 'grayscale(0.02)'
filter: 'grayscale(calc(0.02 * var(--n)))' -> 'grayscale(0.04)'
flex-basis: 'calc(2px)' -> '2px'
flex-basis: 'calc(2px * var(--n))' -> '4px'
flex-grow: 'calc(2)' -> '2'
flex-grow: 'calc(2 * var(--n))' -> '4'
flex-shrink: 'calc(2)' -> 'calc(2)'
flex-shrink: 'calc(2)' -> '2'
flex-shrink: 'calc(2 * var(--n))' -> '4'
font-feature-settings: ''test' calc(2)' -> '"test" calc(2)'
font-feature-settings: ''test' calc(2)' -> '"test" 2'
font-feature-settings: ''test' calc(2 * var(--n))' -> '"test" 4'
font-size: 'calc(2px)' -> '2px'
font-size: 'calc(2px * var(--n))' -> '4px'
font-variation-settings: ''test' calc(2)' -> '"test" calc(2)'
font-variation-settings: ''test' calc(2)' -> '"test" 2'
font-variation-settings: ''test' calc(2 * var(--n))' -> '"test" 4'
font-weight: 'calc(2)' -> '2'
font-weight: 'calc(2 * var(--n))' -> '4'
font-width: 'calc(2%)' -> 'calc(2%)'
font-width: 'calc(2%)' -> '2%'
font-width: 'calc(2% * var(--n))' -> '4%'
grid-auto-columns: 'calc(2fr)' -> 'auto'
grid-auto-columns: 'calc(2fr * var(--n))' -> 'auto'
@ -86,85 +86,85 @@ grid-template-rows: 'calc(2fr)' -> 'auto'
grid-template-rows: 'calc(2fr * var(--n))' -> 'auto'
height: 'calc(2px)' -> '2px'
height: 'calc(2px * var(--n))' -> '4px'
left: 'calc(2px)' -> 'calc(2px)'
left: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
letter-spacing: 'calc(2px)' -> 'calc(2px)'
letter-spacing: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
left: 'calc(2px)' -> '2px'
left: 'calc(2px * var(--n))' -> '4px'
letter-spacing: 'calc(2px)' -> '2px'
letter-spacing: 'calc(2px * var(--n))' -> '4px'
line-height: 'calc(2)' -> '32px'
line-height: 'calc(2 * var(--n))' -> '64px'
margin-bottom: 'calc(2px)' -> 'calc(2px)'
margin-bottom: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
margin-left: 'calc(2%)' -> 'calc(2%)'
margin-left: 'calc(2% * var(--n))' -> '4%'
margin-right: 'calc(2px)' -> 'calc(2px)'
margin-right: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
margin-top: 'calc(2%)' -> 'calc(2%)'
margin-top: 'calc(2% * var(--n))' -> '4%'
margin-bottom: 'calc(2px)' -> '2px'
margin-bottom: 'calc(2px * var(--n))' -> '4px'
margin-left: 'calc(2%)' -> '2%'
margin-left: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
margin-right: 'calc(2px)' -> '2px'
margin-right: 'calc(2px * var(--n))' -> '4px'
margin-top: 'calc(2%)' -> '2%'
margin-top: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
math-depth: 'calc(2)' -> '2'
math-depth: 'calc(2 * var(--n))' -> '4'
max-height: 'calc(2px)' -> 'calc(2px)'
max-height: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
max-width: 'calc(2%)' -> 'calc(2%)'
max-width: 'calc(2% * var(--n))' -> '4%'
min-height: 'calc(2px)' -> 'calc(2px)'
min-height: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
min-width: 'calc(2%)' -> 'calc(2%)'
min-width: 'calc(2% * var(--n))' -> '4%'
opacity: 'calc(2)' -> 'calc(2)'
max-height: 'calc(2px)' -> '2px'
max-height: 'calc(2px * var(--n))' -> '4px'
max-width: 'calc(2%)' -> '2%'
max-width: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
min-height: 'calc(2px)' -> '2px'
min-height: 'calc(2px * var(--n))' -> '4px'
min-width: 'calc(2%)' -> '2%'
min-width: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
opacity: 'calc(2)' -> '2'
opacity: 'calc(2 * var(--n))' -> '4'
order: 'calc(2)' -> 'calc(2)'
order: 'calc(2)' -> '2'
order: 'calc(2 * var(--n))' -> '4'
outline-offset: 'calc(2px)' -> 'calc(2px)'
outline-offset: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
outline-width: 'calc(2px)' -> 'calc(2px)'
outline-width: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
padding-bottom: 'calc(2px)' -> 'calc(2px)'
padding-bottom: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
padding-left: 'calc(2%)' -> 'calc(2%)'
padding-left: 'calc(2% * var(--n))' -> '4%'
padding-right: 'calc(2px)' -> 'calc(2px)'
padding-right: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
padding-top: 'calc(2%)' -> 'calc(2%)'
padding-top: 'calc(2% * var(--n))' -> '4%'
r: 'calc(2px)' -> 'calc(2px)'
r: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
right: 'calc(2%)' -> 'calc(2%)'
right: 'calc(2% * var(--n))' -> '4%'
row-gap: 'calc(2%)' -> 'calc(2%)'
row-gap: 'calc(2% * var(--n))' -> '4%'
rx: 'calc(2px)' -> 'calc(2px)'
rx: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
ry: 'calc(2%)' -> 'calc(2%)'
ry: 'calc(2% * var(--n))' -> '4%'
stop-opacity: 'calc(2)' -> 'calc(2)'
outline-offset: 'calc(2px)' -> '2px'
outline-offset: 'calc(2px * var(--n))' -> '4px'
outline-width: 'calc(2px)' -> '2px'
outline-width: 'calc(2px * var(--n))' -> '4px'
padding-bottom: 'calc(2px)' -> '2px'
padding-bottom: 'calc(2px * var(--n))' -> '4px'
padding-left: 'calc(2%)' -> '2%'
padding-left: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
padding-right: 'calc(2px)' -> '2px'
padding-right: 'calc(2px * var(--n))' -> '4px'
padding-top: 'calc(2%)' -> '2%'
padding-top: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
r: 'calc(2px)' -> '2px'
r: 'calc(2px * var(--n))' -> '4px'
right: 'calc(2%)' -> '2%'
right: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
row-gap: 'calc(2%)' -> '2%'
row-gap: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
rx: 'calc(2px)' -> '2px'
rx: 'calc(2px * var(--n))' -> '4px'
ry: 'calc(2%)' -> '2%'
ry: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
stop-opacity: 'calc(2)' -> '2'
stop-opacity: 'calc(2 * var(--n))' -> '4'
stroke-opacity: 'calc(2%)' -> 'calc(2%)'
stroke-opacity: 'calc(2% * var(--n))' -> '4%'
stroke-width: 'calc(2px)' -> 'calc(2px)'
stroke-width: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
tab-size: 'calc(2px)' -> 'calc(2px)'
tab-size: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
text-decoration-thickness: 'calc(2px)' -> 'calc(2px)'
text-decoration-thickness: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
text-indent: 'calc(2%)' -> 'calc(2%)'
text-indent: 'calc(2% * var(--n))' -> '4%'
top: 'calc(2%)' -> 'calc(2%)'
top: 'calc(2% * var(--n))' -> '4%'
transform-origin: 'calc(2px) calc(2%)' -> 'calc(2px) calc(2%)'
transform-origin: 'calc(2px * var(--n)) calc(2% * var(--n))' -> 'calc(2px * 2) 4%'
transition-delay: 'calc(2s)' -> 'calc(2s)'
stroke-opacity: 'calc(2%)' -> '2%'
stroke-opacity: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
stroke-width: 'calc(2px)' -> '2px'
stroke-width: 'calc(2px * var(--n))' -> '4px'
tab-size: 'calc(2px)' -> '2px'
tab-size: 'calc(2px * var(--n))' -> '4px'
text-decoration-thickness: 'calc(2px)' -> '2px'
text-decoration-thickness: 'calc(2px * var(--n))' -> '4px'
text-indent: 'calc(2%)' -> '2%'
text-indent: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
top: 'calc(2%)' -> '2%'
top: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
transform-origin: 'calc(2px) calc(2%)' -> '2px 2%'
transform-origin: 'calc(2px * var(--n)) calc(2% * var(--n))' -> '4px calc(2% * 2)'
transition-delay: 'calc(2s)' -> '2s'
transition-delay: 'calc(2s * var(--n))' -> '4s'
transition-duration: 'calc(2s)' -> 'calc(2s)'
transition-duration: 'calc(2s)' -> '2s'
transition-duration: 'calc(2s * var(--n))' -> '4s'
vertical-align: 'calc(2px)' -> 'calc(2px)'
vertical-align: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
width: 'calc(2%)' -> '15.6875px'
width: 'calc(2% * var(--n))' -> '31.35938px'
word-spacing: 'calc(2px)' -> 'calc(2px)'
word-spacing: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
x: 'calc(2px)' -> 'calc(2px)'
x: 'calc(2px * var(--n))' -> 'calc(2px * 2)'
y: 'calc(2%)' -> 'calc(2%)'
y: 'calc(2% * var(--n))' -> '4%'
z-index: 'calc(2)' -> 'calc(2)'
vertical-align: 'calc(2px)' -> '2px'
vertical-align: 'calc(2px * var(--n))' -> '4px'
width: 'calc(2%)' -> '15.67188px'
width: 'calc(2% * var(--n))' -> '31.375px'
word-spacing: 'calc(2px)' -> '2px'
word-spacing: 'calc(2px * var(--n))' -> '4px'
x: 'calc(2px)' -> '2px'
x: 'calc(2px * var(--n))' -> '4px'
y: 'calc(2%)' -> '2%'
y: 'calc(2% * var(--n))' -> 'calc(2% * 2)'
z-index: 'calc(2)' -> '2'
z-index: 'calc(2 * var(--n))' -> '4'

View file

@ -2,14 +2,14 @@ Harness status: OK
Found 18 tests
16 Pass
2 Fail
17 Pass
1 Fail
Pass Default column-gap is 'normal'
Pass column-gap accepts pixels
Pass column-gap accepts em
Pass column-gap accepts vw
Pass column-gap accepts percentage
Fail column-gap accepts calc()
Pass column-gap accepts calc()
Fail column-gap accepts calc() mixing fixed and percentage values
Pass Initial column-gap is 'normal'
Pass Initial column-gap is 'normal' 2

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 26 tests
21 Pass
5 Fail
23 Pass
3 Fail
Pass Default gap is 'normal'
Pass gap accepts pixels
Pass gap accepts pixels 2
@ -14,9 +14,9 @@ Pass gap accepts vw
Pass gap accepts vw and vh
Pass gap accepts percentage
Pass gap accepts percentage 2
Fail gap accepts calc()
Pass gap accepts calc()
Fail gap accepts calc() mixing fixed and percentage values
Fail gap accepts calc() 2
Pass gap accepts calc() 2
Pass Initial gap is 'normal'
Pass Initial gap is 'normal' 2
Pass Initial inherited gap is 'normal'

View file

@ -2,14 +2,14 @@ Harness status: OK
Found 18 tests
16 Pass
2 Fail
17 Pass
1 Fail
Pass Default grid-column-gap is 'normal'
Pass grid-column-gap accepts pixels
Pass grid-column-gap accepts em
Pass grid-column-gap accepts vw
Pass grid-column-gap accepts percentage
Fail grid-column-gap accepts calc()
Pass grid-column-gap accepts calc()
Fail grid-column-gap accepts calc() mixing fixed and percentage values
Pass Initial grid-column-gap is 'normal'
Pass Initial grid-column-gap is 'normal' 2

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 26 tests
21 Pass
5 Fail
23 Pass
3 Fail
Pass Default grid-gap is 'normal'
Pass grid-gap accepts pixels
Pass grid-gap accepts pixels 2
@ -14,9 +14,9 @@ Pass grid-gap accepts vw
Pass grid-gap accepts vw and vh
Pass grid-gap accepts percentage
Pass grid-gap accepts percentage 2
Fail grid-gap accepts calc()
Pass grid-gap accepts calc()
Fail grid-gap accepts calc() mixing fixed and percentage values
Fail grid-gap accepts calc() 2
Pass grid-gap accepts calc() 2
Pass Initial grid-gap is 'normal'
Pass Initial grid-gap is 'normal' 2
Pass Initial inherited grid-gap is 'normal'

View file

@ -2,14 +2,14 @@ Harness status: OK
Found 18 tests
16 Pass
2 Fail
17 Pass
1 Fail
Pass Default grid-row-gap is 'normal'
Pass grid-row-gap accepts pixels
Pass grid-row-gap accepts em
Pass grid-row-gap accepts vw
Pass grid-row-gap accepts percentage
Fail grid-row-gap accepts calc()
Pass grid-row-gap accepts calc()
Fail grid-row-gap accepts calc() mixing fixed and percentage values
Pass Initial grid-row-gap is 'normal'
Pass Initial grid-row-gap is 'normal' 2

View file

@ -2,14 +2,14 @@ Harness status: OK
Found 18 tests
16 Pass
2 Fail
17 Pass
1 Fail
Pass Default row-gap is 'normal'
Pass row-gap accepts pixels
Pass row-gap accepts em
Pass row-gap accepts vw
Pass row-gap accepts percentage
Fail row-gap accepts calc()
Pass row-gap accepts calc()
Fail row-gap accepts calc() mixing fixed and percentage values
Pass Initial row-gap is 'normal'
Pass Initial row-gap is 'normal' 2

View file

@ -26,7 +26,7 @@ Pass e.style['color'] = "color(srgb 200% 200% 200% / 200%)" should set the prope
Pass e.style['color'] = "color(srgb -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(srgb calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(srgb calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(srgb none none none / none)" should set the property value
Pass e.style['color'] = "color(srgb none none none)" should set the property value
Pass e.style['color'] = "color(srgb 10% none none / none)" should set the property value
@ -35,7 +35,7 @@ Pass e.style['color'] = "color(srgb 0 0 0 / none)" should set the property value
Pass e.style['color'] = "color(srgb 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(srgb 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(srgb calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(srgb calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(srgb calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(srgb calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(srgb 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(srgb-linear 0% 0% 0%)" should set the property value
@ -60,7 +60,7 @@ Pass e.style['color'] = "color(srgb-linear 200% 200% 200% / 200%)" should set th
Pass e.style['color'] = "color(srgb-linear -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(srgb-linear calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(srgb-linear calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(srgb-linear none none none / none)" should set the property value
Pass e.style['color'] = "color(srgb-linear none none none)" should set the property value
Pass e.style['color'] = "color(srgb-linear 10% none none / none)" should set the property value
@ -69,7 +69,7 @@ Pass e.style['color'] = "color(srgb-linear 0 0 0 / none)" should set the propert
Pass e.style['color'] = "color(srgb-linear 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(srgb-linear 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(srgb-linear calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(srgb-linear calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(srgb-linear calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(srgb-linear calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(srgb-linear 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(a98-rgb 0% 0% 0%)" should set the property value
@ -94,7 +94,7 @@ Pass e.style['color'] = "color(a98-rgb 200% 200% 200% / 200%)" should set the pr
Pass e.style['color'] = "color(a98-rgb -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(a98-rgb calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(a98-rgb calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(a98-rgb none none none / none)" should set the property value
Pass e.style['color'] = "color(a98-rgb none none none)" should set the property value
Pass e.style['color'] = "color(a98-rgb 10% none none / none)" should set the property value
@ -103,7 +103,7 @@ Pass e.style['color'] = "color(a98-rgb 0 0 0 / none)" should set the property va
Pass e.style['color'] = "color(a98-rgb 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(a98-rgb 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(a98-rgb calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(a98-rgb calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(a98-rgb calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(a98-rgb calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(a98-rgb 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(rec2020 0% 0% 0%)" should set the property value
@ -128,7 +128,7 @@ Pass e.style['color'] = "color(rec2020 200% 200% 200% / 200%)" should set the pr
Pass e.style['color'] = "color(rec2020 -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(rec2020 calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(rec2020 calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(rec2020 none none none / none)" should set the property value
Pass e.style['color'] = "color(rec2020 none none none)" should set the property value
Pass e.style['color'] = "color(rec2020 10% none none / none)" should set the property value
@ -137,7 +137,7 @@ Pass e.style['color'] = "color(rec2020 0 0 0 / none)" should set the property va
Pass e.style['color'] = "color(rec2020 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(rec2020 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(rec2020 calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(rec2020 calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(rec2020 calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(rec2020 calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(rec2020 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(prophoto-rgb 0% 0% 0%)" should set the property value
@ -162,7 +162,7 @@ Pass e.style['color'] = "color(prophoto-rgb 200% 200% 200% / 200%)" should set t
Pass e.style['color'] = "color(prophoto-rgb -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(prophoto-rgb calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(prophoto-rgb calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(prophoto-rgb none none none / none)" should set the property value
Pass e.style['color'] = "color(prophoto-rgb none none none)" should set the property value
Pass e.style['color'] = "color(prophoto-rgb 10% none none / none)" should set the property value
@ -171,7 +171,7 @@ Pass e.style['color'] = "color(prophoto-rgb 0 0 0 / none)" should set the proper
Pass e.style['color'] = "color(prophoto-rgb 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(prophoto-rgb 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(prophoto-rgb calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(prophoto-rgb calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(prophoto-rgb calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(prophoto-rgb calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(prophoto-rgb 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(display-p3 0% 0% 0%)" should set the property value
@ -196,7 +196,7 @@ Pass e.style['color'] = "color(display-p3 200% 200% 200% / 200%)" should set the
Pass e.style['color'] = "color(display-p3 -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(display-p3 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(display-p3 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(display-p3 calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(display-p3 calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(display-p3 none none none / none)" should set the property value
Pass e.style['color'] = "color(display-p3 none none none)" should set the property value
Pass e.style['color'] = "color(display-p3 10% none none / none)" should set the property value
@ -205,7 +205,7 @@ Pass e.style['color'] = "color(display-p3 0 0 0 / none)" should set the property
Pass e.style['color'] = "color(display-p3 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(display-p3 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(display-p3 calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(display-p3 calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(display-p3 calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(display-p3 calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(display-p3 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(xyz 0% 0% 0%)" should set the property value
@ -230,7 +230,7 @@ Pass e.style['color'] = "color(xyz 200% 200% 200% / 200%)" should set the proper
Pass e.style['color'] = "color(xyz -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(xyz calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(xyz calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(xyz calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(xyz none none none / none)" should set the property value
Pass e.style['color'] = "color(xyz none none none)" should set the property value
Pass e.style['color'] = "color(xyz 10% none none / none)" should set the property value
@ -239,7 +239,7 @@ Pass e.style['color'] = "color(xyz 0 0 0 / none)" should set the property value
Pass e.style['color'] = "color(xyz 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(xyz 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(xyz calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(xyz calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(xyz calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(xyz calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(xyz 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(xyz-d50 0% 0% 0%)" should set the property value
@ -264,7 +264,7 @@ Pass e.style['color'] = "color(xyz-d50 200% 200% 200% / 200%)" should set the pr
Pass e.style['color'] = "color(xyz-d50 -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(xyz-d50 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(xyz-d50 calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(xyz-d50 calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(xyz-d50 none none none / none)" should set the property value
Pass e.style['color'] = "color(xyz-d50 none none none)" should set the property value
Pass e.style['color'] = "color(xyz-d50 10% none none / none)" should set the property value
@ -273,7 +273,7 @@ Pass e.style['color'] = "color(xyz-d50 0 0 0 / none)" should set the property va
Pass e.style['color'] = "color(xyz-d50 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(xyz-d50 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(xyz-d50 calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(xyz-d50 calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(xyz-d50 calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(xyz-d50 calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(xyz-d50 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value
Pass e.style['color'] = "color(xyz-d65 0% 0% 0%)" should set the property value
@ -298,7 +298,7 @@ Pass e.style['color'] = "color(xyz-d65 200% 200% 200% / 200%)" should set the pr
Pass e.style['color'] = "color(xyz-d65 -200% -200% -200% / -200%)" should set the property value
Fail e.style['color'] = "color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value
Fail e.style['color'] = "color(xyz-d65 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value
Pass e.style['color'] = "color(xyz-d65 calc(50%) 50% 0.5)" should set the property value
Fail e.style['color'] = "color(xyz-d65 calc(50%) 50% 0.5)" should set the property value
Pass e.style['color'] = "color(xyz-d65 none none none / none)" should set the property value
Pass e.style['color'] = "color(xyz-d65 none none none)" should set the property value
Pass e.style['color'] = "color(xyz-d65 10% none none / none)" should set the property value
@ -307,6 +307,6 @@ Pass e.style['color'] = "color(xyz-d65 0 0 0 / none)" should set the property va
Pass e.style['color'] = "color(xyz-d65 0 calc(infinity) 0)" should set the property value
Pass e.style['color'] = "color(xyz-d65 0 calc(-infinity) 0)" should set the property value
Pass e.style['color'] = "color(xyz-d65 calc(NaN) 0 0)" should set the property value
Fail e.style['color'] = "color(xyz-d65 calc(0 / 0) 0 0)" should set the property value
Pass e.style['color'] = "color(xyz-d65 calc(0 / 0) 0 0)" should set the property value
Fail e.style['color'] = "color(xyz-d65 calc(50% + (sign(1em - 10px) * 10%)) 0 0 / 0.5)" should set the property value
Fail e.style['color'] = "color(xyz-d65 0.5 0 0 / calc(50% + (sign(1em - 10px) * 10%)))" should set the property value

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 12 tests
8 Pass
4 Fail
9 Pass
3 Fail
Pass Property flex-basis value '1px'
Pass Property flex-basis value '400%'
Pass Property flex-basis value 'auto'
@ -13,6 +13,6 @@ Pass Property flex-basis value 'min-content'
Pass Property flex-basis value 'max-content'
Fail Property flex-basis value 'calc(10px + 0.5em)'
Fail Property flex-basis value 'calc(10px - 0.5em)'
Fail Property flex-basis value 'calc(10%)'
Pass Property flex-basis value 'calc(10%)'
Pass Property flex-basis value 'calc(0% + 10px)'
Fail Property flex-basis value 'calc(10% + 0px)'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 40 tests
23 Pass
17 Fail
22 Pass
18 Fail
Pass Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithFixedElement' : grid-template-columns = '7px 11px', grid-template-rows = '17px 2px'
Pass Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithPercentElement' : grid-template-columns = '400px 800px', grid-template-rows = '150px 450px'
Fail Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithPercentWithoutSize' : grid-template-columns = '3.5px 7px', grid-template-rows = '4px 12px'
@ -28,7 +28,7 @@ Pass Test getting and setting grid-template-rows and grid-template-columns throu
Pass Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '0px 160px 22px', element.style.gridTemplateColumns = 'auto 16em 22px', grid-template-rows = '336px 100px 0px', element.style.gridTemplateRows = '56% 10em auto'
Pass Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '160px 20px', element.style.gridTemplateColumns = '16em minmax(16px, 20px)', grid-template-rows = '90px 0px', element.style.gridTemplateRows = 'minmax(10%, 15%) auto'
Pass Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '160px 640px', element.style.gridTemplateColumns = '16em 2fr', grid-template-rows = '600px 0px', element.style.gridTemplateRows = '14fr auto'
Pass Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '25px 20px', element.style.gridTemplateColumns = 'calc(25px) calc(2em)', grid-template-rows = '0px 60px', element.style.gridTemplateRows = 'auto calc(10%)'
Fail Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '25px 20px', element.style.gridTemplateColumns = 'calc(25px) calc(2em)', grid-template-rows = '0px 60px', element.style.gridTemplateRows = 'auto calc(10%)'
Fail Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '345px 92px', element.style.gridTemplateColumns = 'calc(25px + 40%) minmax(min-content, calc(10% + 12px))', grid-template-rows = '100px 0px', element.style.gridTemplateRows = 'minmax(calc(75% - 350px), max-content) auto'
Fail Test setting wrong/invalid values through CSS
Fail Test setting bad JS values: grid-template-columns = 'none auto', grid-template-rows = 'none auto'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 126 tests
122 Pass
4 Fail
124 Pass
2 Fail
Pass new DOMMatrix()
Pass new DOMMatrix(undefined)
Pass new DOMMatrix(new DOMMatrix())
@ -23,7 +23,7 @@ Pass new DOMMatrix(sequence) 6 elements
Pass new DOMMatrix("scale(2) translateX(5px) translateY(5px)")
Pass new DOMMatrix("scale(2, 2) translateX(5px) translateY(5px)")
Pass new DOMMatrix("scale(2)translateX(5px)translateY(5px)")
Fail new DOMMatrix("scale(2) translateX(calc(2 * 2.5px)) translateY(5px)")
Pass new DOMMatrix("scale(2) translateX(calc(2 * 2.5px)) translateY(5px)")
Pass new DOMMatrix("scale(2) translateX(5px) translateY(5px) rotate(5deg) rotate(-5deg)")
Pass new DOMMatrix("translateX (5px)")
Pass new DOMMatrix("scale(2 2) translateX(5) translateY(5)")
@ -86,7 +86,7 @@ Pass new DOMMatrixReadOnly(sequence) 6 elements
Pass new DOMMatrixReadOnly("scale(2) translateX(5px) translateY(5px)")
Pass new DOMMatrixReadOnly("scale(2, 2) translateX(5px) translateY(5px)")
Pass new DOMMatrixReadOnly("scale(2)translateX(5px)translateY(5px)")
Fail new DOMMatrixReadOnly("scale(2) translateX(calc(2 * 2.5px)) translateY(5px)")
Pass new DOMMatrixReadOnly("scale(2) translateX(calc(2 * 2.5px)) translateY(5px)")
Pass new DOMMatrixReadOnly("scale(2) translateX(5px) translateY(5px) rotate(5deg) rotate(-5deg)")
Pass new DOMMatrixReadOnly("translateX (5px)")
Pass new DOMMatrixReadOnly("scale(2 2) translateX(5) translateY(5)")