LibWeb: Use CSSKeywordValue for CSS-wide keywords

We previously had 4 single-instance StyleValues for these keywords.
CSS-Typed-OM expects them keywords to be exposed as CSSKeywordValue, so
it's simpler to treat them the same. The single-instance behaviour is
kept by having StyleValue::create() use a cached instance for each of
these.
This commit is contained in:
Sam Atkins 2024-08-14 15:00:10 +01:00 committed by Sam Atkins
parent 6a74b01644
commit f518811f73
Notes: github-actions[bot] 2024-08-15 12:59:29 +00:00
12 changed files with 38 additions and 203 deletions

View file

@ -35,8 +35,6 @@
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
#include <LibWeb/CSS/StyleValues/ImageStyleValue.h>
#include <LibWeb/CSS/StyleValues/InheritStyleValue.h>
#include <LibWeb/CSS/StyleValues/InitialStyleValue.h>
#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/LinearGradientStyleValue.h>
@ -48,7 +46,6 @@
#include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
#include <LibWeb/CSS/StyleValues/RectStyleValue.h>
#include <LibWeb/CSS/StyleValues/ResolutionStyleValue.h>
#include <LibWeb/CSS/StyleValues/RevertStyleValue.h>
#include <LibWeb/CSS/StyleValues/ScrollbarGutterStyleValue.h>
#include <LibWeb/CSS/StyleValues/ShadowStyleValue.h>
#include <LibWeb/CSS/StyleValues/ShorthandStyleValue.h>
@ -59,7 +56,6 @@
#include <LibWeb/CSS/StyleValues/TransitionStyleValue.h>
#include <LibWeb/CSS/StyleValues/URLStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnresolvedStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnsetStyleValue.h>
namespace Web::CSS {
@ -218,18 +214,6 @@ ImageStyleValue const& CSSStyleValue::as_image() const
return static_cast<ImageStyleValue const&>(*this);
}
InheritStyleValue const& CSSStyleValue::as_inherit() const
{
VERIFY(is_inherit());
return static_cast<InheritStyleValue const&>(*this);
}
InitialStyleValue const& CSSStyleValue::as_initial() const
{
VERIFY(is_initial());
return static_cast<InitialStyleValue const&>(*this);
}
IntegerStyleValue const& CSSStyleValue::as_integer() const
{
VERIFY(is_integer());
@ -296,12 +280,6 @@ ResolutionStyleValue const& CSSStyleValue::as_resolution() const
return static_cast<ResolutionStyleValue const&>(*this);
}
RevertStyleValue const& CSSStyleValue::as_revert() const
{
VERIFY(is_revert());
return static_cast<RevertStyleValue const&>(*this);
}
ScrollbarGutterStyleValue const& CSSStyleValue::as_scrollbar_gutter() const
{
VERIFY(is_scrollbar_gutter());
@ -350,12 +328,6 @@ UnresolvedStyleValue const& CSSStyleValue::as_unresolved() const
return static_cast<UnresolvedStyleValue const&>(*this);
}
UnsetStyleValue const& CSSStyleValue::as_unset() const
{
VERIFY(is_unset());
return static_cast<UnsetStyleValue const&>(*this);
}
URLStyleValue const& CSSStyleValue::as_url() const
{
VERIFY(is_url());

View file

@ -111,8 +111,6 @@ public:
GridTrackPlacement,
GridTrackSizeList,
Image,
Inherit,
Initial,
Integer,
Keyword,
Length,
@ -125,7 +123,6 @@ public:
Ratio,
Rect,
Resolution,
Revert,
ScrollbarGutter,
Shadow,
Shorthand,
@ -134,7 +131,6 @@ public:
Transformation,
Transition,
Unresolved,
Unset,
URL,
ValueList,
};
@ -240,14 +236,6 @@ public:
ImageStyleValue const& as_image() const;
ImageStyleValue& as_image() { return const_cast<ImageStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_image()); }
bool is_inherit() const { return type() == Type::Inherit; }
InheritStyleValue const& as_inherit() const;
InheritStyleValue& as_inherit() { return const_cast<InheritStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_inherit()); }
bool is_initial() const { return type() == Type::Initial; }
InitialStyleValue const& as_initial() const;
InitialStyleValue& as_initial() { return const_cast<InitialStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_initial()); }
bool is_integer() const { return type() == Type::Integer; }
IntegerStyleValue const& as_integer() const;
IntegerStyleValue& as_integer() { return const_cast<IntegerStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_integer()); }
@ -296,10 +284,6 @@ public:
ResolutionStyleValue const& as_resolution() const;
ResolutionStyleValue& as_resolution() { return const_cast<ResolutionStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_resolution()); }
bool is_revert() const { return type() == Type::Revert; }
RevertStyleValue const& as_revert() const;
RevertStyleValue& as_revert() { return const_cast<RevertStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_revert()); }
bool is_scrollbar_gutter() const { return type() == Type::ScrollbarGutter; }
ScrollbarGutterStyleValue const& as_scrollbar_gutter() const;
ScrollbarGutterStyleValue& as_scrollbar_gutter() { return const_cast<ScrollbarGutterStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_scrollbar_gutter()); }
@ -332,10 +316,6 @@ public:
UnresolvedStyleValue const& as_unresolved() const;
UnresolvedStyleValue& as_unresolved() { return const_cast<UnresolvedStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_unresolved()); }
bool is_unset() const { return type() == Type::Unset; }
UnsetStyleValue const& as_unset() const;
UnsetStyleValue& as_unset() { return const_cast<UnsetStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_unset()); }
bool is_url() const { return type() == Type::URL; }
URLStyleValue const& as_url() const;
URLStyleValue& as_url() { return const_cast<URLStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_url()); }
@ -347,6 +327,10 @@ public:
// https://www.w3.org/TR/css-values-4/#common-keywords
// https://drafts.csswg.org/css-cascade-4/#valdef-all-revert
bool is_css_wide_keyword() const { return is_inherit() || is_initial() || is_revert() || is_unset(); }
bool is_inherit() const { return to_keyword() == Keyword::Inherit; }
bool is_initial() const { return to_keyword() == Keyword::Initial; }
bool is_revert() const { return to_keyword() == Keyword::Revert; }
bool is_unset() const { return to_keyword() == Keyword::Unset; }
bool has_auto() const;
virtual bool has_color() const { return false; }

View file

@ -186,6 +186,8 @@
"infinite",
"infobackground",
"infotext",
"inherit",
"initial",
"initial-only",
"inline",
"inline-block",
@ -290,6 +292,7 @@
"repeat-x",
"repeat-y",
"reverse",
"revert",
"ridge",
"right",
"round",
@ -378,6 +381,7 @@
"ultra-expanded",
"underline",
"unsafe",
"unset",
"up",
"upper-alpha",
"upper-latin",

View file

@ -59,8 +59,6 @@
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
#include <LibWeb/CSS/StyleValues/ImageStyleValue.h>
#include <LibWeb/CSS/StyleValues/InheritStyleValue.h>
#include <LibWeb/CSS/StyleValues/InitialStyleValue.h>
#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/MathDepthStyleValue.h>
@ -70,7 +68,6 @@
#include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
#include <LibWeb/CSS/StyleValues/RectStyleValue.h>
#include <LibWeb/CSS/StyleValues/ResolutionStyleValue.h>
#include <LibWeb/CSS/StyleValues/RevertStyleValue.h>
#include <LibWeb/CSS/StyleValues/ScrollbarGutterStyleValue.h>
#include <LibWeb/CSS/StyleValues/ShadowStyleValue.h>
#include <LibWeb/CSS/StyleValues/ShorthandStyleValue.h>
@ -81,7 +78,6 @@
#include <LibWeb/CSS/StyleValues/TransitionStyleValue.h>
#include <LibWeb/CSS/StyleValues/URLStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnresolvedStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnsetStyleValue.h>
#include <LibWeb/Dump.h>
#include <LibWeb/Infra/CharacterTypes.h>
#include <LibWeb/Infra/Strings.h>
@ -1626,19 +1622,19 @@ RefPtr<CSSStyleValue> Parser::parse_builtin_value(TokenStream<ComponentValue>& t
auto ident = component_value.token().ident();
if (ident.equals_ignoring_ascii_case("inherit"sv)) {
transaction.commit();
return InheritStyleValue::the();
return CSSKeywordValue::create(Keyword::Inherit);
}
if (ident.equals_ignoring_ascii_case("initial"sv)) {
transaction.commit();
return InitialStyleValue::the();
return CSSKeywordValue::create(Keyword::Initial);
}
if (ident.equals_ignoring_ascii_case("unset"sv)) {
transaction.commit();
return UnsetStyleValue::the();
return CSSKeywordValue::create(Keyword::Unset);
}
if (ident.equals_ignoring_ascii_case("revert"sv)) {
transaction.commit();
return RevertStyleValue::the();
return CSSKeywordValue::create(Keyword::Revert);
}
// FIXME: Implement `revert-layer` from CSS-CASCADE-5.
}
@ -7947,18 +7943,18 @@ NonnullRefPtr<CSSStyleValue> Parser::resolve_unresolved_style_value(DOM::Element
HashMap<FlyString, NonnullRefPtr<PropertyDependencyNode>> dependencies;
if (!expand_variables(element, pseudo_element, string_from_property_id(property_id), dependencies, unresolved_values_without_variables_expanded, values_with_variables_expanded))
return UnsetStyleValue::the();
return CSSKeywordValue::create(Keyword::Unset);
TokenStream unresolved_values_with_variables_expanded { values_with_variables_expanded };
Vector<ComponentValue> expanded_values;
if (!expand_unresolved_values(element, string_from_property_id(property_id), unresolved_values_with_variables_expanded, expanded_values))
return UnsetStyleValue::the();
return CSSKeywordValue::create(Keyword::Unset);
auto expanded_value_tokens = TokenStream { expanded_values };
if (auto parsed_value = parse_css_value(property_id, expanded_value_tokens); !parsed_value.is_error())
return parsed_value.release_value();
return UnsetStyleValue::the();
return CSSKeywordValue::create(Keyword::Unset);
}
static RefPtr<CSSStyleValue const> get_custom_property(DOM::Element const& element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, FlyString const& custom_property_name)

View file

@ -21,7 +21,6 @@
#include <LibWeb/CSS/StyleValues/EdgeStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
#include <LibWeb/CSS/StyleValues/InitialStyleValue.h>
#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>

View file

@ -61,7 +61,6 @@
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
#include <LibWeb/CSS/StyleValues/TransitionStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnresolvedStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnsetStyleValue.h>
#include <LibWeb/DOM/Attr.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Element.h>
@ -1869,7 +1868,7 @@ NonnullRefPtr<CSSStyleValue const> StyleComputer::get_inherit_value(JS::Realm& i
void StyleComputer::compute_defaulted_property_value(StyleProperties& style, DOM::Element const* element, CSS::PropertyID property_id, Optional<CSS::Selector::PseudoElement::Type> pseudo_element) const
{
// FIXME: If we don't know the correct initial value for a property, we fall back to InitialStyleValue.
// FIXME: If we don't know the correct initial value for a property, we fall back to `initial`.
auto& value_slot = style.m_property_values[to_underlying(property_id)];
if (!value_slot) {

View file

@ -15,11 +15,31 @@
namespace Web::CSS {
// https://drafts.css-houdini.org/css-typed-om-1/#csskeywordvalue
class CSSKeywordValue final : public StyleValueWithDefaultOperators<CSSKeywordValue> {
class CSSKeywordValue : public StyleValueWithDefaultOperators<CSSKeywordValue> {
public:
static ValueComparingNonnullRefPtr<CSSKeywordValue> create(Keyword keyword)
{
return adopt_ref(*new (nothrow) CSSKeywordValue(keyword));
// NOTE: We'll have to be much more careful with caching once we expose CSSKeywordValue to JS, as it's mutable.
switch (keyword) {
case Keyword::Inherit: {
static ValueComparingNonnullRefPtr<CSSKeywordValue> const inherit_instance = adopt_ref(*new (nothrow) CSSKeywordValue(Keyword::Inherit));
return inherit_instance;
}
case Keyword::Initial: {
static ValueComparingNonnullRefPtr<CSSKeywordValue> const initial_instance = adopt_ref(*new (nothrow) CSSKeywordValue(Keyword::Initial));
return initial_instance;
}
case Keyword::Revert: {
static ValueComparingNonnullRefPtr<CSSKeywordValue> const revert_instance = adopt_ref(*new (nothrow) CSSKeywordValue(Keyword::Revert));
return revert_instance;
}
case Keyword::Unset: {
static ValueComparingNonnullRefPtr<CSSKeywordValue> const unset_instance = adopt_ref(*new (nothrow) CSSKeywordValue(Keyword::Unset));
return unset_instance;
}
default:
return adopt_ref(*new (nothrow) CSSKeywordValue(keyword));
}
}
virtual ~CSSKeywordValue() override = default;

View file

@ -1,33 +0,0 @@
/*
* Copyright (c) 2022-2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
namespace Web::CSS {
class InheritStyleValue final : public StyleValueWithDefaultOperators<InheritStyleValue> {
public:
static ValueComparingNonnullRefPtr<InheritStyleValue> the()
{
static ValueComparingNonnullRefPtr<InheritStyleValue> instance = adopt_ref(*new (nothrow) InheritStyleValue);
return instance;
}
virtual ~InheritStyleValue() override = default;
String to_string() const override { return "inherit"_string; }
bool properties_equal(InheritStyleValue const&) const { return true; }
private:
InheritStyleValue()
: StyleValueWithDefaultOperators(Type::Inherit)
{
}
};
}

View file

@ -1,33 +0,0 @@
/*
* Copyright (c) 2022-2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
namespace Web::CSS {
class InitialStyleValue final : public StyleValueWithDefaultOperators<InitialStyleValue> {
public:
static ValueComparingNonnullRefPtr<InitialStyleValue> the()
{
static ValueComparingNonnullRefPtr<InitialStyleValue> instance = adopt_ref(*new (nothrow) InitialStyleValue);
return instance;
}
virtual ~InitialStyleValue() override = default;
String to_string() const override { return "initial"_string; }
bool properties_equal(InitialStyleValue const&) const { return true; }
private:
InitialStyleValue()
: StyleValueWithDefaultOperators(Type::Initial)
{
}
};
}

View file

@ -1,33 +0,0 @@
/*
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
namespace Web::CSS {
class RevertStyleValue final : public StyleValueWithDefaultOperators<RevertStyleValue> {
public:
static ValueComparingNonnullRefPtr<RevertStyleValue> the()
{
static ValueComparingNonnullRefPtr<RevertStyleValue> instance = adopt_ref(*new (nothrow) RevertStyleValue);
return instance;
}
virtual ~RevertStyleValue() override = default;
String to_string() const override { return "revert"_string; }
bool properties_equal(RevertStyleValue const&) const { return true; }
private:
RevertStyleValue()
: StyleValueWithDefaultOperators(Type::Revert)
{
}
};
}

View file

@ -1,36 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/CSSStyleValue.h>
namespace Web::CSS {
class UnsetStyleValue final : public StyleValueWithDefaultOperators<UnsetStyleValue> {
public:
static ValueComparingNonnullRefPtr<UnsetStyleValue> the()
{
static ValueComparingNonnullRefPtr<UnsetStyleValue> instance = adopt_ref(*new (nothrow) UnsetStyleValue);
return instance;
}
virtual ~UnsetStyleValue() override = default;
String to_string() const override { return "unset"_string; }
bool properties_equal(UnsetStyleValue const&) const { return true; }
private:
UnsetStyleValue()
: StyleValueWithDefaultOperators(Type::Unset)
{
}
};
}

View file

@ -152,8 +152,6 @@ class GridTrackPlacementStyleValue;
class GridTrackSizeList;
class GridTrackSizeListStyleValue;
class ImageStyleValue;
class InheritStyleValue;
class InitialStyleValue;
class IntegerOrCalculated;
class IntegerStyleValue;
class Length;
@ -184,7 +182,6 @@ class RectStyleValue;
class Resolution;
class ResolutionOrCalculated;
class ResolutionStyleValue;
class RevertStyleValue;
class Screen;
class ScreenOrientation;
class ScrollbarGutterStyleValue;
@ -209,7 +206,6 @@ class TransformationStyleValue;
class TransitionStyleValue;
class URLStyleValue;
class UnresolvedStyleValue;
class UnsetStyleValue;
class VisualViewport;
enum class Keyword;