LibWeb: Handle special cases of PseudoElement::Type correctly

There are some special values for CSS::Selector::PseudoElement::Type
which are after `KnownPseudoElementCount` and therefore not present in
various arrays of pseudo elements, this leads to some errors, if a type
after `KnownPseudoElementCount` is used without checking first. This
adds explicit checks to all usages
This commit is contained in:
Totto16 2024-12-19 19:15:02 +01:00 committed by Sam Atkins
commit d21bfda900
Notes: github-actions[bot] 2024-12-19 19:37:02 +00:00
4 changed files with 59 additions and 7 deletions

View file

@ -187,14 +187,21 @@ void Animatable::visit_edges(JS::Cell::Visitor& visitor)
GC::Ptr<CSS::CSSStyleDeclaration const> Animatable::cached_animation_name_source(Optional<CSS::Selector::PseudoElement::Type> pseudo_element) const GC::Ptr<CSS::CSSStyleDeclaration const> Animatable::cached_animation_name_source(Optional<CSS::Selector::PseudoElement::Type> pseudo_element) const
{ {
if (pseudo_element.has_value()) if (pseudo_element.has_value()) {
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value())) {
return {};
}
return m_cached_animation_name_source[to_underlying(pseudo_element.value()) + 1]; return m_cached_animation_name_source[to_underlying(pseudo_element.value()) + 1];
}
return m_cached_animation_name_source[0]; return m_cached_animation_name_source[0];
} }
void Animatable::set_cached_animation_name_source(GC::Ptr<CSS::CSSStyleDeclaration const> value, Optional<CSS::Selector::PseudoElement::Type> pseudo_element) void Animatable::set_cached_animation_name_source(GC::Ptr<CSS::CSSStyleDeclaration const> value, Optional<CSS::Selector::PseudoElement::Type> pseudo_element)
{ {
if (pseudo_element.has_value()) { if (pseudo_element.has_value()) {
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value())) {
return;
}
m_cached_animation_name_source[to_underlying(pseudo_element.value()) + 1] = value; m_cached_animation_name_source[to_underlying(pseudo_element.value()) + 1] = value;
} else { } else {
m_cached_animation_name_source[0] = value; m_cached_animation_name_source[0] = value;
@ -203,18 +210,27 @@ void Animatable::set_cached_animation_name_source(GC::Ptr<CSS::CSSStyleDeclarati
GC::Ptr<Animations::Animation> Animatable::cached_animation_name_animation(Optional<CSS::Selector::PseudoElement::Type> pseudo_element) const GC::Ptr<Animations::Animation> Animatable::cached_animation_name_animation(Optional<CSS::Selector::PseudoElement::Type> pseudo_element) const
{ {
if (pseudo_element.has_value()) if (pseudo_element.has_value()) {
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value())) {
return {};
}
return m_cached_animation_name_animation[to_underlying(pseudo_element.value()) + 1]; return m_cached_animation_name_animation[to_underlying(pseudo_element.value()) + 1];
}
return m_cached_animation_name_animation[0]; return m_cached_animation_name_animation[0];
} }
void Animatable::set_cached_animation_name_animation(GC::Ptr<Animations::Animation> value, Optional<CSS::Selector::PseudoElement::Type> pseudo_element) void Animatable::set_cached_animation_name_animation(GC::Ptr<Animations::Animation> value, Optional<CSS::Selector::PseudoElement::Type> pseudo_element)
{ {
if (pseudo_element.has_value()) { if (pseudo_element.has_value()) {
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value())) {
return;
}
m_cached_animation_name_animation[to_underlying(pseudo_element.value()) + 1] = value; m_cached_animation_name_animation[to_underlying(pseudo_element.value()) + 1] = value;
} else { } else {
m_cached_animation_name_animation[0] = value; m_cached_animation_name_animation[0] = value;
} }
} }
} }

View file

@ -55,7 +55,7 @@ public:
explicit PseudoElement(Type type) explicit PseudoElement(Type type)
: m_type(type) : m_type(type)
{ {
VERIFY(type != Type::UnknownWebKit); VERIFY(is_known_pseudo_element_type(type));
} }
PseudoElement(Type type, String name) PseudoElement(Type type, String name)
@ -68,6 +68,11 @@ public:
static Optional<PseudoElement> from_string(FlyString const&); static Optional<PseudoElement> from_string(FlyString const&);
[[nodiscard]] static bool is_known_pseudo_element_type(Type type)
{
return to_underlying(type) < to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount);
}
static StringView name(Selector::PseudoElement::Type pseudo_element); static StringView name(Selector::PseudoElement::Type pseudo_element);
StringView name() const StringView name() const

View file

@ -466,8 +466,14 @@ Vector<MatchingRule> StyleComputer::collect_matching_rules(DOM::Element const& e
} }
if (auto it = rule_cache.rules_by_tag_name.find(element.local_name()); it != rule_cache.rules_by_tag_name.end()) if (auto it = rule_cache.rules_by_tag_name.find(element.local_name()); it != rule_cache.rules_by_tag_name.end())
add_rules_to_run(it->value); add_rules_to_run(it->value);
if (pseudo_element.has_value()) if (pseudo_element.has_value()) {
add_rules_to_run(rule_cache.rules_by_pseudo_element[to_underlying(pseudo_element.value())]); if (CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value())) {
add_rules_to_run(rule_cache.rules_by_pseudo_element.at(to_underlying(pseudo_element.value())));
} else {
// NOTE: We don't cache rules for unknown pseudo-elements. They can't match anything anyway.
}
}
if (element.is_document_element()) if (element.is_document_element())
add_rules_to_run(rule_cache.root_rules); add_rules_to_run(rule_cache.root_rules);
@ -2632,7 +2638,7 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
} }
if (!added_to_bucket) { if (!added_to_bucket) {
if (matching_rule.contains_pseudo_element) { if (matching_rule.contains_pseudo_element) {
if (to_underlying(pseudo_element.value()) < to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount)) { if (CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value())) {
rule_cache->rules_by_pseudo_element[to_underlying(pseudo_element.value())].append(move(matching_rule)); rule_cache->rules_by_pseudo_element[to_underlying(pseudo_element.value())].append(move(matching_rule));
} else { } else {
// NOTE: We don't cache rules for unknown pseudo-elements. They can't match anything anyway. // NOTE: We don't cache rules for unknown pseudo-elements. They can't match anything anyway.

View file

@ -1069,6 +1069,10 @@ void Element::set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::Selector:
if (!existing_pseudo_element.has_value() && !pseudo_element_node) if (!existing_pseudo_element.has_value() && !pseudo_element_node)
return; return;
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element)) {
return;
}
ensure_pseudo_element(pseudo_element).layout_node = move(pseudo_element_node); ensure_pseudo_element(pseudo_element).layout_node = move(pseudo_element_node);
} }
@ -2279,6 +2283,11 @@ void Element::set_pseudo_element_computed_css_values(CSS::Selector::PseudoElemen
{ {
if (!m_pseudo_element_data && !style.has_value()) if (!m_pseudo_element_data && !style.has_value())
return; return;
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element)) {
return;
}
ensure_pseudo_element(pseudo_element).computed_css_values = move(style); ensure_pseudo_element(pseudo_element).computed_css_values = move(style);
} }
@ -2294,6 +2303,11 @@ Optional<Element::PseudoElement&> Element::get_pseudo_element(CSS::Selector::Pse
{ {
if (!m_pseudo_element_data) if (!m_pseudo_element_data)
return {}; return {};
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(type)) {
return {};
}
return m_pseudo_element_data->at(to_underlying(type)); return m_pseudo_element_data->at(to_underlying(type));
} }
@ -2301,6 +2315,9 @@ Element::PseudoElement& Element::ensure_pseudo_element(CSS::Selector::PseudoElem
{ {
if (!m_pseudo_element_data) if (!m_pseudo_element_data)
m_pseudo_element_data = make<PseudoElementData>(); m_pseudo_element_data = make<PseudoElementData>();
VERIFY(CSS::Selector::PseudoElement::is_known_pseudo_element_type(type));
return m_pseudo_element_data->at(to_underlying(type)); return m_pseudo_element_data->at(to_underlying(type));
} }
@ -2310,6 +2327,11 @@ void Element::set_custom_properties(Optional<CSS::Selector::PseudoElement::Type>
m_custom_properties = move(custom_properties); m_custom_properties = move(custom_properties);
return; return;
} }
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value())) {
return;
}
ensure_pseudo_element(pseudo_element.value()).custom_properties = move(custom_properties); ensure_pseudo_element(pseudo_element.value()).custom_properties = move(custom_properties);
} }
@ -2317,6 +2339,9 @@ HashMap<FlyString, CSS::StyleProperty> const& Element::custom_properties(Optiona
{ {
if (!pseudo_element.has_value()) if (!pseudo_element.has_value())
return m_custom_properties; return m_custom_properties;
VERIFY(CSS::Selector::PseudoElement::is_known_pseudo_element_type(pseudo_element.value()));
return ensure_pseudo_element(pseudo_element.value()).custom_properties; return ensure_pseudo_element(pseudo_element.value()).custom_properties;
} }