소스 검색

LibWeb: Only invalidate shadow root when style sheet inside changes

We don't have to invalidate style for the entire document when a style
sheet changes inside of a shadow root.

To make this possible, StyleSheetList now keeps track of which
Document-or-ShadowRoot it corresponds to, instead of just tracking the
containing Document.

This avoids a lot of style recomputation on pages with lots of shadow
DOM content (like GitHub).
Andreas Kling 10 달 전
부모
커밋
4bc3055c0f

+ 2 - 3
Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp

@@ -108,9 +108,8 @@ void CSSStyleRule::set_selector_text(StringView selector_text)
         m_selectors = parsed_selectors.release_value();
         m_selectors = parsed_selectors.release_value();
         if (auto* sheet = parent_style_sheet()) {
         if (auto* sheet = parent_style_sheet()) {
             if (auto style_sheet_list = sheet->style_sheet_list()) {
             if (auto style_sheet_list = sheet->style_sheet_list()) {
-                auto& document = style_sheet_list->document();
-                document.style_computer().invalidate_rule_cache();
-                document.invalidate_style();
+                style_sheet_list->document().style_computer().invalidate_rule_cache();
+                style_sheet_list->document_or_shadow_root().invalidate_style();
             }
             }
         }
         }
     }
     }

+ 2 - 2
Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp

@@ -155,7 +155,7 @@ WebIDL::ExceptionOr<unsigned> CSSStyleSheet::insert_rule(StringView rule, unsign
 
 
         if (m_style_sheet_list) {
         if (m_style_sheet_list) {
             m_style_sheet_list->document().style_computer().invalidate_rule_cache();
             m_style_sheet_list->document().style_computer().invalidate_rule_cache();
-            m_style_sheet_list->document().invalidate_style();
+            m_style_sheet_list->document_or_shadow_root().invalidate_style();
         }
         }
     }
     }
 
 
@@ -176,7 +176,7 @@ WebIDL::ExceptionOr<void> CSSStyleSheet::delete_rule(unsigned index)
     if (!result.is_exception()) {
     if (!result.is_exception()) {
         if (m_style_sheet_list) {
         if (m_style_sheet_list) {
             m_style_sheet_list->document().style_computer().invalidate_rule_cache();
             m_style_sheet_list->document().style_computer().invalidate_rule_cache();
-            m_style_sheet_list->document().invalidate_style();
+            m_style_sheet_list->document_or_shadow_root().invalidate_style();
         }
         }
     }
     }
     return result;
     return result;

+ 23 - 13
Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2020-2024, Andreas Kling <andreas@ladybird.org>
  *
  *
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
@@ -107,9 +107,9 @@ void StyleSheetList::add_sheet(CSSStyleSheet& sheet)
         return;
         return;
     }
     }
 
 
-    m_document->style_computer().invalidate_rule_cache();
-    m_document->style_computer().load_fonts_from_sheet(sheet);
-    m_document->invalidate_style();
+    document().style_computer().invalidate_rule_cache();
+    document().style_computer().load_fonts_from_sheet(sheet);
+    document_or_shadow_root().invalidate_style();
 }
 }
 
 
 void StyleSheetList::remove_sheet(CSSStyleSheet& sheet)
 void StyleSheetList::remove_sheet(CSSStyleSheet& sheet)
@@ -123,19 +123,19 @@ void StyleSheetList::remove_sheet(CSSStyleSheet& sheet)
         return;
         return;
     }
     }
 
 
-    m_document->style_computer().invalidate_rule_cache();
-    m_document->invalidate_style();
+    m_document_or_shadow_root->document().style_computer().invalidate_rule_cache();
+    document_or_shadow_root().invalidate_style();
 }
 }
 
 
-JS::NonnullGCPtr<StyleSheetList> StyleSheetList::create(DOM::Document& document)
+JS::NonnullGCPtr<StyleSheetList> StyleSheetList::create(JS::NonnullGCPtr<DOM::Node> document_or_shadow_root)
 {
 {
-    auto& realm = document.realm();
-    return realm.heap().allocate<StyleSheetList>(realm, document);
+    auto& realm = document_or_shadow_root->realm();
+    return realm.heap().allocate<StyleSheetList>(realm, document_or_shadow_root);
 }
 }
 
 
-StyleSheetList::StyleSheetList(DOM::Document& document)
-    : Bindings::PlatformObject(document.realm())
-    , m_document(document)
+StyleSheetList::StyleSheetList(JS::NonnullGCPtr<DOM::Node> document_or_shadow_root)
+    : Bindings::PlatformObject(document_or_shadow_root->realm())
+    , m_document_or_shadow_root(document_or_shadow_root)
 {
 {
     m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = true };
     m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .supports_indexed_properties = true };
 }
 }
@@ -149,7 +149,7 @@ void StyleSheetList::initialize(JS::Realm& realm)
 void StyleSheetList::visit_edges(Cell::Visitor& visitor)
 void StyleSheetList::visit_edges(Cell::Visitor& visitor)
 {
 {
     Base::visit_edges(visitor);
     Base::visit_edges(visitor);
-    visitor.visit(m_document);
+    visitor.visit(m_document_or_shadow_root);
     visitor.visit(m_sheets);
     visitor.visit(m_sheets);
 }
 }
 
 
@@ -161,4 +161,14 @@ Optional<JS::Value> StyleSheetList::item_value(size_t index) const
     return m_sheets[index].ptr();
     return m_sheets[index].ptr();
 }
 }
 
 
+DOM::Document& StyleSheetList::document()
+{
+    return m_document_or_shadow_root->document();
+}
+
+DOM::Document const& StyleSheetList::document() const
+{
+    return m_document_or_shadow_root->document();
+}
+
 }
 }

+ 9 - 6
Userland/Libraries/LibWeb/CSS/StyleSheetList.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2020-2024, Andreas Kling <andreas@ladybird.org>
  * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  *
  *
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
@@ -17,7 +17,7 @@ class StyleSheetList final : public Bindings::PlatformObject {
     JS_DECLARE_ALLOCATOR(StyleSheetList);
     JS_DECLARE_ALLOCATOR(StyleSheetList);
 
 
 public:
 public:
-    [[nodiscard]] static JS::NonnullGCPtr<StyleSheetList> create(DOM::Document&);
+    [[nodiscard]] static JS::NonnullGCPtr<StyleSheetList> create(JS::NonnullGCPtr<DOM::Node> document_or_shadow_root);
 
 
     void add_a_css_style_sheet(CSS::CSSStyleSheet&);
     void add_a_css_style_sheet(CSS::CSSStyleSheet&);
     void remove_a_css_style_sheet(CSS::CSSStyleSheet&);
     void remove_a_css_style_sheet(CSS::CSSStyleSheet&);
@@ -37,11 +37,14 @@ public:
 
 
     virtual Optional<JS::Value> item_value(size_t index) const override;
     virtual Optional<JS::Value> item_value(size_t index) const override;
 
 
-    DOM::Document& document() { return m_document; }
-    DOM::Document const& document() const { return m_document; }
+    [[nodiscard]] DOM::Document& document();
+    [[nodiscard]] DOM::Document const& document() const;
+
+    [[nodiscard]] DOM::Node& document_or_shadow_root() { return m_document_or_shadow_root; }
+    [[nodiscard]] DOM::Node const& document_or_shadow_root() const { return m_document_or_shadow_root; }
 
 
 private:
 private:
-    explicit StyleSheetList(DOM::Document&);
+    explicit StyleSheetList(JS::NonnullGCPtr<DOM::Node> document_or_shadow_root);
 
 
     virtual void initialize(JS::Realm&) override;
     virtual void initialize(JS::Realm&) override;
     virtual void visit_edges(Cell::Visitor&) override;
     virtual void visit_edges(Cell::Visitor&) override;
@@ -49,7 +52,7 @@ private:
     void add_sheet(CSSStyleSheet&);
     void add_sheet(CSSStyleSheet&);
     void remove_sheet(CSSStyleSheet&);
     void remove_sheet(CSSStyleSheet&);
 
 
-    JS::NonnullGCPtr<DOM::Document> m_document;
+    JS::NonnullGCPtr<DOM::Node> m_document_or_shadow_root;
     Vector<JS::NonnullGCPtr<CSSStyleSheet>> m_sheets;
     Vector<JS::NonnullGCPtr<CSSStyleSheet>> m_sheets;
 
 
     // https://www.w3.org/TR/cssom/#preferred-css-style-sheet-set-name
     // https://www.w3.org/TR/cssom/#preferred-css-style-sheet-set-name

+ 1 - 1
Userland/Libraries/LibWeb/DOM/ShadowRoot.cpp

@@ -122,7 +122,7 @@ WebIDL::ExceptionOr<void> ShadowRoot::set_html_unsafe(StringView html)
 CSS::StyleSheetList& ShadowRoot::style_sheets()
 CSS::StyleSheetList& ShadowRoot::style_sheets()
 {
 {
     if (!m_style_sheets)
     if (!m_style_sheets)
-        m_style_sheets = CSS::StyleSheetList::create(document());
+        m_style_sheets = CSS::StyleSheetList::create(*this);
     return *m_style_sheets;
     return *m_style_sheets;
 }
 }