mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-22 17:24:48 -05:00
LibWeb/CSS: Block shadow host matching in DOM
Fixes an issue where selectors inside a shadow root could incorrectly match their shadow host directly using selectors like #host, instead of requiring :host pseudo-class selectors. Fixes issue #2319
This commit is contained in:
parent
90d884a150
commit
3ff8c5c8f1
Notes:
github-actions[bot]
2024-12-04 16:20:31 +00:00
Author: https://github.com/ycarmon 🔰 Commit: https://github.com/LadybirdBrowser/ladybird/commit/3ff8c5c8f1a Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2552 Reviewed-by: https://github.com/AtkinsSJ ✅ Reviewed-by: https://github.com/awesomekling
1 changed files with 28 additions and 0 deletions
|
@ -363,6 +363,29 @@ static inline DOM::Element const* next_sibling_with_same_tag_name(DOM::Element c
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/// Returns true if this selector should be blocked from matching against the shadow host from within a shadow tree.
|
||||
/// Only :host pseudo-class is allowed to match the shadow host from within shadow tree, all other selectors (including other pseudo-classes) are blocked.
|
||||
/// Compound selectors (:has(), :is(), :where()), nesting, and pseudo-elements are allowed as they may contain or be contained within :host.
|
||||
static inline bool should_block_shadow_host_matching(CSS::Selector::SimpleSelector const& component, GC::Ptr<DOM::Element const> shadow_host, DOM::Element const& element)
|
||||
{
|
||||
if (!shadow_host || &element != shadow_host.ptr())
|
||||
return false;
|
||||
|
||||
// From within shadow tree, only :host pseudo-class can match the host element
|
||||
if (component.type == CSS::Selector::SimpleSelector::Type::PseudoClass) {
|
||||
auto const& pseudo_class = component.pseudo_class();
|
||||
return pseudo_class.type != CSS::PseudoClass::Host
|
||||
&& pseudo_class.type != CSS::PseudoClass::Has
|
||||
&& pseudo_class.type != CSS::PseudoClass::Is
|
||||
&& pseudo_class.type != CSS::PseudoClass::Where;
|
||||
}
|
||||
|
||||
// Allow nesting and PseudoElement as it may contain :host class
|
||||
if (component.type == CSS::Selector::SimpleSelector::Type::Nesting || component.type == CSS::Selector::SimpleSelector::Type::PseudoElement)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-read-write
|
||||
static bool matches_read_write_pseudo_class(DOM::Element const& element)
|
||||
{
|
||||
|
@ -755,6 +778,8 @@ static ALWAYS_INLINE bool matches_namespace(
|
|||
|
||||
static inline bool matches(CSS::Selector::SimpleSelector const& component, Optional<CSS::CSSStyleSheet const&> style_sheet_for_rule, DOM::Element const& element, GC::Ptr<DOM::Element const> shadow_host, GC::Ptr<DOM::ParentNode const> scope, SelectorKind selector_kind, [[maybe_unused]] GC::Ptr<DOM::Element const> anchor)
|
||||
{
|
||||
if (should_block_shadow_host_matching(component, shadow_host, element))
|
||||
return false;
|
||||
switch (component.type) {
|
||||
case CSS::Selector::SimpleSelector::Type::Universal:
|
||||
case CSS::Selector::SimpleSelector::Type::TagName: {
|
||||
|
@ -866,6 +891,9 @@ bool matches(CSS::Selector const& selector, Optional<CSS::CSSStyleSheet const&>
|
|||
|
||||
static bool fast_matches_simple_selector(CSS::Selector::SimpleSelector const& simple_selector, Optional<CSS::CSSStyleSheet const&> style_sheet_for_rule, DOM::Element const& element, GC::Ptr<DOM::Element const> shadow_host)
|
||||
{
|
||||
if (should_block_shadow_host_matching(simple_selector, shadow_host, element))
|
||||
return false;
|
||||
|
||||
switch (simple_selector.type) {
|
||||
case CSS::Selector::SimpleSelector::Type::Universal:
|
||||
return matches_namespace(simple_selector.qualified_name(), element, style_sheet_for_rule);
|
||||
|
|
Loading…
Reference in a new issue