Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 47 additions & 7 deletions Libraries/LibWeb/CSS/CSSCounterStyleRule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
#include <LibWeb/Bindings/CSSCounterStyleRulePrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/CSSCounterStyleRule.h>
#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/Enums.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/Serialize.h>
#include <LibWeb/CSS/StyleScope.h>
#include <LibWeb/CSS/StyleValues/CounterStyleSystemStyleValue.h>
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
#include <LibWeb/DOM/Node.h>

namespace Web::CSS {

Expand Down Expand Up @@ -122,6 +125,8 @@ void CSSCounterStyleRule::set_name(FlyString name)

// 3. Replace the associated rule’s name with an identifier equal to the value.
m_name = move(name);

clear_caches();
}

FlyString CSSCounterStyleRule::system() const
Expand Down Expand Up @@ -155,6 +160,8 @@ void CSSCounterStyleRule::set_system(FlyString const& system)

// 4. Set the descriptor to the value.
m_system = value;

clear_caches();
}

FlyString CSSCounterStyleRule::negative() const
Expand All @@ -169,8 +176,10 @@ void CSSCounterStyleRule::set_negative(FlyString const& negative)
{
Parser::ParsingParams parsing_params { realm() };

if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Negative), negative))
if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Negative), negative)) {
m_negative = value;
clear_caches();
}
}

FlyString CSSCounterStyleRule::prefix() const
Expand All @@ -185,8 +194,10 @@ void CSSCounterStyleRule::set_prefix(FlyString const& prefix)
{
Parser::ParsingParams parsing_params { realm() };

if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Prefix), prefix))
if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Prefix), prefix)) {
m_prefix = value;
clear_caches();
}
}

FlyString CSSCounterStyleRule::suffix() const
Expand All @@ -201,8 +212,10 @@ void CSSCounterStyleRule::set_suffix(FlyString const& suffix)
{
Parser::ParsingParams parsing_params { realm() };

if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Suffix), suffix))
if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Suffix), suffix)) {
m_suffix = value;
clear_caches();
}
}

FlyString CSSCounterStyleRule::range() const
Expand All @@ -217,8 +230,10 @@ void CSSCounterStyleRule::set_range(FlyString const& range)
{
Parser::ParsingParams parsing_params { realm() };

if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Range), range))
if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Range), range)) {
m_range = value;
clear_caches();
}
}

FlyString CSSCounterStyleRule::pad() const
Expand All @@ -233,8 +248,10 @@ void CSSCounterStyleRule::set_pad(FlyString const& pad)
{
Parser::ParsingParams parsing_params { realm() };

if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Pad), pad))
if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Pad), pad)) {
m_pad = value;
clear_caches();
}
}

FlyString CSSCounterStyleRule::fallback() const
Expand All @@ -249,8 +266,10 @@ void CSSCounterStyleRule::set_fallback(FlyString const& fallback)
{
Parser::ParsingParams parsing_params { realm() };

if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Fallback), fallback))
if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::Fallback), fallback)) {
m_fallback = value;
clear_caches();
}
}

FlyString CSSCounterStyleRule::symbols() const
Expand Down Expand Up @@ -282,6 +301,8 @@ void CSSCounterStyleRule::set_symbols(FlyString const& symbols)

// 4. Set the descriptor to the value.
m_symbols = value;

clear_caches();
}

FlyString CSSCounterStyleRule::additive_symbols() const
Expand Down Expand Up @@ -313,6 +334,8 @@ void CSSCounterStyleRule::set_additive_symbols(FlyString const& additive_symbols

// 4. Set the descriptor to the value.
m_additive_symbols = value;

clear_caches();
}

FlyString CSSCounterStyleRule::speak_as() const
Expand All @@ -327,8 +350,25 @@ void CSSCounterStyleRule::set_speak_as(FlyString const& speak_as)
{
Parser::ParsingParams parsing_params { realm() };

if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::SpeakAs), speak_as))
if (auto value = parse_css_descriptor(parsing_params, CSS::AtRuleID::CounterStyle, DescriptorNameAndID::from_id(CSS::DescriptorID::SpeakAs), speak_as)) {
m_speak_as = value;
clear_caches();
}
}

void CSSCounterStyleRule::clear_caches()
{
Base::clear_caches();

auto* parent_style_sheet = this->parent_style_sheet();

if (!parent_style_sheet)
return;

parent_style_sheet->for_each_owning_style_scope([&](StyleScope& style_scope) {
style_scope.invalidate_counter_style_cache();
style_scope.node().invalidate_style(DOM::StyleInvalidationReason::CounterStyleCacheInvalidated);
});
}

void CSSCounterStyleRule::initialize(JS::Realm& realm)
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/CSS/CSSCounterStyleRule.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class CSSCounterStyleRule : public CSSRule {
return name.is_one_of_ignoring_ascii_case("decimal"sv, "disc"sv, "square"sv, "circle"sv, "disclosure-open"sv, "disclosure-closed"sv);
}

virtual void clear_caches() override;

protected:
CSSCounterStyleRule(JS::Realm&, FlyString name, RefPtr<StyleValue const> system, RefPtr<StyleValue const> negative, RefPtr<StyleValue const> prefix, RefPtr<StyleValue const> suffix, RefPtr<StyleValue const> range, RefPtr<StyleValue const> pad, RefPtr<StyleValue const> fallback, RefPtr<StyleValue const> symbols, RefPtr<StyleValue const> additive_symbols, RefPtr<StyleValue const> speak_as);

Expand Down
19 changes: 15 additions & 4 deletions Libraries/LibWeb/CSS/CSSStyleSheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,14 +376,25 @@ void CSSStyleSheet::set_disabled(bool disabled)
invalidate_owners(DOM::StyleInvalidationReason::StyleSheetDisabledStateChange);
}

void CSSStyleSheet::for_each_owning_style_scope(Function<void(StyleScope&)> const& callback) const
{
for (auto& document_or_shadow_root : m_owning_documents_or_shadow_roots) {
auto& style_scope = document_or_shadow_root->is_shadow_root()
? as<DOM::ShadowRoot>(*document_or_shadow_root).style_scope()
: document_or_shadow_root->document().style_scope();

callback(style_scope);
}
}

void CSSStyleSheet::invalidate_owners(DOM::StyleInvalidationReason reason)
{
m_did_match = {};
for (auto& document_or_shadow_root : m_owning_documents_or_shadow_roots) {
document_or_shadow_root->invalidate_style(reason);
auto& style_scope = document_or_shadow_root->is_shadow_root() ? as<DOM::ShadowRoot>(*document_or_shadow_root).style_scope() : document_or_shadow_root->document().style_scope();

for_each_owning_style_scope([&](StyleScope& style_scope) {
style_scope.invalidate_rule_cache();
}
style_scope.node().invalidate_style(reason);
});
}

GC::Ptr<DOM::Document> CSSStyleSheet::owning_document() const
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/CSS/CSSStyleSheet.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class WEB_API CSSStyleSheet final : public StyleSheet {
void invalidate_owners(DOM::StyleInvalidationReason);
GC::Ptr<DOM::Document> owning_document() const;
void set_disabled(bool);
void for_each_owning_style_scope(Function<void(StyleScope&)> const&) const;

Optional<FlyString> default_namespace() const;
GC::Ptr<CSSNamespaceRule> default_namespace_rule() const { return m_default_namespace_rule; }
Expand Down
10 changes: 6 additions & 4 deletions Libraries/LibWeb/CSS/ComputedProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,7 @@ ComputedProperties::ContentDataAndQuoteNestingLevel ComputedProperties::content(
break;
}
} else if (item->is_counter()) {
content_data.counter_style_dependencies.append(item->as_counter().counter_style()->as_counter_style().resolve_counter_style(element_reference.style_scope()));
content_data.data.append(item->as_counter().resolve(element_reference));
} else if (item->is_image()) {
content_data.data.append(NonnullRefPtr { const_cast<ImageStyleValue&>(item->as_image()) });
Expand All @@ -1218,6 +1219,7 @@ ComputedProperties::ContentDataAndQuoteNestingLevel ComputedProperties::content(
if (item->is_string()) {
alt_text_builder.append(item->as_string().string_value());
} else if (item->is_counter()) {
content_data.counter_style_dependencies.append(item->as_counter().counter_style()->as_counter_style().resolve_counter_style(element_reference.style_scope()));
alt_text_builder.append(item->as_counter().resolve(element_reference));
} else {
dbgln("`{}` is not supported in `content` alt-text (yet?)", item->to_string(SerializationMode::Normal));
Expand All @@ -1231,9 +1233,9 @@ ComputedProperties::ContentDataAndQuoteNestingLevel ComputedProperties::content(

switch (value.to_keyword()) {
case Keyword::None:
return { { ContentData::Type::None, {} }, quote_nesting_level };
return { { ContentData::Type::None, {}, {} }, quote_nesting_level };
case Keyword::Normal:
return { { ContentData::Type::Normal, {} }, quote_nesting_level };
return { { ContentData::Type::Normal, {}, {} }, quote_nesting_level };
default:
break;
}
Expand Down Expand Up @@ -1344,7 +1346,7 @@ TextTransform ComputedProperties::text_transform() const
return keyword_to_text_transform(value.to_keyword()).release_value();
}

ListStyleType ComputedProperties::list_style_type(HashMap<FlyString, NonnullRefPtr<CSS::CounterStyle const>> const& registered_counter_styles) const
ListStyleType ComputedProperties::list_style_type(StyleScope const& style_scope) const
{
auto const& value = property(PropertyID::ListStyleType);

Expand All @@ -1354,7 +1356,7 @@ ListStyleType ComputedProperties::list_style_type(HashMap<FlyString, NonnullRefP
if (value.is_string())
return value.as_string().string_value().to_string();

return value.as_counter_style().resolve_counter_style(registered_counter_styles);
return value.as_counter_style().resolve_counter_style(style_scope);
}

ListStylePosition ComputedProperties::list_style_position() const
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibWeb/CSS/ComputedProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class WEB_API ComputedProperties final : public JS::Cell {
Vector<ShadowData> text_shadow(Layout::Node const&) const;
TextIndentData text_indent() const;
TextWrapMode text_wrap_mode() const;
ListStyleType list_style_type(HashMap<FlyString, NonnullRefPtr<CSS::CounterStyle const>> const&) const;
ListStyleType list_style_type(StyleScope const&) const;
ListStylePosition list_style_position() const;
FlexDirection flex_direction() const;
FlexWrap flex_wrap() const;
Expand Down
8 changes: 5 additions & 3 deletions Libraries/LibWeb/CSS/ComputedValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ struct ContentData {
} type { Type::Normal };

Vector<Variant<String, NonnullRefPtr<ImageStyleValue>>> data;
Vector<ValueComparingRefPtr<CounterStyle const>> counter_style_dependencies;
Optional<String> alt_text {};

void visit_edges(GC::Cell::Visitor& visitor) const
Expand Down Expand Up @@ -525,7 +526,7 @@ class ComputedValues {
PreferredColorScheme color_scheme() const { return m_inherited.color_scheme; }
ContentVisibility content_visibility() const { return m_inherited.content_visibility; }
Vector<CursorData> const& cursor() const { return m_inherited.cursor; }
ContentData const& content() const { return m_noninherited.content; }
Optional<ContentData> const& content() const { return m_noninherited.content; }
PointerEvents pointer_events() const { return m_inherited.pointer_events; }
Display display() const { return m_noninherited.display; }
Display display_before_box_type_transformation() const { return m_noninherited.display_before_box_type_transformation; }
Expand Down Expand Up @@ -848,7 +849,7 @@ class ComputedValues {
Vector<ShadowData> box_shadow {};
Vector<NonnullRefPtr<TransformationStyleValue const>> transformations {};
TransformOrigin transform_origin {};
ContentData content;
Optional<ContentData> content;
Variant<VerticalAlign, LengthPercentage> vertical_align { InitialValues::vertical_align() };
GridTrackSizeList grid_auto_columns;
GridTrackSizeList grid_auto_rows;
Expand Down Expand Up @@ -923,7 +924,8 @@ class ComputedValues {
translate->visit_edges(visitor);
if (scale)
scale->visit_edges(visitor);
content.visit_edges(visitor);
if (content.has_value())
content->visit_edges(visitor);
}
};

Expand Down
39 changes: 27 additions & 12 deletions Libraries/LibWeb/CSS/CounterStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,16 @@ NonnullRefPtr<CounterStyle const> CounterStyle::disc()
CounterStylePad { .minimum_length = 0, .symbol = ""_fly_string });
}

NonnullRefPtr<CounterStyle const> CounterStyle::from_counter_style_definition(CounterStyleDefinition const& definition, HashMap<FlyString, NonnullRefPtr<CounterStyle const>> const& registered_counter_styles)
NonnullRefPtr<CounterStyle const> CounterStyle::from_counter_style_definition(CounterStyleDefinition const& definition, StyleScope const& style_scope)
{
return definition.algorithm().visit(
[&](CounterStyleSystemStyleValue::Extends const& extends) {
// NB: The caller should ensure that this is always set (i.e. by ensuring the relevant rule is registered
// before this one, and replacing the extended counter style with "decimal" if it is not defined).
auto const* extended_counter_style = registered_counter_styles.get(extends.name).value();
// NB: The caller should ensure that any dependencies (i.e. counter styles that occur in the extends chain)
// of this counter style are registered before this counter style.
auto extended_counter_style = style_scope.get_registered_counter_style(extends.name);

if (!extended_counter_style)
extended_counter_style = style_scope.get_registered_counter_style("decimal"_fly_string);

return CounterStyle::create(
definition.name(),
Expand Down Expand Up @@ -73,6 +76,18 @@ NonnullRefPtr<CounterStyle const> CounterStyle::from_counter_style_definition(Co
});
}

bool CounterStyle::equals(CounterStyle const& other) const
{
return name() == other.name()
&& algorithm() == other.algorithm()
&& negative_sign() == other.negative_sign()
&& prefix() == other.prefix()
&& suffix() == other.suffix()
&& range() == other.range()
&& pad() == other.pad()
&& fallback() == other.fallback();
}

// https://drafts.csswg.org/css-counter-styles-3/#extended-range-optional
static String generate_an_initial_representation_for_extended_cjk_system(i64 value, ExtendedCJKCounterStyleAlgorithm::Type type, Array<FlyString, 10> const& digit_strings, Array<FlyString, 3> const& digit_marker_strings, Array<FlyString, 3> const& group_marker_strings)
{
Expand Down Expand Up @@ -590,33 +605,33 @@ bool CounterStyle::uses_a_negative_sign() const
}

// https://drafts.csswg.org/css-counter-styles-3/#generate-a-counter
static String generate_a_counter_representation_impl(RefPtr<CounterStyle const> const& counter_style, HashMap<FlyString, NonnullRefPtr<CounterStyle const>> const& registered_counter_styles, i32 value, HashTable<FlyString>& fallback_history)
static String generate_a_counter_representation_impl(RefPtr<CounterStyle const> const& counter_style, StyleScope const& style_scope, i32 value, HashTable<FlyString>& fallback_history)
{
// When asked to generate a counter representation using a particular counter style for a particular
// counter value, follow these steps:

// 1. If the counter style is unknown, exit this algorithm and instead generate a counter representation using the
// decimal style and the same counter value.
if (!counter_style)
return generate_a_counter_representation_impl(CounterStyle::decimal(), registered_counter_styles, value, fallback_history);
return generate_a_counter_representation_impl(CounterStyle::decimal(), style_scope, value, fallback_history);

auto const generate_a_counter_representation_using_fallback = [&]() {
VERIFY(counter_style->name() != "decimal"_fly_string);

auto const& fallback_name = counter_style->fallback().value();
auto const& fallback = registered_counter_styles.get(fallback_name);
auto fallback = style_scope.get_registered_counter_style(fallback_name);

// https://drafts.csswg.org/css-counter-styles-3/#counter-style-fallback
// If the value of the fallback descriptor isn’t the name of any defined counter style, the used value of the
// fallback descriptor is decimal instead. Similarly, while following fallbacks to find a counter style that
// can render the given counter value, if a loop in the specified fallbacks is detected, the decimal style must
// be used instead.
if (!fallback.has_value() || fallback_history.contains(fallback_name))
return generate_a_counter_representation_impl(CounterStyle::decimal(), registered_counter_styles, value, fallback_history);
if (!fallback || fallback_history.contains(fallback_name))
return generate_a_counter_representation_impl(CounterStyle::decimal(), style_scope, value, fallback_history);

fallback_history.set(counter_style->name());

return generate_a_counter_representation_impl(fallback.value(), registered_counter_styles, value, fallback_history);
return generate_a_counter_representation_impl(fallback.release_nonnull(), style_scope, value, fallback_history);
};

// 2. If the counter value is outside the range of the counter style, exit this algorithm and instead generate a
Expand Down Expand Up @@ -666,10 +681,10 @@ static String generate_a_counter_representation_impl(RefPtr<CounterStyle const>
return representation;
}

String generate_a_counter_representation(RefPtr<CounterStyle const> const& counter_style, HashMap<FlyString, NonnullRefPtr<CounterStyle const>> const& registered_counter_styles, i32 value)
String generate_a_counter_representation(RefPtr<CounterStyle const> const& counter_style, StyleScope const& style_scope, i32 value)
{
HashTable<FlyString> fallback_history;
return generate_a_counter_representation_impl(counter_style, registered_counter_styles, value, fallback_history);
return generate_a_counter_representation_impl(counter_style, style_scope, value, fallback_history);
}

}
Loading
Loading