diff --git a/Tests/LibWeb/Layout/expected/input-element-with-display-inline.txt b/Tests/LibWeb/Layout/expected/input-element-with-display-inline.txt index 26cadcefc5..8571526d23 100644 --- a/Tests/LibWeb/Layout/expected/input-element-with-display-inline.txt +++ b/Tests/LibWeb/Layout/expected/input-element-with-display-inline.txt @@ -1,15 +1,15 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline - BlockContainer at (1,1) content-size 798x46 [BFC] children: not-inline - BlockContainer at (10,10) content-size 780x28 children: inline - frag 0 from BlockContainer start: 0, length: 0, rect: [11,11 200x26] baseline: 28 - BlockContainer at (11,11) content-size 200x26 inline-block [BFC] children: not-inline - Box
at (13,12) content-size 196x24 flex-container(row) [FFC] children: not-inline - BlockContainer
at (14,13) content-size 194x22 flex-item [BFC] children: inline + BlockContainer at (1,1) content-size 798x44 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x26 children: inline + frag 0 from BlockContainer start: 0, length: 0, rect: [11,11 200x24] baseline: 26 + BlockContainer at (11,11) content-size 200x24 inline-block [BFC] children: not-inline + Box
at (13,12) content-size 196x22 flex-container(row) [FFC] children: not-inline + BlockContainer
at (13,12) content-size 196x22 flex-item [BFC] children: inline TextNode <#text> ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x48] - PaintableWithLines (BlockContainer) [9,9 782x30] - PaintableWithLines (BlockContainer) [10,10 202x28] - PaintableBox (Box
) [11,11 200x26] - PaintableWithLines (BlockContainer
) [13,12 196x24] + PaintableWithLines (BlockContainer) [0,0 800x46] + PaintableWithLines (BlockContainer) [9,9 782x28] + PaintableWithLines (BlockContainer) [10,10 202x26] + PaintableBox (Box
) [11,11 200x24] + PaintableWithLines (BlockContainer
) [13,12 196x22] diff --git a/Tests/LibWeb/Text/expected/shadow-root-adopted-style-sheets.txt b/Tests/LibWeb/Text/expected/shadow-root-adopted-style-sheets.txt new file mode 100644 index 0000000000..2f0a8b4968 --- /dev/null +++ b/Tests/LibWeb/Text/expected/shadow-root-adopted-style-sheets.txt @@ -0,0 +1 @@ + border of #test = (2px solid rgb(173, 255, 47)) diff --git a/Tests/LibWeb/Text/input/shadow-root-adopted-style-sheets.html b/Tests/LibWeb/Text/input/shadow-root-adopted-style-sheets.html new file mode 100644 index 0000000000..492f2d9a92 --- /dev/null +++ b/Tests/LibWeb/Text/input/shadow-root-adopted-style-sheets.html @@ -0,0 +1,37 @@ + + + + diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 71b79a720b..d7af0637bc 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -255,19 +256,25 @@ template void StyleComputer::for_each_stylesheet(CascadeOrigin cascade_origin, Callback callback) const { if (cascade_origin == CascadeOrigin::UserAgent) { - callback(default_stylesheet(document())); + callback(default_stylesheet(document()), {}); if (document().in_quirks_mode()) - callback(quirks_mode_stylesheet(document())); - callback(mathml_stylesheet(document())); - callback(svg_stylesheet(document())); + callback(quirks_mode_stylesheet(document()), {}); + callback(mathml_stylesheet(document()), {}); + callback(svg_stylesheet(document()), {}); } if (cascade_origin == CascadeOrigin::User) { if (m_user_style_sheet) - callback(*m_user_style_sheet); + callback(*m_user_style_sheet, {}); } if (cascade_origin == CascadeOrigin::Author) { document().for_each_css_style_sheet([&](CSSStyleSheet& sheet) { - callback(sheet); + callback(sheet, {}); + }); + + const_cast(document()).for_each_shadow_root([&](DOM::ShadowRoot& shadow_root) { + shadow_root.for_each_css_style_sheet([&](CSSStyleSheet& sheet) { + callback(sheet, &shadow_root); + }); }); } } @@ -298,6 +305,9 @@ StyleComputer::RuleCache const& StyleComputer::rule_cache_for_cascade_origin(Cas Vector StyleComputer::collect_matching_rules(DOM::Element const& element, CascadeOrigin cascade_origin, Optional pseudo_element) const { + auto const& root_node = element.root(); + auto shadow_root = is(root_node) ? static_cast(&root_node) : nullptr; + auto const& rule_cache = rule_cache_for_cascade_origin(cascade_origin); Vector rules_to_run; @@ -331,6 +341,12 @@ Vector StyleComputer::collect_matching_rules(DOM::Element const& e Vector matching_rules; matching_rules.ensure_capacity(rules_to_run.size()); for (auto const& rule_to_run : rules_to_run) { + // FIXME: This needs to be revised when adding support for the :host and ::shadow selectors, which transition shadow tree boundaries + auto rule_root = rule_to_run.shadow_root; + auto from_user_agent_or_user_stylesheet = rule_to_run.cascade_origin == CascadeOrigin::UserAgent || rule_to_run.cascade_origin == CascadeOrigin::User; + if (rule_root != shadow_root && !from_user_agent_or_user_stylesheet) + continue; + auto const& selector = rule_to_run.rule->selectors()[rule_to_run.selector_index]; if (SelectorEngine::matches(selector, *rule_to_run.sheet, element, pseudo_element)) matching_rules.append(rule_to_run); @@ -2277,12 +2293,14 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca Vector matching_rules; size_t style_sheet_index = 0; - for_each_stylesheet(cascade_origin, [&](auto& sheet) { + for_each_stylesheet(cascade_origin, [&](auto& sheet, JS::GCPtr shadow_root) { size_t rule_index = 0; sheet.for_each_effective_style_rule([&](auto const& rule) { size_t selector_index = 0; for (CSS::Selector const& selector : rule.selectors()) { MatchingRule matching_rule { + cascade_origin, + shadow_root, &rule, sheet, style_sheet_index, diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h index 31c2be6016..bd15fec532 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h @@ -20,7 +20,18 @@ namespace Web::CSS { +// https://www.w3.org/TR/css-cascade/#origin +enum class CascadeOrigin { + Author, + User, + UserAgent, + Animation, + Transition, +}; + struct MatchingRule { + CascadeOrigin cascade_origin; + JS::GCPtr shadow_root; JS::GCPtr rule; JS::GCPtr sheet; size_t style_sheet_index { 0 }; @@ -55,15 +66,6 @@ public: NonnullRefPtr compute_style(DOM::Element&, Optional = {}) const; RefPtr compute_pseudo_element_style_if_needed(DOM::Element&, Optional) const; - // https://www.w3.org/TR/css-cascade/#origin - enum class CascadeOrigin { - Author, - User, - UserAgent, - Animation, - Transition, - }; - Vector collect_matching_rules(DOM::Element const&, CascadeOrigin, Optional) const; void invalidate_rule_cache(); diff --git a/Userland/Libraries/LibWeb/DOM/ShadowRoot.cpp b/Userland/Libraries/LibWeb/DOM/ShadowRoot.cpp index 48323f990d..9de779f366 100644 --- a/Userland/Libraries/LibWeb/DOM/ShadowRoot.cpp +++ b/Userland/Libraries/LibWeb/DOM/ShadowRoot.cpp @@ -105,4 +105,16 @@ WebIDL::ExceptionOr ShadowRoot::set_adopted_style_sheets(JS::Value new_val return {}; } +void ShadowRoot::for_each_css_style_sheet(Function&& callback) const +{ + for (auto& style_sheet : style_sheets().sheets()) + callback(*style_sheet); + + if (m_adopted_style_sheets) { + m_adopted_style_sheets->for_each([&](auto& style_sheet) { + callback(style_sheet); + }); + } +} + } diff --git a/Userland/Libraries/LibWeb/DOM/ShadowRoot.h b/Userland/Libraries/LibWeb/DOM/ShadowRoot.h index 532f99985b..f1d2c01149 100644 --- a/Userland/Libraries/LibWeb/DOM/ShadowRoot.h +++ b/Userland/Libraries/LibWeb/DOM/ShadowRoot.h @@ -42,6 +42,8 @@ public: JS::NonnullGCPtr adopted_style_sheets() const; WebIDL::ExceptionOr set_adopted_style_sheets(JS::Value); + void for_each_css_style_sheet(Function&& callback) const; + virtual void finalize() override; protected: