mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:37:46 +00:00
LibWeb: Add styleSheets and adoptedStyleSheets attributes in ShadowRoot
Co-authored-by: Simon Wanner <simon+git@skyrising.xyz>
This commit is contained in:
parent
f19c92d78e
commit
8ce8697a66
11 changed files with 138 additions and 37 deletions
|
@ -135,6 +135,7 @@ set(SOURCES
|
||||||
DOM/AbortSignal.cpp
|
DOM/AbortSignal.cpp
|
||||||
DOM/AbstractRange.cpp
|
DOM/AbstractRange.cpp
|
||||||
DOM/AccessibilityTreeNode.cpp
|
DOM/AccessibilityTreeNode.cpp
|
||||||
|
DOM/AdoptedStyleSheets.cpp
|
||||||
DOM/Attr.cpp
|
DOM/Attr.cpp
|
||||||
DOM/CDATASection.cpp
|
DOM/CDATASection.cpp
|
||||||
DOM/CharacterData.cpp
|
DOM/CharacterData.cpp
|
||||||
|
|
47
Userland/Libraries/LibWeb/DOM/AdoptedStyleSheets.cpp
Normal file
47
Userland/Libraries/LibWeb/DOM/AdoptedStyleSheets.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/CSS/StyleComputer.h>
|
||||||
|
#include <LibWeb/DOM/AdoptedStyleSheets.h>
|
||||||
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
|
||||||
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
JS::NonnullGCPtr<WebIDL::ObservableArray> create_adopted_style_sheets_list(Document& document)
|
||||||
|
{
|
||||||
|
auto adopted_style_sheets = WebIDL::ObservableArray::create(document.realm());
|
||||||
|
adopted_style_sheets->set_on_set_an_indexed_value_callback([&document](JS::Value& value) -> WebIDL::ExceptionOr<void> {
|
||||||
|
auto& vm = document.vm();
|
||||||
|
if (!value.is_object())
|
||||||
|
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "CSSStyleSheet");
|
||||||
|
auto& object = value.as_object();
|
||||||
|
if (!is<CSS::CSSStyleSheet>(object))
|
||||||
|
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "CSSStyleSheet");
|
||||||
|
auto& style_sheet = static_cast<CSS::CSSStyleSheet&>(object);
|
||||||
|
|
||||||
|
// The set an indexed value algorithm for adoptedStyleSheets, given value and index, is the following:
|
||||||
|
// 1. If value’s constructed flag is not set, or its constructor document is not equal to this
|
||||||
|
// DocumentOrShadowRoot's node document, throw a "NotAllowedError" DOMException.
|
||||||
|
if (!style_sheet.constructed())
|
||||||
|
return WebIDL::NotAllowedError::create(document.realm(), "StyleSheet's constructed flag is not set."_fly_string);
|
||||||
|
if (!style_sheet.constructed() || style_sheet.constructor_document().ptr() != &document)
|
||||||
|
return WebIDL::NotAllowedError::create(document.realm(), "Sharing a StyleSheet between documents is not allowed."_fly_string);
|
||||||
|
|
||||||
|
document.style_computer().load_fonts_from_sheet(style_sheet);
|
||||||
|
document.style_computer().invalidate_rule_cache();
|
||||||
|
document.invalidate_style();
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
adopted_style_sheets->set_on_delete_an_indexed_value_callback([&document]() -> WebIDL::ExceptionOr<void> {
|
||||||
|
document.style_computer().invalidate_rule_cache();
|
||||||
|
document.invalidate_style();
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
|
return adopted_style_sheets;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
Userland/Libraries/LibWeb/DOM/AdoptedStyleSheets.h
Normal file
16
Userland/Libraries/LibWeb/DOM/AdoptedStyleSheets.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibWeb/Forward.h>
|
||||||
|
#include <LibWeb/WebIDL/ObservableArray.h>
|
||||||
|
|
||||||
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
JS::NonnullGCPtr<WebIDL::ObservableArray> create_adopted_style_sheets_list(Document& document);
|
||||||
|
|
||||||
|
}
|
|
@ -31,6 +31,7 @@
|
||||||
#include <LibWeb/CSS/SystemColor.h>
|
#include <LibWeb/CSS/SystemColor.h>
|
||||||
#include <LibWeb/CSS/VisualViewport.h>
|
#include <LibWeb/CSS/VisualViewport.h>
|
||||||
#include <LibWeb/Cookie/ParsedCookie.h>
|
#include <LibWeb/Cookie/ParsedCookie.h>
|
||||||
|
#include <LibWeb/DOM/AdoptedStyleSheets.h>
|
||||||
#include <LibWeb/DOM/Attr.h>
|
#include <LibWeb/DOM/Attr.h>
|
||||||
#include <LibWeb/DOM/CDATASection.h>
|
#include <LibWeb/DOM/CDATASection.h>
|
||||||
#include <LibWeb/DOM/Comment.h>
|
#include <LibWeb/DOM/Comment.h>
|
||||||
|
@ -4564,40 +4565,6 @@ bool Document::has_skipped_resize_observations()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS::NonnullGCPtr<WebIDL::ObservableArray> create_adopted_style_sheets_list(Document& document)
|
|
||||||
{
|
|
||||||
auto adopted_style_sheets = WebIDL::ObservableArray::create(document.realm());
|
|
||||||
adopted_style_sheets->set_on_set_an_indexed_value_callback([&document](JS::Value& value) -> WebIDL::ExceptionOr<void> {
|
|
||||||
auto& vm = document.vm();
|
|
||||||
if (!value.is_object())
|
|
||||||
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "CSSStyleSheet");
|
|
||||||
auto& object = value.as_object();
|
|
||||||
if (!is<CSS::CSSStyleSheet>(object))
|
|
||||||
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "CSSStyleSheet");
|
|
||||||
auto& style_sheet = static_cast<CSS::CSSStyleSheet&>(object);
|
|
||||||
|
|
||||||
// The set an indexed value algorithm for adoptedStyleSheets, given value and index, is the following:
|
|
||||||
// 1. If value’s constructed flag is not set, or its constructor document is not equal to this
|
|
||||||
// DocumentOrShadowRoot's node document, throw a "NotAllowedError" DOMException.
|
|
||||||
if (!style_sheet.constructed())
|
|
||||||
return WebIDL::NotAllowedError::create(document.realm(), "StyleSheet's constructed flag is not set."_fly_string);
|
|
||||||
if (!style_sheet.constructed() || style_sheet.constructor_document().ptr() != &document)
|
|
||||||
return WebIDL::NotAllowedError::create(document.realm(), "Sharing a StyleSheet between documents is not allowed."_fly_string);
|
|
||||||
|
|
||||||
document.style_computer().load_fonts_from_sheet(style_sheet);
|
|
||||||
document.style_computer().invalidate_rule_cache();
|
|
||||||
document.invalidate_style();
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
adopted_style_sheets->set_on_delete_an_indexed_value_callback([&document]() -> WebIDL::ExceptionOr<void> {
|
|
||||||
document.style_computer().invalidate_rule_cache();
|
|
||||||
document.invalidate_style();
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
|
|
||||||
return adopted_style_sheets;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::NonnullGCPtr<WebIDL::ObservableArray> Document::adopted_style_sheets() const
|
JS::NonnullGCPtr<WebIDL::ObservableArray> Document::adopted_style_sheets() const
|
||||||
{
|
{
|
||||||
if (!m_adopted_style_sheets)
|
if (!m_adopted_style_sheets)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#import <DOM/Comment.idl>
|
#import <DOM/Comment.idl>
|
||||||
#import <DOM/DOMImplementation.idl>
|
#import <DOM/DOMImplementation.idl>
|
||||||
#import <DOM/DocumentFragment.idl>
|
#import <DOM/DocumentFragment.idl>
|
||||||
|
#import <DOM/DocumentOrShadowRoot.idl>
|
||||||
#import <DOM/DocumentType.idl>
|
#import <DOM/DocumentType.idl>
|
||||||
#import <DOM/Element.idl>
|
#import <DOM/Element.idl>
|
||||||
#import <DOM/Event.idl>
|
#import <DOM/Event.idl>
|
||||||
|
@ -94,9 +95,6 @@ interface Document : Node {
|
||||||
[CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false);
|
[CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false);
|
||||||
[CEReactions, ImplementedAs=adopt_node_binding] Node adoptNode(Node node);
|
[CEReactions, ImplementedAs=adopt_node_binding] Node adoptNode(Node node);
|
||||||
|
|
||||||
[ImplementedAs=style_sheets_for_bindings] readonly attribute StyleSheetList styleSheets;
|
|
||||||
attribute any adoptedStyleSheets;
|
|
||||||
|
|
||||||
readonly attribute DOMString compatMode;
|
readonly attribute DOMString compatMode;
|
||||||
readonly attribute DocumentType? doctype;
|
readonly attribute DocumentType? doctype;
|
||||||
|
|
||||||
|
@ -141,3 +139,4 @@ dictionary ElementCreationOptions {
|
||||||
};
|
};
|
||||||
Document includes ParentNode;
|
Document includes ParentNode;
|
||||||
Document includes GlobalEventHandlers;
|
Document includes GlobalEventHandlers;
|
||||||
|
Document includes DocumentOrShadowRoot;
|
||||||
|
|
8
Userland/Libraries/LibWeb/DOM/DocumentOrShadowRoot.idl
Normal file
8
Userland/Libraries/LibWeb/DOM/DocumentOrShadowRoot.idl
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#import <CSS/StyleSheetList.idl>
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#documentorshadowroot
|
||||||
|
interface mixin DocumentOrShadowRoot {
|
||||||
|
// https://w3c.github.io/csswg-drafts/cssom/#extensions-to-the-document-or-shadow-root-interface
|
||||||
|
[SameObject, ImplementedAs=style_sheets_for_bindings] readonly attribute StyleSheetList styleSheets;
|
||||||
|
attribute any adoptedStyleSheets;
|
||||||
|
};
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/DOM/AdoptedStyleSheets.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOM/Event.h>
|
#include <LibWeb/DOM/Event.h>
|
||||||
#include <LibWeb/DOM/ShadowRoot.h>
|
#include <LibWeb/DOM/ShadowRoot.h>
|
||||||
|
@ -54,4 +55,47 @@ WebIDL::ExceptionOr<void> ShadowRoot::set_inner_html(StringView markup)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSS::StyleSheetList& ShadowRoot::style_sheets()
|
||||||
|
{
|
||||||
|
if (!m_style_sheets)
|
||||||
|
m_style_sheets = CSS::StyleSheetList::create(document());
|
||||||
|
return *m_style_sheets;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSS::StyleSheetList const& ShadowRoot::style_sheets() const
|
||||||
|
{
|
||||||
|
return const_cast<ShadowRoot*>(this)->style_sheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowRoot::visit_edges(Visitor& visitor)
|
||||||
|
{
|
||||||
|
Base::visit_edges(visitor);
|
||||||
|
visitor.visit(m_style_sheets);
|
||||||
|
visitor.visit(m_adopted_style_sheets);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::NonnullGCPtr<WebIDL::ObservableArray> ShadowRoot::adopted_style_sheets() const
|
||||||
|
{
|
||||||
|
if (!m_adopted_style_sheets)
|
||||||
|
m_adopted_style_sheets = create_adopted_style_sheets_list(const_cast<Document&>(document()));
|
||||||
|
return *m_adopted_style_sheets;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebIDL::ExceptionOr<void> ShadowRoot::set_adopted_style_sheets(JS::Value new_value)
|
||||||
|
{
|
||||||
|
if (!m_adopted_style_sheets)
|
||||||
|
m_adopted_style_sheets = create_adopted_style_sheets_list(const_cast<Document&>(document()));
|
||||||
|
|
||||||
|
m_adopted_style_sheets->clear();
|
||||||
|
auto iterator_record = TRY(get_iterator(vm(), new_value, JS::IteratorHint::Sync));
|
||||||
|
while (true) {
|
||||||
|
auto next = TRY(iterator_step_value(vm(), iterator_record));
|
||||||
|
if (!next.has_value())
|
||||||
|
break;
|
||||||
|
TRY(m_adopted_style_sheets->append(*next));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <LibWeb/Bindings/ShadowRootPrototype.h>
|
#include <LibWeb/Bindings/ShadowRootPrototype.h>
|
||||||
#include <LibWeb/DOM/DocumentFragment.h>
|
#include <LibWeb/DOM/DocumentFragment.h>
|
||||||
|
#include <LibWeb/WebIDL/ObservableArray.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
@ -33,6 +34,17 @@ public:
|
||||||
WebIDL::ExceptionOr<String> inner_html() const;
|
WebIDL::ExceptionOr<String> inner_html() const;
|
||||||
WebIDL::ExceptionOr<void> set_inner_html(StringView);
|
WebIDL::ExceptionOr<void> set_inner_html(StringView);
|
||||||
|
|
||||||
|
CSS::StyleSheetList& style_sheets();
|
||||||
|
CSS::StyleSheetList const& style_sheets() const;
|
||||||
|
|
||||||
|
CSS::StyleSheetList* style_sheets_for_bindings() { return &style_sheets(); }
|
||||||
|
|
||||||
|
JS::NonnullGCPtr<WebIDL::ObservableArray> adopted_style_sheets() const;
|
||||||
|
WebIDL::ExceptionOr<void> set_adopted_style_sheets(JS::Value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ShadowRoot(Document&, Element& host, Bindings::ShadowRootMode);
|
ShadowRoot(Document&, Element& host, Bindings::ShadowRootMode);
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
@ -46,6 +58,9 @@ private:
|
||||||
Bindings::SlotAssignmentMode m_slot_assignment { Bindings::SlotAssignmentMode::Named };
|
Bindings::SlotAssignmentMode m_slot_assignment { Bindings::SlotAssignmentMode::Named };
|
||||||
bool m_delegates_focus { false };
|
bool m_delegates_focus { false };
|
||||||
bool m_available_to_element_internals { false };
|
bool m_available_to_element_internals { false };
|
||||||
|
|
||||||
|
JS::GCPtr<CSS::StyleSheetList> m_style_sheets;
|
||||||
|
mutable JS::GCPtr<WebIDL::ObservableArray> m_adopted_style_sheets;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#import <DOM/DocumentFragment.idl>
|
#import <DOM/DocumentFragment.idl>
|
||||||
|
#import <DOM/DocumentOrShadowRoot.idl>
|
||||||
#import <DOM/InnerHTML.idl>
|
#import <DOM/InnerHTML.idl>
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#shadowroot
|
// https://dom.spec.whatwg.org/#shadowroot
|
||||||
|
@ -12,6 +13,7 @@ interface ShadowRoot : DocumentFragment {
|
||||||
};
|
};
|
||||||
|
|
||||||
ShadowRoot includes InnerHTML;
|
ShadowRoot includes InnerHTML;
|
||||||
|
ShadowRoot includes DocumentOrShadowRoot;
|
||||||
|
|
||||||
enum ShadowRootMode { "open", "closed" };
|
enum ShadowRootMode { "open", "closed" };
|
||||||
enum SlotAssignmentMode { "manual", "named" };
|
enum SlotAssignmentMode { "manual", "named" };
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibWeb/CSS/Parser/Parser.h>
|
#include <LibWeb/CSS/Parser/Parser.h>
|
||||||
|
#include <LibWeb/CSS/StyleComputer.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOM/StyleElementUtils.h>
|
#include <LibWeb/DOM/StyleElementUtils.h>
|
||||||
#include <LibWeb/Infra/Strings.h>
|
#include <LibWeb/Infra/Strings.h>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <LibWeb/CSS/CSSStyleSheet.h>
|
#include <LibWeb/CSS/CSSStyleSheet.h>
|
||||||
#include <LibWeb/DOM/Element.h>
|
#include <LibWeb/DOM/Element.h>
|
||||||
|
#include <LibWeb/WebIDL/ObservableArray.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue