mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:27:35 +00:00
LibWeb: Implement adoptedStyleSheets attribute for Document
https://drafts.csswg.org/cssom/#dom-documentorshadowroot-adoptedstylesheets The attribute implementation for ShadowRoot is currently missing because we do not yet distinguish between the style sheets of ShadowRoot and Document, and we need to address the issue first.
This commit is contained in:
parent
fceba6a257
commit
7c322ec710
6 changed files with 171 additions and 2 deletions
|
@ -483,6 +483,8 @@ void Document::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(event.event);
|
||||
visitor.visit(event.target);
|
||||
}
|
||||
|
||||
visitor.visit(m_adopted_style_sheets);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/selection-api/#dom-document-getselection
|
||||
|
@ -4562,4 +4564,78 @@ 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)
|
||||
m_adopted_style_sheets = create_adopted_style_sheets_list(const_cast<Document&>(*this));
|
||||
return *m_adopted_style_sheets;
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> Document::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&>(*this));
|
||||
|
||||
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 {};
|
||||
}
|
||||
|
||||
void Document::for_each_css_style_sheet(Function<void(CSS::CSSStyleSheet&)>&& callback) const
|
||||
{
|
||||
for (auto& style_sheet : m_style_sheets->sheets())
|
||||
callback(*style_sheet);
|
||||
|
||||
if (m_adopted_style_sheets) {
|
||||
for (auto& entry : m_adopted_style_sheets->indexed_properties()) {
|
||||
auto value_and_attributes = m_adopted_style_sheets->indexed_properties().storage()->get(entry.index());
|
||||
if (value_and_attributes.has_value()) {
|
||||
auto& style_sheet = verify_cast<CSS::CSSStyleSheet>(value_and_attributes->value.as_object());
|
||||
callback(style_sheet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue