diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index e7d287d6f42..bb9b0a85185 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -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 diff --git a/Libraries/LibWeb/CSS/CSSMathMax.cpp b/Libraries/LibWeb/CSS/CSSMathMax.cpp new file mode 100644 index 00000000000..fff7319d60e --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSMathMax.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "CSSMathMax.h" +#include +#include +#include +#include +#include +#include + +namespace Web::CSS { + +GC_DEFINE_ALLOCATOR(CSSMathMax); + +GC::Ref CSSMathMax::create(JS::Realm& realm, NumericType type, GC::Ref values) +{ + return realm.create(realm, move(type), move(values)); +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmathmin-cssmathmin +WebIDL::ExceptionOr> CSSMathMax::construct_impl(JS::Realm& realm, Vector 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> 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 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 this’s 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 CSSMathMax::values() const +{ + return m_values; +} + +} diff --git a/Libraries/LibWeb/CSS/CSSMathMax.h b/Libraries/LibWeb/CSS/CSSMathMax.h new file mode 100644 index 00000000000..387c5d9b6ee --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSMathMax.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +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 create(JS::Realm&, NumericType, GC::Ref); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Vector); + + virtual ~CSSMathMax() override; + + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Visitor&) override; + + GC::Ref values() const; + + virtual String serialize_math_value(Nested, Parens) const override; + +private: + CSSMathMax(JS::Realm&, NumericType, GC::Ref); + GC::Ref m_values; +}; + +} diff --git a/Libraries/LibWeb/CSS/CSSMathMax.idl b/Libraries/LibWeb/CSS/CSSMathMax.idl new file mode 100644 index 00000000000..a3f356ede30 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSMathMax.idl @@ -0,0 +1,9 @@ +#import +#import + +// 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; +}; diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 741580d4ad8..a6da29a1063 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -243,6 +243,7 @@ class CSSLayerBlockRule; class CSSLayerStatementRule; class CSSMarginRule; class CSSMathInvert; +class CSSMathMax; class CSSMathMin; class CSSMathNegate; class CSSMathProduct; diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index 563169728bf..8f18514dc3f 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -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) diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 6b291c16212..6f01c4e33c0 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -50,6 +50,7 @@ CSSLayerBlockRule CSSLayerStatementRule CSSMarginRule CSSMathInvert +CSSMathMax CSSMathMin CSSMathNegate CSSMathProduct diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssRGB.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssRGB.txt index 6055c864758..835e07f43e5 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssRGB.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssRGB.txt @@ -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 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 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 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 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 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. \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/arithmetic.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/arithmetic.tentative.txt index 6055c864758..58de45e2942 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/arithmetic.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/arithmetic.tentative.txt @@ -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. \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssMathValue.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssMathValue.tentative.txt index 6055c864758..adf14f44720 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssMathValue.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssMathValue.tentative.txt @@ -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 \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/to.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/to.tentative.txt index 1492f8e5d31..7e47d3adbde 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/to.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/to.tentative.txt @@ -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 diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/toSum.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/toSum.tentative.txt index 00657ac2877..cc170ded305 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/toSum.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/numeric-objects/toSum.tentative.txt @@ -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