LibWeb: Make CSSRule and all its subclasses GC-allocated

This commit is contained in:
Andreas Kling 2022-08-07 15:46:44 +02:00
parent 5d6cb9cbdb
commit 12042f0757
39 changed files with 338 additions and 236 deletions

View file

@ -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)

View file

@ -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(<LibWeb/Bindings/@wrapper_class@.h>)
#include <LibWeb/Bindings/@wrapper_class@.h>
#endif
#include <LibWeb/Bindings/CSSRuleWrapperFactory.h>
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
#include <LibWeb/Bindings/EventWrapperFactory.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>

View file

@ -1,41 +0,0 @@
/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/TypeCasts.h>
#include <LibWeb/Bindings/CSSFontFaceRuleWrapper.h>
#include <LibWeb/Bindings/CSSImportRuleWrapper.h>
#include <LibWeb/Bindings/CSSMediaRuleWrapper.h>
#include <LibWeb/Bindings/CSSRuleWrapper.h>
#include <LibWeb/Bindings/CSSRuleWrapperFactory.h>
#include <LibWeb/Bindings/CSSStyleRuleWrapper.h>
#include <LibWeb/Bindings/CSSSupportsRuleWrapper.h>
#include <LibWeb/CSS/CSSFontFaceRule.h>
#include <LibWeb/CSS/CSSImportRule.h>
#include <LibWeb/CSS/CSSMediaRule.h>
#include <LibWeb/CSS/CSSStyleRule.h>
#include <LibWeb/CSS/CSSSupportsRule.h>
namespace Web::Bindings {
CSSRuleWrapper* wrap(JS::Realm& realm, CSS::CSSRule& rule)
{
if (rule.wrapper())
return static_cast<CSSRuleWrapper*>(rule.wrapper());
if (is<CSS::CSSStyleRule>(rule))
return static_cast<CSSRuleWrapper*>(wrap_impl(realm, verify_cast<CSS::CSSStyleRule>(rule)));
if (is<CSS::CSSImportRule>(rule))
return static_cast<CSSRuleWrapper*>(wrap_impl(realm, verify_cast<CSS::CSSImportRule>(rule)));
if (is<CSS::CSSMediaRule>(rule))
return static_cast<CSSRuleWrapper*>(wrap_impl(realm, verify_cast<CSS::CSSMediaRule>(rule)));
if (is<CSS::CSSFontFaceRule>(rule))
return static_cast<CSSRuleWrapper*>(wrap_impl(realm, verify_cast<CSS::CSSFontFaceRule>(rule)));
if (is<CSS::CSSSupportsRule>(rule))
return static_cast<CSSRuleWrapper*>(wrap_impl(realm, verify_cast<CSS::CSSSupportsRule>(rule)));
return static_cast<CSSRuleWrapper*>(wrap_impl(realm, rule));
}
}

View file

@ -1,16 +0,0 @@
/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Forward.h>
#include <LibWeb/Forward.h>
namespace Web::Bindings {
CSSRuleWrapper* wrap(JS::Realm&, CSS::CSSRule&);
}

View file

@ -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

View file

@ -1,16 +1,20 @@
/*
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSConditionRulePrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSConditionRule.h>
namespace Web::CSS {
CSSConditionRule::CSSConditionRule(NonnullRefPtrVector<CSSRule>&& rules)
: CSSGroupingRule(move(rules))
CSSConditionRule::CSSConditionRule(Bindings::WindowObject& window_object, CSSRuleList& rules)
: CSSGroupingRule(window_object, rules)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::CSSConditionRulePrototype>("CSSConditionRule"));
}
void CSSConditionRule::for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const

View file

@ -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<void(CSSStyleRule const&)> const& callback) const override;
protected:
explicit CSSConditionRule(NonnullRefPtrVector<CSSRule>&&);
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;
}

View file

@ -1,6 +1,6 @@
#import <CSS/CSSGroupingRule.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface CSSConditionRule : CSSGroupingRule {
attribute CSSOMString conditionText;
};

View file

@ -1,16 +1,26 @@
/*
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSFontFaceRulePrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSFontFaceRule.h>
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<CSSFontFaceRule>(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<Bindings::CSSFontFaceRulePrototype>("CSSFontFaceRule"));
}
CSSStyleDeclaration* CSSFontFaceRule::style()

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* 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<CSSFontFaceRule> 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<CSSFontFaceRule>() 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;
}

View file

@ -1,7 +1,7 @@
#import <CSS/CSSRule.idl>
#import <CSS/CSSStyleDeclaration.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface CSSFontFaceRule : CSSRule {
readonly attribute CSSStyleDeclaration style;
};

View file

@ -1,45 +1,55 @@
/*
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSGroupingRulePrototype.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSGroupingRule.h>
#include <LibWeb/CSS/CSSRuleList.h>
namespace Web::CSS {
CSSGroupingRule::CSSGroupingRule(NonnullRefPtrVector<CSSRule>&& 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<Bindings::CSSGroupingRulePrototype>("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<u32> 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<void> 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<void(CSSStyleRule const&)> 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);
}

View file

@ -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<u32> insert_rule(StringView rule, u32 index = 0);
DOM::ExceptionOr<void> delete_rule(u32 index);
@ -34,10 +35,17 @@ public:
virtual void set_parent_style_sheet(CSSStyleSheet*) override;
protected:
explicit CSSGroupingRule(NonnullRefPtrVector<CSSRule>&&);
explicit CSSGroupingRule(Bindings::WindowObject&, CSSRuleList&);
private:
JS::Handle<CSSRuleList> 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;
}

View file

@ -1,7 +1,7 @@
#import <CSS/CSSRule.idl>
#import <CSS/CSSRuleList.idl>
[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);

View file

@ -1,12 +1,15 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Debug.h>
#include <AK/URL.h>
#include <LibWeb/Bindings/CSSImportRulePrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSImportRule.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/DOM/Document.h>
@ -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<CSSImportRule>(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<Bindings::CSSImportRulePrototype>("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();

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* 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<CSSImportRule> 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<DOM::Document> m_document;
Optional<DOM::DocumentLoadEventDelayer> m_document_load_event_delayer;
JS::Handle<CSSStyleSheet> m_style_sheet;
CSSStyleSheet* m_style_sheet { nullptr };
};
template<>
inline bool CSSRule::fast_is<CSSImportRule>() 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;
}

View file

@ -2,7 +2,7 @@
#import <CSS/CSSStyleSheet.idl>
#import <CSS/MediaList.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface CSSImportRule : CSSRule {
readonly attribute USVString href;
// [SameObject, PutForwards=mediaText] readonly attribute MediaList media;

View file

@ -1,17 +1,26 @@
/*
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSMediaRulePrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSMediaRule.h>
namespace Web::CSS {
CSSMediaRule::CSSMediaRule(NonnullRefPtr<MediaList>&& media, NonnullRefPtrVector<CSSRule>&& rules)
: CSSConditionRule(move(rules))
CSSMediaRule* CSSMediaRule::create(Bindings::WindowObject& window_object, NonnullRefPtr<MediaList>&& media_queries, CSSRuleList& rules)
{
return window_object.heap().allocate<CSSMediaRule>(window_object.realm(), window_object, move(media_queries), rules);
}
CSSMediaRule::CSSMediaRule(Bindings::WindowObject& window_object, NonnullRefPtr<MediaList>&& media, CSSRuleList& rules)
: CSSConditionRule(window_object, rules)
, m_media(move(media))
{
set_prototype(&window_object.ensure_web_prototype<Bindings::CSSMediaRulePrototype>("CSSMediaRule"));
}
String CSSMediaRule::condition_text() const

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* 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<CSSMediaRule> create(NonnullRefPtr<MediaList>&& media_queries, NonnullRefPtrVector<CSSRule>&& rules)
{
return adopt_ref(*new CSSMediaRule(move(media_queries), move(rules)));
}
static CSSMediaRule* create(Bindings::WindowObject&, NonnullRefPtr<MediaList>&& media_queries, CSSRuleList&);
explicit CSSMediaRule(Bindings::WindowObject&, NonnullRefPtr<MediaList>&&, 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<MediaList>&&, NonnullRefPtrVector<CSSRule>&&);
virtual String serialized() const override;
NonnullRefPtr<MediaList> m_media;
@ -50,3 +47,8 @@ template<>
inline bool CSSRule::fast_is<CSSMediaRule>() 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;
}

View file

@ -1,7 +1,7 @@
#import <CSS/CSSConditionRule.idl>
#import <CSS/MediaList.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface CSSMediaRule : CSSConditionRule {
[SameObject, PutForwards=mediaText] readonly attribute MediaList media;
};

View file

@ -1,15 +1,30 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSRulePrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSRule.h>
#include <LibWeb/CSS/CSSStyleSheet.h>
namespace Web::CSS {
CSSRule::CSSRule(Bindings::WindowObject& window_object)
: PlatformObject(window_object.ensure_web_prototype<Bindings::CSSRulePrototype>("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
{

View file

@ -1,27 +1,25 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/RefCounted.h>
#include <AK/String.h>
#include <AK/Weakable.h>
#include <LibWeb/Bindings/Wrappable.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/CSS/CSSStyleDeclaration.h>
#include <LibWeb/CSS/Selector.h>
namespace Web::CSS {
class CSSRule
: public RefCounted<CSSRule>
, public Bindings::Wrappable
, public Weakable<CSSRule> {
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<typename T>
bool fast_is() const = delete;
protected:
explicit CSSRule(Bindings::WindowObject&);
virtual String serialized() const = 0;
WeakPtr<CSSRule> m_parent_rule;
WeakPtr<CSSStyleSheet> m_parent_style_sheet;
virtual void visit_edges(Cell::Visitor&) override;
JS::GCPtr<CSSRule> m_parent_rule;
JS::GCPtr<CSSStyleSheet> m_parent_style_sheet;
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::CSS::CSSRule& object) { return &object; }
using CSSRuleWrapper = Web::CSS::CSSRule;
}

View file

@ -1,6 +1,6 @@
#import <CSS/CSSStyleSheet.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface CSSRule {
attribute CSSOMString cssText;

View file

@ -9,23 +9,38 @@
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSImportRule.h>
#include <LibWeb/CSS/CSSMediaRule.h>
#include <LibWeb/CSS/CSSRule.h>
#include <LibWeb/CSS/CSSRuleList.h>
#include <LibWeb/CSS/CSSSupportsRule.h>
#include <LibWeb/CSS/Parser/Parser.h>
namespace Web::CSS {
CSSRuleList* CSSRuleList::create(Bindings::WindowObject& window_object, NonnullRefPtrVector<Web::CSS::CSSRule>&& rules)
CSSRuleList* CSSRuleList::create(Bindings::WindowObject& window_object, JS::MarkedVector<CSSRule*> const& rules)
{
return window_object.heap().allocate<CSSRuleList>(window_object.realm(), window_object, move(rules));
auto* rule_list = window_object.heap().allocate<CSSRuleList>(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<CSSRule>&& rules)
CSSRuleList::CSSRuleList(Bindings::WindowObject& window_object)
: Bindings::LegacyPlatformObject(window_object.ensure_web_prototype<Bindings::CSSRuleListPrototype>("CSSRuleList"))
, m_rules(move(rules))
{
}
CSSRuleList* CSSRuleList::create_empty(Bindings::WindowObject& window_object)
{
return window_object.heap().allocate<CSSRuleList>(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 objects 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<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView, NonnullRefPtr<CSSRule>> rule, u32 index)
DOM::ExceptionOr<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView, CSSRule*> rule, u32 index)
{
// 1. Set length to the number of items in list.
auto length = m_rules.size();
@ -47,11 +62,13 @@ DOM::ExceptionOr<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView, No
// NOTE: The insert-a-css-rule spec expects `rule` to be a string, but the CSSStyleSheet.insertRule()
// spec calls this algorithm with an already-parsed CSSRule. So, we use a Variant and skip step 3
// if that variant holds a CSSRule already.
RefPtr<CSSRule> new_rule;
CSSRule* new_rule = nullptr;
if (rule.has<StringView>()) {
new_rule = parse_css_rule(CSS::Parser::ParsingContext {}, rule.get<StringView>());
new_rule = parse_css_rule(
CSS::Parser::ParsingContext { static_cast<Bindings::WindowObject&>(global_object()) },
rule.get<StringView>());
} else {
new_rule = rule.get<NonnullRefPtr<CSSRule>>();
new_rule = rule.get<CSSRule*>();
}
// 4. If new rule is a syntax error, throw a SyntaxError exception.
@ -63,7 +80,7 @@ DOM::ExceptionOr<unsigned> CSSRuleList::insert_a_css_rule(Variant<StringView, No
// FIXME: 6. If new rule is an @namespace at-rule, and list contains anything other than @import at-rules, and @namespace at-rules, throw an InvalidStateError exception.
// 7. Insert new rule into list at the zero-indexed position index.
m_rules.insert(index, new_rule.release_nonnull());
m_rules.insert(index, *new_rule);
// 8. Return index.
return index;
@ -80,7 +97,7 @@ DOM::ExceptionOr<void> 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<CSSRule> 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<void> CSSRuleList::remove_a_css_rule(u32 index)
m_rules.remove(index);
// 6. Set old rules 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<void(CSSStyleRule const
break;
case CSSRule::Type::Import: {
auto const& import_rule = static_cast<CSSImportRule const&>(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<CSSImportRule>(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;
}

View file

@ -25,20 +25,30 @@ class CSSRuleList : public Bindings::LegacyPlatformObject {
public:
CSSRuleList& impl() { return *this; }
static CSSRuleList* create(Bindings::WindowObject&, NonnullRefPtrVector<CSSRule>&& rules);
CSSRuleList(Bindings::WindowObject&, NonnullRefPtrVector<CSSRule>&&);
static CSSRuleList* create(Bindings::WindowObject&, JS::MarkedVector<CSSRule*> const&);
static CSSRuleList* create_empty(Bindings::WindowObject&);
explicit CSSRuleList(Bindings::WindowObject&);
~CSSRuleList() = default;
RefPtr<CSSRule> 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<AK::NonnullPtrVector<NonnullRefPtr<CSSRule>> const, CSSRule const>;
using Iterator = AK::SimpleIterator<AK::NonnullPtrVector<NonnullRefPtr<CSSRule>>, CSSRule>;
using ConstIterator = AK::SimpleIterator<Vector<CSSRule&> const, CSSRule const>;
using Iterator = AK::SimpleIterator<Vector<CSSRule&>, 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<void> remove_a_css_rule(u32 index);
DOM::ExceptionOr<unsigned> insert_a_css_rule(Variant<StringView, NonnullRefPtr<CSSRule>>, u32 index);
DOM::ExceptionOr<unsigned> insert_a_css_rule(Variant<StringView, CSSRule*>, u32 index);
void for_each_effective_style_rule(Function<void(CSSStyleRule const&)> const& callback) const;
// Returns whether the match state of any media queries changed after evaluation.
bool evaluate_media_queries(HTML::Window const&);
private:
NonnullRefPtrVector<CSSRule> m_rules;
virtual void visit_edges(Cell::Visitor&) override;
Vector<CSSRule&> 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;
}

View file

@ -4,15 +4,24 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSStyleRulePrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSStyleRule.h>
#include <LibWeb/CSS/Parser/Parser.h>
namespace Web::CSS {
CSSStyleRule::CSSStyleRule(NonnullRefPtrVector<Selector>&& selectors, NonnullRefPtr<CSSStyleDeclaration>&& declaration)
: m_selectors(move(selectors))
CSSStyleRule* CSSStyleRule::create(Bindings::WindowObject& window_object, NonnullRefPtrVector<Web::CSS::Selector>&& selectors, NonnullRefPtr<Web::CSS::CSSStyleDeclaration>&& declaration)
{
return window_object.heap().allocate<CSSStyleRule>(window_object.realm(), window_object, move(selectors), move(declaration));
}
CSSStyleRule::CSSStyleRule(Bindings::WindowObject& window_object, NonnullRefPtrVector<Selector>&& selectors, NonnullRefPtr<CSSStyleDeclaration>&& declaration)
: CSSRule(window_object)
, m_selectors(move(selectors))
, m_declaration(move(declaration))
{
set_prototype(&window_object.ensure_web_prototype<Bindings::CSSStyleRulePrototype>("CSSStyleRule"));
}
// https://www.w3.org/TR/cssom/#dom-cssstylerule-style

View file

@ -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<CSSStyleRule> create(NonnullRefPtrVector<Selector>&& selectors, NonnullRefPtr<CSSStyleDeclaration>&& declaration)
{
return adopt_ref(*new CSSStyleRule(move(selectors), move(declaration)));
}
static CSSStyleRule* create(Bindings::WindowObject&, NonnullRefPtrVector<Selector>&&, NonnullRefPtr<CSSStyleDeclaration>&&);
CSSStyleRule(Bindings::WindowObject&, NonnullRefPtrVector<Selector>&&, NonnullRefPtr<CSSStyleDeclaration>&&);
virtual ~CSSStyleRule() override = default;
CSSStyleRule& impl() { return *this; }
NonnullRefPtrVector<Selector> 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<Selector>&&, NonnullRefPtr<CSSStyleDeclaration>&&);
virtual String serialized() const override;
NonnullRefPtrVector<Selector> m_selectors;
@ -53,3 +49,8 @@ template<>
inline bool CSSRule::fast_is<CSSStyleRule>() 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;
}

View file

@ -1,6 +1,7 @@
#import <CSS/CSSRule.idl>
#import <CSS/CSSStyleDeclaration.idl>
[Exposed=Window, NoInstanceWrapper]
interface CSSStyleRule : CSSRule {
attribute CSSOMString selectorText;

View file

@ -13,14 +13,14 @@
namespace Web::CSS {
CSSStyleSheet* CSSStyleSheet::create(Bindings::WindowObject& window_object, NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location)
CSSStyleSheet* CSSStyleSheet::create(Bindings::WindowObject& window_object, CSSRuleList& rules, Optional<AK::URL> location)
{
return window_object.heap().allocate<CSSStyleSheet>(window_object.realm(), window_object, move(rules), move(location));
return window_object.heap().allocate<CSSStyleSheet>(window_object.realm(), window_object, rules, move(location));
}
CSSStyleSheet::CSSStyleSheet(Bindings::WindowObject& window_object, NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location)
CSSStyleSheet::CSSStyleSheet(Bindings::WindowObject& window_object, CSSRuleList& rules, Optional<AK::URL> location)
: StyleSheet(window_object)
, m_rules(CSSRuleList::create(window_object, move(rules)))
, m_rules(&rules)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::CSSStyleSheetPrototype>("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<unsigned> 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();

View file

@ -24,9 +24,9 @@ class CSSStyleSheet final
JS_OBJECT(CSSStyleSheet, StyleSheet);
public:
static CSSStyleSheet* create(Bindings::WindowObject&, NonnullRefPtrVector<CSSRule> rules, Optional<AK::URL> location);
static CSSStyleSheet* create(Bindings::WindowObject&, CSSRuleList& rules, Optional<AK::URL> location);
explicit CSSStyleSheet(Bindings::WindowObject&, NonnullRefPtrVector<CSSRule>, Optional<AK::URL> location);
explicit CSSStyleSheet(Bindings::WindowObject&, CSSRuleList&, Optional<AK::URL> location);
virtual ~CSSStyleSheet() override = default;
CSSStyleSheet& impl() { return *this; }
@ -57,9 +57,8 @@ private:
CSSRuleList* m_rules { nullptr };
WeakPtr<CSSRule> m_owner_css_rule;
JS::GCPtr<StyleSheetList> m_style_sheet_list;
CSSRule* m_owner_css_rule { nullptr };
};
}

View file

@ -4,15 +4,23 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CSSSupportsRulePrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/CSSSupportsRule.h>
#include <LibWeb/CSS/Parser/Parser.h>
namespace Web::CSS {
CSSSupportsRule::CSSSupportsRule(NonnullRefPtr<Supports>&& supports, NonnullRefPtrVector<CSSRule>&& rules)
: CSSConditionRule(move(rules))
CSSSupportsRule* CSSSupportsRule::create(Bindings::WindowObject& window_object, NonnullRefPtr<Supports>&& supports, CSSRuleList& rules)
{
return window_object.heap().allocate<CSSSupportsRule>(window_object.realm(), window_object, move(supports), rules);
}
CSSSupportsRule::CSSSupportsRule(Bindings::WindowObject& window_object, NonnullRefPtr<Supports>&& supports, CSSRuleList& rules)
: CSSConditionRule(window_object, rules)
, m_supports(move(supports))
{
set_prototype(&window_object.ensure_web_prototype<Bindings::CSSSupportsRulePrototype>("CSSSupportsRule"));
}
String CSSSupportsRule::condition_text() const

View file

@ -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<CSSSupportsRule> create(NonnullRefPtr<Supports>&& supports, NonnullRefPtrVector<CSSRule>&& rules)
{
return adopt_ref(*new CSSSupportsRule(move(supports), move(rules)));
}
static CSSSupportsRule* create(Bindings::WindowObject&, NonnullRefPtr<Supports>&&, CSSRuleList&);
explicit CSSSupportsRule(Bindings::WindowObject&, NonnullRefPtr<Supports>&&, 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<Supports>&&, NonnullRefPtrVector<CSSRule>&&);
virtual String serialized() const override;
NonnullRefPtr<Supports> m_supports;
@ -49,3 +45,8 @@ template<>
inline bool CSSRule::fast_is<CSSSupportsRule>() 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;
}

View file

@ -1,5 +1,5 @@
#import <CSS/CSSConditionRule.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface CSSSupportsRule : CSSConditionRule {
};

View file

@ -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<AK::URL> 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<CSSRule> rules;
JS::MarkedVector<CSSRule*> 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, its 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<SelectorList> Parser::parse_as_selector(SelectorParsingMode parsing_mode)
@ -2096,7 +2102,7 @@ Vector<DeclarationOrAtRule> Parser::consume_a_list_of_declarations(TokenStream<T
}
}
RefPtr<CSSRule> 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<StyleValue> Parser::parse_linear_gradient_function(ComponentValue const&
return LinearGradientStyleValue::create(gradient_direction, move(color_stops), gradient_type, repeating_gradient);
}
RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<Rule> rule)
CSSRule* Parser::convert_to_rule(NonnullRefPtr<Rule> rule)
{
if (rule->is_at_rule()) {
if (has_ignored_vendor_prefix(rule->at_rule_name())) {
@ -2625,8 +2631,7 @@ RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<Rule> rule)
if (url.has_value())
return CSSImportRule::create(url.value(), const_cast<DOM::Document&>(*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<CSSRule> Parser::convert_to_rule(NonnullRefPtr<Rule> rule)
auto child_tokens = TokenStream { rule->block()->values() };
auto parser_rules = parse_a_list_of_rules(child_tokens);
NonnullRefPtrVector<CSSRule> child_rules;
JS::MarkedVector<CSSRule*> 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<CSSRule> Parser::convert_to_rule(NonnullRefPtr<Rule> rule)
return {};
auto child_tokens = TokenStream { rule->block()->values() };
auto parser_rules = parse_a_list_of_rules(child_tokens);
NonnullRefPtrVector<CSSRule> child_rules;
JS::MarkedVector<CSSRule*> 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<CSSRule> Parser::convert_to_rule(NonnullRefPtr<Rule> 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<StyleValue> Parser::parse_font_family_value(Vector<ComponentValue> const&
return StyleValueList::create(move(font_families), StyleValueList::Separator::Comma);
}
RefPtr<CSSRule> Parser::parse_font_face_rule(TokenStream<ComponentValue>& tokens)
CSSRule* Parser::parse_font_face_rule(TokenStream<ComponentValue>& tokens)
{
auto declarations_and_at_rules = parse_a_list_of_declarations(tokens);
@ -4791,7 +4797,7 @@ RefPtr<CSSRule> Parser::parse_font_face_rule(TokenStream<ComponentValue>& 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<FontFace::Source> Parser::parse_font_face_src(TokenStream<ComponentValue>& component_values)
@ -6385,7 +6391,7 @@ namespace Web {
CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingContext const& context, StringView css, Optional<AK::URL> 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<CSS::StyleValue> parse_css_value(CSS::Parser::ParsingContext const& conte
return parser.parse_as_css_value(property_id);
}
RefPtr<CSS::CSSRule> 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();

View file

@ -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<AK::URL> location);
RefPtr<ElementInlineCSSStyleDeclaration> parse_as_style_attribute(DOM::Element&);
RefPtr<CSSRule> parse_as_css_rule();
CSSRule* parse_as_css_rule();
Optional<StyleProperty> parse_as_supports_condition();
enum class SelectorParsingMode {
@ -235,10 +236,10 @@ private:
Optional<GeneralEnclosed> parse_general_enclosed(TokenStream<ComponentValue>&);
RefPtr<CSSRule> parse_font_face_rule(TokenStream<ComponentValue>&);
CSSRule* parse_font_face_rule(TokenStream<ComponentValue>&);
Vector<FontFace::Source> parse_font_face_src(TokenStream<ComponentValue>&);
RefPtr<CSSRule> convert_to_rule(NonnullRefPtr<Rule>);
CSSRule* convert_to_rule(NonnullRefPtr<Rule>);
RefPtr<PropertyOwningCSSStyleDeclaration> convert_to_style_declaration(Vector<DeclarationOrAtRule> declarations);
Optional<StyleProperty> convert_to_style_property(Declaration const&);
@ -423,7 +424,7 @@ CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingContext const&, Str
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);
RefPtr<CSS::CSSRule> parse_css_rule(CSS::Parser::ParsingContext const&, StringView);
CSS::CSSRule* parse_css_rule(CSS::Parser::ParsingContext const&, StringView);
RefPtr<CSS::MediaQuery> parse_media_query(CSS::Parser::ParsingContext const&, StringView);
NonnullRefPtrVector<CSS::MediaQuery> parse_media_query_list(CSS::Parser::ParsingContext const&, StringView);
RefPtr<CSS::Supports> parse_css_supports(CSS::Parser::ParsingContext const&, StringView);

View file

@ -184,7 +184,7 @@ Vector<MatchingRule> 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) {

View file

@ -21,7 +21,7 @@
namespace Web::CSS {
struct MatchingRule {
RefPtr<CSSStyleRule> rule;
CSSStyleRule const* rule { nullptr };
size_t style_sheet_index { 0 };
size_t rule_index { 0 };
size_t selector_index { 0 };

View file

@ -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;

View file

@ -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)