From 3bb54ffd59ef6c35470979d6c2e85184eb531ec9 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Mon, 11 Aug 2025 15:11:49 +0100 Subject: [PATCH] LibWeb/CSS: Stub out StylePropertyMap --- Libraries/LibWeb/CMakeLists.txt | 1 + Libraries/LibWeb/CSS/StylePropertyMap.cpp | 142 ++++++++++++++++++ Libraries/LibWeb/CSS/StylePropertyMap.h | 34 +++++ Libraries/LibWeb/CSS/StylePropertyMap.idl | 10 ++ Libraries/LibWeb/Forward.h | 1 + Libraries/LibWeb/idl_files.cmake | 1 + .../Text/expected/all-window-properties.txt | 1 + 7 files changed, 190 insertions(+) create mode 100644 Libraries/LibWeb/CSS/StylePropertyMap.cpp create mode 100644 Libraries/LibWeb/CSS/StylePropertyMap.h create mode 100644 Libraries/LibWeb/CSS/StylePropertyMap.idl diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 5c1d1f1c7fb..4f90d86f894 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -187,6 +187,7 @@ set(SOURCES CSS/StyleInvalidationData.cpp CSS/StyleProperty.cpp CSS/StylePropertyMapReadOnly.cpp + CSS/StylePropertyMap.cpp CSS/StyleSheet.cpp CSS/StyleSheetIdentifier.cpp CSS/StyleSheetList.cpp diff --git a/Libraries/LibWeb/CSS/StylePropertyMap.cpp b/Libraries/LibWeb/CSS/StylePropertyMap.cpp new file mode 100644 index 00000000000..cda2d5717a2 --- /dev/null +++ b/Libraries/LibWeb/CSS/StylePropertyMap.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "StylePropertyMap.h" +#include +#include +#include +#include + +namespace Web::CSS { + +GC_DEFINE_ALLOCATOR(StylePropertyMap); + +GC::Ref StylePropertyMap::create(JS::Realm& realm, GC::Ref declaration) +{ + return realm.create(realm, declaration); +} + +StylePropertyMap::StylePropertyMap(JS::Realm& realm, GC::Ref declaration) + : StylePropertyMapReadOnly(realm, declaration) +{ +} + +StylePropertyMap::~StylePropertyMap() = default; + +void StylePropertyMap::initialize(JS::Realm& realm) +{ + WEB_SET_PROTOTYPE_FOR_INTERFACE(StylePropertyMap); + Base::initialize(realm); +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set +WebIDL::ExceptionOr StylePropertyMap::set(String property, Vector, String>> values) +{ + // The set(property, ...values) method, when called on a StylePropertyMap this, must perform the following steps: + + // 1. If property is not a custom property name string, set property to property ASCII lowercased. + if (!is_a_custom_property_name_string(property)) + property = property.to_ascii_lowercase(); + + // 2. If property is not a valid CSS property, throw a TypeError. + if (!is_a_valid_css_property(property)) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("'{}' is not a valid CSS property", property)) }; + + // FIXME: 3. If property is a single-valued property and values has more than one item, throw a TypeError. + + // FIXME: 4. If any of the items in values have a non-null [[associatedProperty]] internal slot, and that slot’s value is anything other than property, throw a TypeError. + + // FIXME: 5. If the size of values is two or more, and one or more of the items are a CSSUnparsedValue or CSSVariableReferenceValue object, throw a TypeError. + // NOTE: Having 2+ values implies that you’re setting multiple items of a list-valued property, but the presence of + // a var() function in the string-based OM disables all syntax parsing, including splitting into individual + // iterations (because there might be more commas inside of the var() value, so you can’t tell how many items + // are actually going to show up). This step’s restriction preserves the same semantics in the Typed OM. + + // 6. Let props be the value of this’s [[declarations]] internal slot. + auto& props = m_declarations; + + // 7. If props[property] exists, remove it. + props.remove(property); + + // FIXME: 8. Let values to set be an empty list. + + // FIXME: 9. For each value in values, create an internal representation for property and value, and append the result to values to set. + (void)values; + + // FIXME: 10. Set props[property] to values to set. + // NOTE: The property is deleted then added back so that it gets put at the end of the ordered map, which gives the + // expected behavior in the face of shorthand properties. + + return {}; +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-append +WebIDL::ExceptionOr StylePropertyMap::append(String property, Vector, String>> values) +{ + // The append(property, ...values) method, when called on a StylePropertyMap this, must perform the following steps: + + // 1. If property is not a custom property name string, set property to property ASCII lowercased. + if (!is_a_custom_property_name_string(property)) + property = property.to_ascii_lowercase(); + + // 2. If property is not a valid CSS property, throw a TypeError. + if (!is_a_valid_css_property(property)) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("'{}' is not a valid CSS property", property)) }; + + // FIXME: 3. If property is not a list-valued property, throw a TypeError. + + // FIXME: 4. If any of the items in values have a non-null [[associatedProperty]] internal slot, and that slot’s value is anything other than property, throw a TypeError. + + // FIXME: 5. If any of the items in values are a CSSUnparsedValue or CSSVariableReferenceValue object, throw a TypeError. + + // NOTE: When a property is set via string-based APIs, the presence of var() in a property prevents the entire thing from being interpreted. In other words, everything besides the var() is a plain component value, not a meaningful type. This step’s restriction preserves the same semantics in the Typed OM. + + // 6. Let props be the value of this’s [[declarations]] internal slot. + auto& props = m_declarations; + + // FIXME: 7. If props[property] does not exist, set props[property] to an empty list. + (void)props; + + // FIXME: 8. If props[property] contains a var() reference, throw a TypeError. + + // FIXME: 9. Let temp values be an empty list. + + // FIXME: 10. For each value in values, create an internal representation with property and value, and append the returned value to temp values. + (void)values; + + // FIXME: 11. Append the entries of temp values to props[property]. + + return {}; +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-delete +WebIDL::ExceptionOr StylePropertyMap::delete_(String property) +{ + // The delete(property) method, when called on a StylePropertyMap this, must perform the following steps: + + // 1. If property is not a custom property name string, set property to property ASCII lowercased. + if (!is_a_custom_property_name_string(property)) + property = property.to_ascii_lowercase(); + + // 2. If property is not a valid CSS property, throw a TypeError. + if (!is_a_valid_css_property(property)) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("'{}' is not a valid CSS property", property)) }; + + // 3. If this’s [[declarations]] internal slot contains property, remove it. + m_declarations.remove(property); + return {}; +} + +// https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-clear +void StylePropertyMap::clear() +{ + // The clear() method, when called on a StylePropertyMap this, must perform the following steps: + + // 1. Remove all of the declarations in this’s [[declarations]] internal slot. + m_declarations.clear(); +} + +} diff --git a/Libraries/LibWeb/CSS/StylePropertyMap.h b/Libraries/LibWeb/CSS/StylePropertyMap.h new file mode 100644 index 00000000000..511ae425a78 --- /dev/null +++ b/Libraries/LibWeb/CSS/StylePropertyMap.h @@ -0,0 +1,34 @@ +/* + * 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/#stylepropertymap +class StylePropertyMap : public StylePropertyMapReadOnly { + WEB_PLATFORM_OBJECT(StylePropertyMap, StylePropertyMapReadOnly); + GC_DECLARE_ALLOCATOR(StylePropertyMap); + +public: + [[nodiscard]] static GC::Ref create(JS::Realm&, GC::Ref); + + virtual ~StylePropertyMap() override; + + WebIDL::ExceptionOr set(String property, Vector, String>> values); + WebIDL::ExceptionOr append(String property, Vector, String>> values); + WebIDL::ExceptionOr delete_(String property); + void clear(); + +private: + explicit StylePropertyMap(JS::Realm&, GC::Ref); + + virtual void initialize(JS::Realm&) override; +}; + +} diff --git a/Libraries/LibWeb/CSS/StylePropertyMap.idl b/Libraries/LibWeb/CSS/StylePropertyMap.idl new file mode 100644 index 00000000000..20d5bbd76d9 --- /dev/null +++ b/Libraries/LibWeb/CSS/StylePropertyMap.idl @@ -0,0 +1,10 @@ +#import + +// https://drafts.css-houdini.org/css-typed-om-1/#stylepropertymap +[Exposed=Window] +interface StylePropertyMap : StylePropertyMapReadOnly { + undefined set(USVString property, (CSSStyleValue or USVString)... values); + undefined append(USVString property, (CSSStyleValue or USVString)... values); + undefined delete(USVString property); + undefined clear(); +}; diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 04aa34d4be2..68905e8ca45 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -337,6 +337,7 @@ class Size; class ScrollbarColorStyleValue; class StringStyleValue; class StyleComputer; +class StylePropertyMap; class StylePropertyMapReadOnly; class StyleSheet; class StyleSheetList; diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index 534111cb6e3..9b7421d3a62 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -58,6 +58,7 @@ libweb_js_bindings(CSS/MediaQueryList) libweb_js_bindings(CSS/MediaQueryListEvent) libweb_js_bindings(CSS/Screen) libweb_js_bindings(CSS/ScreenOrientation) +libweb_js_bindings(CSS/StylePropertyMap) libweb_js_bindings(CSS/StylePropertyMapReadOnly) libweb_js_bindings(CSS/StyleSheet) libweb_js_bindings(CSS/StyleSheetList) diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index a6b89b5da10..5f7e0260fe0 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -409,6 +409,7 @@ Storage StorageEvent StorageManager String +StylePropertyMap StylePropertyMapReadOnly StyleSheet StyleSheetList