diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 5f9d1cac8b5..5628ae9a08e 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -116,6 +116,7 @@ set(SOURCES CSS/CSSLayerBlockRule.cpp CSS/CSSLayerStatementRule.cpp CSS/CSSMarginRule.cpp + CSS/CSSMathInvert.cpp CSS/CSSMathNegate.cpp CSS/CSSMathProduct.cpp CSS/CSSMathSum.cpp diff --git a/Libraries/LibWeb/CSS/CSSMathInvert.cpp b/Libraries/LibWeb/CSS/CSSMathInvert.cpp new file mode 100644 index 00000000000..62493796ed0 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSMathInvert.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "CSSMathInvert.h" +#include +#include +#include + +namespace Web::CSS { + +GC_DEFINE_ALLOCATOR(CSSMathInvert); + +GC::Ref CSSMathInvert::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-cssmathinvert-cssmathinvert +WebIDL::ExceptionOr> CSSMathInvert::construct_impl(JS::Realm& realm, CSSNumberish value) +{ + // The CSSMathInvert(arg) constructor is defined identically to the above, except that in the last step it returns + // a new CSSMathInvert object. + // NB: So, the steps below are a modification of the CSSMathNegate steps. + + // 1. Replace arg with the result of rectifying a numberish value for arg. + auto converted_value = rectify_a_numberish_value(realm, value); + + // 2. Return a new CSSMathInvert whose value internal slot is set to arg. + return CSSMathInvert::create(realm, converted_value->type().inverted(), converted_value); +} + +CSSMathInvert::CSSMathInvert(JS::Realm& realm, NumericType type, GC::Ref values) + : CSSMathValue(realm, Bindings::CSSMathOperator::Invert, move(type)) + , m_value(move(values)) +{ +} + +CSSMathInvert::~CSSMathInvert() = default; + +void CSSMathInvert::initialize(JS::Realm& realm) +{ + WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSMathInvert); + Base::initialize(realm); +} + +void CSSMathInvert::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_value); +} + +// https://drafts.css-houdini.org/css-typed-om-1/#serialize-a-cssmathvalue +String CSSMathInvert::serialize_math_value(Nested nested, Parens parens) const +{ + // NB: Only steps 1 and 6 apply here. + // 1. Let s initially be the empty string. + StringBuilder s; + + // 6. Otherwise, if this is a CSSMathInvert: + { + // 1. If paren-less is true, continue to the next step; otherwise, if nested is true, append "(" to s; + // otherwise, append "calc(" to s. + if (parens == Parens::With) { + if (nested == Nested::Yes) { + s.append("("sv); + } else { + s.append("calc("sv); + } + } + + // 2. Append "1 / " to s. + s.append("1 / "sv); + + // 3. Serialize this’s value internal slot with nested set to true, and append the result to s. + s.append(m_value->to_string({ .nested = true })); + + // 4. If paren-less is false, append ")" to s, + if (parens == Parens::With) + s.append(")"sv); + + // 5. Return s. + return s.to_string_without_validation(); + } +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmathinvert-value +GC::Ref CSSMathInvert::value() const +{ + return m_value; +} + +} diff --git a/Libraries/LibWeb/CSS/CSSMathInvert.h b/Libraries/LibWeb/CSS/CSSMathInvert.h new file mode 100644 index 00000000000..231bd14af19 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSMathInvert.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/#cssmathinvert +class CSSMathInvert : public CSSMathValue { + WEB_PLATFORM_OBJECT(CSSMathInvert, CSSMathValue); + GC_DECLARE_ALLOCATOR(CSSMathInvert); + +public: + [[nodiscard]] static GC::Ref create(JS::Realm&, NumericType, GC::Ref); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, CSSNumberish); + + virtual ~CSSMathInvert() override; + + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Visitor&) override; + + GC::Ref value() const; + + virtual String serialize_math_value(Nested, Parens) const override; + +private: + CSSMathInvert(JS::Realm&, NumericType, GC::Ref); + GC::Ref m_value; +}; + +} diff --git a/Libraries/LibWeb/CSS/CSSMathInvert.idl b/Libraries/LibWeb/CSS/CSSMathInvert.idl new file mode 100644 index 00000000000..a51b6f30f55 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSMathInvert.idl @@ -0,0 +1,9 @@ +#import +#import + +// https://drafts.css-houdini.org/css-typed-om-1/#cssmathinvert +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] +interface CSSMathInvert : CSSMathValue { + constructor(CSSNumberish arg); + readonly attribute CSSNumericValue value; +}; diff --git a/Libraries/LibWeb/CSS/CSSMathProduct.cpp b/Libraries/LibWeb/CSS/CSSMathProduct.cpp index e94b603a71e..120db0ed6bd 100644 --- a/Libraries/LibWeb/CSS/CSSMathProduct.cpp +++ b/Libraries/LibWeb/CSS/CSSMathProduct.cpp @@ -7,6 +7,7 @@ #include "CSSMathProduct.h" #include #include +#include #include #include #include @@ -110,10 +111,9 @@ String CSSMathProduct::serialize_math_value(Nested nested, Parens parens) const // 1. If arg is a CSSMathInvert, append " / " to s, then serialize arg’s value internal slot with nested // set to true, and append the result to s. - // FIXME: Detect CSSMathInvert once that's implemented. - if (false) { + if (auto* invert = as_if(*arg)) { s.append(" / "sv); - s.append(arg->to_string({ .nested = true })); + s.append(invert->value()->to_string({ .nested = true })); } // 2. Otherwise, append " * " to s, then serialize arg with nested set to true, and append the result to s. diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 69ff65e3c1b..1f90a407d04 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -242,6 +242,7 @@ class CSSKeywordValue; class CSSLayerBlockRule; class CSSLayerStatementRule; class CSSMarginRule; +class CSSMathInvert; class CSSMathNegate; class CSSMathProduct; class CSSMathSum; diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index 0ba14faa6c0..65bcfeaed12 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -36,6 +36,7 @@ libweb_js_bindings(CSS/CSSKeywordValue) libweb_js_bindings(CSS/CSSLayerBlockRule) libweb_js_bindings(CSS/CSSLayerStatementRule) libweb_js_bindings(CSS/CSSMarginRule) +libweb_js_bindings(CSS/CSSMathInvert) libweb_js_bindings(CSS/CSSMathNegate) libweb_js_bindings(CSS/CSSMathProduct) libweb_js_bindings(CSS/CSSMathSum) diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 95fb9230bf1..7c8aaae834a 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -49,6 +49,7 @@ CSSKeywordValue CSSLayerBlockRule CSSLayerStatementRule CSSMarginRule +CSSMathInvert CSSMathNegate CSSMathProduct CSSMathSum