LibWeb/CSS: Implement CSSSkewY

Equivalent to the skewY() transform function.

+27 WPT subtests.
This commit is contained in:
Sam Atkins 2025-09-15 15:33:37 +01:00
parent b0cc1c6406
commit da883877f5
10 changed files with 196 additions and 32 deletions

View File

@ -140,6 +140,7 @@ set(SOURCES
CSS/CSSScale.cpp
CSS/CSSSkew.cpp
CSS/CSSSkewX.cpp
CSS/CSSSkewY.cpp
CSS/CSSStyleDeclaration.cpp
CSS/CSSStyleProperties.cpp
CSS/CSSStyleRule.cpp

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CSSSkewY.h"
#include <LibWeb/Bindings/CSSSkewYPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSNumericValue.h>
#include <LibWeb/CSS/CSSUnitValue.h>
#include <LibWeb/Geometry/DOMMatrix.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::CSS {
GC_DEFINE_ALLOCATOR(CSSSkewY);
GC::Ref<CSSSkewY> CSSSkewY::create(JS::Realm& realm, GC::Ref<CSSNumericValue> ay)
{
return realm.create<CSSSkewY>(realm, ay);
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssskewy-cssskewy
WebIDL::ExceptionOr<GC::Ref<CSSSkewY>> CSSSkewY::construct_impl(JS::Realm& realm, GC::Ref<CSSNumericValue> ay)
{
// The CSSSkewY(ay) constructor must, when invoked, perform the following steps:
// 1. If ay does not match <angle>, throw a TypeError.
if (!ay->type().matches_angle({}))
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "CSSSkewY ay component doesn't match <angle>"sv };
// 2. Return a new CSSSkewY object with its ay internal slot set to ay, and its is2D internal slot set to true.
return CSSSkewY::create(realm, ay);
}
CSSSkewY::CSSSkewY(JS::Realm& realm, GC::Ref<CSSNumericValue> ay)
: CSSTransformComponent(realm, Is2D::Yes)
, m_ay(ay)
{
}
CSSSkewY::~CSSSkewY() = default;
void CSSSkewY::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSSkewY);
Base::initialize(realm);
}
void CSSSkewY::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_ay);
}
// https://drafts.css-houdini.org/css-typed-om-1/#serialize-a-cssskewy
WebIDL::ExceptionOr<Utf16String> CSSSkewY::to_string() const
{
// 1. Let s initially be "skewY(".
StringBuilder builder { StringBuilder::Mode::UTF16 };
builder.append("skewY("sv);
// 2. Serialize thiss ay internal slot, and append it to s.
builder.append(m_ay->to_string());
// 3. Append ")" to s, and return s.
builder.append(")"sv);
return builder.to_utf16_string();
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-csstransformcomponent-tomatrix
WebIDL::ExceptionOr<GC::Ref<Geometry::DOMMatrix>> CSSSkewY::to_matrix() const
{
// 1. Let matrix be a new DOMMatrix object, initialized to thiss equivalent 4x4 transform matrix, as defined in
// CSS Transforms 1 § 12. Mathematical Description of Transform Functions, and with its is2D internal slot set
// to the same value as thiss is2D internal slot.
// NOTE: Recall that the is2D flag affects what transform, and thus what equivalent matrix, a
// CSSTransformComponent represents.
// As the entries of such a matrix are defined relative to the px unit, if any <length>s in this involved in
// generating the matrix are not compatible units with px (such as relative lengths or percentages), throw a
// TypeError.
auto matrix = Geometry::DOMMatrix::create(realm());
// NB: to() throws a TypeError if the conversion can't be done.
auto ay_rad = TRY(m_ay->to("rad"_fly_string))->value();
matrix->set_m12(tanf(ay_rad));
// 2. Return matrix.
return matrix;
}
WebIDL::ExceptionOr<void> CSSSkewY::set_ay(GC::Ref<CSSNumericValue> ay)
{
// AD-HOC: Not specced. https://github.com/w3c/css-houdini-drafts/issues/1153
// WPT expects this to throw for invalid values.
if (!ay->type().matches_angle({}))
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "CSSSkewY ay component doesn't match <angle>"sv };
m_ay = ay;
return {};
}
// https://drafts.css-houdini.org/css-typed-om-1/#dom-cssskew-is2d
void CSSSkewY::set_is_2d(bool)
{
// The is2D attribute of a CSSSkewY, CSSSkewYX, or CSSSkewYY object must, on setting, do nothing.
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSTransformComponent.h>
namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#cssskewy
class CSSSkewY final : public CSSTransformComponent {
WEB_PLATFORM_OBJECT(CSSSkewY, CSSTransformComponent);
GC_DECLARE_ALLOCATOR(CSSSkewY);
public:
[[nodiscard]] static GC::Ref<CSSSkewY> create(JS::Realm&, GC::Ref<CSSNumericValue> ay);
static WebIDL::ExceptionOr<GC::Ref<CSSSkewY>> construct_impl(JS::Realm&, GC::Ref<CSSNumericValue> ay);
virtual ~CSSSkewY() override;
virtual WebIDL::ExceptionOr<Utf16String> to_string() const override;
virtual WebIDL::ExceptionOr<GC::Ref<Geometry::DOMMatrix>> to_matrix() const override;
GC::Ref<CSSNumericValue> ay() const { return m_ay; }
WebIDL::ExceptionOr<void> set_ay(GC::Ref<CSSNumericValue> value);
virtual void set_is_2d(bool value) override;
private:
explicit CSSSkewY(JS::Realm&, GC::Ref<CSSNumericValue> ay);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;
GC::Ref<CSSNumericValue> m_ay;
};
}

View File

@ -0,0 +1,9 @@
#import <CSS/CSSNumericValue.idl>
#import <CSS/CSSTransformComponent.idl>
// https://drafts.css-houdini.org/css-typed-om-1/#cssskewy
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
interface CSSSkewY : CSSTransformComponent {
constructor(CSSNumericValue ay);
attribute CSSNumericValue ay;
};

View File

@ -265,6 +265,7 @@ class CSSRuleList;
class CSSScale;
class CSSSkew;
class CSSSkewX;
class CSSSkewY;
class CSSStyleDeclaration;
class CSSStyleProperties;
class CSSStyleRule;

View File

@ -60,6 +60,7 @@ libweb_js_bindings(CSS/CSSRuleList)
libweb_js_bindings(CSS/CSSScale)
libweb_js_bindings(CSS/CSSSkew)
libweb_js_bindings(CSS/CSSSkewX)
libweb_js_bindings(CSS/CSSSkewY)
libweb_js_bindings(CSS/CSSStyleDeclaration)
libweb_js_bindings(CSS/CSSStyleProperties)
libweb_js_bindings(CSS/CSSStyleRule)

View File

@ -72,6 +72,7 @@ CSSRuleList
CSSScale
CSSSkew
CSSSkewX
CSSSkewY
CSSStyleDeclaration
CSSStyleProperties
CSSStyleRule

View File

@ -2,8 +2,8 @@ Harness status: OK
Found 545 tests
339 Pass
206 Fail
346 Pass
199 Fail
Pass idl_test setup
Pass idl_test validation
Pass Partial interface Element: original interface defined
@ -352,13 +352,13 @@ Fail Stringification of skewX
Fail CSSSkewX interface: skewX must inherit property "ax" with the proper type
Fail CSSTransformComponent interface: skewX must inherit property "is2D" with the proper type
Fail CSSTransformComponent interface: skewX must inherit property "toMatrix()" with the proper type
Fail CSSSkewY interface: existence and properties of interface object
Fail CSSSkewY interface object length
Fail CSSSkewY interface object name
Fail CSSSkewY interface: existence and properties of interface prototype object
Fail CSSSkewY interface: existence and properties of interface prototype object's "constructor" property
Fail CSSSkewY interface: existence and properties of interface prototype object's @@unscopables property
Fail CSSSkewY interface: attribute ay
Pass CSSSkewY interface: existence and properties of interface object
Pass CSSSkewY interface object length
Pass CSSSkewY interface object name
Pass CSSSkewY interface: existence and properties of interface prototype object
Pass CSSSkewY interface: existence and properties of interface prototype object's "constructor" property
Pass CSSSkewY interface: existence and properties of interface prototype object's @@unscopables property
Pass CSSSkewY interface: attribute ay
Fail CSSSkewY must be primary interface of skewY
Fail Stringification of skewY
Fail CSSSkewY interface: skewY must inherit property "ay" with the proper type

View File

@ -2,23 +2,23 @@ Harness status: OK
Found 19 tests
19 Fail
Fail Constructing a CSSSkewY with a keyword throws a TypeError
Fail Constructing a CSSSkewY with a double throws a TypeError
Fail Constructing a CSSSkewY with a unitless zero throws a TypeError
Fail Constructing a CSSSkewY with a string angle throws a TypeError
Fail Constructing a CSSSkewY with a number CSSUnitValue throws a TypeError
Fail Constructing a CSSSkewY with a time dimension CSSUnitValue throws a TypeError
Fail Constructing a CSSSkewY with a CSSMathValue of length type throws a TypeError
Fail Updating CSSSkewY.ay with a keyword throws a TypeError
Fail Updating CSSSkewY.ay with a double throws a TypeError
Fail Updating CSSSkewY.ay with a unitless zero throws a TypeError
Fail Updating CSSSkewY.ay with a string angle throws a TypeError
Fail Updating CSSSkewY.ay with a number CSSUnitValue throws a TypeError
Fail Updating CSSSkewY.ay with a time dimension CSSUnitValue throws a TypeError
Fail Updating CSSSkewY.ay with a CSSMathValue of length type throws a TypeError
Fail CSSSkewY can be constructed from an angle CSSUnitValue
Fail CSSSkewY can be constructed from a CSSMathValue of angle type
Fail CSSSkewY.ay can be updated to an angle CSSUnitValue
Fail CSSSkewY.ay can be updated to a CSSMathValue of angle type
Fail Modifying skewY.is2D is a no-op
19 Pass
Pass Constructing a CSSSkewY with a keyword throws a TypeError
Pass Constructing a CSSSkewY with a double throws a TypeError
Pass Constructing a CSSSkewY with a unitless zero throws a TypeError
Pass Constructing a CSSSkewY with a string angle throws a TypeError
Pass Constructing a CSSSkewY with a number CSSUnitValue throws a TypeError
Pass Constructing a CSSSkewY with a time dimension CSSUnitValue throws a TypeError
Pass Constructing a CSSSkewY with a CSSMathValue of length type throws a TypeError
Pass Updating CSSSkewY.ay with a keyword throws a TypeError
Pass Updating CSSSkewY.ay with a double throws a TypeError
Pass Updating CSSSkewY.ay with a unitless zero throws a TypeError
Pass Updating CSSSkewY.ay with a string angle throws a TypeError
Pass Updating CSSSkewY.ay with a number CSSUnitValue throws a TypeError
Pass Updating CSSSkewY.ay with a time dimension CSSUnitValue throws a TypeError
Pass Updating CSSSkewY.ay with a CSSMathValue of length type throws a TypeError
Pass CSSSkewY can be constructed from an angle CSSUnitValue
Pass CSSSkewY can be constructed from a CSSMathValue of angle type
Pass CSSSkewY.ay can be updated to an angle CSSUnitValue
Pass CSSSkewY.ay can be updated to a CSSMathValue of angle type
Pass Modifying skewY.is2D is a no-op

View File

@ -2,13 +2,13 @@ Harness status: OK
Found 8 tests
5 Pass
3 Fail
6 Pass
2 Fail
Pass CSSTranslate.toMatrix() returns correct matrix
Pass CSSRotate.toMatrix() returns correct matrix
Pass CSSScale.toMatrix() returns correct matrix
Pass CSSSkew.toMatrix() returns correct matrix
Pass CSSSkewX.toMatrix() returns correct matrix
Fail CSSSkewY.toMatrix() returns correct matrix
Pass CSSSkewY.toMatrix() returns correct matrix
Fail CSSPerspective.toMatrix() returns correct matrix
Fail CSSMatrixComponent.toMatrix() returns correct matrix