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
Notes:
sideshowbarker
2024-07-17 01:46:00 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/8ce8697a66 Pull-request: https://github.com/SerenityOS/serenity/pull/23533 Issue: https://github.com/SerenityOS/serenity/issues/23410 Reviewed-by: https://github.com/awesomekling
11 changed files with 138 additions and 37 deletions
|
@ -135,6 +135,7 @@ set(SOURCES
|
|||
DOM/AbortSignal.cpp
|
||||
DOM/AbstractRange.cpp
|
||||
DOM/AccessibilityTreeNode.cpp
|
||||
DOM/AdoptedStyleSheets.cpp
|
||||
DOM/Attr.cpp
|
||||
DOM/CDATASection.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/VisualViewport.h>
|
||||
#include <LibWeb/Cookie/ParsedCookie.h>
|
||||
#include <LibWeb/DOM/AdoptedStyleSheets.h>
|
||||
#include <LibWeb/DOM/Attr.h>
|
||||
#include <LibWeb/DOM/CDATASection.h>
|
||||
#include <LibWeb/DOM/Comment.h>
|
||||
|
@ -4564,40 +4565,6 @@ bool Document::has_skipped_resize_observations()
|
|||
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
|
||||
{
|
||||
if (!m_adopted_style_sheets)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#import <DOM/Comment.idl>
|
||||
#import <DOM/DOMImplementation.idl>
|
||||
#import <DOM/DocumentFragment.idl>
|
||||
#import <DOM/DocumentOrShadowRoot.idl>
|
||||
#import <DOM/DocumentType.idl>
|
||||
#import <DOM/Element.idl>
|
||||
#import <DOM/Event.idl>
|
||||
|
@ -94,9 +95,6 @@ interface Document : Node {
|
|||
[CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false);
|
||||
[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 DocumentType? doctype;
|
||||
|
||||
|
@ -141,3 +139,4 @@ dictionary ElementCreationOptions {
|
|||
};
|
||||
Document includes ParentNode;
|
||||
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
|
||||
*/
|
||||
|
||||
#include <LibWeb/DOM/AdoptedStyleSheets.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
|
@ -54,4 +55,47 @@ WebIDL::ExceptionOr<void> ShadowRoot::set_inner_html(StringView markup)
|
|||
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/DOM/DocumentFragment.h>
|
||||
#include <LibWeb/WebIDL/ObservableArray.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
|
@ -33,6 +34,17 @@ public:
|
|||
WebIDL::ExceptionOr<String> inner_html() const;
|
||||
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:
|
||||
ShadowRoot(Document&, Element& host, Bindings::ShadowRootMode);
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
@ -46,6 +58,9 @@ private:
|
|||
Bindings::SlotAssignmentMode m_slot_assignment { Bindings::SlotAssignmentMode::Named };
|
||||
bool m_delegates_focus { 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<>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#import <DOM/DocumentFragment.idl>
|
||||
#import <DOM/DocumentOrShadowRoot.idl>
|
||||
#import <DOM/InnerHTML.idl>
|
||||
|
||||
// https://dom.spec.whatwg.org/#shadowroot
|
||||
|
@ -12,6 +13,7 @@ interface ShadowRoot : DocumentFragment {
|
|||
};
|
||||
|
||||
ShadowRoot includes InnerHTML;
|
||||
ShadowRoot includes DocumentOrShadowRoot;
|
||||
|
||||
enum ShadowRootMode { "open", "closed" };
|
||||
enum SlotAssignmentMode { "manual", "named" };
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/CSS/StyleComputer.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/StyleElementUtils.h>
|
||||
#include <LibWeb/Infra/Strings.h>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <LibWeb/CSS/CSSStyleSheet.h>
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/WebIDL/ObservableArray.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue