1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 10:17:35 +00:00

LibWeb: Make StyleSheet and CSSStyleSheet GC-allocated

This commit is contained in:
Andreas Kling 2022-08-07 13:14:54 +02:00
parent 0fe923e355
commit 5d60212076
21 changed files with 166 additions and 96 deletions

View file

@ -73,13 +73,13 @@ void CSSImportRule::resource_did_load()
dbgln_if(CSS_LOADER_DEBUG, "CSSImportRule: Resource did load, has encoded data. URL: {}", resource()->url());
}
auto sheet = parse_css_stylesheet(CSS::Parser::ParsingContext(*m_document, resource()->url()), resource()->encoded_data());
auto* sheet = parse_css_stylesheet(CSS::Parser::ParsingContext(*m_document, resource()->url()), resource()->encoded_data());
if (!sheet) {
dbgln_if(CSS_LOADER_DEBUG, "CSSImportRule: Failed to parse stylesheet: {}", resource()->url());
return;
}
m_style_sheet = move(sheet);
m_style_sheet = JS::make_handle(sheet);
m_document->style_computer().invalidate_rule_cache();
m_document->invalidate_style();

View file

@ -8,6 +8,7 @@
#pragma once
#include <AK/URL.h>
#include <LibJS/Heap/Handle.h>
#include <LibWeb/CSS/CSSRule.h>
#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/DOM/DocumentLoadEventDelayer.h>
@ -35,10 +36,10 @@ public:
String href() const { return m_url.to_string(); }
bool has_import_result() const { return !m_style_sheet.is_null(); }
RefPtr<CSSStyleSheet> loaded_style_sheet() { return m_style_sheet; }
RefPtr<CSSStyleSheet> const loaded_style_sheet() const { return m_style_sheet; }
NonnullRefPtr<CSSStyleSheet> style_sheet_for_bindings() { return *m_style_sheet; }
void set_style_sheet(RefPtr<CSSStyleSheet> const& style_sheet) { m_style_sheet = style_sheet; }
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); }
virtual StringView class_name() const override { return "CSSImportRule"sv; };
virtual Type type() const override { return Type::Import; };
@ -55,7 +56,7 @@ private:
AK::URL m_url;
WeakPtr<DOM::Document> m_document;
Optional<DOM::DocumentLoadEventDelayer> m_document_load_event_delayer;
RefPtr<CSSStyleSheet> m_style_sheet;
JS::Handle<CSSStyleSheet> m_style_sheet;
};
template<>

View file

@ -1,9 +1,10 @@
/*
* Copyright (c) 2019-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2019-2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSStyleSheetPrototype.h>
#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/StyleSheetList.h>
@ -12,9 +13,17 @@
namespace Web::CSS {
CSSStyleSheet::CSSStyleSheet(NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location)
: m_rules(CSSRuleList::create(move(rules)))
CSSStyleSheet* CSSStyleSheet::create(Bindings::WindowObject& window_object, NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location)
{
return window_object.heap().allocate<CSSStyleSheet>(window_object.realm(), window_object, move(rules), move(location));
}
CSSStyleSheet::CSSStyleSheet(Bindings::WindowObject& window_object, NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location)
: StyleSheet(window_object)
, m_rules(CSSRuleList::create(move(rules)))
{
set_prototype(&window_object.ensure_web_prototype<Bindings::CSSStyleSheetPrototype>("CSSStyleSheet"));
if (location.has_value())
set_location(location->to_string());

View file

@ -21,16 +21,16 @@ class CSSImportRule;
class CSSStyleSheet final
: public StyleSheet
, public Weakable<CSSStyleSheet> {
JS_OBJECT(CSSStyleSheet, StyleSheet);
public:
using WrapperType = Bindings::CSSStyleSheetWrapper;
static NonnullRefPtr<CSSStyleSheet> create(NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location)
{
return adopt_ref(*new CSSStyleSheet(move(rules), move(location)));
}
static CSSStyleSheet* create(Bindings::WindowObject&, NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location);
explicit CSSStyleSheet(Bindings::WindowObject&, NonnullRefPtrVector<CSSRule>, Optional<AK::URL> location);
virtual ~CSSStyleSheet() override = default;
CSSStyleSheet& impl() { return *this; }
void set_owner_css_rule(CSSRule* rule) { m_owner_css_rule = rule; }
virtual String type() const override { return "text/css"; }
@ -53,8 +53,6 @@ public:
void set_style_sheet_list(Badge<StyleSheetList>, StyleSheetList*);
private:
explicit CSSStyleSheet(NonnullRefPtrVector<CSSRule>, Optional<AK::URL> location);
NonnullRefPtr<CSSRuleList> m_rules;
WeakPtr<CSSRule> m_owner_css_rule;
@ -65,7 +63,6 @@ private:
}
namespace Web::Bindings {
CSSStyleSheetWrapper* wrap(JS::Realm&, CSS::CSSStyleSheet&);
inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSStyleSheet& object) { return &object; }
using CSSStyleSheetWrapper = Web::CSS::CSSStyleSheet;
}

View file

@ -13,6 +13,7 @@
#include <AK/GenericLexer.h>
#include <AK/NonnullRefPtrVector.h>
#include <AK/SourceLocation.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/CSS/CSSFontFaceRule.h>
#include <LibWeb/CSS/CSSImportRule.h>
#include <LibWeb/CSS/CSSMediaRule.h>
@ -38,20 +39,28 @@ static void log_parse_error(SourceLocation const& location = SourceLocation::cur
namespace Web::CSS::Parser {
ParsingContext::ParsingContext()
: m_window_object(Bindings::main_thread_internal_window_object())
{
}
ParsingContext::ParsingContext(DOM::Document const& document, AK::URL url)
: m_document(&document)
: m_window_object(document.preferred_window_object())
, m_document(&document)
, m_url(move(url))
{
}
ParsingContext::ParsingContext(DOM::Document const& document)
: m_document(&document)
: m_window_object(document.preferred_window_object())
, m_document(&document)
, m_url(document.url())
{
}
ParsingContext::ParsingContext(DOM::ParentNode& parent_node)
: m_document(&parent_node.document())
: m_window_object(parent_node.document().preferred_window_object())
, m_document(&parent_node.document())
, m_url(parent_node.document().url())
{
}
@ -179,7 +188,7 @@ Parser::ParsedStyleSheet Parser::parse_a_stylesheet(TokenStream<T>& tokens, Opti
}
// https://www.w3.org/TR/css-syntax-3/#parse-a-css-stylesheet
NonnullRefPtr<CSSStyleSheet> Parser::parse_as_css_stylesheet(Optional<AK::URL> location)
CSSStyleSheet* Parser::parse_as_css_stylesheet(Optional<AK::URL> location)
{
// To parse a CSS stylesheet, first parse a stylesheet.
auto style_sheet = parse_a_stylesheet(m_token_stream, {});
@ -193,7 +202,7 @@ NonnullRefPtr<CSSStyleSheet> Parser::parse_as_css_stylesheet(Optional<AK::URL> l
rules.append(*rule);
}
return CSSStyleSheet::create(move(rules), move(location));
return CSSStyleSheet::create(m_context.window_object(), move(rules), move(location));
}
Optional<SelectorList> Parser::parse_as_selector(SelectorParsingMode parsing_mode)
@ -6373,10 +6382,10 @@ TimePercentage Parser::Dimension::time_percentage() const
namespace Web {
RefPtr<CSS::CSSStyleSheet> parse_css_stylesheet(CSS::Parser::ParsingContext const& context, StringView css, Optional<AK::URL> location)
CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingContext const& context, StringView css, Optional<AK::URL> location)
{
if (css.is_empty())
return CSS::CSSStyleSheet::create({}, location);
return CSS::CSSStyleSheet::create(context.window_object(), {}, location);
CSS::Parser::Parser parser(context, css);
return parser.parse_as_css_stylesheet(location);
}

View file

@ -34,7 +34,7 @@ namespace Web::CSS::Parser {
class ParsingContext {
public:
ParsingContext() = default;
ParsingContext();
explicit ParsingContext(DOM::Document const&);
explicit ParsingContext(DOM::Document const&, AK::URL);
explicit ParsingContext(DOM::ParentNode&);
@ -46,7 +46,10 @@ public:
PropertyID current_property_id() const { return m_current_property_id; }
void set_current_property_id(PropertyID property_id) { m_current_property_id = property_id; }
Bindings::WindowObject& window_object() const { return m_window_object; }
private:
Bindings::WindowObject& m_window_object;
DOM::Document const* m_document { nullptr };
PropertyID m_current_property_id { PropertyID::Invalid };
AK::URL m_url;
@ -122,7 +125,7 @@ public:
Parser(ParsingContext const&, StringView input, String const& encoding = "utf-8");
~Parser() = default;
NonnullRefPtr<CSSStyleSheet> parse_as_css_stylesheet(Optional<AK::URL> location);
CSSStyleSheet* parse_as_css_stylesheet(Optional<AK::URL> location);
RefPtr<ElementInlineCSSStyleDeclaration> parse_as_style_attribute(DOM::Element&);
RefPtr<CSSRule> parse_as_css_rule();
Optional<StyleProperty> parse_as_supports_condition();
@ -416,7 +419,7 @@ private:
namespace Web {
RefPtr<CSS::CSSStyleSheet> parse_css_stylesheet(CSS::Parser::ParsingContext const&, StringView, Optional<AK::URL> location = {});
CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingContext const&, StringView, Optional<AK::URL> location = {});
RefPtr<CSS::ElementInlineCSSStyleDeclaration> parse_css_style_attribute(CSS::Parser::ParsingContext const&, StringView, DOM::Element&);
RefPtr<CSS::StyleValue> parse_css_value(CSS::Parser::ParsingContext const&, StringView, CSS::PropertyID property_id = CSS::PropertyID::Invalid);
Optional<CSS::SelectorList> parse_selector(CSS::Parser::ParsingContext const&, StringView);

View file

@ -108,24 +108,24 @@ private:
HashMap<float, NonnullRefPtr<Gfx::ScaledFont>> mutable m_cached_fonts;
};
static StyleSheet& default_stylesheet()
static CSSStyleSheet& default_stylesheet()
{
static StyleSheet* sheet;
if (!sheet) {
static JS::Handle<CSSStyleSheet> sheet;
if (!sheet.cell()) {
extern char const default_stylesheet_source[];
String css = default_stylesheet_source;
sheet = parse_css_stylesheet(CSS::Parser::ParsingContext(), css).leak_ref();
sheet = JS::make_handle(parse_css_stylesheet(CSS::Parser::ParsingContext(), css));
}
return *sheet;
}
static StyleSheet& quirks_mode_stylesheet()
static CSSStyleSheet& quirks_mode_stylesheet()
{
static StyleSheet* sheet;
if (!sheet) {
static JS::Handle<CSSStyleSheet> sheet;
if (!sheet.cell()) {
extern char const quirks_mode_stylesheet_source[];
String css = quirks_mode_stylesheet_source;
sheet = parse_css_stylesheet(CSS::Parser::ParsingContext(), css).leak_ref();
sheet = JS::make_handle(parse_css_stylesheet(CSS::Parser::ParsingContext(), css));
}
return *sheet;
}
@ -140,7 +140,7 @@ void StyleComputer::for_each_stylesheet(CascadeOrigin cascade_origin, Callback c
}
if (cascade_origin == CascadeOrigin::Author) {
for (auto const& sheet : document().style_sheets().sheets()) {
callback(sheet);
callback(*sheet);
}
}
}
@ -180,7 +180,7 @@ Vector<MatchingRule> StyleComputer::collect_matching_rules(DOM::Element const& e
size_t style_sheet_index = 0;
for_each_stylesheet(cascade_origin, [&](auto& sheet) {
size_t rule_index = 0;
static_cast<CSSStyleSheet const&>(sheet).for_each_effective_style_rule([&](auto const& rule) {
sheet.for_each_effective_style_rule([&](auto const& rule) {
size_t selector_index = 0;
for (auto& selector : rule.selectors()) {
if (SelectorEngine::matches(selector, element, pseudo_element)) {
@ -1261,7 +1261,7 @@ void StyleComputer::build_rule_cache()
size_t style_sheet_index = 0;
for_each_stylesheet(CascadeOrigin::Author, [&](auto& sheet) {
size_t rule_index = 0;
static_cast<CSSStyleSheet const&>(sheet).for_each_effective_style_rule([&](auto const& rule) {
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() };

View file

@ -5,12 +5,25 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/StyleSheetPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/StyleSheet.h>
#include <LibWeb/DOM/Element.h>
namespace Web::CSS {
StyleSheet::StyleSheet(Bindings::WindowObject& window_object)
: PlatformObject(window_object.ensure_web_prototype<Bindings::StyleSheetPrototype>("StyleSheet"))
{
}
void StyleSheet::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_parent_style_sheet);
}
void StyleSheet::set_owner_node(DOM::Element* element)
{
if (element)

View file

@ -7,17 +7,16 @@
#pragma once
#include <AK/RefCounted.h>
#include <LibWeb/Bindings/Wrappable.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/Forward.h>
namespace Web::CSS {
class StyleSheet
: public RefCounted<StyleSheet>
, public Bindings::Wrappable {
class StyleSheet : public Bindings::PlatformObject {
JS_OBJECT(StyleSheet, Bindings::PlatformObject);
public:
using WrapperType = Bindings::StyleSheetWrapper;
StyleSheet& impl() { return *this; }
virtual ~StyleSheet() = default;
@ -49,12 +48,14 @@ public:
void set_parent_css_style_sheet(CSSStyleSheet*);
protected:
StyleSheet() = default;
explicit StyleSheet(Bindings::WindowObject&);
private:
virtual void visit_edges(Cell::Visitor&) override;
WeakPtr<DOM::Element> m_owner_node;
WeakPtr<CSSStyleSheet> m_parent_style_sheet;
CSSStyleSheet* m_parent_style_sheet { nullptr };
String m_location;
String m_title;
@ -67,3 +68,8 @@ private:
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::CSS::StyleSheet& object) { return &object; }
using StyleSheetWrapper = Web::CSS::StyleSheet;
}

View file

@ -9,14 +9,13 @@
namespace Web::CSS {
void StyleSheetList::add_sheet(NonnullRefPtr<CSSStyleSheet> sheet)
void StyleSheetList::add_sheet(CSSStyleSheet& sheet)
{
VERIFY(!m_sheets.contains_slow(sheet));
sheet->set_style_sheet_list({}, this);
m_sheets.append(sheet);
sheet.set_style_sheet_list({}, this);
m_sheets.append(JS::make_handle(sheet));
m_document.style_computer().invalidate_rule_cache();
m_document.style_computer().load_fonts_from_sheet(*sheet);
m_document.style_computer().load_fonts_from_sheet(sheet);
m_document.invalidate_style();
}

View file

@ -26,17 +26,17 @@ public:
return adopt_ref(*new StyleSheetList(document));
}
void add_sheet(NonnullRefPtr<CSSStyleSheet>);
void add_sheet(CSSStyleSheet&);
void remove_sheet(CSSStyleSheet&);
NonnullRefPtrVector<CSSStyleSheet> const& sheets() const { return m_sheets; }
NonnullRefPtrVector<CSSStyleSheet>& sheets() { return m_sheets; }
Vector<JS::Handle<CSSStyleSheet>> const& sheets() const { return m_sheets; }
Vector<JS::Handle<CSSStyleSheet>>& sheets() { return m_sheets; }
RefPtr<CSSStyleSheet> item(size_t index) const
CSSStyleSheet* item(size_t index) const
{
if (index >= m_sheets.size())
return {};
return m_sheets[index];
return const_cast<CSSStyleSheet*>(m_sheets[index].cell());
}
size_t length() const { return m_sheets.size(); }
@ -50,7 +50,7 @@ private:
explicit StyleSheetList(DOM::Document&);
DOM::Document& m_document;
NonnullRefPtrVector<CSSStyleSheet> m_sheets;
Vector<JS::Handle<CSSStyleSheet>> m_sheets;
};
}