LibWeb/CSS: Implement CSSMathMax

Basically the same as CSSMathMin.
This commit is contained in:
Sam Atkins 2025-08-19 17:18:12 +01:00 committed by Andreas Kling
commit dd3007dcd7
Notes: github-actions[bot] 2025-08-29 09:59:17 +00:00
12 changed files with 322 additions and 12 deletions

View file

@ -117,6 +117,7 @@ set(SOURCES
CSS/CSSLayerStatementRule.cpp
CSS/CSSMarginRule.cpp
CSS/CSSMathInvert.cpp
CSS/CSSMathMax.cpp
CSS/CSSMathMin.cpp
CSS/CSSMathNegate.cpp
CSS/CSSMathProduct.cpp

View file

@ -0,0 +1,118 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CSSMathMax.h"
#include <LibWeb/Bindings/CSSMathMaxPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSMathNegate.h>
#include <LibWeb/CSS/CSSNumericArray.h>
#include <LibWeb/WebIDL/DOMException.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::CSS {
GC_DEFINE_ALLOCATOR(CSSMathMax);
GC::Ref<CSSMathMax> CSSMathMax::create(JS::Realm& realm, NumericType type, GC::Ref<CSSNumericArray> values)
{
return realm.create<CSSMathMax>(realm, move(type), move(values));
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmathmin-cssmathmin
WebIDL::ExceptionOr<GC::Ref<CSSMathMax>> CSSMathMax::construct_impl(JS::Realm& realm, Vector<CSSNumberish> values)
{
// The CSSMathMin(...args) and CSSMathMax(...args) constructors are defined identically to the above, except that
// in the last step they return a new CSSMathMin or CSSMathMax object, respectively.
// NB: So, the steps below are a modification of the CSSMathSum steps.
// 1. Replace each item of args with the result of rectifying a numberish value for the item.
GC::RootVector<GC::Ref<CSSNumericValue>> converted_values { realm.heap() };
converted_values.ensure_capacity(values.size());
for (auto const& value : values) {
converted_values.append(rectify_a_numberish_value(realm, value));
}
// 2. If args is empty, throw a SyntaxError.
if (converted_values.is_empty())
return WebIDL::SyntaxError::create(realm, "Cannot create an empty CSSMathMax"_utf16);
// 3. Let type be the result of adding the types of all the items of args. If type is failure, throw a TypeError.
auto type = converted_values.first()->type();
bool first = true;
for (auto const& value : converted_values) {
if (first) {
first = false;
continue;
}
if (auto added_types = type.added_to(value->type()); added_types.has_value()) {
type = added_types.release_value();
} else {
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot create a CSSMathMax with values of incompatible types"sv };
}
}
// 4. Return a new CSSMathMax whose values internal slot is set to args.
auto values_array = CSSNumericArray::create(realm, { converted_values });
return CSSMathMax::create(realm, move(type), move(values_array));
}
CSSMathMax::CSSMathMax(JS::Realm& realm, NumericType type, GC::Ref<CSSNumericArray> values)
: CSSMathValue(realm, Bindings::CSSMathOperator::Max, move(type))
, m_values(move(values))
{
}
CSSMathMax::~CSSMathMax() = default;
void CSSMathMax::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSMathMax);
Base::initialize(realm);
}
void CSSMathMax::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_values);
}
// https://drafts.css-houdini.org/css-typed-om-1/#serialize-a-cssmathvalue
String CSSMathMax::serialize_math_value(Nested, Parens) const
{
// NB: Only steps 1 and 2 apply here.
// 1. Let s initially be the empty string.
StringBuilder s;
// 2. If this is a CSSMathMin or CSSMathMax:
{
// 1. Append "min(" or "max(" to s, as appropriate.
s.append("max("sv);
// 2. For each arg in thiss values internal slot, serialize arg with nested and paren-less both true, and
// append the result to s, appending a ", " between successive values.
bool first = true;
for (auto const& arg : m_values->values()) {
if (first) {
first = false;
} else {
s.append(", "sv);
}
s.append(arg->to_string({ .nested = true, .parenless = true }));
}
// 3. Append ")" to s and return s.
s.append(")"sv);
return s.to_string_without_validation();
}
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmathmin-values
GC::Ref<CSSNumericArray> CSSMathMax::values() const
{
return m_values;
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSMathValue.h>
namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#cssmathmax
class CSSMathMax : public CSSMathValue {
WEB_PLATFORM_OBJECT(CSSMathMax, CSSMathValue);
GC_DECLARE_ALLOCATOR(CSSMathMax);
public:
[[nodiscard]] static GC::Ref<CSSMathMax> create(JS::Realm&, NumericType, GC::Ref<CSSNumericArray>);
static WebIDL::ExceptionOr<GC::Ref<CSSMathMax>> construct_impl(JS::Realm&, Vector<CSSNumberish>);
virtual ~CSSMathMax() override;
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;
GC::Ref<CSSNumericArray> values() const;
virtual String serialize_math_value(Nested, Parens) const override;
private:
CSSMathMax(JS::Realm&, NumericType, GC::Ref<CSSNumericArray>);
GC::Ref<CSSNumericArray> m_values;
};
}

View file

@ -0,0 +1,9 @@
#import <CSS/CSSMathValue.idl>
#import <CSS/CSSNumericArray.idl>
// https://drafts.css-houdini.org/css-typed-om-1/#cssmathmax
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
interface CSSMathMax : CSSMathValue {
constructor(CSSNumberish... args);
readonly attribute CSSNumericArray values;
};

View file

@ -243,6 +243,7 @@ class CSSLayerBlockRule;
class CSSLayerStatementRule;
class CSSMarginRule;
class CSSMathInvert;
class CSSMathMax;
class CSSMathMin;
class CSSMathNegate;
class CSSMathProduct;

View file

@ -37,6 +37,7 @@ libweb_js_bindings(CSS/CSSLayerBlockRule)
libweb_js_bindings(CSS/CSSLayerStatementRule)
libweb_js_bindings(CSS/CSSMarginRule)
libweb_js_bindings(CSS/CSSMathInvert)
libweb_js_bindings(CSS/CSSMathMax)
libweb_js_bindings(CSS/CSSMathMin)
libweb_js_bindings(CSS/CSSMathNegate)
libweb_js_bindings(CSS/CSSMathProduct)

View file

@ -50,6 +50,7 @@ CSSLayerBlockRule
CSSLayerStatementRule
CSSMarginRule
CSSMathInvert
CSSMathMax
CSSMathMin
CSSMathNegate
CSSMathProduct

View file

@ -1,3 +1,56 @@
Harness status: Error
Harness status: OK
Found 0 tests
Found 51 tests
51 Fail
Fail Constructing a CSSRGB with an angle CSSUnitValue for the color channels throws a SyntaxError.
Fail Constructing a CSSRGB with a CSSMathValue that doesn"t match <number> for the color channels throws a SyntaxError.
Fail Constructing a CSSRGB with undefined for the color channels throws a SyntaxError.
Fail Constructing a CSSRGB with a CSS math calculation for the color channels throws a SyntaxError.
Fail Constructing a CSSRGB with a CSS number for the alpha channels throws a SyntaxError.
Fail Updating CSSRGB. r to an angle CSSUnitValue throws a SyntaxError.
Fail Updating CSSRGB. r to a CSSMathValue that doesn"t match <number> throws a SyntaxError.
Fail Updating CSSRGB. r to undefined throws a SyntaxError.
Fail Updating CSSRGB. r to a CSS math calculation throws a SyntaxError.
Fail Updating CSSRGB. g to an angle CSSUnitValue throws a SyntaxError.
Fail Updating CSSRGB. g to a CSSMathValue that doesn"t match <number> throws a SyntaxError.
Fail Updating CSSRGB. g to undefined throws a SyntaxError.
Fail Updating CSSRGB. g to a CSS math calculation throws a SyntaxError.
Fail Updating CSSRGB. b to an angle CSSUnitValue throws a SyntaxError.
Fail Updating CSSRGB. b to a CSSMathValue that doesn"t match <number> throws a SyntaxError.
Fail Updating CSSRGB. b to undefined throws a SyntaxError.
Fail Updating CSSRGB. b to a CSS math calculation throws a SyntaxError.
Fail Updating CSSRGB. alpha to an angle CSSUnitValue throws a SyntaxError.
Fail Updating CSSRGB. alpha to a CSSMathValue that doesn"t match <number> throws a SyntaxError.
Fail Updating CSSRGB. alpha to undefined throws a SyntaxError.
Fail Updating CSSRGB. alpha to a CSS math calculation throws a SyntaxError.
Fail Updating the alpha channel to a CSS number throws a SyntaxError.
Fail CSSRGB can be constructed from three numbers and will get an alpha of 100%.
Fail CSSRGB can be constructed from four numbers.
Fail CSSRGB.r can be updated with a number with the resulting value being a percentage.
Fail CSSRGB.r can be updated with a CSS number.
Fail CSSRGB.r can be updated with CSS percent.
Fail CSSRGB.r can be updated with CSS math sum.
Fail CSSRGB.r can be updated with CSS math product.
Fail CSSRGB.r can be updated with CSS math max.
Fail CSSRGB.r can be updated with CSS math min.
Fail CSSRGB.g can be updated with a number with the resulting value being a percentage.
Fail CSSRGB.g can be updated with a CSS number.
Fail CSSRGB.g can be updated with CSS percent.
Fail CSSRGB.g can be updated with CSS math sum.
Fail CSSRGB.g can be updated with CSS math product.
Fail CSSRGB.g can be updated with CSS math max.
Fail CSSRGB.g can be updated with CSS math min.
Fail CSSRGB.b can be updated with a number with the resulting value being a percentage.
Fail CSSRGB.b can be updated with a CSS number.
Fail CSSRGB.b can be updated with CSS percent.
Fail CSSRGB.b can be updated with CSS math sum.
Fail CSSRGB.b can be updated with CSS math product.
Fail CSSRGB.b can be updated with CSS math max.
Fail CSSRGB.b can be updated with CSS math min.
Fail CSSRGB.alpha can be updated with a number with the resulting value being a percentage.
Fail CSSRGB.alpha can be updated with CSS percent.
Fail CSSRGB.alpha can be updated with CSS math sum.
Fail CSSRGB.alpha can be updated with CSS math product.
Fail CSSRGB.alpha can be updated with CSS math max.
Fail CSSRGB.alpha can be updated with CSS math min.

View file

@ -1,3 +1,71 @@
Harness status: Error
Harness status: OK
Found 0 tests
Found 65 tests
10 Pass
55 Fail
Fail Calling CSSUnitValue.add with no arguments returns itself
Fail Calling CSSMathValue.add with no arguments returns itself
Fail Calling CSSNumericValue.add with a single CSSNumericValue returns correct type
Fail Calling CSSMathValue.add with a single CSSNumericValue returns correct type
Fail Calling CSSNumericValue.add with more than one number CSSNumericValues returns correct type
Fail Calling CSSNumericValue.add can take numberish values
Fail Calling CSSMathSum.add with number CSSUnitValues simplifies to a CSSUnitValue
Pass Calling CSSNumericValue.add with incompatible types throws TypeError
Fail Calling CSSUnitValue.sub with no arguments returns itself
Fail Calling CSSMathValue.sub with no arguments returns itself
Fail Calling CSSNumericValue.sub with a single CSSNumericValue returns correct type
Fail Calling CSSMathValue.sub with a single CSSNumericValue returns correct type
Fail Calling CSSNumericValue.sub with more than one number CSSNumericValues returns correct type
Fail Calling CSSNumericValue.sub can take numberish values
Fail Calling CSSMathSum.sub with number CSSUnitValues simplifies to a CSSUnitValue
Pass Calling CSSNumericValue.sub with incompatible types throws TypeError
Fail Calling CSSUnitValue.mul with no arguments returns itself
Fail Calling CSSMathValue.mul with no arguments returns itself
Fail Calling CSSNumericValue.mul with a single CSSNumericValue returns correct type
Fail Calling CSSMathValue.mul with a single CSSNumericValue returns correct type
Fail Calling CSSNumericValue.mul with more than one number CSSNumericValues returns correct type
Fail Calling CSSNumericValue.mul can take numberish values
Fail Calling CSSMathProduct.mul with number CSSUnitValues simplifies to a CSSUnitValue
Pass Calling CSSNumericValue.mul with incompatible types throws TypeError
Fail Calling CSSUnitValue.div with no arguments returns itself
Fail Calling CSSMathValue.div with no arguments returns itself
Fail Calling CSSNumericValue.div with a single CSSNumericValue returns correct type
Fail Calling CSSMathValue.div with a single CSSNumericValue returns correct type
Fail Calling CSSNumericValue.div with more than one number CSSNumericValues returns correct type
Fail Calling CSSNumericValue.div can take numberish values
Fail Calling CSSMathProduct.div with number CSSUnitValues simplifies to a CSSUnitValue
Pass Calling CSSNumericValue.div with incompatible types throws TypeError
Fail Calling CSSUnitValue.min with no arguments returns itself
Fail Calling CSSMathValue.min with no arguments returns itself
Fail Calling CSSNumericValue.min with a single CSSNumericValue returns correct type
Fail Calling CSSMathValue.min with a single CSSNumericValue returns correct type
Fail Calling CSSNumericValue.min with more than one number CSSNumericValues returns correct type
Fail Calling CSSNumericValue.min can take numberish values
Fail Calling CSSMathMin.min with number CSSUnitValues simplifies to a CSSUnitValue
Pass Calling CSSNumericValue.min with incompatible types throws TypeError
Fail Calling CSSUnitValue.max with no arguments returns itself
Fail Calling CSSMathValue.max with no arguments returns itself
Fail Calling CSSNumericValue.max with a single CSSNumericValue returns correct type
Fail Calling CSSMathValue.max with a single CSSNumericValue returns correct type
Fail Calling CSSNumericValue.max with more than one number CSSNumericValues returns correct type
Fail Calling CSSNumericValue.max can take numberish values
Fail Calling CSSMathMax.max with number CSSUnitValues simplifies to a CSSUnitValue
Pass Calling CSSNumericValue.max with incompatible types throws TypeError
Fail Calling CSSUnitValue.add with CSSUnitValues with same unit simplifies to a CSSUnitValue
Fail Calling CSSUnitValue.sub with CSSUnitValues with same unit simplifies to a CSSUnitValue
Fail Calling CSSUnitValue.mul with all numbers simplifies to a CSSUnitValue
Fail Calling CSSUnitValue.mul with only one non-number simplifies to a CSSUnitValue
Fail Calling CSSUnitValue.mul with more than one non-number does not simplify to a CSSUnitValue
Fail Calling CSSUnitValue.div with all numbers simplifies to a CSSUnitValue
Fail Calling CSSUnitValue.div on a non-number value simplifies to a CSSUnitValue
Fail Calling CSSUnitValue.div with a non-number value in the arguments does not simplify to a CSSUnitValue
Fail Calling CSSUnitValue.min with CSSUnitValues with same unit simplifies to a CSSUnitValue
Fail Calling CSSUnitValue.max with CSSUnitValues with same unit simplifies to a CSSUnitValue
Fail Calling CSSNumericValue.sub negates all argument values
Fail Calling CSSNumericValue.div inverts all argument values
Fail Can not divide with CSSUnitValue which has zero value and number type
Pass CSSNumericValue.add should throw TypeError when the types are different.
Pass CSSNumericValue.sub should throw TypeError when the types are different.
Pass CSSNumericValue.max should throw TypeError when the types are different.
Pass CSSNumericValue.min should throw TypeError when the types are different.

View file

@ -1,3 +1,25 @@
Harness status: Error
Found 0 tests
Found 20 tests
20 Pass
Pass Constructing a CSSMathSum with no arguments throws a SyntaxError
Pass CSSMathSum can be constructed from a single number CSSUnitValue
Pass CSSMathSum can be constructed from more than one number CSSUnitValue
Pass CSSMathSum.operator is readonly
Pass Constructing a CSSMathProduct with no arguments throws a SyntaxError
Pass CSSMathProduct can be constructed from a single number CSSUnitValue
Pass CSSMathProduct can be constructed from more than one number CSSUnitValue
Pass CSSMathProduct.operator is readonly
Pass Constructing a CSSMathMin with no arguments throws a SyntaxError
Pass CSSMathMin can be constructed from a single number CSSUnitValue
Pass CSSMathMin can be constructed from more than one number CSSUnitValue
Pass CSSMathMin.operator is readonly
Pass Constructing a CSSMathMax with no arguments throws a SyntaxError
Pass CSSMathMax can be constructed from a single number CSSUnitValue
Pass CSSMathMax can be constructed from more than one number CSSUnitValue
Pass CSSMathMax.operator is readonly
Pass CSSMathNegate can be constructed from a single numberish value
Pass CSSMathNegate.operator is readonly
Pass CSSMathInvert can be constructed from a single numberish value
Pass CSSMathInvert.operator is readonly

View file

@ -2,10 +2,10 @@ Harness status: OK
Found 17 tests
3 Pass
14 Fail
5 Pass
12 Fail
Fail Converting a CSSUnitValue to an invalid unit throws SyntaxError
Fail Converting a CSSNumericValue with invalid sum value throws TypeError
Pass Converting a CSSNumericValue with invalid sum value throws TypeError
Pass Converting a CSSNumericValue with sum value containing more than one value throws TypeError
Pass Converting a CSSUnitValue to an incompatible unit throws TypeError
Fail Converting a CSSUnitValue to its own unit returns itself
@ -15,7 +15,7 @@ Fail Converting a CSSMathProduct to a single unit multiplies the values
Fail Converting a CSSMathMin to a single unit finds the min value
Pass Converting a CSSMathMin to a single unit with different units throws a TypeError
Fail Converting a CSSMathMax to a single unit finds the max value
Fail Converting a CSSMathMax to a single unit with different units throws a TypeError
Pass Converting a CSSMathMax to a single unit with different units throws a TypeError
Fail Converting a CSSMathClamp to a single unit returns the clamped value
Fail Converting a CSSMathClamp to a single unit with different units throws a TypeError
Fail Converting a CSSMathNegate to a single unit negates its value

View file

@ -2,10 +2,10 @@ Harness status: OK
Found 11 tests
4 Pass
7 Fail
5 Pass
6 Fail
Fail Converting a CSSNumericValue to a sum with invalid units throws SyntaxError
Fail Converting a CSSNumericValue with an invalid sum value to a sum throws TypeError
Pass Converting a CSSNumericValue with an invalid sum value to a sum throws TypeError
Pass Converting a CSSNumericValue with compound units to a sum throws TypeError
Pass Converting a CSSNumericValue to a sum with an incompatible unit throws TypeError
Pass Converting a CSSNumericValue to a sum with units that are not addable throws TypeError