diff --git a/Libraries/LibWeb/CSS/EasingFunction.cpp b/Libraries/LibWeb/CSS/EasingFunction.cpp index b9b99402f3..4f322adf0b 100644 --- a/Libraries/LibWeb/CSS/EasingFunction.cpp +++ b/Libraries/LibWeb/CSS/EasingFunction.cpp @@ -320,7 +320,7 @@ EasingFunction EasingFunction::from_style_value(StyleValue const& style_value) return CubicBezierEasingFunction { resolved_x1, resolved_y1, resolved_x2, resolved_y2, cubic_bezier.to_string(SerializationMode::Normal) }; }, [](EasingStyleValue::Steps const& steps) -> EasingFunction { - auto resolved_interval_count = max(steps.number_of_intervals.resolved({}).value_or(1), steps.position == StepPosition::JumpNone ? 2 : 1); + auto resolved_interval_count = steps.number_of_intervals.resolved({}).value_or(1); return StepsEasingFunction { resolved_interval_count, steps.position, steps.to_string(SerializationMode::ResolvedValue) }; }); diff --git a/Libraries/LibWeb/CSS/Parser/Parser.h b/Libraries/LibWeb/CSS/Parser/Parser.h index f05ee70174..8845786557 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Libraries/LibWeb/CSS/Parser/Parser.h @@ -568,6 +568,8 @@ private: AngularColorStopList, CubicBezierFunctionXCoordinate, ShadowBlurRadius, + StepsIntervalsJumpNone, + StepsIntervalsNormal, TranslateZArgument }; // FIXME: Use PropertyNameAndID instead of PropertyID as the context, for registered custom properties. diff --git a/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp b/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp index e98260424c..2e03478291 100644 --- a/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/ValueParsing.cpp @@ -2991,13 +2991,7 @@ RefPtr Parser::parse_easing_value(TokenStream& return nullptr; } - EasingStyleValue::Steps steps; - - auto const& intervals_argument = comma_separated_arguments[0][0]; - auto intervals_token = TokenStream::of_single_token(intervals_argument); - auto intervals = parse_integer(intervals_token); - if (!intervals.has_value()) - return nullptr; + StepPosition position = StepPosition::End; if (comma_separated_arguments.size() == 2) { if (comma_separated_arguments[1].size() != 1) @@ -3018,15 +3012,23 @@ RefPtr Parser::parse_easing_value(TokenStream& if (!step_position.has_value()) return nullptr; - steps.position = step_position.value(); + position = step_position.value(); } + auto const& intervals_argument = comma_separated_arguments[0][0]; + auto intervals_token = TokenStream::of_single_token(intervals_argument); + m_value_context.append(position == StepPosition::JumpNone ? SpecialContext::StepsIntervalsJumpNone : SpecialContext::StepsIntervalsNormal); + auto intervals = parse_integer(intervals_token); + m_value_context.take_last(); + if (!intervals.has_value()) + return nullptr; + // Perform extra validation // https://drafts.csswg.org/css-easing/#step-easing-functions // If the is jump-none, the must be at least 2, or the function is invalid. // Otherwise, the must be at least 1, or the function is invalid. if (!intervals->is_calculated()) { - if (steps.position == StepPosition::JumpNone) { + if (position == StepPosition::JumpNone) { if (intervals->value() <= 1) return nullptr; } else if (intervals->value() <= 0) { @@ -3034,9 +3036,8 @@ RefPtr Parser::parse_easing_value(TokenStream& } } - steps.number_of_intervals = *intervals; transaction.commit(); - return EasingStyleValue::create(steps); + return EasingStyleValue::create(EasingStyleValue::Steps { *intervals, position }); } return nullptr; @@ -4142,6 +4143,10 @@ 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::StepsIntervalsJumpNone: + return CalculationContext { .resolve_numbers_as_integers = true, .accepted_type_ranges = { { ValueType::Integer, { 2, NumericLimits::max() } } } }; + case SpecialContext::StepsIntervalsNormal: + return CalculationContext { .resolve_numbers_as_integers = true, .accepted_type_ranges = { { ValueType::Integer, { 1, NumericLimits::max() } } } }; case SpecialContext::ShadowBlurRadius: return CalculationContext { .accepted_type_ranges = { { ValueType::Length, { 0, NumericLimits::max() } } } }; case SpecialContext::TranslateZArgument: diff --git a/Libraries/LibWeb/CSS/StyleValues/EasingStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/EasingStyleValue.cpp index ec8853ca68..f8eecff8a0 100644 --- a/Libraries/LibWeb/CSS/StyleValues/EasingStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/EasingStyleValue.cpp @@ -137,15 +137,10 @@ String EasingStyleValue::Steps::to_string(SerializationMode mode) const return {}; return CSS::to_string(this->position); }(); - auto intervals = number_of_intervals; - if (mode == SerializationMode::ResolvedValue) { - auto resolved_value = number_of_intervals.resolved({}).value_or(1); - intervals = max(resolved_value, this->position == StepPosition::JumpNone ? 2 : 1); - } if (position.has_value()) { - builder.appendff("steps({}, {})", intervals.to_string(mode), position.value()); + builder.appendff("steps({}, {})", number_of_intervals.to_string(mode), position.value()); } else { - builder.appendff("steps({})", intervals.to_string(mode)); + builder.appendff("steps({})", number_of_intervals.to_string(mode)); } } return MUST(builder.to_string()); diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-transitions/parsing/transition-timing-function-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-transitions/parsing/transition-timing-function-computed.txt index 9654595213..d586e89e46 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-transitions/parsing/transition-timing-function-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-transitions/parsing/transition-timing-function-computed.txt @@ -2,8 +2,8 @@ Harness status: OK Found 22 tests -20 Pass -2 Fail +18 Pass +4 Fail Pass Property transition-timing-function value 'linear' Pass Property transition-timing-function value 'ease' Pass Property transition-timing-function value 'ease-in' @@ -23,6 +23,6 @@ Pass Property transition-timing-function value 'steps(2, jump-both)' Pass Property transition-timing-function value 'steps(2, jump-none)' Fail Property transition-timing-function value 'steps(calc(2 * sibling-index()), jump-none)' Fail Property transition-timing-function value 'steps(sibling-index(), jump-none)' -Pass Property transition-timing-function value 'steps(calc(2 * sign(1em - 1000px)), jump-none)' -Pass Property transition-timing-function value 'steps(calc(2 * sign(1em - 1000px)), start)' +Fail Property transition-timing-function value 'steps(calc(2 * sign(1em - 1000px)), jump-none)' +Fail Property transition-timing-function value 'steps(calc(2 * sign(1em - 1000px)), start)' Pass Property transition-timing-function value 'linear, ease, linear' \ No newline at end of file