mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-23 09:46:04 -05:00
98691810b1
Invalidation for adopted style sheets was broken because we had an assumption that "active" style sheet is always attached to StyleSheetList which is not true for adopted style sheets. This change addresses that by keeping track of all documents/shadow roots that own a style sheet and notifying them about invalidation instead of going through the StyleSheetList.
55 lines
2.9 KiB
C++
55 lines
2.9 KiB
C++
/*
|
||
* 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 {
|
||
|
||
GC::Ref<WebIDL::ObservableArray> create_adopted_style_sheets_list(Node& document_or_shadow_root)
|
||
{
|
||
auto adopted_style_sheets = WebIDL::ObservableArray::create(document_or_shadow_root.realm());
|
||
adopted_style_sheets->set_on_set_an_indexed_value_callback([&document_or_shadow_root](JS::Value& value) -> WebIDL::ExceptionOr<void> {
|
||
auto& vm = document_or_shadow_root.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_or_shadow_root.realm(), "StyleSheet's constructed flag is not set."_string);
|
||
if (!style_sheet.constructed() || style_sheet.constructor_document().ptr() != &document_or_shadow_root.document())
|
||
return WebIDL::NotAllowedError::create(document_or_shadow_root.realm(), "Sharing a StyleSheet between documents is not allowed."_string);
|
||
|
||
style_sheet.add_owning_document_or_shadow_root(document_or_shadow_root);
|
||
document_or_shadow_root.document().style_computer().load_fonts_from_sheet(style_sheet);
|
||
document_or_shadow_root.document().style_computer().invalidate_rule_cache();
|
||
document_or_shadow_root.invalidate_style(DOM::StyleInvalidationReason::AdoptedStyleSheetsList);
|
||
return {};
|
||
});
|
||
adopted_style_sheets->set_on_delete_an_indexed_value_callback([&document_or_shadow_root](JS::Value value) -> WebIDL::ExceptionOr<void> {
|
||
VERIFY(value.is_object());
|
||
auto& object = value.as_object();
|
||
VERIFY(is<CSS::CSSStyleSheet>(object));
|
||
auto& style_sheet = static_cast<CSS::CSSStyleSheet&>(object);
|
||
|
||
style_sheet.remove_owning_document_or_shadow_root(document_or_shadow_root);
|
||
document_or_shadow_root.document().style_computer().unload_fonts_from_sheet(style_sheet);
|
||
document_or_shadow_root.document().style_computer().invalidate_rule_cache();
|
||
document_or_shadow_root.invalidate_style(DOM::StyleInvalidationReason::AdoptedStyleSheetsList);
|
||
return {};
|
||
});
|
||
|
||
return adopted_style_sheets;
|
||
}
|
||
|
||
}
|