mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-17 15:51:55 +00:00
LibWeb/CSS: Allow Selector::absolutized() to return null
It's possible for absolutizing a selector to return an invalid selector (eg, it could cause `:has()` inside `:has()`) so we need to be able to express that.
This commit is contained in:
parent
3a43fa9e35
commit
da31c10ce1
Notes:
github-actions[bot]
2024-11-14 19:08:23 +00:00
Author: https://github.com/AtkinsSJ
Commit: da31c10ce1
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2340
3 changed files with 31 additions and 14 deletions
|
@ -187,8 +187,10 @@ SelectorList const& CSSStyleRule::absolutized_selectors() const
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
SelectorList absolutized_selectors;
|
SelectorList absolutized_selectors;
|
||||||
for (auto const& selector : selectors())
|
for (auto const& selector : selectors()) {
|
||||||
absolutized_selectors.append(selector->absolutized(parent_selector));
|
if (auto absolutized = selector->absolutized(parent_selector))
|
||||||
|
absolutized_selectors.append(absolutized.release_nonnull());
|
||||||
|
}
|
||||||
m_cached_absolutized_selectors = move(absolutized_selectors);
|
m_cached_absolutized_selectors = move(absolutized_selectors);
|
||||||
} else {
|
} else {
|
||||||
// NOTE: We can't actually replace & with :scope, because & has to have 0 specificity.
|
// NOTE: We can't actually replace & with :scope, because & has to have 0 specificity.
|
||||||
|
|
|
@ -586,27 +586,37 @@ NonnullRefPtr<Selector> Selector::relative_to(SimpleSelector const& parent) cons
|
||||||
return Selector::create(move(copied_compound_selectors));
|
return Selector::create(move(copied_compound_selectors));
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Selector> Selector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
|
RefPtr<Selector> Selector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
|
||||||
{
|
{
|
||||||
if (!contains_the_nesting_selector())
|
if (!contains_the_nesting_selector())
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
Vector<CompoundSelector> absolutized_compound_selectors;
|
Vector<CompoundSelector> absolutized_compound_selectors;
|
||||||
absolutized_compound_selectors.ensure_capacity(m_compound_selectors.size());
|
absolutized_compound_selectors.ensure_capacity(m_compound_selectors.size());
|
||||||
for (auto const& compound_selector : m_compound_selectors)
|
for (auto const& compound_selector : m_compound_selectors) {
|
||||||
absolutized_compound_selectors.append(compound_selector.absolutized(selector_for_nesting));
|
if (auto absolutized = compound_selector.absolutized(selector_for_nesting); absolutized.has_value()) {
|
||||||
|
absolutized_compound_selectors.append(absolutized.release_value());
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Selector::create(move(absolutized_compound_selectors));
|
return Selector::create(move(absolutized_compound_selectors));
|
||||||
}
|
}
|
||||||
|
|
||||||
Selector::CompoundSelector Selector::CompoundSelector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
|
Optional<Selector::CompoundSelector> Selector::CompoundSelector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
|
||||||
{
|
{
|
||||||
// TODO: Cache if it contains the nesting selector?
|
// TODO: Cache if it contains the nesting selector?
|
||||||
|
|
||||||
Vector<SimpleSelector> absolutized_simple_selectors;
|
Vector<SimpleSelector> absolutized_simple_selectors;
|
||||||
absolutized_simple_selectors.ensure_capacity(simple_selectors.size());
|
absolutized_simple_selectors.ensure_capacity(simple_selectors.size());
|
||||||
for (auto const& simple_selector : simple_selectors)
|
for (auto const& simple_selector : simple_selectors) {
|
||||||
absolutized_simple_selectors.append(simple_selector.absolutized(selector_for_nesting));
|
if (auto absolutized = simple_selector.absolutized(selector_for_nesting); absolutized.has_value()) {
|
||||||
|
absolutized_simple_selectors.append(absolutized.release_value());
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CompoundSelector {
|
return CompoundSelector {
|
||||||
.combinator = this->combinator,
|
.combinator = this->combinator,
|
||||||
|
@ -614,7 +624,7 @@ Selector::CompoundSelector Selector::CompoundSelector::absolutized(Selector::Sim
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Selector::SimpleSelector Selector::SimpleSelector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
|
Optional<Selector::SimpleSelector> Selector::SimpleSelector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Nesting:
|
case Type::Nesting:
|
||||||
|
@ -628,8 +638,13 @@ Selector::SimpleSelector Selector::SimpleSelector::absolutized(Selector::SimpleS
|
||||||
if (!pseudo_class.argument_selector_list.is_empty()) {
|
if (!pseudo_class.argument_selector_list.is_empty()) {
|
||||||
SelectorList new_selector_list;
|
SelectorList new_selector_list;
|
||||||
new_selector_list.ensure_capacity(pseudo_class.argument_selector_list.size());
|
new_selector_list.ensure_capacity(pseudo_class.argument_selector_list.size());
|
||||||
for (auto const& argument_selector : pseudo_class.argument_selector_list)
|
for (auto const& argument_selector : pseudo_class.argument_selector_list) {
|
||||||
new_selector_list.append(argument_selector->absolutized(selector_for_nesting));
|
if (auto absolutized = argument_selector->absolutized(selector_for_nesting)) {
|
||||||
|
new_selector_list.append(absolutized.release_nonnull());
|
||||||
|
} else if (!pseudo_class.is_forgiving) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
pseudo_class.argument_selector_list = move(new_selector_list);
|
pseudo_class.argument_selector_list = move(new_selector_list);
|
||||||
}
|
}
|
||||||
return SimpleSelector {
|
return SimpleSelector {
|
||||||
|
|
|
@ -222,7 +222,7 @@ public:
|
||||||
|
|
||||||
String serialize() const;
|
String serialize() const;
|
||||||
|
|
||||||
SimpleSelector absolutized(SimpleSelector const& selector_for_nesting) const;
|
Optional<SimpleSelector> absolutized(SimpleSelector const& selector_for_nesting) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Combinator {
|
enum class Combinator {
|
||||||
|
@ -240,7 +240,7 @@ public:
|
||||||
Combinator combinator { Combinator::None };
|
Combinator combinator { Combinator::None };
|
||||||
Vector<SimpleSelector> simple_selectors;
|
Vector<SimpleSelector> simple_selectors;
|
||||||
|
|
||||||
CompoundSelector absolutized(SimpleSelector const& selector_for_nesting) const;
|
Optional<CompoundSelector> absolutized(SimpleSelector const& selector_for_nesting) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static NonnullRefPtr<Selector> create(Vector<CompoundSelector>&& compound_selectors)
|
static NonnullRefPtr<Selector> create(Vector<CompoundSelector>&& compound_selectors)
|
||||||
|
@ -254,7 +254,7 @@ public:
|
||||||
Optional<PseudoElement> const& pseudo_element() const { return m_pseudo_element; }
|
Optional<PseudoElement> const& pseudo_element() const { return m_pseudo_element; }
|
||||||
NonnullRefPtr<Selector> relative_to(SimpleSelector const&) const;
|
NonnullRefPtr<Selector> relative_to(SimpleSelector const&) const;
|
||||||
bool contains_the_nesting_selector() const { return m_contains_the_nesting_selector; }
|
bool contains_the_nesting_selector() const { return m_contains_the_nesting_selector; }
|
||||||
NonnullRefPtr<Selector> absolutized(SimpleSelector const& selector_for_nesting) const;
|
RefPtr<Selector> absolutized(SimpleSelector const& selector_for_nesting) const;
|
||||||
u32 specificity() const;
|
u32 specificity() const;
|
||||||
String serialize() const;
|
String serialize() const;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue