mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 01:27:34 +00:00
LibWeb: Make StyleSheet and CSSStyleSheet GC-allocated
This commit is contained in:
parent
0fe923e355
commit
5d60212076
21 changed files with 166 additions and 96 deletions
|
@ -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();
|
||||
|
|
|
@ -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<>
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() };
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue