2021-09-12 20:05:29 +02:00
/*
2025-02-26 18:16:36 +01:00
* Copyright ( c ) 2021 - 2025 , Andreas Kling < andreas @ ladybird . org >
2021-09-13 19:54:54 +02:00
* Copyright ( c ) 2021 , Tobias Christiansen < tobyase @ serenityos . org >
2025-02-06 11:10:36 +00:00
* Copyright ( c ) 2022 - 2025 , Sam Atkins < sam @ ladybird . org >
2021-09-12 20:05:29 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2022-02-06 14:17:42 +01:00
# include <AK/Debug.h>
2022-12-06 03:08:20 -03:00
# include <AK/Format.h>
2021-09-14 00:38:46 +02:00
# include <AK/NonnullRefPtr.h>
2025-02-18 09:19:56 +01:00
# include <LibWeb/CSS/ComputedProperties.h>
2021-09-23 12:35:56 +02:00
# include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h>
2021-09-24 13:49:57 +02:00
# include <LibWeb/CSS/StyleComputer.h>
2023-03-23 17:44:13 +00:00
# include <LibWeb/CSS/StyleValues/BackgroundRepeatStyleValue.h>
2023-05-27 15:50:17 +01:00
# include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
2024-08-14 16:37:02 +01:00
# include <LibWeb/CSS/StyleValues/CSSColorValue.h>
2024-08-14 11:46:56 +01:00
# include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
2025-02-26 18:16:36 +01:00
# include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
2023-03-24 17:04:04 +00:00
# include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
2023-06-01 16:16:15 +01:00
# include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
2023-03-24 17:28:43 +00:00
# include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
2023-03-24 17:45:25 +00:00
# include <LibWeb/CSS/StyleValues/ShadowStyleValue.h>
2023-09-19 15:27:13 +01:00
# include <LibWeb/CSS/StyleValues/ShorthandStyleValue.h>
2023-03-25 00:12:21 +00:00
# include <LibWeb/CSS/StyleValues/StyleValueList.h>
2023-03-24 17:59:33 +00:00
# include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
2021-09-12 20:05:29 +02:00
# include <LibWeb/DOM/Document.h>
# include <LibWeb/DOM/Element.h>
2022-07-19 16:44:24 +01:00
# include <LibWeb/Painting/PaintableBox.h>
# include <LibWeb/Painting/StackingContext.h>
2021-09-12 20:05:29 +02:00
namespace Web : : CSS {
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( ResolvedCSSStyleDeclaration ) ;
2023-11-19 19:47:52 +01:00
2024-11-15 04:01:23 +13:00
GC : : Ref < ResolvedCSSStyleDeclaration > ResolvedCSSStyleDeclaration : : create ( DOM : : Element & element , Optional < Selector : : PseudoElement : : Type > pseudo_element )
2022-08-07 16:21:26 +02:00
{
2024-11-14 05:50:17 +13:00
return element . realm ( ) . create < ResolvedCSSStyleDeclaration > ( element , move ( pseudo_element ) ) ;
2022-08-07 16:21:26 +02:00
}
2024-08-06 12:48:21 +01:00
ResolvedCSSStyleDeclaration : : ResolvedCSSStyleDeclaration ( DOM : : Element & element , Optional < CSS : : Selector : : PseudoElement : : Type > pseudo_element )
2022-09-24 16:34:04 -06:00
: CSSStyleDeclaration ( element . realm ( ) )
2022-08-07 16:21:26 +02:00
, m_element ( element )
2024-08-06 12:48:21 +01:00
, m_pseudo_element ( move ( pseudo_element ) )
2021-09-12 20:05:29 +02:00
{
}
2022-08-28 13:42:07 +02:00
void ResolvedCSSStyleDeclaration : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
2023-11-19 16:18:00 +13:00
visitor . visit ( m_element ) ;
2022-08-28 13:42:07 +02:00
}
2023-09-29 16:48:54 +01:00
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-length
2021-09-23 12:35:56 +02:00
size_t ResolvedCSSStyleDeclaration : : length ( ) const
2021-09-12 20:05:29 +02:00
{
2023-09-29 16:48:54 +01:00
// The length attribute must return the number of CSS declarations in the declarations.
// FIXME: Include the number of custom properties.
return to_underlying ( last_longhand_property_id ) - to_underlying ( first_longhand_property_id ) + 1 ;
2021-09-12 20:05:29 +02:00
}
2023-09-29 16:48:54 +01:00
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-item
2023-09-06 19:07:24 +12:00
String ResolvedCSSStyleDeclaration : : item ( size_t index ) const
2021-09-12 20:05:29 +02:00
{
2023-09-29 16:48:54 +01:00
// The item(index) method must return the property name of the CSS declaration at position index.
// FIXME: Return custom properties if index > last_longhand_property_id.
2024-11-14 15:37:48 +00:00
if ( index > = length ( ) )
2023-09-29 16:48:54 +01:00
return { } ;
auto property_id = static_cast < PropertyID > ( index + to_underlying ( first_longhand_property_id ) ) ;
2024-03-15 20:32:45 +01:00
return string_from_property_id ( property_id ) . to_string ( ) ;
2021-09-12 20:05:29 +02:00
}
2024-08-14 11:10:54 +01:00
static NonnullRefPtr < CSSStyleValue const > style_value_for_length_percentage ( LengthPercentage const & length_percentage )
2022-01-19 11:52:01 +00:00
{
2023-04-19 11:20:50 +01:00
if ( length_percentage . is_auto ( ) )
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : Auto ) ;
2022-01-19 11:52:01 +00:00
if ( length_percentage . is_percentage ( ) )
2023-05-02 14:52:31 +01:00
return PercentageStyleValue : : create ( length_percentage . percentage ( ) ) ;
2022-04-03 22:05:03 +02:00
if ( length_percentage . is_length ( ) )
2023-05-02 14:52:31 +01:00
return LengthStyleValue : : create ( length_percentage . length ( ) ) ;
2022-04-03 22:05:03 +02:00
return length_percentage . calculated ( ) ;
2022-01-19 11:52:01 +00:00
}
2024-08-14 11:10:54 +01:00
static NonnullRefPtr < CSSStyleValue const > style_value_for_size ( Size const & size )
2022-09-25 15:48:23 +02:00
{
if ( size . is_none ( ) )
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : None ) ;
2022-09-25 15:48:23 +02:00
if ( size . is_percentage ( ) )
2023-05-02 14:52:31 +01:00
return PercentageStyleValue : : create ( size . percentage ( ) ) ;
2022-09-25 15:48:23 +02:00
if ( size . is_length ( ) )
2023-05-02 14:52:31 +01:00
return LengthStyleValue : : create ( size . length ( ) ) ;
2022-09-25 15:48:23 +02:00
if ( size . is_auto ( ) )
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : Auto ) ;
2023-03-30 10:50:40 +01:00
if ( size . is_calculated ( ) )
return size . calculated ( ) ;
2022-09-25 15:48:23 +02:00
if ( size . is_min_content ( ) )
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : MinContent ) ;
2022-09-25 15:48:23 +02:00
if ( size . is_max_content ( ) )
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : MaxContent ) ;
2023-08-30 11:53:50 +02:00
if ( size . is_fit_content ( ) )
2025-02-26 18:16:36 +01:00
return FitContentStyleValue : : create ( size . fit_content_available_space ( ) ) ;
2022-09-25 15:48:23 +02:00
TODO ( ) ;
}
2023-09-29 13:13:18 +01:00
enum class LogicalSide {
BlockStart ,
BlockEnd ,
InlineStart ,
InlineEnd ,
} ;
2024-08-14 11:10:54 +01:00
static RefPtr < CSSStyleValue const > style_value_for_length_box_logical_side ( Layout : : NodeWithStyle const & , LengthBox const & box , LogicalSide logical_side )
2023-09-29 13:13:18 +01:00
{
// FIXME: Actually determine the logical sides based on layout_node's writing-mode and direction.
switch ( logical_side ) {
case LogicalSide : : BlockStart :
return style_value_for_length_percentage ( box . top ( ) ) ;
case LogicalSide : : BlockEnd :
return style_value_for_length_percentage ( box . bottom ( ) ) ;
case LogicalSide : : InlineStart :
return style_value_for_length_percentage ( box . left ( ) ) ;
case LogicalSide : : InlineEnd :
return style_value_for_length_percentage ( box . right ( ) ) ;
}
VERIFY_NOT_REACHED ( ) ;
}
2025-02-21 11:52:37 +01:00
static CSSPixels pixels_for_pixel_box_logical_side ( Layout : : NodeWithStyle const & , Painting : : PixelBox const & box , LogicalSide logical_side )
{
// FIXME: Actually determine the logical sides based on layout_node's writing-mode and direction.
switch ( logical_side ) {
case LogicalSide : : BlockStart :
return box . top ;
case LogicalSide : : BlockEnd :
return box . bottom ;
case LogicalSide : : InlineStart :
return box . left ;
case LogicalSide : : InlineEnd :
return box . right ;
}
VERIFY_NOT_REACHED ( ) ;
}
2024-08-14 11:10:54 +01:00
static RefPtr < CSSStyleValue const > style_value_for_shadow ( Vector < ShadowData > const & shadow_data )
2023-09-29 13:53:47 +01:00
{
if ( shadow_data . is_empty ( ) )
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : None ) ;
2023-09-29 13:53:47 +01:00
auto make_shadow_style_value = [ ] ( ShadowData const & shadow ) {
return ShadowStyleValue : : create (
2025-02-19 21:02:12 +11:00
CSSColorValue : : create_from_color ( shadow . color , ColorSyntax : : Modern ) ,
2023-09-29 13:53:47 +01:00
style_value_for_length_percentage ( shadow . offset_x ) ,
style_value_for_length_percentage ( shadow . offset_y ) ,
style_value_for_length_percentage ( shadow . blur_radius ) ,
style_value_for_length_percentage ( shadow . spread_distance ) ,
shadow . placement ) ;
} ;
if ( shadow_data . size ( ) = = 1 )
return make_shadow_style_value ( shadow_data . first ( ) ) ;
StyleValueVector style_values ;
style_values . ensure_capacity ( shadow_data . size ( ) ) ;
for ( auto & shadow : shadow_data )
style_values . unchecked_append ( make_shadow_style_value ( shadow ) ) ;
return StyleValueList : : create ( move ( style_values ) , StyleValueList : : Separator : : Comma ) ;
}
2024-08-14 11:10:54 +01:00
RefPtr < CSSStyleValue const > ResolvedCSSStyleDeclaration : : style_value_for_property ( Layout : : NodeWithStyle const & layout_node , PropertyID property_id ) const
2021-09-12 20:05:29 +02:00
{
2024-06-14 17:17:16 +02:00
auto used_value_for_property = [ & layout_node , property_id ] ( Function < CSSPixels ( Painting : : PaintableBox const & ) > & & used_value_getter ) - > Optional < CSSPixels > {
2024-05-06 23:29:21 +01:00
auto const & display = layout_node . computed_values ( ) . display ( ) ;
2024-10-16 15:19:32 +02:00
if ( ! display . is_none ( ) & & ! display . is_contents ( ) & & layout_node . first_paintable ( ) ) {
if ( layout_node . first_paintable ( ) - > is_paintable_box ( ) ) {
auto const & paintable_box = static_cast < Painting : : PaintableBox const & > ( * layout_node . first_paintable ( ) ) ;
2024-05-06 23:29:21 +01:00
return used_value_getter ( paintable_box ) ;
}
2024-06-14 17:17:16 +02:00
dbgln ( " FIXME: Support getting used value for property `{}` on {} " , string_from_property_id ( property_id ) , layout_node . debug_description ( ) ) ;
2024-05-06 23:29:21 +01:00
}
return { } ;
} ;
2025-03-17 16:12:50 +00:00
auto used_value_for_inset = [ & layout_node , used_value_for_property ] ( LengthPercentage const & start_side , LengthPercentage const & end_side , Function < CSSPixels ( Painting : : PaintableBox const & ) > & & used_value_getter ) - > Optional < CSSPixels > {
if ( ! layout_node . is_positioned ( ) )
return { } ;
// FIXME: Support getting the used value when position is sticky.
if ( layout_node . is_sticky_position ( ) )
return { } ;
if ( ! start_side . is_percentage ( ) & & ! start_side . is_calculated ( ) & & ! start_side . is_auto ( ) & & ! end_side . is_auto ( ) )
return { } ;
return used_value_for_property ( move ( used_value_getter ) ) ;
} ;
2024-11-03 13:20:04 +01:00
auto get_computed_value = [ this ] ( PropertyID property_id ) - > auto const & {
2024-08-06 12:48:21 +01:00
if ( m_pseudo_element . has_value ( ) )
2024-12-20 16:35:12 +01:00
return m_element - > pseudo_element_computed_properties ( m_pseudo_element . value ( ) ) - > property ( property_id ) ;
return m_element - > computed_properties ( ) - > property ( property_id ) ;
2024-08-06 12:48:21 +01:00
} ;
2023-09-09 12:04:40 +01:00
// A limited number of properties have special rules for producing their "resolved value".
// We also have to manually construct shorthands from their longhands here.
// Everything else uses the computed value.
2024-12-19 12:18:07 +01:00
// https://drafts.csswg.org/cssom/#resolved-values
2023-09-29 13:58:01 +01:00
// The resolved value for a given longhand property can be determined as follows:
2021-09-12 20:05:29 +02:00
switch ( property_id ) {
2023-09-29 13:58:01 +01:00
// -> background-color
2025-03-10 23:16:50 +00:00
// -> border-block-end-color
// -> border-block-start-color
2023-09-29 13:58:01 +01:00
// -> border-bottom-color
2025-03-10 22:39:22 +00:00
// -> border-inline-end-color
// -> border-inline-start-color
2023-09-29 13:58:01 +01:00
// -> border-left-color
// -> border-right-color
// -> border-top-color
2023-09-29 13:53:47 +01:00
// -> box-shadow
2025-03-09 13:59:33 +00:00
// -> caret-color
2023-09-29 13:58:01 +01:00
// -> color
// -> outline-color
// -> A resolved value special case property like color defined in another specification
// The resolved value is the used value.
2022-07-14 17:04:03 +01:00
case PropertyID : : BackgroundColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . background_color ( ) , ColorSyntax : : Modern ) ;
2025-03-10 23:16:50 +00:00
case PropertyID : : BorderBlockEndColor :
// FIXME: Honor writing-mode, direction and text-orientation.
return style_value_for_property ( layout_node , PropertyID : : BorderBottomColor ) ;
case PropertyID : : BorderBlockStartColor :
// FIXME: Honor writing-mode, direction and text-orientation.
return style_value_for_property ( layout_node , PropertyID : : BorderTopColor ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : BorderBottomColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . border_bottom ( ) . color , ColorSyntax : : Modern ) ;
2025-03-10 22:39:22 +00:00
case PropertyID : : BorderInlineEndColor :
// FIXME: Honor writing-mode, direction and text-orientation.
return style_value_for_property ( layout_node , PropertyID : : BorderRightColor ) ;
case PropertyID : : BorderInlineStartColor :
// FIXME: Honor writing-mode, direction and text-orientation.
return style_value_for_property ( layout_node , PropertyID : : BorderLeftColor ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : BorderLeftColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . border_left ( ) . color , ColorSyntax : : Modern ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : BorderRightColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . border_right ( ) . color , ColorSyntax : : Modern ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : BorderTopColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . border_top ( ) . color , ColorSyntax : : Modern ) ;
2023-09-29 13:53:47 +01:00
case PropertyID : : BoxShadow :
return style_value_for_shadow ( layout_node . computed_values ( ) . box_shadow ( ) ) ;
2025-03-09 13:59:33 +00:00
case PropertyID : : CaretColor :
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . caret_color ( ) , ColorSyntax : : Modern ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : Color :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . color ( ) , ColorSyntax : : Modern ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : OutlineColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . outline_color ( ) , ColorSyntax : : Modern ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : TextDecorationColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . text_decoration_color ( ) , ColorSyntax : : Modern ) ;
2023-09-29 13:53:47 +01:00
// NOTE: text-shadow isn't listed, but is computed the same as box-shadow.
case PropertyID : : TextShadow :
return style_value_for_shadow ( layout_node . computed_values ( ) . text_shadow ( ) ) ;
2023-09-29 13:58:01 +01:00
2023-09-29 12:47:20 +01:00
// -> line-height
2023-09-29 13:58:01 +01:00
// The resolved value is normal if the computed value is normal, or the used value otherwise.
2023-09-29 12:47:20 +01:00
case PropertyID : : LineHeight : {
2024-11-03 13:20:04 +01:00
auto const & line_height = get_computed_value ( property_id ) ;
if ( line_height . is_keyword ( ) & & line_height . to_keyword ( ) = = Keyword : : Normal )
2023-09-29 12:47:20 +01:00
return line_height ;
2024-01-12 15:34:13 +01:00
return LengthStyleValue : : create ( Length : : make_px ( layout_node . computed_values ( ) . line_height ( ) ) ) ;
2023-09-29 12:47:20 +01:00
}
2023-09-29 13:58:01 +01:00
2025-03-09 20:25:34 +00:00
// -> block-size
2023-09-29 13:58:01 +01:00
// -> height
2025-03-09 20:28:59 +00:00
// -> inline-size
2023-09-29 13:13:18 +01:00
// -> margin-block-end
// -> margin-block-start
2023-09-29 13:58:01 +01:00
// -> margin-bottom
2023-09-29 13:13:18 +01:00
// -> margin-inline-end
// -> margin-inline-start
2023-09-29 13:58:01 +01:00
// -> margin-left
// -> margin-right
// -> margin-top
2023-09-29 13:13:18 +01:00
// -> padding-block-end
// -> padding-block-start
2023-09-29 13:58:01 +01:00
// -> padding-bottom
2023-09-29 13:13:18 +01:00
// -> padding-inline-end
// -> padding-inline-start
2023-09-29 13:58:01 +01:00
// -> padding-left
// -> padding-right
// -> padding-top
2023-09-29 13:02:11 +01:00
// -> width
2024-02-05 09:43:55 +01:00
// If the property applies to the element or pseudo-element and the resolved value of the
// display property is not none or contents, then the resolved value is the used value.
// Otherwise the resolved value is the computed value.
2025-03-09 20:25:34 +00:00
case PropertyID : : BlockSize : {
auto writing_mode = layout_node . computed_values ( ) . writing_mode ( ) ;
auto is_vertically_oriented = first_is_one_of ( writing_mode , WritingMode : : VerticalLr , WritingMode : : VerticalRl ) ;
if ( is_vertically_oriented )
return style_value_for_property ( layout_node , PropertyID : : Width ) ;
return style_value_for_property ( layout_node , PropertyID : : Height ) ;
}
2024-05-06 23:29:21 +01:00
case PropertyID : : Height : {
auto maybe_used_height = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . content_height ( ) ; } ) ;
if ( maybe_used_height . has_value ( ) )
return style_value_for_size ( Size : : make_px ( maybe_used_height . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_size ( layout_node . computed_values ( ) . height ( ) ) ;
2024-02-05 09:43:55 +01:00
}
2025-03-09 20:28:59 +00:00
case PropertyID : : InlineSize : {
auto writing_mode = layout_node . computed_values ( ) . writing_mode ( ) ;
auto is_vertically_oriented = first_is_one_of ( writing_mode , WritingMode : : VerticalLr , WritingMode : : VerticalRl ) ;
if ( is_vertically_oriented )
return style_value_for_property ( layout_node , PropertyID : : Height ) ;
return style_value_for_property ( layout_node , PropertyID : : Width ) ;
}
2023-09-29 13:13:18 +01:00
case PropertyID : : MarginBlockEnd :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . margin , LogicalSide : : BlockEnd ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . margin ( ) , LogicalSide : : BlockEnd ) ;
case PropertyID : : MarginBlockStart :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . margin , LogicalSide : : BlockStart ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . margin ( ) , LogicalSide : : BlockStart ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : MarginBottom :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . margin . bottom ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . bottom ( ) ) ;
2023-09-29 13:13:18 +01:00
case PropertyID : : MarginInlineEnd :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . margin , LogicalSide : : InlineEnd ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . margin ( ) , LogicalSide : : InlineEnd ) ;
case PropertyID : : MarginInlineStart :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . margin , LogicalSide : : InlineStart ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . margin ( ) , LogicalSide : : InlineStart ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : MarginLeft :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . margin . left ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . left ( ) ) ;
case PropertyID : : MarginRight :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . margin . right ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . right ( ) ) ;
case PropertyID : : MarginTop :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . margin . top ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . top ( ) ) ;
2023-09-29 13:13:18 +01:00
case PropertyID : : PaddingBlockEnd :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . padding , LogicalSide : : BlockEnd ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . padding ( ) , LogicalSide : : BlockEnd ) ;
case PropertyID : : PaddingBlockStart :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . padding , LogicalSide : : BlockStart ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . padding ( ) , LogicalSide : : BlockStart ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : PaddingBottom :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . padding . bottom ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . bottom ( ) ) ;
2023-09-29 13:13:18 +01:00
case PropertyID : : PaddingInlineEnd :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . padding , LogicalSide : : InlineEnd ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . padding ( ) , LogicalSide : : InlineEnd ) ;
case PropertyID : : PaddingInlineStart :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ & ] ( auto const & paintable_box ) { return pixels_for_pixel_box_logical_side ( layout_node , paintable_box . box_model ( ) . padding , LogicalSide : : InlineStart ) ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:13:18 +01:00
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . padding ( ) , LogicalSide : : InlineStart ) ;
2023-09-29 13:58:01 +01:00
case PropertyID : : PaddingLeft :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . padding . left ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . left ( ) ) ;
case PropertyID : : PaddingRight :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . padding . right ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . right ( ) ) ;
case PropertyID : : PaddingTop :
2025-02-21 11:52:37 +01:00
if ( auto maybe_used_value = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . padding . top ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . top ( ) ) ;
2024-05-06 23:29:21 +01:00
case PropertyID : : Width : {
auto maybe_used_width = used_value_for_property ( [ ] ( auto const & paintable_box ) { return paintable_box . content_width ( ) ; } ) ;
if ( maybe_used_width . has_value ( ) )
return style_value_for_size ( Size : : make_px ( maybe_used_width . release_value ( ) ) ) ;
2023-09-29 13:58:01 +01:00
return style_value_for_size ( layout_node . computed_values ( ) . width ( ) ) ;
2024-05-06 23:29:21 +01:00
}
2023-09-29 13:58:01 +01:00
// -> bottom
// -> left
2023-09-29 13:13:18 +01:00
// -> inset-block-end
// -> inset-block-start
// -> inset-inline-end
// -> inset-inline-start
2023-09-29 13:58:01 +01:00
// -> right
// -> top
// -> A resolved value special case property like top defined in another specification
2025-03-17 16:12:50 +00:00
// If the property applies to a positioned element and the resolved value of the display property is not
2023-09-29 13:58:01 +01:00
// none or contents, and the property is not over-constrained, then the resolved value is the used value.
// Otherwise the resolved value is the computed value.
2025-03-17 16:12:50 +00:00
case PropertyID : : Bottom : {
auto & inset = layout_node . computed_values ( ) . inset ( ) ;
if ( auto maybe_used_value = used_value_for_inset ( inset . bottom ( ) , inset . top ( ) , [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . inset . bottom ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
return style_value_for_length_percentage ( inset . bottom ( ) ) ;
}
2023-09-29 13:13:18 +01:00
case PropertyID : : InsetBlockEnd :
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . inset ( ) , LogicalSide : : BlockEnd ) ;
case PropertyID : : InsetBlockStart :
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . inset ( ) , LogicalSide : : BlockStart ) ;
case PropertyID : : InsetInlineEnd :
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . inset ( ) , LogicalSide : : InlineEnd ) ;
case PropertyID : : InsetInlineStart :
return style_value_for_length_box_logical_side ( layout_node , layout_node . computed_values ( ) . inset ( ) , LogicalSide : : InlineStart ) ;
2025-03-17 16:12:50 +00:00
case PropertyID : : Left : {
auto & inset = layout_node . computed_values ( ) . inset ( ) ;
if ( auto maybe_used_value = used_value_for_inset ( inset . left ( ) , inset . right ( ) , [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . inset . left ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
return style_value_for_length_percentage ( inset . left ( ) ) ;
}
case PropertyID : : Right : {
auto & inset = layout_node . computed_values ( ) . inset ( ) ;
if ( auto maybe_used_value = used_value_for_inset ( inset . right ( ) , inset . left ( ) , [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . inset . right ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
return style_value_for_length_percentage ( inset . right ( ) ) ;
}
case PropertyID : : Top : {
auto & inset = layout_node . computed_values ( ) . inset ( ) ;
if ( auto maybe_used_value = used_value_for_inset ( inset . top ( ) , inset . bottom ( ) , [ ] ( auto const & paintable_box ) { return paintable_box . box_model ( ) . inset . top ; } ) ; maybe_used_value . has_value ( ) )
return LengthStyleValue : : create ( Length : : make_px ( maybe_used_value . release_value ( ) ) ) ;
return style_value_for_length_percentage ( inset . top ( ) ) ;
}
2023-09-29 13:58:01 +01:00
// -> A resolved value special case property defined in another specification
// As defined in the relevant specification.
case PropertyID : : Transform : {
auto transformations = layout_node . computed_values ( ) . transformations ( ) ;
if ( transformations . is_empty ( ) )
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : None ) ;
2023-09-29 13:58:01 +01:00
2023-10-12 12:30:28 +01:00
// https://drafts.csswg.org/css-transforms-2/#serialization-of-the-computed-value
// The transform property is a resolved value special case property. [CSSOM]
// When the computed value is a <transform-list>, the resolved value is one <matrix()> function or one <matrix3d()> function computed by the following algorithm:
// 1. Let transform be a 4x4 matrix initialized to the identity matrix.
// The elements m11, m22, m33 and m44 of transform must be set to 1; all other elements of transform must be set to 0.
auto transform = FloatMatrix4x4 : : identity ( ) ;
2023-09-29 13:58:01 +01:00
2023-10-12 12:30:28 +01:00
// 2. Post-multiply all <transform-function>s in <transform-list> to transform.
2024-10-16 15:19:32 +02:00
VERIFY ( layout_node . first_paintable ( ) ) ;
2025-01-21 09:12:05 -05:00
auto const & paintable_box = as < Painting : : PaintableBox const > ( * layout_node . first_paintable ( ) ) ;
2023-10-12 12:30:28 +01:00
for ( auto transformation : transformations ) {
2024-01-06 18:05:21 +01:00
transform = transform * transformation . to_matrix ( paintable_box ) . release_value ( ) ;
2023-10-12 12:30:28 +01:00
}
// https://drafts.csswg.org/css-transforms-1/#2d-matrix
auto is_2d_matrix = [ ] ( Gfx : : FloatMatrix4x4 const & matrix ) - > bool {
// A 3x2 transformation matrix,
// or a 4x4 matrix where the items m31, m32, m13, m23, m43, m14, m24, m34 are equal to 0
// and m33, m44 are equal to 1.
// NOTE: We only care about 4x4 matrices here.
// NOTE: Our elements are 0-indexed not 1-indexed, and in the opposite order.
if ( matrix . elements ( ) [ 0 ] [ 2 ] ! = 0 // m31
| | matrix . elements ( ) [ 1 ] [ 2 ] ! = 0 // m32
| | matrix . elements ( ) [ 2 ] [ 0 ] ! = 0 // m13
| | matrix . elements ( ) [ 2 ] [ 1 ] ! = 0 // m23
| | matrix . elements ( ) [ 2 ] [ 3 ] ! = 0 // m43
| | matrix . elements ( ) [ 3 ] [ 0 ] ! = 0 // m14
| | matrix . elements ( ) [ 3 ] [ 1 ] ! = 0 // m24
| | matrix . elements ( ) [ 3 ] [ 2 ] ! = 0 ) // m34
return false ;
if ( matrix . elements ( ) [ 2 ] [ 2 ] ! = 1 // m33
| | matrix . elements ( ) [ 3 ] [ 3 ] ! = 1 ) // m44
return false ;
return true ;
} ;
// 3. Chose between <matrix()> or <matrix3d()> serialization:
// -> If transform is a 2D matrix
// Serialize transform to a <matrix()> function.
if ( is_2d_matrix ( transform ) ) {
StyleValueVector parameters {
NumberStyleValue : : create ( transform . elements ( ) [ 0 ] [ 0 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 1 ] [ 0 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 0 ] [ 1 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 1 ] [ 1 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 0 ] [ 3 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 1 ] [ 3 ] ) ,
} ;
2025-01-15 14:58:23 +00:00
return TransformationStyleValue : : create ( PropertyID : : Transform , TransformFunction : : Matrix , move ( parameters ) ) ;
2023-10-12 12:30:28 +01:00
}
// -> Otherwise
// Serialize transform to a <matrix3d()> function.
else {
StyleValueVector parameters {
NumberStyleValue : : create ( transform . elements ( ) [ 0 ] [ 0 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 1 ] [ 0 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 2 ] [ 0 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 3 ] [ 0 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 0 ] [ 1 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 1 ] [ 1 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 2 ] [ 1 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 3 ] [ 1 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 0 ] [ 2 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 1 ] [ 2 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 2 ] [ 2 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 3 ] [ 2 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 0 ] [ 3 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 1 ] [ 3 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 2 ] [ 3 ] ) ,
NumberStyleValue : : create ( transform . elements ( ) [ 3 ] [ 3 ] ) ,
} ;
2025-01-15 14:58:23 +00:00
return TransformationStyleValue : : create ( PropertyID : : Transform , TransformFunction : : Matrix3d , move ( parameters ) ) ;
2023-10-12 12:30:28 +01:00
}
2023-09-29 13:58:01 +01:00
}
// -> Any other property
// The resolved value is the computed value.
// NOTE: This is handled inside the `default` case.
2024-07-07 19:41:18 -06:00
case PropertyID : : WebkitTextFillColor :
2025-02-19 21:02:12 +11:00
return CSSColorValue : : create_from_color ( layout_node . computed_values ( ) . webkit_text_fill_color ( ) , ColorSyntax : : Modern ) ;
2023-05-27 15:52:49 +01:00
case PropertyID : : Invalid :
2024-08-14 14:06:03 +01:00
return CSSKeywordValue : : create ( Keyword : : Invalid ) ;
2023-05-27 15:52:49 +01:00
case PropertyID : : Custom :
2022-02-06 14:17:42 +01:00
dbgln_if ( LIBWEB_CSS_DEBUG , " Computed style for custom properties was requested (?) " ) ;
2023-05-02 14:52:31 +01:00
return nullptr ;
2021-09-12 20:05:29 +02:00
default :
2024-09-09 18:13:24 +02:00
// For grid-template-columns and grid-template-rows the resolved value is the used value.
// https://www.w3.org/TR/css-grid-2/#resolved-track-list-standalone
if ( property_id = = PropertyID : : GridTemplateColumns ) {
2024-10-16 15:19:32 +02:00
if ( layout_node . first_paintable ( ) & & layout_node . first_paintable ( ) - > is_paintable_box ( ) ) {
2025-01-21 09:12:05 -05:00
auto const & paintable_box = as < Painting : : PaintableBox const > ( * layout_node . first_paintable ( ) ) ;
2024-09-12 16:28:31 +01:00
if ( auto used_values_for_grid_template_columns = paintable_box . used_values_for_grid_template_columns ( ) ) {
return used_values_for_grid_template_columns ;
}
2024-09-09 18:13:24 +02:00
}
} else if ( property_id = = PropertyID : : GridTemplateRows ) {
2024-10-16 15:19:32 +02:00
if ( layout_node . first_paintable ( ) & & layout_node . first_paintable ( ) - > is_paintable_box ( ) ) {
2025-01-21 09:12:05 -05:00
auto const & paintable_box = as < Painting : : PaintableBox const > ( * layout_node . first_paintable ( ) ) ;
2024-09-12 16:28:31 +01:00
if ( auto used_values_for_grid_template_rows = paintable_box . used_values_for_grid_template_rows ( ) ) {
return used_values_for_grid_template_rows ;
}
2024-09-09 18:13:24 +02:00
}
}
2023-09-09 12:04:40 +01:00
if ( ! property_is_shorthand ( property_id ) )
2024-08-06 12:48:21 +01:00
return get_computed_value ( property_id ) ;
2023-09-26 14:05:57 +01:00
// Handle shorthands in a generic way
auto longhand_ids = longhands_for_shorthand ( property_id ) ;
StyleValueVector longhand_values ;
longhand_values . ensure_capacity ( longhand_ids . size ( ) ) ;
for ( auto longhand_id : longhand_ids )
longhand_values . append ( style_value_for_property ( layout_node , longhand_id ) . release_nonnull ( ) ) ;
return ShorthandStyleValue : : create ( property_id , move ( longhand_ids ) , move ( longhand_values ) ) ;
2021-09-12 20:05:29 +02:00
}
2021-09-18 13:14:40 +02:00
}
2021-09-23 12:35:56 +02:00
Optional < StyleProperty > ResolvedCSSStyleDeclaration : : property ( PropertyID property_id ) const
2021-09-18 13:14:40 +02:00
{
2023-05-10 15:33:10 +02:00
// https://www.w3.org/TR/cssom-1/#dom-window-getcomputedstyle
// NOTE: This is a partial enforcement of step 5 ("If elt is connected, ...")
if ( ! m_element - > is_connected ( ) )
return { } ;
2024-08-06 12:48:21 +01:00
auto get_layout_node = [ & ] ( ) {
if ( m_pseudo_element . has_value ( ) )
return m_element - > get_pseudo_element_node ( m_pseudo_element . value ( ) ) ;
return m_element - > layout_node ( ) ;
} ;
Layout : : NodeWithStyle * layout_node = get_layout_node ( ) ;
2023-10-13 17:44:36 +01:00
// FIXME: Be smarter about updating layout if there's no layout node.
// We may legitimately have no layout node if we're not visible, but this protects against situations
// where we're requesting the computed style before layout has happened.
2024-08-06 12:48:21 +01:00
if ( ! layout_node | | property_affects_layout ( property_id ) ) {
2025-03-05 20:50:05 +01:00
const_cast < DOM : : Document & > ( m_element - > document ( ) ) . update_layout ( DOM : : UpdateLayoutReason : : ResolvedCSSStyleDeclarationProperty ) ;
2024-08-06 12:48:21 +01:00
layout_node = get_layout_node ( ) ;
2022-03-20 21:12:19 +01:00
} else {
// FIXME: If we had a way to update style for a single element, this would be a good place to use it.
const_cast < DOM : : Document & > ( m_element - > document ( ) ) . update_style ( ) ;
}
2021-09-18 13:14:40 +02:00
2024-08-06 12:48:21 +01:00
if ( ! layout_node ) {
auto style = m_element - > document ( ) . style_computer ( ) . compute_style ( const_cast < DOM : : Element & > ( * m_element ) , m_pseudo_element ) ;
2022-12-06 03:08:20 -03:00
2022-10-28 15:42:18 +01:00
// FIXME: This is a stopgap until we implement shorthand -> longhand conversion.
2024-12-20 16:35:12 +01:00
auto const * value = style - > maybe_null_property ( property_id ) ;
2022-10-28 15:42:18 +01:00
if ( ! value ) {
2024-02-21 09:38:31 -05:00
dbgln ( " FIXME: ResolvedCSSStyleDeclaration::property(property_id={:#x}) No value for property ID in newly computed style case. " , to_underlying ( property_id ) ) ;
2022-10-28 15:42:18 +01:00
return { } ;
}
2022-04-14 11:52:35 +01:00
return StyleProperty {
. property_id = property_id ,
2024-11-03 13:20:04 +01:00
. value = * value ,
2022-04-14 11:52:35 +01:00
} ;
2021-09-18 13:14:40 +02:00
}
2024-08-06 12:48:21 +01:00
auto value = style_value_for_property ( * layout_node , property_id ) ;
2021-09-18 13:14:40 +02:00
if ( ! value )
return { } ;
return StyleProperty {
. property_id = property_id ,
2024-11-03 13:20:04 +01:00
. value = * value ,
2021-09-18 13:14:40 +02:00
} ;
2021-09-12 20:05:29 +02:00
}
2024-11-25 13:23:31 +01:00
Optional < StyleProperty const & > ResolvedCSSStyleDeclaration : : custom_property ( FlyString const & name ) const
2024-11-20 17:21:22 +01:00
{
2024-11-21 20:12:18 +01:00
const_cast < DOM : : Document & > ( m_element - > document ( ) ) . update_style ( ) ;
2024-11-21 16:11:18 -06:00
auto const * element_to_check = m_element . ptr ( ) ;
while ( element_to_check ) {
if ( auto property = element_to_check - > custom_properties ( m_pseudo_element ) . get ( name ) ; property . has_value ( ) )
return * property ;
element_to_check = element_to_check - > parent_element ( ) ;
}
return { } ;
2024-11-20 17:21:22 +01:00
}
2024-08-04 22:12:31 +01:00
static WebIDL : : ExceptionOr < void > cannot_modify_computed_property_error ( JS : : Realm & realm )
{
2024-10-12 20:56:21 +02:00
return WebIDL : : NoModificationAllowedError : : create ( realm , " Cannot modify properties in result of getComputedStyle() " _string ) ;
2024-08-04 22:12:31 +01:00
}
2022-04-11 16:10:55 +02:00
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty
2022-09-25 17:03:42 +01:00
WebIDL : : ExceptionOr < void > ResolvedCSSStyleDeclaration : : set_property ( PropertyID , StringView , StringView )
2021-09-12 20:05:29 +02:00
{
2022-04-11 16:10:55 +02:00
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
2024-08-04 22:12:31 +01:00
return cannot_modify_computed_property_error ( realm ( ) ) ;
}
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty
WebIDL : : ExceptionOr < void > ResolvedCSSStyleDeclaration : : set_property ( StringView , StringView , StringView )
{
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
return cannot_modify_computed_property_error ( realm ( ) ) ;
}
static WebIDL : : ExceptionOr < String > cannot_remove_computed_property_error ( JS : : Realm & realm )
{
2024-10-12 20:56:21 +02:00
return WebIDL : : NoModificationAllowedError : : create ( realm , " Cannot remove properties from result of getComputedStyle() " _string ) ;
2022-04-11 16:10:55 +02:00
}
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-removeproperty
2023-09-06 19:07:24 +12:00
WebIDL : : ExceptionOr < String > ResolvedCSSStyleDeclaration : : remove_property ( PropertyID )
2022-04-11 16:10:55 +02:00
{
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
2024-08-04 22:12:31 +01:00
return cannot_remove_computed_property_error ( realm ( ) ) ;
}
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-removeproperty
WebIDL : : ExceptionOr < String > ResolvedCSSStyleDeclaration : : remove_property ( StringView )
{
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
return cannot_remove_computed_property_error ( realm ( ) ) ;
2021-09-12 20:05:29 +02:00
}
2021-10-01 19:57:45 +02:00
2023-11-21 10:39:54 +13:00
String ResolvedCSSStyleDeclaration : : serialized ( ) const
2021-10-01 19:57:45 +02:00
{
2021-10-15 19:38:39 +01:00
// https://www.w3.org/TR/cssom/#dom-cssstyledeclaration-csstext
2021-10-01 19:57:45 +02:00
// If the computed flag is set, then return the empty string.
// NOTE: ResolvedCSSStyleDeclaration is something you would only get from window.getComputedStyle(),
// which returns what the spec calls "resolved style". The "computed flag" is always set here.
2023-11-21 10:39:54 +13:00
return String { } ;
2021-10-01 19:57:45 +02:00
}
2022-11-05 04:51:05 +00:00
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext
WebIDL : : ExceptionOr < void > ResolvedCSSStyleDeclaration : : set_css_text ( StringView )
{
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
2024-10-12 20:56:21 +02:00
return WebIDL : : NoModificationAllowedError : : create ( realm ( ) , " Cannot modify properties in result of getComputedStyle() " _string ) ;
2022-11-05 04:51:05 +00:00
}
2021-09-12 20:05:29 +02:00
}