From 12042f075767d357a3d54b008609b0dd76354ad9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 7 Aug 2022 15:46:44 +0200 Subject: [PATCH] LibWeb: Make CSSRule and all its subclasses GC-allocated --- Documentation/Browser/AddNewIDLFile.md | 1 - .../LibWeb/WrapperGenerator/IDLGenerators.cpp | 22 ++++++++- .../LibWeb/Bindings/CSSRuleWrapperFactory.cpp | 41 ----------------- .../LibWeb/Bindings/CSSRuleWrapperFactory.h | 16 ------- Userland/Libraries/LibWeb/CMakeLists.txt | 1 - .../Libraries/LibWeb/CSS/CSSConditionRule.cpp | 8 +++- .../Libraries/LibWeb/CSS/CSSConditionRule.h | 10 +++- .../Libraries/LibWeb/CSS/CSSConditionRule.idl | 2 +- .../Libraries/LibWeb/CSS/CSSFontFaceRule.cpp | 14 +++++- .../Libraries/LibWeb/CSS/CSSFontFaceRule.h | 19 ++++---- .../Libraries/LibWeb/CSS/CSSFontFaceRule.idl | 2 +- .../Libraries/LibWeb/CSS/CSSGroupingRule.cpp | 28 +++++++---- .../Libraries/LibWeb/CSS/CSSGroupingRule.h | 20 +++++--- .../Libraries/LibWeb/CSS/CSSGroupingRule.idl | 2 +- .../Libraries/LibWeb/CSS/CSSImportRule.cpp | 22 ++++++++- Userland/Libraries/LibWeb/CSS/CSSImportRule.h | 32 +++++++------ .../Libraries/LibWeb/CSS/CSSImportRule.idl | 2 +- .../Libraries/LibWeb/CSS/CSSMediaRule.cpp | 13 +++++- Userland/Libraries/LibWeb/CSS/CSSMediaRule.h | 18 ++++---- .../Libraries/LibWeb/CSS/CSSMediaRule.idl | 2 +- Userland/Libraries/LibWeb/CSS/CSSRule.cpp | 15 ++++++ Userland/Libraries/LibWeb/CSS/CSSRule.h | 34 ++++++++------ Userland/Libraries/LibWeb/CSS/CSSRule.idl | 2 +- Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp | 45 ++++++++++++------ Userland/Libraries/LibWeb/CSS/CSSRuleList.h | 30 ++++++++---- .../Libraries/LibWeb/CSS/CSSStyleRule.cpp | 13 +++++- Userland/Libraries/LibWeb/CSS/CSSStyleRule.h | 19 ++++---- .../Libraries/LibWeb/CSS/CSSStyleRule.idl | 1 + .../Libraries/LibWeb/CSS/CSSStyleSheet.cpp | 15 +++--- Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h | 7 ++- .../Libraries/LibWeb/CSS/CSSSupportsRule.cpp | 12 ++++- .../Libraries/LibWeb/CSS/CSSSupportsRule.h | 19 ++++---- .../Libraries/LibWeb/CSS/CSSSupportsRule.idl | 2 +- .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 46 +++++++++++-------- Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 9 ++-- .../Libraries/LibWeb/CSS/StyleComputer.cpp | 4 +- Userland/Libraries/LibWeb/CSS/StyleComputer.h | 2 +- Userland/Libraries/LibWeb/Forward.h | 8 ---- Userland/Libraries/LibWeb/idl_files.cmake | 16 +++---- 39 files changed, 338 insertions(+), 236 deletions(-) delete mode 100644 Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.cpp delete mode 100644 Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.h diff --git a/Documentation/Browser/AddNewIDLFile.md b/Documentation/Browser/AddNewIDLFile.md index 1024e728c62..54f6e455bd7 100644 --- a/Documentation/Browser/AddNewIDLFile.md +++ b/Documentation/Browser/AddNewIDLFile.md @@ -39,7 +39,6 @@ interface CSSRule { - It must have a public `using WrapperType = Bindings::HTMLDetailsElementWrapper;` 7. Depending on what kind of thing your interface is, you may need to add it to the `WrapperFactory` of that kind: - - CSSRules: [`LibWeb/Bindings/CSSRuleWrapperFactory.cpp`](../../Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.cpp) - Events: [`LibWeb/Bindings/EventWrapperFactory.cpp`](../../Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp) - Elements: [`LibWeb/Bindings/NodeWrapperFactory.cpp`](../../Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp index 8b22a1b2e46..14020284c15 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp @@ -87,6 +87,27 @@ static bool impl_is_wrapper(Type const& type) if (type.name == "CSSRuleList"sv) return true; + if (type.name == "CSSRule"sv) + return true; + + if (type.name == "CSSStyleRule"sv) + return true; + + if (type.name == "CSSFontFaceRule"sv) + return true; + + if (type.name == "CSSConditionRule"sv) + return true; + + if (type.name == "CSSGroupingRule"sv) + return true; + + if (type.name == "CSSMediaRule"sv) + return true; + + if (type.name == "CSSImportRule"sv) + return true; + return false; } @@ -2884,7 +2905,6 @@ void generate_constructor_implementation(IDL::Interface const& interface) #if __has_include() #include #endif -#include #include #include #include diff --git a/Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.cpp deleted file mode 100644 index 2870c97f4ca..00000000000 --- a/Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2021, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Web::Bindings { - -CSSRuleWrapper* wrap(JS::Realm& realm, CSS::CSSRule& rule) -{ - if (rule.wrapper()) - return static_cast(rule.wrapper()); - - if (is(rule)) - return static_cast(wrap_impl(realm, verify_cast(rule))); - if (is(rule)) - return static_cast(wrap_impl(realm, verify_cast(rule))); - if (is(rule)) - return static_cast(wrap_impl(realm, verify_cast(rule))); - if (is(rule)) - return static_cast(wrap_impl(realm, verify_cast(rule))); - if (is(rule)) - return static_cast(wrap_impl(realm, verify_cast(rule))); - return static_cast(wrap_impl(realm, rule)); -} - -} diff --git a/Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.h b/Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.h deleted file mode 100644 index 2382bfef97f..00000000000 --- a/Userland/Libraries/LibWeb/Bindings/CSSRuleWrapperFactory.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2021, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace Web::Bindings { - -CSSRuleWrapper* wrap(JS::Realm&, CSS::CSSRule&); - -} diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 4983599a2c3..65e039f4047 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -4,7 +4,6 @@ set(SOURCES Bindings/AudioConstructor.cpp Bindings/CrossOriginAbstractOperations.cpp Bindings/CSSNamespace.cpp - Bindings/CSSRuleWrapperFactory.cpp Bindings/CSSStyleDeclarationWrapperCustom.cpp Bindings/EventListenerWrapper.cpp Bindings/EventTargetWrapperFactory.cpp diff --git a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp index f6ac1a254b4..cd10d454018 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.cpp @@ -1,16 +1,20 @@ /* * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include namespace Web::CSS { -CSSConditionRule::CSSConditionRule(NonnullRefPtrVector&& rules) - : CSSGroupingRule(move(rules)) +CSSConditionRule::CSSConditionRule(Bindings::WindowObject& window_object, CSSRuleList& rules) + : CSSGroupingRule(window_object, rules) { + set_prototype(&window_object.ensure_web_prototype("CSSConditionRule")); } void CSSConditionRule::for_each_effective_style_rule(Function const& callback) const diff --git a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h index 6cf61c2219e..58d040a5ee2 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.h @@ -15,9 +15,10 @@ namespace Web::CSS { class CSSConditionRule : public CSSGroupingRule { AK_MAKE_NONCOPYABLE(CSSConditionRule); AK_MAKE_NONMOVABLE(CSSConditionRule); + JS_OBJECT(CSSConditionRule, CSSGroupingRule); public: - using WrapperType = Bindings::CSSConditionRuleWrapper; + CSSConditionRule& impl() { return *this; } virtual ~CSSConditionRule() = default; @@ -28,7 +29,12 @@ public: virtual void for_each_effective_style_rule(Function const& callback) const override; protected: - explicit CSSConditionRule(NonnullRefPtrVector&&); + explicit CSSConditionRule(Bindings::WindowObject&, CSSRuleList&); }; } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSConditionRule& object) { return &object; } +using CSSConditionRuleWrapper = Web::CSS::CSSConditionRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.idl b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.idl index 73c336eaaae..ad01e7db8ea 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSConditionRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSConditionRule.idl @@ -1,6 +1,6 @@ #import -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface CSSConditionRule : CSSGroupingRule { attribute CSSOMString conditionText; }; diff --git a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp index f001068142f..f6b3f69086a 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp @@ -1,16 +1,26 @@ /* * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include namespace Web::CSS { -CSSFontFaceRule::CSSFontFaceRule(FontFace&& font_face) - : m_font_face(move(font_face)) +CSSFontFaceRule* CSSFontFaceRule::create(Bindings::WindowObject& window_object, FontFace&& font_face) { + return window_object.heap().allocate(window_object.realm(), window_object, move(font_face)); +} + +CSSFontFaceRule::CSSFontFaceRule(Bindings::WindowObject& window_object, FontFace&& font_face) + : CSSRule(window_object) + , m_font_face(move(font_face)) +{ + set_prototype(&window_object.ensure_web_prototype("CSSFontFaceRule")); } CSSStyleDeclaration* CSSFontFaceRule::style() diff --git a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h index 80b8866dc37..5967add8fcb 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -14,26 +15,21 @@ namespace Web::CSS { class CSSFontFaceRule final : public CSSRule { AK_MAKE_NONCOPYABLE(CSSFontFaceRule); AK_MAKE_NONMOVABLE(CSSFontFaceRule); + JS_OBJECT(CSSFontFaceRule, CSSRule); public: - using WrapperType = Bindings::CSSFontFaceRuleWrapper; - - static NonnullRefPtr create(FontFace&& font_face) - { - return adopt_ref(*new CSSFontFaceRule(move(font_face))); - } + static CSSFontFaceRule* create(Bindings::WindowObject&, FontFace&&); + explicit CSSFontFaceRule(Bindings::WindowObject&, FontFace&&); virtual ~CSSFontFaceRule() override = default; + CSSFontFaceRule& impl() { return *this; } - virtual StringView class_name() const override { return "CSSFontFaceRule"sv; } virtual Type type() const override { return Type::FontFace; } FontFace const& font_face() const { return m_font_face; } CSSStyleDeclaration* style(); private: - explicit CSSFontFaceRule(FontFace&&); - virtual String serialized() const override; FontFace m_font_face; @@ -43,3 +39,8 @@ template<> inline bool CSSRule::fast_is() const { return type() == CSSRule::Type::FontFace; } } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSFontFaceRule& object) { return &object; } +using CSSFontFaceRuleWrapper = Web::CSS::CSSFontFaceRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.idl b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.idl index cf5701a19b2..3dd9926ec3f 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.idl @@ -1,7 +1,7 @@ #import #import -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface CSSFontFaceRule : CSSRule { readonly attribute CSSStyleDeclaration style; }; diff --git a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp index bb214da973c..e852b1ff446 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.cpp @@ -1,45 +1,55 @@ /* * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include #include #include namespace Web::CSS { -CSSGroupingRule::CSSGroupingRule(NonnullRefPtrVector&& rules) - // FIXME: Use the same window object for the rule list. - : m_rules(JS::make_handle(CSSRuleList::create(Bindings::main_thread_internal_window_object(), move(rules)))) +CSSGroupingRule::CSSGroupingRule(Bindings::WindowObject& window_object, CSSRuleList& rules) + : CSSRule(window_object) + , m_rules(rules) { - for (auto& rule : *m_rules) + set_prototype(&window_object.ensure_web_prototype("CSSGroupingRule")); + for (auto& rule : m_rules) rule.set_parent_rule(this); } +void CSSGroupingRule::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(&m_rules); +} + DOM::ExceptionOr CSSGroupingRule::insert_rule(StringView rule, u32 index) { - TRY(m_rules->insert_a_css_rule(rule, index)); + TRY(m_rules.insert_a_css_rule(rule, index)); // NOTE: The spec doesn't say where to set the parent rule, so we'll do it here. - m_rules->item(index)->set_parent_rule(this); + m_rules.item(index)->set_parent_rule(this); return index; } DOM::ExceptionOr CSSGroupingRule::delete_rule(u32 index) { - return m_rules->remove_a_css_rule(index); + return m_rules.remove_a_css_rule(index); } void CSSGroupingRule::for_each_effective_style_rule(Function const& callback) const { - m_rules->for_each_effective_style_rule(callback); + m_rules.for_each_effective_style_rule(callback); } void CSSGroupingRule::set_parent_style_sheet(CSSStyleSheet* parent_style_sheet) { CSSRule::set_parent_style_sheet(parent_style_sheet); - for (auto& rule : *m_rules) + for (auto& rule : m_rules) rule.set_parent_style_sheet(parent_style_sheet); } diff --git a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h index 19dae632d3b..271572d226c 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.h @@ -17,15 +17,16 @@ namespace Web::CSS { class CSSGroupingRule : public CSSRule { AK_MAKE_NONCOPYABLE(CSSGroupingRule); AK_MAKE_NONMOVABLE(CSSGroupingRule); + JS_OBJECT(CSSGroupingRule, CSSRule); public: - using WrapperType = Bindings::CSSGroupingRuleWrapper; + CSSGroupingRule& impl() { return *this; } virtual ~CSSGroupingRule() = default; - CSSRuleList const& css_rules() const { return *m_rules; } - CSSRuleList& css_rules() { return *m_rules; } - CSSRuleList* css_rules_for_bindings() { return m_rules.cell(); } + CSSRuleList const& css_rules() const { return m_rules; } + CSSRuleList& css_rules() { return m_rules; } + CSSRuleList* css_rules_for_bindings() { return &m_rules; } DOM::ExceptionOr insert_rule(StringView rule, u32 index = 0); DOM::ExceptionOr delete_rule(u32 index); @@ -34,10 +35,17 @@ public: virtual void set_parent_style_sheet(CSSStyleSheet*) override; protected: - explicit CSSGroupingRule(NonnullRefPtrVector&&); + explicit CSSGroupingRule(Bindings::WindowObject&, CSSRuleList&); private: - JS::Handle m_rules; + virtual void visit_edges(Cell::Visitor&) override; + + CSSRuleList& m_rules; }; } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSGroupingRule& object) { return &object; } +using CSSGroupingRuleWrapper = Web::CSS::CSSGroupingRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.idl b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.idl index 6f8280a0fd5..7a1c3e3d007 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSGroupingRule.idl @@ -1,7 +1,7 @@ #import #import -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface CSSGroupingRule : CSSRule { [SameObject, ImplementedAs=css_rules_for_bindings] readonly attribute CSSRuleList cssRules; unsigned long insertRule(CSSOMString rule, optional unsigned long index = 0); diff --git a/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp index 61ea65e7bcf..52c25953bbc 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSImportRule.cpp @@ -1,12 +1,15 @@ /* * Copyright (c) 2021, the SerenityOS developers. * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include +#include +#include #include #include #include @@ -14,10 +17,19 @@ namespace Web::CSS { +CSSImportRule* CSSImportRule::create(AK::URL url, DOM::Document& document) +{ + auto& window_object = document.preferred_window_object(); + return window_object.heap().allocate(window_object.realm(), move(url), document); +} + CSSImportRule::CSSImportRule(AK::URL url, DOM::Document& document) - : m_url(move(url)) + : CSSRule(document.preferred_window_object()) + , m_url(move(url)) , m_document(document) { + set_prototype(&document.preferred_window_object().ensure_web_prototype("CSSImportRule")); + dbgln_if(CSS_LOADER_DEBUG, "CSSImportRule: Loading import URL: {}", m_url); auto request = LoadRequest::create_for_url_on_page(m_url, document.page()); @@ -28,6 +40,12 @@ CSSImportRule::CSSImportRule(AK::URL url, DOM::Document& document) set_resource(ResourceLoader::the().load_resource(Resource::Type::Generic, request)); } +void CSSImportRule::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_style_sheet); +} + // https://www.w3.org/TR/cssom/#serialize-a-css-rule String CSSImportRule::serialized() const { @@ -79,7 +97,7 @@ void CSSImportRule::resource_did_load() return; } - m_style_sheet = JS::make_handle(sheet); + m_style_sheet = sheet; m_document->style_computer().invalidate_rule_cache(); m_document->invalidate_style(); diff --git a/Userland/Libraries/LibWeb/CSS/CSSImportRule.h b/Userland/Libraries/LibWeb/CSS/CSSImportRule.h index abe16dfb730..ac2cb26a38c 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSImportRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSImportRule.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2021, the SerenityOS developers. * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -20,32 +21,30 @@ class CSSImportRule final , public ResourceClient { AK_MAKE_NONCOPYABLE(CSSImportRule); AK_MAKE_NONMOVABLE(CSSImportRule); + JS_OBJECT(CSSImportRule, CSSRule); public: - using WrapperType = Bindings::CSSImportRuleWrapper; - - static NonnullRefPtr create(AK::URL url, DOM::Document& document) - { - return adopt_ref(*new CSSImportRule(move(url), document)); - } + static CSSImportRule* create(AK::URL, DOM::Document&); + CSSImportRule(AK::URL, DOM::Document&); virtual ~CSSImportRule() = default; + CSSImportRule& impl() { return *this; } + AK::URL const& url() const { return m_url; } // FIXME: This should return only the specified part of the url. eg, "stuff/foo.css", not "https://example.com/stuff/foo.css". String href() const { return m_url.to_string(); } - bool has_import_result() const { return !m_style_sheet.is_null(); } - CSSStyleSheet* loaded_style_sheet() { return m_style_sheet.cell(); } - CSSStyleSheet const* loaded_style_sheet() const { return m_style_sheet.cell(); } - CSSStyleSheet* style_sheet_for_bindings() { return m_style_sheet.cell(); } - void set_style_sheet(CSSStyleSheet* style_sheet) { m_style_sheet = JS::make_handle(style_sheet); } + bool has_import_result() const { return !m_style_sheet; } + CSSStyleSheet* loaded_style_sheet() { return m_style_sheet; } + CSSStyleSheet const* loaded_style_sheet() const { return m_style_sheet; } + CSSStyleSheet* style_sheet_for_bindings() { return m_style_sheet; } + void set_style_sheet(CSSStyleSheet* style_sheet) { m_style_sheet = style_sheet; } - virtual StringView class_name() const override { return "CSSImportRule"sv; }; virtual Type type() const override { return Type::Import; }; private: - explicit CSSImportRule(AK::URL, DOM::Document&); + virtual void visit_edges(Cell::Visitor&) override; virtual String serialized() const override; @@ -56,10 +55,15 @@ private: AK::URL m_url; WeakPtr m_document; Optional m_document_load_event_delayer; - JS::Handle m_style_sheet; + CSSStyleSheet* m_style_sheet { nullptr }; }; template<> inline bool CSSRule::fast_is() const { return type() == CSSRule::Type::Import; } } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSImportRule& object) { return &object; } +using CSSImportRuleWrapper = Web::CSS::CSSImportRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSImportRule.idl b/Userland/Libraries/LibWeb/CSS/CSSImportRule.idl index 838e64d77ad..e274ff93b86 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSImportRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSImportRule.idl @@ -2,7 +2,7 @@ #import #import -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface CSSImportRule : CSSRule { readonly attribute USVString href; // [SameObject, PutForwards=mediaText] readonly attribute MediaList media; diff --git a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp index 3e5361817e7..698e563fa69 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.cpp @@ -1,17 +1,26 @@ /* * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include namespace Web::CSS { -CSSMediaRule::CSSMediaRule(NonnullRefPtr&& media, NonnullRefPtrVector&& rules) - : CSSConditionRule(move(rules)) +CSSMediaRule* CSSMediaRule::create(Bindings::WindowObject& window_object, NonnullRefPtr&& media_queries, CSSRuleList& rules) +{ + return window_object.heap().allocate(window_object.realm(), window_object, move(media_queries), rules); +} + +CSSMediaRule::CSSMediaRule(Bindings::WindowObject& window_object, NonnullRefPtr&& media, CSSRuleList& rules) + : CSSConditionRule(window_object, rules) , m_media(move(media)) { + set_prototype(&window_object.ensure_web_prototype("CSSMediaRule")); } String CSSMediaRule::condition_text() const diff --git a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h index 3bd72142430..f3563660d20 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -16,18 +17,16 @@ namespace Web::CSS { class CSSMediaRule final : public CSSConditionRule { AK_MAKE_NONCOPYABLE(CSSMediaRule); AK_MAKE_NONMOVABLE(CSSMediaRule); + JS_OBJECT(CSSMediaRule, CSSConditionRule); public: - using WrapperType = Bindings::CSSMediaRuleWrapper; + CSSMediaRule& impl() { return *this; } - static NonnullRefPtr create(NonnullRefPtr&& media_queries, NonnullRefPtrVector&& rules) - { - return adopt_ref(*new CSSMediaRule(move(media_queries), move(rules))); - } + static CSSMediaRule* create(Bindings::WindowObject&, NonnullRefPtr&& media_queries, CSSRuleList&); + explicit CSSMediaRule(Bindings::WindowObject&, NonnullRefPtr&&, CSSRuleList&); virtual ~CSSMediaRule() = default; - virtual StringView class_name() const override { return "CSSMediaRule"sv; }; virtual Type type() const override { return Type::Media; }; virtual String condition_text() const override; @@ -39,8 +38,6 @@ public: bool evaluate(HTML::Window const& window) { return m_media->evaluate(window); } private: - explicit CSSMediaRule(NonnullRefPtr&&, NonnullRefPtrVector&&); - virtual String serialized() const override; NonnullRefPtr m_media; @@ -50,3 +47,8 @@ template<> inline bool CSSRule::fast_is() const { return type() == CSSRule::Type::Media; } } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSMediaRule& object) { return &object; } +using CSSMediaRuleWrapper = Web::CSS::CSSMediaRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.idl b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.idl index 72e3c554544..60fda190c1d 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSMediaRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSMediaRule.idl @@ -1,7 +1,7 @@ #import #import -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface CSSMediaRule : CSSConditionRule { [SameObject, PutForwards=mediaText] readonly attribute MediaList media; }; diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSRule.cpp index bd1b94493aa..b3c8fcf351b 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.cpp @@ -1,15 +1,30 @@ /* * Copyright (c) 2021, the SerenityOS developers. * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include #include namespace Web::CSS { +CSSRule::CSSRule(Bindings::WindowObject& window_object) + : PlatformObject(window_object.ensure_web_prototype("CSSRule")) +{ +} + +void CSSRule::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_parent_style_sheet.ptr()); + visitor.visit(m_parent_rule.ptr()); +} + // https://www.w3.org/TR/cssom/#dom-cssrule-csstext String CSSRule::css_text() const { diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.h b/Userland/Libraries/LibWeb/CSS/CSSRule.h index 986dc3a6e6a..7b82ba62ce6 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.h @@ -1,27 +1,25 @@ /* * Copyright (c) 2021, the SerenityOS developers. + * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include #include -#include -#include +#include +#include #include #include namespace Web::CSS { -class CSSRule - : public RefCounted - , public Bindings::Wrappable - , public Weakable { -public: - using WrapperType = Bindings::CSSRuleWrapper; +class CSSRule : public Bindings::PlatformObject { + JS_OBJECT(CSSRule, JS::Object); +public: + CSSRule& impl() { return *this; } virtual ~CSSRule() = default; // https://drafts.csswg.org/cssom/#dom-cssrule-type @@ -33,26 +31,34 @@ public: Supports = 12, }; - virtual StringView class_name() const = 0; virtual Type type() const = 0; String css_text() const; void set_css_text(StringView); - CSSRule* parent_rule() { return m_parent_rule; } + CSSRule* parent_rule() { return m_parent_rule.ptr(); } void set_parent_rule(CSSRule*); - CSSStyleSheet* parent_style_sheet() { return m_parent_style_sheet; } + CSSStyleSheet* parent_style_sheet() { return m_parent_style_sheet.ptr(); } virtual void set_parent_style_sheet(CSSStyleSheet*); template bool fast_is() const = delete; protected: + explicit CSSRule(Bindings::WindowObject&); + virtual String serialized() const = 0; - WeakPtr m_parent_rule; - WeakPtr m_parent_style_sheet; + virtual void visit_edges(Cell::Visitor&) override; + + JS::GCPtr m_parent_rule; + JS::GCPtr m_parent_style_sheet; }; } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSRule& object) { return &object; } +using CSSRuleWrapper = Web::CSS::CSSRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.idl b/Userland/Libraries/LibWeb/CSS/CSSRule.idl index bd40b41bd6a..e7e262bc321 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.idl @@ -1,6 +1,6 @@ #import -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface CSSRule { attribute CSSOMString cssText; diff --git a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp index b076c58febc..8aa7bf293c0 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp @@ -9,23 +9,38 @@ #include #include #include +#include #include #include #include namespace Web::CSS { -CSSRuleList* CSSRuleList::create(Bindings::WindowObject& window_object, NonnullRefPtrVector&& rules) +CSSRuleList* CSSRuleList::create(Bindings::WindowObject& window_object, JS::MarkedVector const& rules) { - return window_object.heap().allocate(window_object.realm(), window_object, move(rules)); + auto* rule_list = window_object.heap().allocate(window_object.realm(), window_object); + for (auto* rule : rules) + rule_list->m_rules.append(*rule); + return rule_list; } -CSSRuleList::CSSRuleList(Bindings::WindowObject& window_object, NonnullRefPtrVector&& rules) +CSSRuleList::CSSRuleList(Bindings::WindowObject& window_object) : Bindings::LegacyPlatformObject(window_object.ensure_web_prototype("CSSRuleList")) - , m_rules(move(rules)) { } +CSSRuleList* CSSRuleList::create_empty(Bindings::WindowObject& window_object) +{ + return window_object.heap().allocate(window_object.realm(), window_object); +} + +void CSSRuleList::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + for (auto& rule : m_rules) + visitor.visit(&rule); +} + bool CSSRuleList::is_supported_property_index(u32 index) const { // The object’s supported property indices are the numbers in the range zero to one less than the number of CSSRule objects represented by the collection. @@ -34,7 +49,7 @@ bool CSSRuleList::is_supported_property_index(u32 index) const } // https://www.w3.org/TR/cssom/#insert-a-css-rule -DOM::ExceptionOr CSSRuleList::insert_a_css_rule(Variant> rule, u32 index) +DOM::ExceptionOr CSSRuleList::insert_a_css_rule(Variant rule, u32 index) { // 1. Set length to the number of items in list. auto length = m_rules.size(); @@ -47,11 +62,13 @@ DOM::ExceptionOr CSSRuleList::insert_a_css_rule(Variant new_rule; + CSSRule* new_rule = nullptr; if (rule.has()) { - new_rule = parse_css_rule(CSS::Parser::ParsingContext {}, rule.get()); + new_rule = parse_css_rule( + CSS::Parser::ParsingContext { static_cast(global_object()) }, + rule.get()); } else { - new_rule = rule.get>(); + new_rule = rule.get(); } // 4. If new rule is a syntax error, throw a SyntaxError exception. @@ -63,7 +80,7 @@ DOM::ExceptionOr CSSRuleList::insert_a_css_rule(Variant CSSRuleList::remove_a_css_rule(u32 index) return DOM::IndexSizeError::create("CSS rule index out of bounds."); // 3. Set old rule to the indexth item in list. - NonnullRefPtr old_rule = m_rules[index]; + CSSRule& old_rule = m_rules[index]; // FIXME: 4. If old rule is an @namespace at-rule, and list contains anything other than @import at-rules, and @namespace at-rules, throw an InvalidStateError exception. @@ -88,8 +105,8 @@ DOM::ExceptionOr CSSRuleList::remove_a_css_rule(u32 index) m_rules.remove(index); // 6. Set old rule’s parent CSS rule and parent CSS style sheet to null. - old_rule->set_parent_rule(nullptr); - old_rule->set_parent_style_sheet(nullptr); + old_rule.set_parent_rule(nullptr); + old_rule.set_parent_style_sheet(nullptr); return {}; } @@ -102,7 +119,7 @@ void CSSRuleList::for_each_effective_style_rule(Function(rule); - if (import_rule.has_import_result()) + if (import_rule.has_import_result() && import_rule.loaded_style_sheet()) import_rule.loaded_style_sheet()->for_each_effective_style_rule(callback); break; } @@ -129,7 +146,7 @@ bool CSSRuleList::evaluate_media_queries(HTML::Window const& window) break; case CSSRule::Type::Import: { auto& import_rule = verify_cast(rule); - if (import_rule.has_import_result() && import_rule.loaded_style_sheet()->evaluate_media_queries(window)) + if (import_rule.has_import_result() && import_rule.loaded_style_sheet() && import_rule.loaded_style_sheet()->evaluate_media_queries(window)) any_media_queries_changed_match_state = true; break; } diff --git a/Userland/Libraries/LibWeb/CSS/CSSRuleList.h b/Userland/Libraries/LibWeb/CSS/CSSRuleList.h index af4157f61bc..9f94bcc1d4d 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRuleList.h +++ b/Userland/Libraries/LibWeb/CSS/CSSRuleList.h @@ -25,20 +25,30 @@ class CSSRuleList : public Bindings::LegacyPlatformObject { public: CSSRuleList& impl() { return *this; } - static CSSRuleList* create(Bindings::WindowObject&, NonnullRefPtrVector&& rules); - CSSRuleList(Bindings::WindowObject&, NonnullRefPtrVector&&); + static CSSRuleList* create(Bindings::WindowObject&, JS::MarkedVector const&); + static CSSRuleList* create_empty(Bindings::WindowObject&); + + explicit CSSRuleList(Bindings::WindowObject&); ~CSSRuleList() = default; - RefPtr item(size_t index) const + CSSRule const* item(size_t index) const { if (index >= length()) return nullptr; - return m_rules[index]; + return &m_rules[index]; } + + CSSRule* item(size_t index) + { + if (index >= length()) + return nullptr; + return &m_rules[index]; + } + size_t length() const { return m_rules.size(); } - using ConstIterator = AK::SimpleIterator> const, CSSRule const>; - using Iterator = AK::SimpleIterator>, CSSRule>; + using ConstIterator = AK::SimpleIterator const, CSSRule const>; + using Iterator = AK::SimpleIterator, CSSRule>; ConstIterator const begin() const { return m_rules.begin(); } Iterator begin() { return m_rules.begin(); } @@ -50,19 +60,21 @@ public: virtual JS::Value item_value(size_t index) const override; DOM::ExceptionOr remove_a_css_rule(u32 index); - DOM::ExceptionOr insert_a_css_rule(Variant>, u32 index); + DOM::ExceptionOr insert_a_css_rule(Variant, u32 index); void for_each_effective_style_rule(Function const& callback) const; // Returns whether the match state of any media queries changed after evaluation. bool evaluate_media_queries(HTML::Window const&); private: - NonnullRefPtrVector m_rules; + virtual void visit_edges(Cell::Visitor&) override; + + Vector m_rules; }; } namespace Web::Bindings { -inline JS::Object* wrap(JS::GlobalObject&, Web::CSS::CSSRuleList& object) { return &object; } +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSRuleList& object) { return &object; } using CSSRuleListWrapper = Web::CSS::CSSRuleList; } diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp index 9b6a2ad0c2d..25757b16366 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.cpp @@ -4,15 +4,24 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include #include namespace Web::CSS { -CSSStyleRule::CSSStyleRule(NonnullRefPtrVector&& selectors, NonnullRefPtr&& declaration) - : m_selectors(move(selectors)) +CSSStyleRule* CSSStyleRule::create(Bindings::WindowObject& window_object, NonnullRefPtrVector&& selectors, NonnullRefPtr&& declaration) +{ + return window_object.heap().allocate(window_object.realm(), window_object, move(selectors), move(declaration)); +} + +CSSStyleRule::CSSStyleRule(Bindings::WindowObject& window_object, NonnullRefPtrVector&& selectors, NonnullRefPtr&& declaration) + : CSSRule(window_object) + , m_selectors(move(selectors)) , m_declaration(move(declaration)) { + set_prototype(&window_object.ensure_web_prototype("CSSStyleRule")); } // https://www.w3.org/TR/cssom/#dom-cssstylerule-style diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h index 090c15db1ff..cff6461137d 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.h @@ -16,23 +16,21 @@ namespace Web::CSS { class CSSStyleRule final : public CSSRule { + JS_OBJECT(CSSStyleRule, CSSRule); AK_MAKE_NONCOPYABLE(CSSStyleRule); AK_MAKE_NONMOVABLE(CSSStyleRule); public: - using WrapperType = Bindings::CSSStyleRuleWrapper; - - static NonnullRefPtr create(NonnullRefPtrVector&& selectors, NonnullRefPtr&& declaration) - { - return adopt_ref(*new CSSStyleRule(move(selectors), move(declaration))); - } + static CSSStyleRule* create(Bindings::WindowObject&, NonnullRefPtrVector&&, NonnullRefPtr&&); + CSSStyleRule(Bindings::WindowObject&, NonnullRefPtrVector&&, NonnullRefPtr&&); virtual ~CSSStyleRule() override = default; + CSSStyleRule& impl() { return *this; } + NonnullRefPtrVector const& selectors() const { return m_selectors; } CSSStyleDeclaration const& declaration() const { return m_declaration; } - virtual StringView class_name() const override { return "CSSStyleRule"sv; }; virtual Type type() const override { return Type::Style; }; String selector_text() const; @@ -41,8 +39,6 @@ public: CSSStyleDeclaration* style(); private: - CSSStyleRule(NonnullRefPtrVector&&, NonnullRefPtr&&); - virtual String serialized() const override; NonnullRefPtrVector m_selectors; @@ -53,3 +49,8 @@ template<> inline bool CSSRule::fast_is() const { return type() == CSSRule::Type::Style; } } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSStyleRule& object) { return &object; } +using CSSStyleRuleWrapper = Web::CSS::CSSStyleRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.idl b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.idl index 5e4708a6e69..2d6a8dc2146 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleRule.idl @@ -1,6 +1,7 @@ #import #import +[Exposed=Window, NoInstanceWrapper] interface CSSStyleRule : CSSRule { attribute CSSOMString selectorText; diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp index dd0e33c7317..1828e30f628 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp @@ -13,14 +13,14 @@ namespace Web::CSS { -CSSStyleSheet* CSSStyleSheet::create(Bindings::WindowObject& window_object, NonnullRefPtrVector rules, Optional location) +CSSStyleSheet* CSSStyleSheet::create(Bindings::WindowObject& window_object, CSSRuleList& rules, Optional location) { - return window_object.heap().allocate(window_object.realm(), window_object, move(rules), move(location)); + return window_object.heap().allocate(window_object.realm(), window_object, rules, move(location)); } -CSSStyleSheet::CSSStyleSheet(Bindings::WindowObject& window_object, NonnullRefPtrVector rules, Optional location) +CSSStyleSheet::CSSStyleSheet(Bindings::WindowObject& window_object, CSSRuleList& rules, Optional location) : StyleSheet(window_object) - , m_rules(CSSRuleList::create(window_object, move(rules))) + , m_rules(&rules) { set_prototype(&window_object.ensure_web_prototype("CSSStyleSheet")); @@ -35,6 +35,8 @@ void CSSStyleSheet::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_style_sheet_list.ptr()); + visitor.visit(m_rules); + visitor.visit(m_owner_css_rule); } // https://www.w3.org/TR/cssom/#dom-cssstylesheet-insertrule @@ -54,12 +56,11 @@ DOM::ExceptionOr CSSStyleSheet::insert_rule(StringView rule, unsigned // FIXME: 5. If parsed rule is an @import rule, and the constructed flag is set, throw a SyntaxError DOMException. // 6. Return the result of invoking insert a CSS rule rule in the CSS rules at index. - auto parsed_rule_nonnull = parsed_rule.release_nonnull(); - auto result = m_rules->insert_a_css_rule(parsed_rule_nonnull, index); + auto result = m_rules->insert_a_css_rule(parsed_rule, index); if (!result.is_exception()) { // NOTE: The spec doesn't say where to set the parent style sheet, so we'll do it here. - parsed_rule_nonnull->set_parent_style_sheet(this); + parsed_rule->set_parent_style_sheet(this); if (m_style_sheet_list) { m_style_sheet_list->document().style_computer().invalidate_rule_cache(); diff --git a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h index 3dd08e1733b..7712a13f3fa 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h +++ b/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h @@ -24,9 +24,9 @@ class CSSStyleSheet final JS_OBJECT(CSSStyleSheet, StyleSheet); public: - static CSSStyleSheet* create(Bindings::WindowObject&, NonnullRefPtrVector rules, Optional location); + static CSSStyleSheet* create(Bindings::WindowObject&, CSSRuleList& rules, Optional location); - explicit CSSStyleSheet(Bindings::WindowObject&, NonnullRefPtrVector, Optional location); + explicit CSSStyleSheet(Bindings::WindowObject&, CSSRuleList&, Optional location); virtual ~CSSStyleSheet() override = default; CSSStyleSheet& impl() { return *this; } @@ -57,9 +57,8 @@ private: CSSRuleList* m_rules { nullptr }; - WeakPtr m_owner_css_rule; - JS::GCPtr m_style_sheet_list; + CSSRule* m_owner_css_rule { nullptr }; }; } diff --git a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp index b00611f32ef..602ca34768a 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp @@ -4,15 +4,23 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include #include namespace Web::CSS { -CSSSupportsRule::CSSSupportsRule(NonnullRefPtr&& supports, NonnullRefPtrVector&& rules) - : CSSConditionRule(move(rules)) +CSSSupportsRule* CSSSupportsRule::create(Bindings::WindowObject& window_object, NonnullRefPtr&& supports, CSSRuleList& rules) +{ + return window_object.heap().allocate(window_object.realm(), window_object, move(supports), rules); +} + +CSSSupportsRule::CSSSupportsRule(Bindings::WindowObject& window_object, NonnullRefPtr&& supports, CSSRuleList& rules) + : CSSConditionRule(window_object, rules) , m_supports(move(supports)) { + set_prototype(&window_object.ensure_web_prototype("CSSSupportsRule")); } String CSSSupportsRule::condition_text() const diff --git a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h index 6bc3b1ea4c9..31e0dcac7b9 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h @@ -17,20 +17,18 @@ namespace Web::CSS { // https://www.w3.org/TR/css-conditional-3/#the-csssupportsrule-interface class CSSSupportsRule final : public CSSConditionRule { + JS_OBJECT(CSSSupportsRule, CSSConditionRule); AK_MAKE_NONCOPYABLE(CSSSupportsRule); AK_MAKE_NONMOVABLE(CSSSupportsRule); public: - using WrapperType = Bindings::CSSSupportsRuleWrapper; - - static NonnullRefPtr create(NonnullRefPtr&& supports, NonnullRefPtrVector&& rules) - { - return adopt_ref(*new CSSSupportsRule(move(supports), move(rules))); - } + static CSSSupportsRule* create(Bindings::WindowObject&, NonnullRefPtr&&, CSSRuleList&); + explicit CSSSupportsRule(Bindings::WindowObject&, NonnullRefPtr&&, CSSRuleList&); virtual ~CSSSupportsRule() = default; - virtual StringView class_name() const override { return "CSSSupportsRule"sv; }; + CSSSupportsRule& impl() { return *this; } + virtual Type type() const override { return Type::Supports; }; String condition_text() const override; @@ -38,8 +36,6 @@ public: virtual bool condition_matches() const override { return m_supports->matches(); } private: - explicit CSSSupportsRule(NonnullRefPtr&&, NonnullRefPtrVector&&); - virtual String serialized() const override; NonnullRefPtr m_supports; @@ -49,3 +45,8 @@ template<> inline bool CSSRule::fast_is() const { return type() == CSSRule::Type::Supports; } } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSSupportsRule& object) { return &object; } +using CSSSupportsRuleWrapper = Web::CSS::CSSSupportsRule; +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.idl b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.idl index f60b2a2ebf9..f4e9fbb89d7 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.idl @@ -1,5 +1,5 @@ #import -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface CSSSupportsRule : CSSConditionRule { }; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 359f58635e0..e32ae4efdb3 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -44,6 +44,11 @@ ParsingContext::ParsingContext() { } +ParsingContext::ParsingContext(Bindings::WindowObject& window_object) + : m_window_object(window_object) +{ +} + ParsingContext::ParsingContext(DOM::Document const& document, AK::URL url) : m_window_object(document.preferred_window_object()) , m_document(&document) @@ -194,15 +199,16 @@ CSSStyleSheet* Parser::parse_as_css_stylesheet(Optional location) auto style_sheet = parse_a_stylesheet(m_token_stream, {}); // Interpret all of the resulting top-level qualified rules as style rules, defined below. - NonnullRefPtrVector rules; + JS::MarkedVector rules(m_context.window_object().heap()); for (auto& raw_rule : style_sheet.rules) { - auto rule = convert_to_rule(raw_rule); + auto* rule = convert_to_rule(raw_rule); // If any style rule is invalid, or any at-rule is not recognized or is invalid according to its grammar or context, it’s a parse error. Discard that rule. if (rule) - rules.append(*rule); + rules.append(rule); } - return CSSStyleSheet::create(m_context.window_object(), move(rules), move(location)); + auto* rule_list = CSSRuleList::create(m_context.window_object(), move(rules)); + return CSSStyleSheet::create(m_context.window_object(), *rule_list, move(location)); } Optional Parser::parse_as_selector(SelectorParsingMode parsing_mode) @@ -2096,7 +2102,7 @@ Vector Parser::consume_a_list_of_declarations(TokenStream Parser::parse_as_css_rule() +CSSRule* Parser::parse_as_css_rule() { auto maybe_rule = parse_a_rule(m_token_stream); if (maybe_rule) @@ -2593,7 +2599,7 @@ RefPtr Parser::parse_linear_gradient_function(ComponentValue const& return LinearGradientStyleValue::create(gradient_direction, move(color_stops), gradient_type, repeating_gradient); } -RefPtr Parser::convert_to_rule(NonnullRefPtr rule) +CSSRule* Parser::convert_to_rule(NonnullRefPtr rule) { if (rule->is_at_rule()) { if (has_ignored_vendor_prefix(rule->at_rule_name())) { @@ -2625,8 +2631,7 @@ RefPtr Parser::convert_to_rule(NonnullRefPtr rule) if (url.has_value()) return CSSImportRule::create(url.value(), const_cast(*m_context.document())); - else - dbgln_if(CSS_PARSER_DEBUG, "Unable to parse url from @import rule"); + dbgln_if(CSS_PARSER_DEBUG, "Unable to parse url from @import rule"); } else if (rule->at_rule_name().equals_ignoring_case("media"sv)) { @@ -2637,13 +2642,13 @@ RefPtr Parser::convert_to_rule(NonnullRefPtr rule) auto child_tokens = TokenStream { rule->block()->values() }; auto parser_rules = parse_a_list_of_rules(child_tokens); - NonnullRefPtrVector child_rules; + JS::MarkedVector child_rules(m_context.window_object().heap()); for (auto& raw_rule : parser_rules) { if (auto child_rule = convert_to_rule(raw_rule)) - child_rules.append(*child_rule); + child_rules.append(child_rule); } - - return CSSMediaRule::create(MediaList::create(move(media_query_list)), move(child_rules)); + auto* rule_list = CSSRuleList::create(m_context.window_object(), move(child_rules)); + return CSSMediaRule::create(m_context.window_object(), MediaList::create(move(media_query_list)), *rule_list); } else if (rule->at_rule_name().equals_ignoring_case("supports"sv)) { @@ -2661,13 +2666,14 @@ RefPtr Parser::convert_to_rule(NonnullRefPtr rule) return {}; auto child_tokens = TokenStream { rule->block()->values() }; auto parser_rules = parse_a_list_of_rules(child_tokens); - NonnullRefPtrVector child_rules; + JS::MarkedVector child_rules(m_context.window_object().heap()); for (auto& raw_rule : parser_rules) { if (auto child_rule = convert_to_rule(raw_rule)) - child_rules.append(*child_rule); + child_rules.append(child_rule); } - return CSSSupportsRule::create(supports.release_nonnull(), move(child_rules)); + auto* rule_list = CSSRuleList::create(m_context.window_object(), move(child_rules)); + return CSSSupportsRule::create(m_context.window_object(), supports.release_nonnull(), *rule_list); } else { dbgln_if(CSS_PARSER_DEBUG, "Unrecognized CSS at-rule: @{}", rule->at_rule_name()); @@ -2706,7 +2712,7 @@ RefPtr Parser::convert_to_rule(NonnullRefPtr rule) return {}; } - return CSSStyleRule::create(move(selectors.value()), move(*declaration)); + return CSSStyleRule::create(m_context.window_object(), move(selectors.value()), move(*declaration)); } return {}; @@ -4690,7 +4696,7 @@ RefPtr Parser::parse_font_family_value(Vector const& return StyleValueList::create(move(font_families), StyleValueList::Separator::Comma); } -RefPtr Parser::parse_font_face_rule(TokenStream& tokens) +CSSRule* Parser::parse_font_face_rule(TokenStream& tokens) { auto declarations_and_at_rules = parse_a_list_of_declarations(tokens); @@ -4791,7 +4797,7 @@ RefPtr Parser::parse_font_face_rule(TokenStream& tokens unicode_range.empend(0x0u, 0x10FFFFu); } - return CSSFontFaceRule::create(FontFace { font_family.release_value(), move(src), move(unicode_range) }); + return CSSFontFaceRule::create(m_context.window_object(), FontFace { font_family.release_value(), move(src), move(unicode_range) }); } Vector Parser::parse_font_face_src(TokenStream& component_values) @@ -6385,7 +6391,7 @@ namespace Web { CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingContext const& context, StringView css, Optional location) { if (css.is_empty()) - return CSS::CSSStyleSheet::create(context.window_object(), {}, location); + return CSS::CSSStyleSheet::create(context.window_object(), *CSS::CSSRuleList::create_empty(context.window_object()), location); CSS::Parser::Parser parser(context, css); return parser.parse_as_css_stylesheet(location); } @@ -6406,7 +6412,7 @@ RefPtr parse_css_value(CSS::Parser::ParsingContext const& conte return parser.parse_as_css_value(property_id); } -RefPtr parse_css_rule(CSS::Parser::ParsingContext const& context, StringView css_text) +CSS::CSSRule* parse_css_rule(CSS::Parser::ParsingContext const& context, StringView css_text) { CSS::Parser::Parser parser(context, css_text); return parser.parse_as_css_rule(); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 262814c49bf..5779008004f 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -35,6 +35,7 @@ namespace Web::CSS::Parser { class ParsingContext { public: ParsingContext(); + explicit ParsingContext(Bindings::WindowObject&); explicit ParsingContext(DOM::Document const&); explicit ParsingContext(DOM::Document const&, AK::URL); explicit ParsingContext(DOM::ParentNode&); @@ -127,7 +128,7 @@ public: CSSStyleSheet* parse_as_css_stylesheet(Optional location); RefPtr parse_as_style_attribute(DOM::Element&); - RefPtr parse_as_css_rule(); + CSSRule* parse_as_css_rule(); Optional parse_as_supports_condition(); enum class SelectorParsingMode { @@ -235,10 +236,10 @@ private: Optional parse_general_enclosed(TokenStream&); - RefPtr parse_font_face_rule(TokenStream&); + CSSRule* parse_font_face_rule(TokenStream&); Vector parse_font_face_src(TokenStream&); - RefPtr convert_to_rule(NonnullRefPtr); + CSSRule* convert_to_rule(NonnullRefPtr); RefPtr convert_to_style_declaration(Vector declarations); Optional convert_to_style_property(Declaration const&); @@ -423,7 +424,7 @@ CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingContext const&, Str RefPtr parse_css_style_attribute(CSS::Parser::ParsingContext const&, StringView, DOM::Element&); RefPtr parse_css_value(CSS::Parser::ParsingContext const&, StringView, CSS::PropertyID property_id = CSS::PropertyID::Invalid); Optional parse_selector(CSS::Parser::ParsingContext const&, StringView); -RefPtr parse_css_rule(CSS::Parser::ParsingContext const&, StringView); +CSS::CSSRule* parse_css_rule(CSS::Parser::ParsingContext const&, StringView); RefPtr parse_media_query(CSS::Parser::ParsingContext const&, StringView); NonnullRefPtrVector parse_media_query_list(CSS::Parser::ParsingContext const&, StringView); RefPtr parse_css_supports(CSS::Parser::ParsingContext const&, StringView); diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index ec1c3950039..fb484acf06f 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -184,7 +184,7 @@ Vector StyleComputer::collect_matching_rules(DOM::Element const& e size_t selector_index = 0; for (auto& selector : rule.selectors()) { if (SelectorEngine::matches(selector, element, pseudo_element)) { - matching_rules.append({ rule, style_sheet_index, rule_index, selector_index, selector.specificity() }); + matching_rules.append({ &rule, style_sheet_index, rule_index, selector_index, selector.specificity() }); break; } ++selector_index; @@ -1264,7 +1264,7 @@ void StyleComputer::build_rule_cache() sheet.for_each_effective_style_rule([&](auto const& rule) { size_t selector_index = 0; for (CSS::Selector const& selector : rule.selectors()) { - MatchingRule matching_rule { rule, style_sheet_index, rule_index, selector_index, selector.specificity() }; + MatchingRule matching_rule { &rule, style_sheet_index, rule_index, selector_index, selector.specificity() }; bool added_to_bucket = false; for (auto const& simple_selector : selector.compound_selectors().last().simple_selectors) { diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h index b9cd4993e40..9f2b05feddb 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h @@ -21,7 +21,7 @@ namespace Web::CSS { struct MatchingRule { - RefPtr rule; + CSSStyleRule const* rule { nullptr }; size_t style_sheet_index { 0 }; size_t rule_index { 0 }; size_t selector_index { 0 }; diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 8e437f2736c..f847f723484 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -459,15 +459,7 @@ class CharacterDataWrapper; class CloseEventWrapper; class CommentWrapper; class CryptoWrapper; -class CSSConditionRuleWrapper; -class CSSFontFaceRuleWrapper; -class CSSGroupingRuleWrapper; -class CSSImportRuleWrapper; -class CSSMediaRuleWrapper; -class CSSRuleWrapper; class CSSStyleDeclarationWrapper; -class CSSStyleRuleWrapper; -class CSSSupportsRuleWrapper; class CustomEventWrapper; class DocumentFragmentWrapper; class DocumentTypeWrapper; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index bb4d5c44448..ac32cd609bb 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -3,17 +3,17 @@ libweb_js_wrapper(Crypto/Crypto) libweb_js_wrapper(Crypto/SubtleCrypto) -libweb_js_wrapper(CSS/CSSConditionRule) -libweb_js_wrapper(CSS/CSSFontFaceRule) -libweb_js_wrapper(CSS/CSSGroupingRule) -libweb_js_wrapper(CSS/CSSImportRule) -libweb_js_wrapper(CSS/CSSMediaRule) -libweb_js_wrapper(CSS/CSSRule) +libweb_js_wrapper(CSS/CSSConditionRule NO_INSTANCE) +libweb_js_wrapper(CSS/CSSFontFaceRule NO_INSTANCE) +libweb_js_wrapper(CSS/CSSGroupingRule NO_INSTANCE) +libweb_js_wrapper(CSS/CSSImportRule NO_INSTANCE) +libweb_js_wrapper(CSS/CSSMediaRule NO_INSTANCE) +libweb_js_wrapper(CSS/CSSRule NO_INSTANCE) libweb_js_wrapper(CSS/CSSRuleList NO_INSTANCE) libweb_js_wrapper(CSS/CSSStyleDeclaration) -libweb_js_wrapper(CSS/CSSStyleRule) +libweb_js_wrapper(CSS/CSSStyleRule NO_INSTANCE) libweb_js_wrapper(CSS/CSSStyleSheet NO_INSTANCE) -libweb_js_wrapper(CSS/CSSSupportsRule) +libweb_js_wrapper(CSS/CSSSupportsRule NO_INSTANCE) libweb_js_wrapper(CSS/MediaList) libweb_js_wrapper(CSS/MediaQueryList) libweb_js_wrapper(CSS/MediaQueryListEvent)