LibWeb: Don't store root as JS::Handle in IntersectionObserver

Instead, use a JS::GCPtr and visit it, to prevent GC reference cycles.
This commit is contained in:
Andreas Kling 2024-04-03 12:44:32 +02:00
commit 518cedc8f3
Notes: sideshowbarker 2024-07-16 23:59:28 +09:00
2 changed files with 16 additions and 6 deletions

View file

@ -50,9 +50,9 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<IntersectionObserver>> IntersectionObserver
IntersectionObserver::IntersectionObserver(JS::Realm& realm, JS::GCPtr<WebIDL::CallbackType> callback, Optional<Variant<JS::Handle<DOM::Element>, JS::Handle<DOM::Document>>> const& root, Vector<double>&& thresholds) IntersectionObserver::IntersectionObserver(JS::Realm& realm, JS::GCPtr<WebIDL::CallbackType> callback, Optional<Variant<JS::Handle<DOM::Element>, JS::Handle<DOM::Document>>> const& root, Vector<double>&& thresholds)
: PlatformObject(realm) : PlatformObject(realm)
, m_callback(callback) , m_callback(callback)
, m_root(root)
, m_thresholds(move(thresholds)) , m_thresholds(move(thresholds))
{ {
m_root = root.has_value() ? root->visit([](auto& value) -> JS::GCPtr<DOM::Node> { return *value; }) : nullptr;
intersection_root().visit([this](auto& node) { intersection_root().visit([this](auto& node) {
m_document = node->document(); m_document = node->document();
}); });
@ -76,6 +76,7 @@ void IntersectionObserver::initialize(JS::Realm& realm)
void IntersectionObserver::visit_edges(JS::Cell::Visitor& visitor) void IntersectionObserver::visit_edges(JS::Cell::Visitor& visitor)
{ {
Base::visit_edges(visitor); Base::visit_edges(visitor);
visitor.visit(m_root);
visitor.visit(m_callback); visitor.visit(m_callback);
for (auto& entry : m_queued_entries) for (auto& entry : m_queued_entries)
visitor.visit(entry); visitor.visit(entry);
@ -152,9 +153,13 @@ Vector<JS::Handle<IntersectionObserverEntry>> IntersectionObserver::take_records
Variant<JS::Handle<DOM::Element>, JS::Handle<DOM::Document>, Empty> IntersectionObserver::root() const Variant<JS::Handle<DOM::Element>, JS::Handle<DOM::Document>, Empty> IntersectionObserver::root() const
{ {
if (!m_root.has_value()) if (!m_root)
return Empty {}; return Empty {};
return m_root.value(); if (m_root->is_element())
return JS::make_handle(static_cast<DOM::Element&>(*m_root));
if (m_root->is_document())
return JS::make_handle(static_cast<DOM::Document&>(*m_root));
VERIFY_NOT_REACHED();
} }
// https://www.w3.org/TR/intersection-observer/#intersectionobserver-intersection-root // https://www.w3.org/TR/intersection-observer/#intersectionobserver-intersection-root
@ -162,8 +167,13 @@ Variant<JS::Handle<DOM::Element>, JS::Handle<DOM::Document>> IntersectionObserve
{ {
// The intersection root for an IntersectionObserver is the value of its root attribute // The intersection root for an IntersectionObserver is the value of its root attribute
// if the attribute is non-null; // if the attribute is non-null;
if (m_root.has_value()) if (m_root) {
return m_root.value(); if (m_root->is_element())
return JS::make_handle(static_cast<DOM::Element&>(*m_root));
if (m_root->is_document())
return JS::make_handle(static_cast<DOM::Document&>(*m_root));
VERIFY_NOT_REACHED();
}
// otherwise, it is the top-level browsing contexts document node, referred to as the implicit root. // otherwise, it is the top-level browsing contexts document node, referred to as the implicit root.
return JS::make_handle(global_object().page().top_level_browsing_context().active_document()); return JS::make_handle(global_object().page().top_level_browsing_context().active_document());

View file

@ -73,7 +73,7 @@ private:
JS::GCPtr<WebIDL::CallbackType> m_callback; JS::GCPtr<WebIDL::CallbackType> m_callback;
// https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-root // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-root
Optional<Variant<JS::Handle<DOM::Element>, JS::Handle<DOM::Document>>> m_root; JS::GCPtr<DOM::Node> m_root;
// https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-thresholds // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-thresholds
Vector<double> m_thresholds; Vector<double> m_thresholds;