LibWeb: Expand invalidation sets usage to any attribute change

Before this change invalidation sets were only used for "class" and "id"
attribute changes.
This commit is contained in:
Aliaksandr Kalenik 2025-01-19 17:22:44 +01:00 committed by Andreas Kling
commit 34bf833a0a
Notes: github-actions[bot] 2025-01-19 18:55:38 +00:00
6 changed files with 91 additions and 43 deletions

View file

@ -37,7 +37,11 @@ namespace AK {
unsigned Traits<Web::CSS::InvalidationSet::Property>::hash(Web::CSS::InvalidationSet::Property const& invalidation_set_property)
{
return pair_int_hash(to_underlying(invalidation_set_property.type), invalidation_set_property.name.hash());
auto value_hash = invalidation_set_property.value.visit(
[](FlyString const& value) -> int { return value.hash(); },
[](Web::CSS::PseudoClass const& value) -> int { return to_underlying(value); },
[](Empty) -> int { return 0; });
return pair_int_hash(to_underlying(invalidation_set_property.type), value_hash);
}
ErrorOr<void> Formatter<Web::CSS::InvalidationSet::Property>::format(FormatBuilder& builder, Web::CSS::InvalidationSet::Property const& invalidation_set_property)
@ -49,24 +53,29 @@ ErrorOr<void> Formatter<Web::CSS::InvalidationSet::Property>::format(FormatBuild
}
case Web::CSS::InvalidationSet::Property::Type::Class: {
TRY(builder.put_string("."sv));
TRY(builder.put_string(invalidation_set_property.name));
TRY(builder.put_string(invalidation_set_property.name()));
return {};
}
case Web::CSS::InvalidationSet::Property::Type::Id: {
TRY(builder.put_string("#"sv));
TRY(builder.put_string(invalidation_set_property.name));
TRY(builder.put_string(invalidation_set_property.name()));
return {};
}
case Web::CSS::InvalidationSet::Property::Type::TagName: {
TRY(builder.put_string(invalidation_set_property.name));
TRY(builder.put_string(invalidation_set_property.name()));
return {};
}
case Web::CSS::InvalidationSet::Property::Type::Attribute: {
TRY(builder.put_string("["sv));
TRY(builder.put_string(invalidation_set_property.name));
TRY(builder.put_string(invalidation_set_property.name()));
TRY(builder.put_string("]"sv));
return {};
}
case Web::CSS::InvalidationSet::Property::Type::PseudoClass: {
TRY(builder.put_string(":"sv));
TRY(builder.put_string(pseudo_class_name(invalidation_set_property.value.get<Web::CSS::PseudoClass>())));
return {};
}
case Web::CSS::InvalidationSet::Property::Type::InvalidateWholeSubtree: {
TRY(builder.put_string("*"sv));
return {};

View file

@ -11,6 +11,7 @@
#include <AK/Forward.h>
#include <AK/HashTable.h>
#include <AK/Traits.h>
#include <LibWeb/CSS/PseudoClass.h>
namespace Web::CSS {
@ -24,10 +25,13 @@ public:
Id,
TagName,
Attribute,
PseudoClass,
};
Type type;
FlyString name {};
Variant<FlyString, PseudoClass, Empty> value { Empty {} };
FlyString const& name() const { return value.get<FlyString>(); }
bool operator==(Property const& other) const = default;
};
@ -44,6 +48,7 @@ public:
void set_needs_invalidate_id(FlyString const& name) { m_properties.set({ Property::Type::Id, name }); }
void set_needs_invalidate_tag_name(FlyString const& name) { m_properties.set({ Property::Type::TagName, name }); }
void set_needs_invalidate_attribute(FlyString const& name) { m_properties.set({ Property::Type::Attribute, name }); }
void set_needs_invalidate_pseudo_class(PseudoClass pseudo_class) { m_properties.set({ Property::Type::PseudoClass, pseudo_class }); }
bool is_empty() const;
void for_each_property(Function<void(Property const&)> const& callback) const;

View file

@ -447,19 +447,23 @@ bool StyleComputer::invalidation_property_used_in_has_selector(InvalidationSet::
return true;
switch (property.type) {
case InvalidationSet::Property::Type::Id:
if (m_style_invalidation_data->ids_used_in_has_selectors.contains(property.name))
if (m_style_invalidation_data->ids_used_in_has_selectors.contains(property.name()))
return true;
break;
case InvalidationSet::Property::Type::Class:
if (m_style_invalidation_data->class_names_used_in_has_selectors.contains(property.name))
if (m_style_invalidation_data->class_names_used_in_has_selectors.contains(property.name()))
return true;
break;
case InvalidationSet::Property::Type::Attribute:
if (m_style_invalidation_data->attribute_names_used_in_has_selectors.contains(property.name))
if (m_style_invalidation_data->attribute_names_used_in_has_selectors.contains(property.name()))
return true;
break;
case InvalidationSet::Property::Type::TagName:
if (m_style_invalidation_data->tag_names_used_in_has_selectors.contains(property.name))
if (m_style_invalidation_data->tag_names_used_in_has_selectors.contains(property.name()))
return true;
break;
case InvalidationSet::Property::Type::PseudoClass:
if (m_style_invalidation_data->pseudo_classes_used_in_has_selectors.contains(property.value.get<PseudoClass>()))
return true;
break;
default:

View file

@ -66,6 +66,16 @@ static void collect_properties_used_in_has(Selector::SimpleSelector const& selec
}
case Selector::SimpleSelector::Type::PseudoClass: {
auto const& pseudo_class = selector.pseudo_class();
switch (pseudo_class.type) {
case PseudoClass::Enabled:
case PseudoClass::Disabled:
case PseudoClass::PlaceholderShown:
case PseudoClass::Checked:
style_invalidation_data.pseudo_classes_used_in_has_selectors.set(pseudo_class.type);
break;
default:
break;
}
for (auto const& child_selector : pseudo_class.argument_selector_list) {
for (auto const& compound_selector : child_selector->compound_selectors()) {
for (auto const& simple_selector : compound_selector.simple_selectors) {
@ -102,6 +112,16 @@ static void build_invalidation_sets_for_simple_selector(Selector::SimpleSelector
break;
case Selector::SimpleSelector::Type::PseudoClass: {
auto const& pseudo_class = selector.pseudo_class();
switch (pseudo_class.type) {
case PseudoClass::Enabled:
case PseudoClass::Disabled:
case PseudoClass::PlaceholderShown:
case PseudoClass::Checked:
invalidation_set.set_needs_invalidate_pseudo_class(pseudo_class.type);
break;
default:
break;
}
if (pseudo_class.type == PseudoClass::Has)
break;
if (exclude_properties_nested_in_not_pseudo_class == ExcludePropertiesNestedInNotPseudoClass::Yes && pseudo_class.type == PseudoClass::Not)

View file

@ -18,6 +18,7 @@ struct StyleInvalidationData {
HashTable<FlyString> class_names_used_in_has_selectors;
HashTable<FlyString> attribute_names_used_in_has_selectors;
HashTable<FlyString> tag_names_used_in_has_selectors;
HashTable<PseudoClass> pseudo_classes_used_in_has_selectors;
InvalidationSet build_invalidation_sets_for_selector(Selector const& selector);
};