diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 6646028a537..0293ce17406 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -265,6 +265,7 @@ set(SOURCES CSS/StyleValues/PositionStyleValue.cpp CSS/StyleValues/RGBColorStyleValue.cpp CSS/StyleValues/RadialGradientStyleValue.cpp + CSS/StyleValues/RandomValueSharingStyleValue.cpp CSS/StyleValues/RectStyleValue.cpp CSS/StyleValues/RepeatStyleStyleValue.cpp CSS/StyleValues/ScrollbarColorStyleValue.cpp diff --git a/Libraries/LibWeb/CSS/MathFunctions.json b/Libraries/LibWeb/CSS/MathFunctions.json index ec5cd633e5a..e1492e5c866 100644 --- a/Libraries/LibWeb/CSS/MathFunctions.json +++ b/Libraries/LibWeb/CSS/MathFunctions.json @@ -168,6 +168,28 @@ } ] }, + "random": { + "parameter-validation": "consistent", + "parameters": [ + { + "name": "random-value-sharing", + "type": "", + "required": false, + "default": "auto", + "__comment": "NOTE: The actual default is hardcoded and we don't respect the value above, we have it there so we know that this argument has a default" + }, + { + "name": "minimum", + "type": "||", + "required": true + }, + { + "name": "maximum", + "type": "||", + "required": true + } + ] + }, "rem": { "parameter-validation": "same", "parameters": [ diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index 64474ad6410..d9e0832f290 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1718,6 +1718,12 @@ bool Parser::context_allows_tree_counting_functions() const return true; } +bool Parser::context_allows_random_functions() const +{ + // For now we only allow random functions within property contexts, see https://drafts.csswg.org/css-values-5/#issue-cd071f29 + return m_value_context.find_first_index_if([](ValueParsingContext context) { return context.has(); }).has_value(); +} + Vector Parser::parse_as_list_of_component_values() { return parse_a_list_of_component_values(m_token_stream); diff --git a/Libraries/LibWeb/CSS/Parser/Parser.h b/Libraries/LibWeb/CSS/Parser/Parser.h index f4273e00c5e..8a5584a9c56 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Libraries/LibWeb/CSS/Parser/Parser.h @@ -77,6 +77,7 @@ enum SpecialContext : u8 { CubicBezierFunctionXCoordinate, DOMMatrixInitString, MediaCondition, + RandomValueSharingFixedValue, ShadowBlurRadius, StepsIntervalsJumpNone, StepsIntervalsNormal, @@ -379,6 +380,7 @@ private: RefPtr parse_custom_ident_value(TokenStream&, ReadonlySpan blacklist); Optional parse_dashed_ident(TokenStream&); RefPtr parse_dashed_ident_value(TokenStream&); + RefPtr parse_random_value_sharing(TokenStream&); // NOTE: Implemented in generated code. (GenerateCSSMathFunctions.cpp) RefPtr parse_math_function(Function const&, CalculationContext const&); RefPtr parse_a_calc_function_node(Function const&, CalculationContext const&); @@ -593,6 +595,7 @@ private: } bool context_allows_quirky_length() const; bool context_allows_tree_counting_functions() const; + bool context_allows_random_functions() const; Vector m_rule_context; HashTable m_declared_namespaces; diff --git a/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp b/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp index d7139b5313d..7faf54fbe7e 100644 --- a/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -3789,6 +3790,40 @@ RefPtr Parser::parse_custom_ident_value(TokenStream return nullptr; } +// https://drafts.csswg.org/css-values-5/#typedef-random-value-sharing +RefPtr Parser::parse_random_value_sharing(TokenStream& tokens) +{ + // = [ [ auto | ] || element-shared ] | fixed + auto transaction = tokens.begin_transaction(); + + tokens.discard_whitespace(); + + // fixed + if (tokens.next_token().is_ident("fixed"sv)) { + tokens.discard_a_token(); + tokens.discard_whitespace(); + + auto context_guard = push_temporary_value_parsing_context(SpecialContext::RandomValueSharingFixedValue); + if (auto fixed_value = parse_number_value(tokens)) { + tokens.discard_whitespace(); + + if (tokens.has_next_token()) + return nullptr; + + if (fixed_value->is_number() && (fixed_value->as_number().number() < 0 || fixed_value->as_number().number() >= 1)) + return nullptr; + + transaction.commit(); + return RandomValueSharingStyleValue::create_fixed(fixed_value.release_nonnull()); + } + + return nullptr; + } + + // FIXME: Support non-fixed values + return nullptr; +} + // https://drafts.csswg.org/css-values-4/#typedef-dashed-ident Optional Parser::parse_dashed_ident(TokenStream& tokens) { @@ -4384,6 +4419,9 @@ RefPtr Parser::parse_calculated_value(ComponentValue case SpecialContext::CubicBezierFunctionXCoordinate: // Coordinates on the X axis must be between 0 and 1 return CalculationContext { .accepted_type_ranges = { { ValueType::Number, { 0, 1 } } } }; + case SpecialContext::RandomValueSharingFixedValue: + // Fixed values have to be less than one and numbers serialize with six digits of precision + return CalculationContext { .accepted_type_ranges = { { ValueType::Number, { 0, 0.999999 } } } }; case SpecialContext::StepsIntervalsJumpNone: return CalculationContext { .resolve_numbers_as_integers = true, .accepted_type_ranges = { { ValueType::Integer, { 2, NumericLimits::max() } } } }; case SpecialContext::StepsIntervalsNormal: diff --git a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp index ac52c4bfd80..80b2ef9d17d 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -284,6 +285,11 @@ static String serialize_a_math_function(CalculationNode const& fn, CalculationCo } } + // AD-HOC: We serialize random() directly since it has abnormal children (e.g. m_random_value_sharing which is not a + // calculation node). + if (fn.type() == CalculationNode::Type::Random) + return as(fn).to_string(context, serialization_mode); + // 3. If the calculation tree’s root node is a numeric value, or a calc-operator node, let s be a string initially // containing "calc(". // Otherwise, let s be a string initially containing the name of the root node, lowercased (such as "sin" or @@ -572,6 +578,8 @@ StringView CalculationNode::name() const return "log"sv; case Type::Exp: return "exp"sv; + case Type::Random: + return "random"sv; case Type::Round: return "round"sv; case Type::Mod: @@ -2434,6 +2442,134 @@ bool ModCalculationNode::equals(CalculationNode const& other) const && m_y->equals(*static_cast(other).m_y); } +NonnullRefPtr RandomCalculationNode::create(NonnullRefPtr random_value_sharing, NonnullRefPtr minimum, NonnullRefPtr maximum) +{ + Optional numeric_type = add_the_types(*minimum, *maximum); + + return adopt_ref(*new (nothrow) RandomCalculationNode(move(random_value_sharing), move(minimum), move(maximum), move(numeric_type))); +} + +RandomCalculationNode::RandomCalculationNode(NonnullRefPtr random_value_sharing, NonnullRefPtr minimum, NonnullRefPtr maximum, Optional numeric_type) + : CalculationNode(Type::Random, move(numeric_type)) + , m_random_value_sharing(move(random_value_sharing)) + , m_minimum(move(minimum)) + , m_maximum(move(maximum)) +{ +} + +RandomCalculationNode::~RandomCalculationNode() = default; + +bool RandomCalculationNode::contains_percentage() const +{ + return m_minimum->contains_percentage() || m_maximum->contains_percentage(); +} + +NonnullRefPtr RandomCalculationNode::with_simplified_children(CalculationContext const& context, CalculationResolutionContext const& resolution_context) const +{ + ValueComparingRefPtr simplified_random_value_sharing; + + // When we are in the absolutization process we should absolutize m_random_value_sharing + if (resolution_context.length_resolution_context.has_value()) { + ComputationContext computation_context { + .length_resolution_context = resolution_context.length_resolution_context.value(), + .abstract_element = resolution_context.abstract_element + }; + + simplified_random_value_sharing = m_random_value_sharing->absolutized(computation_context)->as_random_value_sharing(); + } else { + simplified_random_value_sharing = m_random_value_sharing; + } + + ValueComparingNonnullRefPtr simplified_minimum = simplify_a_calculation_tree(m_minimum, context, resolution_context); + ValueComparingNonnullRefPtr simplified_maximum = simplify_a_calculation_tree(m_maximum, context, resolution_context); + + if (simplified_random_value_sharing == m_random_value_sharing && simplified_minimum == m_minimum && simplified_maximum == m_maximum) + return *this; + + return RandomCalculationNode::create(simplified_random_value_sharing.release_nonnull(), move(simplified_minimum), move(simplified_maximum)); +} + +// https://drafts.csswg.org/css-values-5/#random-evaluation +Optional RandomCalculationNode::run_operation_if_possible(CalculationContext const& context, CalculationResolutionContext const& resolution_context) const +{ + // NB: We don't want to resolve this before computation time even if it's possible + if (!resolution_context.abstract_element.has_value() && !resolution_context.length_resolution_context.has_value() && resolution_context.percentage_basis.has()) + return {}; + + auto random_base_value = m_random_value_sharing->random_base_value(); + + auto minimum = try_get_value_with_canonical_unit(m_minimum, context, resolution_context); + auto maximum = try_get_value_with_canonical_unit(m_maximum, context, resolution_context); + + if (!minimum.has_value() || !maximum.has_value()) + return {}; + + auto minimum_value = minimum->value(); + auto maximum_value = maximum->value(); + + // https://drafts.csswg.org/css-values-5/#random-infinities + // If the maximum value is less than the minimum value, it behaves as if it’s equal to the minimum value. + if (maximum_value < minimum_value) + maximum_value = minimum_value; + + // https://drafts.csswg.org/css-values-5/#random-infinities + // In random(A, B), if A is infinite, the result is infinite. + if (isinf(minimum_value)) + return CalculatedStyleValue::CalculationResult { AK::Infinity, numeric_type() }; + + // If A is finite, but the difference between A and B is either infinite or large enough to be treated as infinite + // in the user agent, the result is NaN. + if (isinf(maximum_value)) + return CalculatedStyleValue::CalculationResult { AK::NaN, numeric_type() }; + + // Note: As usual for math functions, if any argument calculation is NaN, the result is NaN. + if (isnan(minimum_value) || isnan(maximum_value)) + return CalculatedStyleValue::CalculationResult { AK::NaN, numeric_type() }; + + // Given a random function with a random base value R, the value of the function is: + // - for a random() function with min and max, but no step + // Return min + R * (max - min) + return CalculatedStyleValue::CalculationResult { + minimum_value + (random_base_value * (maximum_value - minimum_value)), + numeric_type() + }; +} + +String RandomCalculationNode::to_string(CalculationContext const& context, SerializationMode serialization_mode) const +{ + StringBuilder builder; + + builder.append("random("sv); + builder.appendff("{}, ", m_random_value_sharing->to_string(serialization_mode)); + builder.appendff("{}, ", serialize_a_calculation_tree(m_minimum, context, serialization_mode)); + builder.appendff("{})", serialize_a_calculation_tree(m_maximum, context, serialization_mode)); + + return builder.to_string_without_validation(); +} + +void RandomCalculationNode::dump(StringBuilder& builder, int indent) const +{ + builder.appendff("{: >{}}RANDOM:\n", "", indent); + builder.appendff("{}\n", m_random_value_sharing->to_string(SerializationMode::Normal)); + m_minimum->dump(builder, indent + 2); + m_maximum->dump(builder, indent + 2); +} + +bool RandomCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + + if (type() != other.type()) + return false; + + auto const& other_random = as(other); + + return m_random_value_sharing == other_random.m_random_value_sharing + && m_minimum == other_random.m_minimum + && m_maximum == other_random.m_maximum; +} + NonnullRefPtr RemCalculationNode::create(NonnullRefPtr x, NonnullRefPtr y) { // https://www.w3.org/TR/css-values-4/#determine-the-type-of-a-calculation diff --git a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h index 0a6b2f9f211..02927e37346 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h @@ -190,6 +190,10 @@ public: Mod, Rem, + // Random value generation + // https://drafts.csswg.org/css-values-5/#random + Random, + // Non-math functions NonMathFunction }; @@ -228,6 +232,7 @@ public: case Type::Round: case Type::Mod: case Type::Rem: + case Type::Random: return true; default: @@ -747,6 +752,30 @@ private: NonnullRefPtr m_y; }; +class RandomCalculationNode final : public CalculationNode { +public: + static NonnullRefPtr create(NonnullRefPtr, NonnullRefPtr minimum, NonnullRefPtr maximum); + ~RandomCalculationNode(); + + virtual bool contains_percentage() const override; + virtual NonnullRefPtr with_simplified_children(CalculationContext const&, CalculationResolutionContext const&) const override; + virtual Optional run_operation_if_possible(CalculationContext const&, CalculationResolutionContext const&) const override; + + // NOTE: We don't return children here as serialization is handled ad-hoc + virtual Vector> children() const override { return {}; } + + String to_string(CalculationContext const&, SerializationMode serialization_mode) const; + + virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; + +private: + RandomCalculationNode(NonnullRefPtr, NonnullRefPtr, NonnullRefPtr, Optional); + ValueComparingNonnullRefPtr m_random_value_sharing; + ValueComparingNonnullRefPtr m_minimum; + ValueComparingNonnullRefPtr m_maximum; +}; + class RemCalculationNode final : public CalculationNode { public: static NonnullRefPtr create(NonnullRefPtr, NonnullRefPtr); diff --git a/Libraries/LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.cpp new file mode 100644 index 00000000000..78be21267a1 --- /dev/null +++ b/Libraries/LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025, Callum Law + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "RandomValueSharingStyleValue.h" +#include +#include + +namespace Web::CSS { + +ValueComparingNonnullRefPtr RandomValueSharingStyleValue::absolutized(ComputationContext const& computation_context) const +{ + if (m_fixed_value) { + auto const& absolutized_fixed_value = m_fixed_value->absolutized(computation_context); + + if (m_fixed_value == absolutized_fixed_value) + return *this; + + return RandomValueSharingStyleValue::create_fixed(absolutized_fixed_value); + } + + TODO(); +} + +double RandomValueSharingStyleValue::random_base_value() const +{ + VERIFY(m_fixed_value); + VERIFY(m_fixed_value->is_number() || (m_fixed_value->is_calculated() && m_fixed_value->as_calculated().resolves_to_number())); + + if (m_fixed_value->is_number()) + return m_fixed_value->as_number().number(); + + if (m_fixed_value->is_calculated()) + return m_fixed_value->as_calculated().resolve_number({}).value(); + + VERIFY_NOT_REACHED(); +} + +String RandomValueSharingStyleValue::to_string(SerializationMode serialization_mode) const +{ + if (m_fixed_value) + return MUST(String::formatted("fixed {}", m_fixed_value->to_string(serialization_mode))); + + TODO(); +} + +} diff --git a/Libraries/LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h new file mode 100644 index 00000000000..2096c1525c4 --- /dev/null +++ b/Libraries/LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025, Callum Law + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::CSS { + +class RandomValueSharingStyleValue : public StyleValueWithDefaultOperators { +public: + static ValueComparingNonnullRefPtr create_fixed(NonnullRefPtr const& fixed_value) + { + return adopt_ref(*new (nothrow) RandomValueSharingStyleValue(fixed_value)); + } + + virtual ~RandomValueSharingStyleValue() override = default; + + virtual ValueComparingNonnullRefPtr absolutized(ComputationContext const&) const override; + + double random_base_value() const; + + virtual String to_string(SerializationMode serialization_mode) const override; + + bool properties_equal(RandomValueSharingStyleValue const& other) const + { + return m_fixed_value == other.m_fixed_value; + } + +private: + explicit RandomValueSharingStyleValue(RefPtr fixed_value) + : StyleValueWithDefaultOperators(Type::RandomValueSharing) + , m_fixed_value(move(fixed_value)) + { + } + + ValueComparingRefPtr m_fixed_value; +}; + +} diff --git a/Libraries/LibWeb/CSS/StyleValues/StyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/StyleValue.cpp index b50815e226d..542e2a77b6a 100644 --- a/Libraries/LibWeb/CSS/StyleValues/StyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/StyleValue.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include diff --git a/Libraries/LibWeb/CSS/StyleValues/StyleValue.h b/Libraries/LibWeb/CSS/StyleValues/StyleValue.h index e075e4e1de8..eb15d70014e 100644 --- a/Libraries/LibWeb/CSS/StyleValues/StyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/StyleValue.h @@ -73,6 +73,7 @@ namespace Web::CSS { __ENUMERATE_CSS_STYLE_VALUE_TYPE(Percentage, percentage, PercentageStyleValue) \ __ENUMERATE_CSS_STYLE_VALUE_TYPE(Position, position, PositionStyleValue) \ __ENUMERATE_CSS_STYLE_VALUE_TYPE(RadialGradient, radial_gradient, RadialGradientStyleValue) \ + __ENUMERATE_CSS_STYLE_VALUE_TYPE(RandomValueSharing, random_value_sharing, RandomValueSharingStyleValue) \ __ENUMERATE_CSS_STYLE_VALUE_TYPE(Ratio, ratio, RatioStyleValue) \ __ENUMERATE_CSS_STYLE_VALUE_TYPE(Rect, rect, RectStyleValue) \ __ENUMERATE_CSS_STYLE_VALUE_TYPE(RepeatStyle, repeat_style, RepeatStyleStyleValue) \ diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index f9327899680..fdf6f998c11 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -350,6 +350,7 @@ class PercentageStyleValue; class PositionStyleValue; class PropertyNameAndID; class RadialGradientStyleValue; +class RandomValueSharingStyleValue; class Ratio; class RatioStyleValue; class RectStyleValue; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMathFunctions.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMathFunctions.cpp index 073a67620d3..150b666e2af 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMathFunctions.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSMathFunctions.cpp @@ -98,6 +98,8 @@ ErrorOr generate_implementation_file(JsonObject& functions_data, Core::Fil #include #include #include +#include +#include namespace Web::CSS { @@ -260,6 +262,13 @@ RefPtr Parser::parse_math_function(Function const& functi function_generator.set("min_argument_count", String::number(min_argument_count)); function_generator.set("max_argument_count", String::number(max_argument_count)); + if (name == "random") { + function_generator.append(R"~~~( + if (!context_allows_random_functions()) + return nullptr; +)~~~"); + } + function_generator.append(R"~~~( if (arguments.size() < @min_argument_count@ || arguments.size() > @max_argument_count@) { ErrorReporter::the().report(InvalidValueError { @@ -295,6 +304,14 @@ RefPtr Parser::parse_math_function(Function const& functi } else { parameter_generator.set("parameter_default", ""_string); } + } else if (parameter_type_string == "") { + parameter_is_calculation = false; + parameter_generator.set("parameter_type", "RefPtr"_string); + parameter_generator.set("parse_function", MUST(String::formatted("parse_random_value_sharing(tokens_{})", parameter_index))); + parameter_generator.set("check_function", " != nullptr"_string); + parameter_generator.set("release_function", ".release_nonnull()"_string); + // FIXME: This should be 'auto' rather than 'fixed 0' by default + parameter_generator.set("parameter_default", MUST(String::formatted(" = RandomValueSharingStyleValue::create_fixed(NumberStyleValue::create(0))"))); } else { // NOTE: This assumes everything not handled above is a calculation node of some kind. parameter_is_calculation = true; diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-computed.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-computed.tentative.txt index 4c6383416b7..2326681733a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-computed.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-computed.tentative.txt @@ -2,9 +2,9 @@ Harness status: OK Found 72 tests -4 Pass -68 Fail -Fail Property scale value 'random(1, 11)' +27 Pass +45 Fail +Pass Property scale value 'random(1, 11)' Fail Property scale value 'random(--foo, 2, 12)' Fail Property scale value 'random(--foo element-shared, 3, 13)' Fail Property scale value 'random(element-shared --foo, 4, 14)' @@ -12,15 +12,15 @@ Fail Property scale value 'random(0, 10, 5)' Fail Property scale value 'random(--foo, 10, 20, 5)' Fail Property scale value 'random(--foo element-shared, 20, 30, 5)' Fail Property scale value 'random(element-shared --foo, 30, 40, 5)' -Fail Property scale value 'random(100, 10)' -Fail Property scale value 'random(-10, -100)' -Fail Property scale value 'random(-100, -10)' +Pass Property scale value 'random(100, 10)' +Pass Property scale value 'random(-10, -100)' +Pass Property scale value 'random(-100, -10)' Fail Property scale value 'random(40, 50, -5)' -Fail Property scale value 'random(5 * 1, 30 / 2)' -Fail Property scale value 'calc(2 * random(6, 16))' -Fail Property scale value 'random(NaN, 100)' -Fail Property scale value 'random(10, NaN)' -Fail Property scale value 'random(NaN, NaN)' +Pass Property scale value 'random(5 * 1, 30 / 2)' +Pass Property scale value 'calc(2 * random(6, 16))' +Pass Property scale value 'random(NaN, 100)' +Pass Property scale value 'random(10, NaN)' +Pass Property scale value 'random(NaN, NaN)' Fail Property scale value 'random(NaN, 100, 10)' Fail Property scale value 'random(10, NaN, 10)' Fail Property scale value 'random(NaN, NaN, 10)' @@ -28,9 +28,9 @@ Fail Property scale value 'random(NaN, 100, NaN)' Fail Property scale value 'random(10, NaN, NaN)' Fail Property scale value 'random(NaN, NaN, NaN)' Fail Property scale value 'random(10, 100, NaN)' -Fail Property scale value 'calc(10 + random(NaN, 100))' -Fail Property scale value 'calc(10 + random(10, NaN))' -Fail Property scale value 'calc(10 + random(NaN, NaN))' +Pass Property scale value 'calc(10 + random(NaN, 100))' +Pass Property scale value 'calc(10 + random(10, NaN))' +Pass Property scale value 'calc(10 + random(NaN, NaN))' Fail Property scale value 'calc(10 + random(NaN, 100, 10))' Fail Property scale value 'calc(10 + random(10, NaN, 10))' Fail Property scale value 'calc(10 + random(NaN, NaN, 10))' @@ -38,35 +38,35 @@ Fail Property scale value 'calc(10 + random(NaN, 100, NaN))' Fail Property scale value 'calc(10 + random(10, NaN, NaN))' Fail Property scale value 'calc(10 + random(NaN, NaN, NaN))' Fail Property scale value 'calc(10 + random(10, 100, NaN))' -Fail Property scale value 'random(infinity, 100)' -Fail Property scale value 'random(infinity, infinity)' +Pass Property scale value 'random(infinity, 100)' +Pass Property scale value 'random(infinity, infinity)' Fail Property scale value 'random(infinity, 100, 10)' Fail Property scale value 'random(infinity, infinity, 10)' Fail Property scale value 'random(infinity, 100, infinity)' Fail Property scale value 'random(infinity, infinity, infinity)' -Fail Property scale value 'calc(10 + random(infinity, 100))' -Fail Property scale value 'calc(10 + random(infinity, infinity))' +Pass Property scale value 'calc(10 + random(infinity, 100))' +Pass Property scale value 'calc(10 + random(infinity, infinity))' Fail Property scale value 'calc(10 + random(infinity, infinity, 10))' Fail Property scale value 'calc(10 + random(infinity, 100, infinity))' Fail Property scale value 'calc(10 + random(infinity, infinity, infinity))' Fail Property scale value 'calc(10 + random(infinity, 100, 10))' -Fail Property scale value 'random(10, infinity)' +Pass Property scale value 'random(10, infinity)' Fail Property scale value 'random(10, infinity, 10)' Fail Property scale value 'random(10, infinity, infinity)' -Fail Property scale value 'calc(10 + random(10, infinity))' +Pass Property scale value 'calc(10 + random(10, infinity))' Fail Property scale value 'calc(10 + random(10, infinity, 10))' Fail Property scale value 'calc(10 + random(10, infinity, infinity))' Fail Property scale value 'random(10, 100, infinity)' Fail Property scale value 'calc(10 + random(10, 100, infinity))' Fail Property scale value 'random(10, 100, -infinity)' Fail Property scale value 'calc(10 + random(10, 100, -infinity))' -Fail Property scale value on pseudo element '::before' 'random(7, 17)' +Pass Property scale value on pseudo element '::before' 'random(7, 17)' Fail Property scale value on pseudo element '::before' 'random(--bar, 8, 18)' Fail Property scale value on pseudo element '::before' 'random(element-shared, 9, 19)' Fail Property scale value on pseudo element '::before' 'random(element-shared --foo, 10, 20)' -Fail Property translate value 'random(10%, 100%)' -Fail Property translate value 'random(fixed random(1, 2), 10%, 100%)' -Fail Property translate value 'random(fixed random(-2, -1), 10%, 100%)' +Pass Property translate value 'random(10%, 100%)' +Pass Property translate value 'random(fixed random(1, 2), 10%, 100%)' +Pass Property translate value 'random(fixed random(-2, -1), 10%, 100%)' Fail Maximum random: 'random(a, b)' Fail Maximum random - shorthand: random(a, b)) Fail Shared by name within an element: 'random(--identifier, a, b)' @@ -75,4 +75,4 @@ Pass Shared between elements within a property: random(element-shared, a, b) Pass Shared between elements within a property - shorthand: random(element-shared, a, b)) Fail Shared globally: random(--identifier element-shared, a, b) Pass Shared globally - shorthand: random(element-shared, a, b)) -Fail Fixed: random(fixed , a, b) \ No newline at end of file +Pass Fixed: random(fixed , a, b) \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-in-keyframe.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-in-keyframe.txt index dbb2c5a3ef3..d30a6678ace 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-in-keyframe.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-in-keyframe.txt @@ -2,5 +2,5 @@ Harness status: OK Found 1 tests -1 Fail -Fail random() is not ignored in keyframe \ No newline at end of file +1 Pass +Pass random() is not ignored in keyframe \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-invalid.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-invalid.tentative.txt index 2e8f88a32ff..449ca95203f 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-invalid.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-invalid.tentative.txt @@ -25,4 +25,4 @@ Pass e.style['width'] = "random(fixed 0.5 --foo, 1px, 2px)" should not set the p Pass e.style['width'] = "random(fixed 0.5px, 1px, 2px)" should not set the property value Pass e.style['width'] = "random(fixed 0.5%, 1px, 2px)" should not set the property value Pass e.style['width'] = "random(fixed -1, 1px, 2px)" should not set the property value -Pass e.style['width'] = "random(10deg, 20deg)" should not set the property value \ No newline at end of file +Pass e.style['width'] = "random(10deg, 20deg)" should not set the property value diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-serialize.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-serialize.tentative.txt index bcb5d48a301..b5aaa9e0efb 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-serialize.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/random-serialize.tentative.txt @@ -2,7 +2,8 @@ Harness status: OK Found 32 tests -32 Fail +2 Pass +30 Fail Fail e.style['width'] = "random(0px, 100px)" should set the property value Fail e.style['width'] = "random(0px, 100px, 50px)" should set the property value Fail e.style['width'] = "random(--foo, 0px, 100px)" should set the property value @@ -11,7 +12,7 @@ Fail e.style['width'] = "random(--foo element-shared, 0px, 100px)" should set th Fail e.style['width'] = "random(auto element-shared, 0px, 100px)" should set the property value Fail e.style['width'] = "random(element-shared --foo, 0px, 100px)" should set the property value Fail e.style['width'] = "random(element-shared auto, 0px, 100px)" should set the property value -Fail e.style['width'] = "random(fixed 0.5, 0px, 100px)" should set the property value +Pass e.style['width'] = "random(fixed 0.5, 0px, 100px)" should set the property value Fail e.style['width'] = "random(--foo, 0px, 100px, 50px)" should set the property value Fail e.style['width'] = "random(auto, 0px, 100px, 50px)" should set the property value Fail e.style['width'] = "random(--foo element-shared, 0px, 100px, 50px)" should set the property value @@ -25,7 +26,7 @@ Fail e.style['width'] = "random(-100px, -10px)" should set the property value Fail e.style['width'] = "random(-100px, -10px, -5px)" should set the property value Fail e.style['width'] = "random(1em, 200rem)" should set the property value Fail e.style['width'] = "random(10 * 100px, 200em / 2)" should set the property value -Fail e.style['width'] = "random(fixed calc(2 / 4), 0px, 100px)" should set the property value +Pass e.style['width'] = "random(fixed calc(2 / 4), 0px, 100px)" should set the property value Fail e.style['width'] = "calc(2 * random(0px, 100px))" should set the property value Fail e.style['max-lines'] = "random(25, 50)" should set the property value Fail e.style['max-lines'] = "random(25, 50, 5)" should set the property value