mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 12:19:54 +00:00
LibWeb/CSS: Keep invalid parts of <forgiving-selector-list>
s around
Selectors like `:is(.valid, &!?!?!invalid)` need to keep the invalid part around, even though it will never match, for a couple of reasons: - Serialization needs to include them - For nesting, we care if a `&` appeared anywhere in the selector, even in an invalid part. So this patch introduces an `Invalid` simple selector type, which simply holds its original ComponentValues. We search through these looking for `&`, and we dump them out directly when asked to serialize.
This commit is contained in:
parent
1849eca503
commit
698dd600f2
Notes:
github-actions[bot]
2024-11-13 19:39:05 +00:00
Author: https://github.com/AtkinsSJ
Commit: 698dd600f2
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2317
8 changed files with 110 additions and 3 deletions
|
@ -11,6 +11,28 @@
|
|||
|
||||
namespace Web::CSS {
|
||||
|
||||
static bool component_value_contains_nesting_selector(Parser::ComponentValue const& component_value)
|
||||
{
|
||||
if (component_value.is_delim('&'))
|
||||
return true;
|
||||
|
||||
if (component_value.is_block()) {
|
||||
for (auto const& child_value : component_value.block().value) {
|
||||
if (component_value_contains_nesting_selector(child_value))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (component_value.is_function()) {
|
||||
for (auto const& child_value : component_value.function().value) {
|
||||
if (component_value_contains_nesting_selector(child_value))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Selector::Selector(Vector<CompoundSelector>&& compound_selectors)
|
||||
: m_compound_selectors(move(compound_selectors))
|
||||
{
|
||||
|
@ -44,6 +66,17 @@ Selector::Selector(Vector<CompoundSelector>&& compound_selectors)
|
|||
if (m_contains_the_nesting_selector)
|
||||
break;
|
||||
}
|
||||
if (simple_selector.type == SimpleSelector::Type::Invalid) {
|
||||
auto& invalid = simple_selector.value.get<SimpleSelector::Invalid>();
|
||||
for (auto& item : invalid.component_values) {
|
||||
if (component_value_contains_nesting_selector(item)) {
|
||||
m_contains_the_nesting_selector = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_contains_the_nesting_selector)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_contains_the_nesting_selector)
|
||||
break;
|
||||
|
@ -184,6 +217,9 @@ u32 Selector::specificity() const
|
|||
// The parented case is handled by replacing & with :is().
|
||||
// So if we got here, the specificity is 0.
|
||||
break;
|
||||
case SimpleSelector::Type::Invalid:
|
||||
// Ignore invalid selectors
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +396,12 @@ String Selector::SimpleSelector::serialize() const
|
|||
// AD-HOC: Not in spec yet.
|
||||
s.append('&');
|
||||
break;
|
||||
case Type::Invalid:
|
||||
// AD-HOC: We're not told how to do these. Just serialize their component values.
|
||||
auto invalid = value.get<Invalid>();
|
||||
for (auto const& component_value : invalid.component_values)
|
||||
s.append(component_value.to_string());
|
||||
break;
|
||||
}
|
||||
return MUST(s.to_string());
|
||||
}
|
||||
|
@ -602,6 +644,7 @@ Selector::SimpleSelector Selector::SimpleSelector::absolutized(Selector::SimpleS
|
|||
case Type::Class:
|
||||
case Type::Attribute:
|
||||
case Type::PseudoElement:
|
||||
case Type::Invalid:
|
||||
// Everything else isn't affected
|
||||
return *this;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue