diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 4f90d86f894..6362a1ff259 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -112,6 +112,7 @@ set(SOURCES CSS/CSSImportRule.cpp CSS/CSSKeyframeRule.cpp CSS/CSSKeyframesRule.cpp + CSS/CSSKeywordValue.cpp CSS/CSSLayerBlockRule.cpp CSS/CSSLayerStatementRule.cpp CSS/CSSMarginRule.cpp diff --git a/Libraries/LibWeb/CSS/CSSKeywordValue.cpp b/Libraries/LibWeb/CSS/CSSKeywordValue.cpp new file mode 100644 index 00000000000..0484358a784 --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSKeywordValue.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "CSSKeywordValue.h" +#include +#include +#include +#include + +namespace Web::CSS { + +GC_DEFINE_ALLOCATOR(CSSKeywordValue); + +GC::Ref CSSKeywordValue::create(JS::Realm& realm, FlyString value) +{ + return realm.create(realm, move(value)); +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-csskeywordvalue-csskeywordvalue +WebIDL::ExceptionOr> CSSKeywordValue::construct_impl(JS::Realm& realm, FlyString value) +{ + // 1. If value is an empty string, throw a TypeError. + if (value.is_empty()) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot create a CSSKeywordValue with an empty string as the value"sv }; + + // 2. Otherwise, return a new CSSKeywordValue with its value internal slot set to value. + return CSSKeywordValue::create(realm, move(value)); +} + +CSSKeywordValue::CSSKeywordValue(JS::Realm& realm, FlyString value) + : CSSStyleValue(realm) + , m_value(move(value)) +{ +} + +void CSSKeywordValue::initialize(JS::Realm& realm) +{ + WEB_SET_PROTOTYPE_FOR_INTERFACE(CSSKeywordValue); + Base::initialize(realm); +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-csskeywordvalue-value +WebIDL::ExceptionOr CSSKeywordValue::set_value(FlyString value) +{ + // 1. If value is an empty string, throw a TypeError. + if (value.is_empty()) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot set CSSKeywordValue.value to an empty string"sv }; + + // 2. Otherwise, set this’s value internal slot, to value. + m_value = move(value); + return {}; +} + +// https://drafts.css-houdini.org/css-typed-om-1/#keywordvalue-serialization +String CSSKeywordValue::to_string() const +{ + // To serialize a CSSKeywordValue this: + // 1. Return this’s value internal slot. + // AD-HOC: Serialize it as an identifier. Spec issue: https://github.com/w3c/csswg-drafts/issues/12545 + return serialize_an_identifier(m_value); +} + +} diff --git a/Libraries/LibWeb/CSS/CSSKeywordValue.h b/Libraries/LibWeb/CSS/CSSKeywordValue.h new file mode 100644 index 00000000000..81e6c705a6c --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSKeywordValue.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::CSS { + +// https://drafts.css-houdini.org/css-typed-om-1/#csskeywordvalue +class CSSKeywordValue : public CSSStyleValue { + WEB_PLATFORM_OBJECT(CSSKeywordValue, CSSStyleValue); + GC_DECLARE_ALLOCATOR(CSSKeywordValue); + +public: + [[nodiscard]] static GC::Ref create(JS::Realm&, FlyString value); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, FlyString value); + + virtual ~CSSKeywordValue() override = default; + + FlyString const& value() const { return m_value; } + WebIDL::ExceptionOr set_value(FlyString value); + + virtual String to_string() const override; + +private: + explicit CSSKeywordValue(JS::Realm&, FlyString value); + + virtual void initialize(JS::Realm&) override; + + FlyString m_value; +}; + +} diff --git a/Libraries/LibWeb/CSS/CSSKeywordValue.idl b/Libraries/LibWeb/CSS/CSSKeywordValue.idl new file mode 100644 index 00000000000..dcbe177c8fc --- /dev/null +++ b/Libraries/LibWeb/CSS/CSSKeywordValue.idl @@ -0,0 +1,10 @@ +#import + +// https://drafts.css-houdini.org/css-typed-om-1/#csskeywordvalue +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] +interface CSSKeywordValue : CSSStyleValue { + constructor(USVString value); + attribute USVString value; +}; + +typedef (DOMString or CSSKeywordValue) CSSKeywordish; diff --git a/Libraries/LibWeb/CSS/CSSStyleValue.cpp b/Libraries/LibWeb/CSS/CSSStyleValue.cpp index 846d838e5d5..c96c0c6319d 100644 --- a/Libraries/LibWeb/CSS/CSSStyleValue.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleValue.cpp @@ -18,6 +18,11 @@ GC::Ref CSSStyleValue::create(JS::Realm& realm, String associated return realm.create(realm, move(associated_property), move(constructed_from_string)); } +CSSStyleValue::CSSStyleValue(JS::Realm& realm) + : PlatformObject(realm) +{ +} + CSSStyleValue::CSSStyleValue(JS::Realm& realm, String associated_property, String constructed_from_string) : PlatformObject(realm) , m_associated_property(move(associated_property)) @@ -39,9 +44,10 @@ String CSSStyleValue::to_string() const // the serialization is the USVString from which the value was constructed. return m_constructed_from_string.value(); } - // FIXME: otherwise, if the value was constructed using an IDL constructor + // otherwise, if the value was constructed using an IDL constructor { // the serialization is specified in the sections below. + // NB: This is handled by subclasses overriding this to_string() method. } // FIXME: otherwise, if the value was extracted from the CSSOM { diff --git a/Libraries/LibWeb/CSS/CSSStyleValue.h b/Libraries/LibWeb/CSS/CSSStyleValue.h index eb18a13297b..730d9d3f467 100644 --- a/Libraries/LibWeb/CSS/CSSStyleValue.h +++ b/Libraries/LibWeb/CSS/CSSStyleValue.h @@ -20,13 +20,16 @@ public: virtual ~CSSStyleValue() override = default; + virtual void initialize(JS::Realm&) override; + virtual String to_string() const; +protected: + explicit CSSStyleValue(JS::Realm&); + private: explicit CSSStyleValue(JS::Realm&, String associated_property, String constructed_from_string); - virtual void initialize(JS::Realm&) override; - // https://drafts.css-houdini.org/css-typed-om-1/#dom-cssstylevalue-associatedproperty-slot Optional m_associated_property; diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index ab59cb029b0..8fef334ac5a 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -238,6 +238,7 @@ class CSSGroupingRule; class CSSImportRule; class CSSKeyframeRule; class CSSKeyframesRule; +class CSSKeywordValue; class CSSLayerBlockRule; class CSSLayerStatementRule; class CSSMarginRule; diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index 9b7421d3a62..951018654e3 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -32,6 +32,7 @@ libweb_js_bindings(CSS/CSSGroupingRule) libweb_js_bindings(CSS/CSSImportRule) libweb_js_bindings(CSS/CSSKeyframeRule) libweb_js_bindings(CSS/CSSKeyframesRule) +libweb_js_bindings(CSS/CSSKeywordValue) libweb_js_bindings(CSS/CSSLayerBlockRule) libweb_js_bindings(CSS/CSSLayerStatementRule) libweb_js_bindings(CSS/CSSMarginRule) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 9075dae637b..50e62a0c6bd 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -54,6 +54,7 @@ static bool is_platform_object(Type const& type) "Credential"sv, "CredentialsContainer"sv, "CryptoKey"sv, + "CSSKeywordValue"sv, "CSSStyleValue"sv, "CustomStateSet"sv, "DataTransfer"sv, diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 5f7e0260fe0..53138172835 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -45,6 +45,7 @@ CSSGroupingRule CSSImportRule CSSKeyframeRule CSSKeyframesRule +CSSKeywordValue CSSLayerBlockRule CSSLayerStatementRule CSSMarginRule diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-serialization/cssKeywordValue.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-serialization/cssKeywordValue.tentative.txt index 708a8e4bd62..0ffa9d58f5a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-serialization/cssKeywordValue.tentative.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-serialization/cssKeywordValue.tentative.txt @@ -2,8 +2,9 @@ Harness status: OK Found 4 tests -4 Fail -Fail CSSKeywordValue constructed from IDL serializes correctly -Fail CSSKeywordValue constructed from IDL serializes to escaped strings +2 Pass +2 Fail +Pass CSSKeywordValue constructed from IDL serializes correctly +Pass CSSKeywordValue constructed from IDL serializes to escaped strings Fail CSSKeywordValue from DOMString modified through "value" setter serializes correctly Fail CSSKeywordValue from CSSOM modified through "value" setter serializes correctly \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-invalid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-invalid.txt index 546c7fb4143..032694edda9 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-invalid.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-invalid.txt @@ -2,5 +2,5 @@ Harness status: OK Found 1 tests -1 Fail -Fail Constructing CSSKeywordValue with an empty string throws a TypeError \ No newline at end of file +1 Pass +Pass Constructing CSSKeywordValue with an empty string throws a TypeError \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-value.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-value.txt index 531ca4e8086..c93a38021a0 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-value.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-value.txt @@ -2,10 +2,10 @@ Harness status: OK Found 6 tests -6 Fail -Fail CSSKeywordValue.value can be updated to a CSS wide keyword -Fail CSSKeywordValue.value can be updated to a CSS keyword -Fail CSSKeywordValue.value can be updated to an unsupported CSS keyword -Fail CSSKeywordValue.value can be updated to a string containing multiple tokens -Fail CSSKeywordValue.value can be updated to a unicode string -Fail Updating CSSKeywordValue.value with an empty string throws a TypeError \ No newline at end of file +6 Pass +Pass CSSKeywordValue.value can be updated to a CSS wide keyword +Pass CSSKeywordValue.value can be updated to a CSS keyword +Pass CSSKeywordValue.value can be updated to an unsupported CSS keyword +Pass CSSKeywordValue.value can be updated to a string containing multiple tokens +Pass CSSKeywordValue.value can be updated to a unicode string +Pass Updating CSSKeywordValue.value with an empty string throws a TypeError \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue.txt index efa569d6db9..bc3db8ebbbd 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-typed-om/stylevalue-subclasses/cssKeywordValue.txt @@ -2,9 +2,9 @@ Harness status: OK Found 5 tests -5 Fail -Fail CSSKeywordValue can be constructed from a CSS wide keyword -Fail CSSKeywordValue can be constructed from a CSS keyword -Fail CSSKeywordValue can be constructed from an unsupported CSS keyword -Fail CSSKeywordValue can be constructed from a string containing multiple tokens -Fail CSSKeywordValue can be constructed from a unicode string \ No newline at end of file +5 Pass +Pass CSSKeywordValue can be constructed from a CSS wide keyword +Pass CSSKeywordValue can be constructed from a CSS keyword +Pass CSSKeywordValue can be constructed from an unsupported CSS keyword +Pass CSSKeywordValue can be constructed from a string containing multiple tokens +Pass CSSKeywordValue can be constructed from a unicode string \ No newline at end of file