LibJS+LibWeb: Use GC::Weak instead of AK::WeakPtr for GC-allocated types

This makes some common types like JS::Object smaller (by 8 bytes) and
yields a minor speed improvement on many benchmarks.
This commit is contained in:
Andreas Kling 2025-10-16 11:13:54 +02:00 committed by Andreas Kling
parent 25a5ed94d6
commit dfa796a4e4
Notes: github-actions[bot] 2025-10-17 15:25:08 +00:00
36 changed files with 111 additions and 115 deletions

View file

@ -10,8 +10,9 @@
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
#include <AK/Utf16FlyString.h> #include <AK/Utf16FlyString.h>
#include <AK/WeakPtr.h>
#include <LibGC/CellAllocator.h> #include <LibGC/CellAllocator.h>
#include <LibGC/Weak.h>
#include <LibGC/WeakInlines.h>
#include <LibJS/Bytecode/IdentifierTable.h> #include <LibJS/Bytecode/IdentifierTable.h>
#include <LibJS/Bytecode/Label.h> #include <LibJS/Bytecode/Label.h>
#include <LibJS/Bytecode/StringTable.h> #include <LibJS/Bytecode/StringTable.h>
@ -37,11 +38,11 @@ struct PropertyLookupCache {
GetPropertyInPrototypeChain, GetPropertyInPrototypeChain,
}; };
Type type { Type::Empty }; Type type { Type::Empty };
WeakPtr<Shape> from_shape; GC::Weak<Shape> from_shape;
WeakPtr<Shape> shape; GC::Weak<Shape> shape;
Optional<u32> property_offset; Optional<u32> property_offset;
WeakPtr<Object> prototype; GC::Weak<Object> prototype;
WeakPtr<PrototypeChainValidity> prototype_chain_validity; GC::Weak<PrototypeChainValidity> prototype_chain_validity;
}; };
AK::Array<Entry, max_number_of_shapes_to_remember> entries; AK::Array<Entry, max_number_of_shapes_to_remember> entries;
}; };

View file

@ -9,7 +9,6 @@
#pragma once #pragma once
#include <AK/WeakPtr.h>
#include <LibJS/Bytecode/BasicBlock.h> #include <LibJS/Bytecode/BasicBlock.h>
#include <LibJS/Export.h> #include <LibJS/Export.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>

View file

@ -64,8 +64,7 @@ struct CacheableSetPropertyMetadata {
GC::Ptr<Object const> prototype; GC::Ptr<Object const> prototype;
}; };
class JS_API Object : public Cell class JS_API Object : public Cell {
, public Weakable<Object> {
GC_CELL(Object, Cell); GC_CELL(Object, Cell);
GC_DECLARE_ALLOCATOR(Object); GC_DECLARE_ALLOCATOR(Object);

View file

@ -110,8 +110,8 @@ GC::Ref<Shape> Shape::create_put_transition(PropertyKey const& property_key, Pro
invalidate_prototype_if_needed_for_new_prototype(new_shape); invalidate_prototype_if_needed_for_new_prototype(new_shape);
if (!m_is_prototype_shape) { if (!m_is_prototype_shape) {
if (!m_forward_transitions) if (!m_forward_transitions)
m_forward_transitions = make<HashMap<TransitionKey, WeakPtr<Shape>>>(); m_forward_transitions = make<HashMap<TransitionKey, GC::Weak<Shape>>>();
m_forward_transitions->set(key, new_shape.ptr()); m_forward_transitions->set(key, new_shape);
} }
return new_shape; return new_shape;
} }
@ -125,7 +125,7 @@ GC::Ref<Shape> Shape::create_configure_transition(PropertyKey const& property_ke
invalidate_prototype_if_needed_for_new_prototype(new_shape); invalidate_prototype_if_needed_for_new_prototype(new_shape);
if (!m_is_prototype_shape) { if (!m_is_prototype_shape) {
if (!m_forward_transitions) if (!m_forward_transitions)
m_forward_transitions = make<HashMap<TransitionKey, WeakPtr<Shape>>>(); m_forward_transitions = make<HashMap<TransitionKey, GC::Weak<Shape>>>();
m_forward_transitions->set(key, new_shape.ptr()); m_forward_transitions->set(key, new_shape.ptr());
} }
return new_shape; return new_shape;
@ -141,7 +141,7 @@ GC::Ref<Shape> Shape::create_prototype_transition(Object* new_prototype)
invalidate_prototype_if_needed_for_new_prototype(new_shape); invalidate_prototype_if_needed_for_new_prototype(new_shape);
if (!m_is_prototype_shape) { if (!m_is_prototype_shape) {
if (!m_prototype_transitions) if (!m_prototype_transitions)
m_prototype_transitions = make<HashMap<GC::Ptr<Object>, WeakPtr<Shape>>>(); m_prototype_transitions = make<HashMap<GC::Ptr<Object>, GC::Weak<Shape>>>();
m_prototype_transitions->set(new_prototype, new_shape.ptr()); m_prototype_transitions->set(new_prototype, new_shape.ptr());
} }
return new_shape; return new_shape;
@ -279,7 +279,7 @@ GC::Ref<Shape> Shape::create_delete_transition(PropertyKey const& property_key)
auto new_shape = heap().allocate<Shape>(*this, property_key, TransitionType::Delete); auto new_shape = heap().allocate<Shape>(*this, property_key, TransitionType::Delete);
invalidate_prototype_if_needed_for_new_prototype(new_shape); invalidate_prototype_if_needed_for_new_prototype(new_shape);
if (!m_delete_transitions) if (!m_delete_transitions)
m_delete_transitions = make<HashMap<PropertyKey, WeakPtr<Shape>>>(); m_delete_transitions = make<HashMap<PropertyKey, GC::Weak<Shape>>>();
m_delete_transitions->set(property_key, new_shape.ptr()); m_delete_transitions->set(property_key, new_shape.ptr());
return new_shape; return new_shape;
} }

View file

@ -10,8 +10,8 @@
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
#include <AK/StringView.h> #include <AK/StringView.h>
#include <AK/WeakPtr.h>
#include <AK/Weakable.h> #include <AK/Weakable.h>
#include <LibGC/Weak.h>
#include <LibJS/Export.h> #include <LibJS/Export.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h> #include <LibJS/Heap/Cell.h>
@ -36,8 +36,7 @@ struct TransitionKey {
} }
}; };
class PrototypeChainValidity final : public Cell class PrototypeChainValidity final : public Cell {
, public Weakable<PrototypeChainValidity> {
GC_CELL(PrototypeChainValidity, Cell); GC_CELL(PrototypeChainValidity, Cell);
GC_DECLARE_ALLOCATOR(PrototypeChainValidity); GC_DECLARE_ALLOCATOR(PrototypeChainValidity);
@ -50,8 +49,7 @@ private:
size_t padding { 0 }; size_t padding { 0 };
}; };
class JS_API Shape final : public Cell class JS_API Shape final : public Cell {
, public Weakable<Shape> {
GC_CELL(Shape, Cell); GC_CELL(Shape, Cell);
GC_DECLARE_ALLOCATOR(Shape); GC_DECLARE_ALLOCATOR(Shape);
@ -129,9 +127,9 @@ private:
mutable OwnPtr<OrderedHashMap<PropertyKey, PropertyMetadata>> m_property_table; mutable OwnPtr<OrderedHashMap<PropertyKey, PropertyMetadata>> m_property_table;
OwnPtr<HashMap<TransitionKey, WeakPtr<Shape>>> m_forward_transitions; OwnPtr<HashMap<TransitionKey, GC::Weak<Shape>>> m_forward_transitions;
OwnPtr<HashMap<GC::Ptr<Object>, WeakPtr<Shape>>> m_prototype_transitions; OwnPtr<HashMap<GC::Ptr<Object>, GC::Weak<Shape>>> m_prototype_transitions;
OwnPtr<HashMap<PropertyKey, WeakPtr<Shape>>> m_delete_transitions; OwnPtr<HashMap<PropertyKey, GC::Weak<Shape>>> m_delete_transitions;
GC::Ptr<Shape> m_previous; GC::Ptr<Shape> m_previous;
Optional<PropertyKey> m_property_key; Optional<PropertyKey> m_property_key;
GC::Ptr<Object> m_prototype; GC::Ptr<Object> m_prototype;

View file

@ -248,12 +248,12 @@ ENUMERATE_ARIA_ELEMENT_REFERENCING_ATTRIBUTES
#undef __ENUMERATE_ARIA_ATTRIBUTE #undef __ENUMERATE_ARIA_ATTRIBUTE
#define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \ #define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \
Optional<Vector<WeakPtr<DOM::Element>>> const& ARIAMixin::attribute() const \ Optional<Vector<GC::Weak<DOM::Element>>> const& ARIAMixin::attribute() const \
{ \ { \
return m_##attribute; \ return m_##attribute; \
} \ } \
\ \
void ARIAMixin::set_##attribute(Optional<Vector<WeakPtr<DOM::Element>>> value) \ void ARIAMixin::set_##attribute(Optional<Vector<GC::Weak<DOM::Element>>> value) \
{ \ { \
m_##attribute = move(value); \ m_##attribute = move(value); \
} \ } \

View file

@ -68,8 +68,8 @@ public:
#undef __ENUMERATE_ARIA_ATTRIBUTE #undef __ENUMERATE_ARIA_ATTRIBUTE
#define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \ #define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \
Optional<Vector<WeakPtr<DOM::Element>>> const& attribute() const; \ Optional<Vector<GC::Weak<DOM::Element>>> const& attribute() const; \
void set_##attribute(Optional<Vector<WeakPtr<DOM::Element>>>); \ void set_##attribute(Optional<Vector<GC::Weak<DOM::Element>>>); \
\ \
GC::Ptr<JS::Array> cached_##attribute() const; \ GC::Ptr<JS::Array> cached_##attribute() const; \
void set_cached_##attribute(GC::Ptr<JS::Array>); void set_cached_##attribute(GC::Ptr<JS::Array>);
@ -85,12 +85,12 @@ protected:
private: private:
#define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \ #define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \
WeakPtr<DOM::Element> m_##attribute; GC::Weak<DOM::Element> m_##attribute;
ENUMERATE_ARIA_ELEMENT_REFERENCING_ATTRIBUTES ENUMERATE_ARIA_ELEMENT_REFERENCING_ATTRIBUTES
#undef __ENUMERATE_ARIA_ATTRIBUTE #undef __ENUMERATE_ARIA_ATTRIBUTE
#define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \ #define __ENUMERATE_ARIA_ATTRIBUTE(attribute, referencing_attribute) \
Optional<Vector<WeakPtr<DOM::Element>>> m_##attribute; \ Optional<Vector<GC::Weak<DOM::Element>>> m_##attribute; \
GC::Ptr<JS::Array> m_cached_##attribute; GC::Ptr<JS::Array> m_cached_##attribute;
ENUMERATE_ARIA_ELEMENT_LIST_REFERENCING_ATTRIBUTES ENUMERATE_ARIA_ELEMENT_LIST_REFERENCING_ATTRIBUTES
#undef __ENUMERATE_ARIA_ATTRIBUTE #undef __ENUMERATE_ARIA_ATTRIBUTE

View file

@ -744,7 +744,7 @@ void queue_mutation_observer_microtask(DOM::Document const& document)
// 3. For each node of mos node list, remove all transient registered observers whose observer is mo from nodes registered observer list. // 3. For each node of mos node list, remove all transient registered observers whose observer is mo from nodes registered observer list.
for (auto& node : mutation_observer->node_list()) { for (auto& node : mutation_observer->node_list()) {
// FIXME: Is this correct? // FIXME: Is this correct?
if (node.is_null()) if (!node)
continue; continue;
if (node->registered_observer_list()) { if (node->registered_observer_list()) {

View file

@ -126,7 +126,7 @@ GC::Ptr<HTML::SharedResourceRequest> fetch_an_external_image_for_a_stylesheet(St
auto shared_resource_request = HTML::SharedResourceRequest::get_or_create(realm, document->page(), request->url()); auto shared_resource_request = HTML::SharedResourceRequest::get_or_create(realm, document->page(), request->url());
shared_resource_request->add_callbacks( shared_resource_request->add_callbacks(
[document, weak_document = document->make_weak_ptr<DOM::Document>()] { [document, weak_document = GC::Weak { document }] {
if (!weak_document) if (!weak_document)
return; return;

View file

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <LibGC/Weak.h>
#include <LibJS/Heap/Cell.h> #include <LibJS/Heap/Cell.h>
#include <LibWeb/CSS/Enums.h> #include <LibWeb/CSS/Enums.h>
#include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h> #include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h>
@ -79,7 +80,7 @@ private:
GC::Ptr<CSSStyleSheet> m_style_sheet; GC::Ptr<CSSStyleSheet> m_style_sheet;
URL m_url; URL m_url;
WeakPtr<DOM::Document> m_document; GC::Weak<DOM::Document> m_document;
size_t m_current_frame_index { 0 }; size_t m_current_frame_index { 0 };
size_t m_loops_completed { 0 }; size_t m_loops_completed { 0 };

View file

@ -1788,9 +1788,9 @@ void Document::invalidate_style_of_elements_affected_by_has()
auto nodes = move(m_pending_nodes_for_style_invalidation_due_to_presence_of_has); auto nodes = move(m_pending_nodes_for_style_invalidation_due_to_presence_of_has);
for (auto const& node : nodes) { for (auto const& node : nodes) {
if (node.is_null()) if (!node)
continue; continue;
for (auto* ancestor = node.ptr(); ancestor; ancestor = ancestor->parent_or_shadow_host()) { for (auto ancestor = node.ptr(); ancestor; ancestor = ancestor->parent_or_shadow_host()) {
if (!ancestor->is_element()) if (!ancestor->is_element())
continue; continue;
auto& element = static_cast<Element&>(*ancestor); auto& element = static_cast<Element&>(*ancestor);
@ -3420,7 +3420,7 @@ void Document::run_the_scroll_steps()
void Document::add_media_query_list(GC::Ref<CSS::MediaQueryList> media_query_list) void Document::add_media_query_list(GC::Ref<CSS::MediaQueryList> media_query_list)
{ {
m_needs_media_query_evaluation = true; m_needs_media_query_evaluation = true;
m_media_query_lists.append(*media_query_list); m_media_query_lists.append(media_query_list);
} }
// https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes // https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes
@ -3432,7 +3432,7 @@ void Document::evaluate_media_queries_and_report_changes()
// NOTE: Not in the spec, but we take this opportunity to prune null WeakPtrs. // NOTE: Not in the spec, but we take this opportunity to prune null WeakPtrs.
m_media_query_lists.remove_all_matching([](auto& it) { m_media_query_lists.remove_all_matching([](auto& it) {
return it.is_null(); return !it;
}); });
// 1. For each MediaQueryList object target that has doc as its document, // 1. For each MediaQueryList object target that has doc as its document,
@ -3443,7 +3443,7 @@ void Document::evaluate_media_queries_and_report_changes()
// with its type attribute initialized to change, its isTrusted attribute // with its type attribute initialized to change, its isTrusted attribute
// initialized to true, its media attribute initialized to targets media, // initialized to true, its media attribute initialized to targets media,
// and its matches attribute initialized to targets matches state. // and its matches attribute initialized to targets matches state.
if (media_query_list_ptr.is_null()) if (!media_query_list_ptr)
continue; continue;
GC::Ptr<CSS::MediaQueryList> media_query_list = media_query_list_ptr.ptr(); GC::Ptr<CSS::MediaQueryList> media_query_list = media_query_list_ptr.ptr();
bool did_match = media_query_list->matches(); bool did_match = media_query_list->matches();
@ -6845,7 +6845,7 @@ NonnullRefPtr<CSS::StyleValue const> Document::custom_property_initial_value(Fly
GC::Ptr<Element> ElementByIdMap::get(FlyString const& element_id) const GC::Ptr<Element> ElementByIdMap::get(FlyString const& element_id) const
{ {
if (auto elements = m_map.get(element_id); elements.has_value() && !elements->is_empty()) { if (auto elements = m_map.get(element_id); elements.has_value() && !elements->is_empty()) {
if (auto element = elements->first(); element.has_value()) if (auto element = elements->first())
return *element; return *element;
} }
return {}; return {};

View file

@ -681,7 +681,7 @@ public:
WebIDL::ExceptionOr<String> query_command_value(FlyString const& command); WebIDL::ExceptionOr<String> query_command_value(FlyString const& command);
WebIDL::ExceptionOr<GC::Ref<XPath::XPathExpression>> create_expression(String const& expression, GC::Ptr<XPath::XPathNSResolver> resolver = nullptr); WebIDL::ExceptionOr<GC::Ref<XPath::XPathExpression>> create_expression(String const& expression, GC::Ptr<XPath::XPathNSResolver> resolver = nullptr);
WebIDL::ExceptionOr<GC::Ref<XPath::XPathResult>> evaluate(String const& expression, const DOM::Node& context_node, GC::Ptr<XPath::XPathNSResolver> resolver = nullptr, WebIDL::UnsignedShort type = 0, GC::Ptr<XPath::XPathResult> result = nullptr); WebIDL::ExceptionOr<GC::Ref<XPath::XPathResult>> evaluate(String const& expression, DOM::Node const& context_node, GC::Ptr<XPath::XPathNSResolver> resolver = nullptr, WebIDL::UnsignedShort type = 0, GC::Ptr<XPath::XPathResult> result = nullptr);
GC::Ref<DOM::Node> create_ns_resolver(GC::Ref<DOM::Node> node_resolver); // legacy GC::Ref<DOM::Node> create_ns_resolver(GC::Ref<DOM::Node> node_resolver); // legacy
// https://w3c.github.io/selection-api/#dfn-has-scheduled-selectionchange-event // https://w3c.github.io/selection-api/#dfn-has-scheduled-selectionchange-event
@ -924,7 +924,7 @@ public:
void schedule_ancestors_style_invalidation_due_to_presence_of_has(Node& node) void schedule_ancestors_style_invalidation_due_to_presence_of_has(Node& node)
{ {
m_pending_nodes_for_style_invalidation_due_to_presence_of_has.set(node.make_weak_ptr<Node>()); m_pending_nodes_for_style_invalidation_due_to_presence_of_has.set(node);
} }
ElementByIdMap& element_by_id() const; ElementByIdMap& element_by_id() const;
@ -1117,7 +1117,7 @@ private:
// Used by evaluate_media_queries_and_report_changes(). // Used by evaluate_media_queries_and_report_changes().
bool m_needs_media_query_evaluation { false }; bool m_needs_media_query_evaluation { false };
Vector<WeakPtr<CSS::MediaQueryList>> m_media_query_lists; Vector<GC::Weak<CSS::MediaQueryList>> m_media_query_lists;
bool m_needs_full_style_update { false }; bool m_needs_full_style_update { false };
bool m_needs_full_layout_tree_update { false }; bool m_needs_full_layout_tree_update { false };
@ -1280,8 +1280,8 @@ private:
RefPtr<Core::Timer> m_cursor_blink_timer; RefPtr<Core::Timer> m_cursor_blink_timer;
bool m_cursor_blink_state { false }; bool m_cursor_blink_state { false };
// NOTE: This is WeakPtr, not GCPtr, on purpose. We don't want the document to keep some old detached navigable alive. // NOTE: This is GC::Weak, not GC::Ptr, on purpose. We don't want the document to keep some old detached navigable alive.
WeakPtr<HTML::Navigable> m_cached_navigable; GC::Weak<HTML::Navigable> m_cached_navigable;
bool m_enable_cookies_on_file_domains { false }; bool m_enable_cookies_on_file_domains { false };
@ -1333,7 +1333,7 @@ private:
// https://drafts.csswg.org/css-view-transitions-1/#document-update-callback-queue // https://drafts.csswg.org/css-view-transitions-1/#document-update-callback-queue
Vector<GC::Ptr<ViewTransition::ViewTransition>> m_update_callback_queue = {}; Vector<GC::Ptr<ViewTransition::ViewTransition>> m_update_callback_queue = {};
HashTable<WeakPtr<Node>> m_pending_nodes_for_style_invalidation_due_to_presence_of_has; HashTable<GC::Weak<Node>> m_pending_nodes_for_style_invalidation_due_to_presence_of_has;
GC::Ref<StyleInvalidator> m_style_invalidator; GC::Ref<StyleInvalidator> m_style_invalidator;

View file

@ -541,7 +541,7 @@ GC::Ptr<DOM::Element> Element::get_the_attribute_associated_element(FlyString co
} }
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#attr-associated-elements // https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#attr-associated-elements
Optional<GC::RootVector<GC::Ref<DOM::Element>>> Element::get_the_attribute_associated_elements(FlyString const& content_attribute, Optional<Vector<WeakPtr<DOM::Element>>> const& explicitly_set_attribute_elements) const Optional<GC::RootVector<GC::Ref<DOM::Element>>> Element::get_the_attribute_associated_elements(FlyString const& content_attribute, Optional<Vector<GC::Weak<DOM::Element>>> const& explicitly_set_attribute_elements) const
{ {
// 1. Let elements be an empty list. // 1. Let elements be an empty list.
GC::RootVector<GC::Ref<DOM::Element>> elements(heap()); GC::RootVector<GC::Ref<DOM::Element>> elements(heap());

View file

@ -173,7 +173,7 @@ public:
GC::Ptr<Attr> get_attribute_node_ns(Optional<FlyString> const& namespace_, FlyString const& name) const; GC::Ptr<Attr> get_attribute_node_ns(Optional<FlyString> const& namespace_, FlyString const& name) const;
GC::Ptr<DOM::Element> get_the_attribute_associated_element(FlyString const& content_attribute, GC::Ptr<DOM::Element> explicitly_set_attribute_element) const; GC::Ptr<DOM::Element> get_the_attribute_associated_element(FlyString const& content_attribute, GC::Ptr<DOM::Element> explicitly_set_attribute_element) const;
Optional<GC::RootVector<GC::Ref<DOM::Element>>> get_the_attribute_associated_elements(FlyString const& content_attribute, Optional<Vector<WeakPtr<DOM::Element>>> const& explicitly_set_attribute_elements) const; Optional<GC::RootVector<GC::Ref<DOM::Element>>> get_the_attribute_associated_elements(FlyString const& content_attribute, Optional<Vector<GC::Weak<DOM::Element>>> const& explicitly_set_attribute_elements) const;
DOMTokenList* class_list(); DOMTokenList* class_list();

View file

@ -10,17 +10,17 @@ namespace Web::DOM {
void ElementByIdMap::add(FlyString const& element_id, Element& element) void ElementByIdMap::add(FlyString const& element_id, Element& element)
{ {
auto& elements_with_id = m_map.ensure(element_id, [] { return Vector<WeakPtr<Element>> {}; }); auto& elements_with_id = m_map.ensure(element_id, [] { return Vector<GC::Weak<Element>> {}; });
// Remove all elements that were deallocated. // Remove all elements that were deallocated.
elements_with_id.remove_all_matching([](WeakPtr<Element>& element) { elements_with_id.remove_all_matching([](GC::Weak<Element>& element) {
return !element.has_value(); return !element;
}); });
elements_with_id.remove_first_matching([&](auto const& another_element) { elements_with_id.remove_first_matching([&](auto const& another_element) {
return &element == another_element.ptr(); return &element == another_element.ptr();
}); });
elements_with_id.insert_before_matching(element, [&](auto& another_element) { elements_with_id.insert_before_matching(GC::Weak<Element> { element }, [&](auto& another_element) {
return element.is_before(*another_element); return element.is_before(*another_element);
}); });
} }
@ -32,7 +32,7 @@ void ElementByIdMap::remove(FlyString const& element_id, Element& element)
return; return;
auto& elements_with_id = *maybe_elements_with_id; auto& elements_with_id = *maybe_elements_with_id;
elements_with_id.remove_all_matching([&](auto& another_element) { elements_with_id.remove_all_matching([&](auto& another_element) {
if (!another_element.has_value()) if (!another_element)
return true; return true;
return &element == another_element.ptr(); return &element == another_element.ptr();
}); });

View file

@ -18,7 +18,7 @@ public:
GC::Ptr<Element> get(FlyString const& element_id) const; GC::Ptr<Element> get(FlyString const& element_id) const;
private: private:
HashMap<FlyString, Vector<WeakPtr<Element>>> m_map; HashMap<FlyString, Vector<GC::Weak<Element>>> m_map;
}; };
} }

View file

@ -97,7 +97,7 @@ WebIDL::ExceptionOr<void> MutationObserver::observe(Node& target, MutationObserv
// 1. For each node of thiss node list, remove all transient registered observers whose source is registered from nodes registered observer list. // 1. For each node of thiss node list, remove all transient registered observers whose source is registered from nodes registered observer list.
for (auto& node : m_node_list) { for (auto& node : m_node_list) {
// FIXME: Is this correct? // FIXME: Is this correct?
if (node.is_null()) if (!node)
continue; continue;
if (node->registered_observer_list()) { if (node->registered_observer_list()) {
@ -120,7 +120,7 @@ WebIDL::ExceptionOr<void> MutationObserver::observe(Node& target, MutationObserv
target.add_registered_observer(new_registered_observer); target.add_registered_observer(new_registered_observer);
// 2. Append target to thiss node list. // 2. Append target to thiss node list.
m_node_list.append(target.make_weak_ptr<Node>()); m_node_list.append(target);
} }
return {}; return {};
@ -132,7 +132,7 @@ void MutationObserver::disconnect()
// 1. For each node of thiss node list, remove any registered observer from nodes registered observer list for which this is the observer. // 1. For each node of thiss node list, remove any registered observer from nodes registered observer list for which this is the observer.
for (auto& node : m_node_list) { for (auto& node : m_node_list) {
// FIXME: Is this correct? // FIXME: Is this correct?
if (node.is_null()) if (!node)
continue; continue;
if (node->registered_observer_list()) { if (node->registered_observer_list()) {

View file

@ -38,8 +38,8 @@ public:
void disconnect(); void disconnect();
Vector<GC::Root<MutationRecord>> take_records(); Vector<GC::Root<MutationRecord>> take_records();
Vector<WeakPtr<Node>>& node_list() { return m_node_list; } Vector<GC::Weak<Node>>& node_list() { return m_node_list; }
Vector<WeakPtr<Node>> const& node_list() const { return m_node_list; } Vector<GC::Weak<Node>> const& node_list() const { return m_node_list; }
WebIDL::CallbackType& callback() { return *m_callback; } WebIDL::CallbackType& callback() { return *m_callback; }
@ -61,7 +61,7 @@ private:
// https://dom.spec.whatwg.org/#mutationobserver-node-list // https://dom.spec.whatwg.org/#mutationobserver-node-list
// NOTE: These are weak, per https://dom.spec.whatwg.org/#garbage-collection // NOTE: These are weak, per https://dom.spec.whatwg.org/#garbage-collection
// Registered observers in a nodes registered observer list have a weak reference to the node. // Registered observers in a nodes registered observer list have a weak reference to the node.
Vector<WeakPtr<Node>> m_node_list; Vector<GC::Weak<Node>> m_node_list;
// https://dom.spec.whatwg.org/#concept-mo-queue // https://dom.spec.whatwg.org/#concept-mo-queue
Vector<GC::Ref<MutationRecord>> m_record_queue; Vector<GC::Ref<MutationRecord>> m_record_queue;

View file

@ -8,9 +8,9 @@
#include <AK/Function.h> #include <AK/Function.h>
#include <AK/Noncopyable.h> #include <AK/Noncopyable.h>
#include <AK/WeakPtr.h>
#include <LibCore/Forward.h> #include <LibCore/Forward.h>
#include <LibGC/Ptr.h> #include <LibGC/Ptr.h>
#include <LibGC/Weak.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
#include <LibWeb/Export.h> #include <LibWeb/Export.h>
#include <LibWeb/HTML/EventLoop/TaskQueue.h> #include <LibWeb/HTML/EventLoop/TaskQueue.h>
@ -119,7 +119,7 @@ private:
// https://html.spec.whatwg.org/multipage/webappapis.html#performing-a-microtask-checkpoint // https://html.spec.whatwg.org/multipage/webappapis.html#performing-a-microtask-checkpoint
bool m_performing_a_microtask_checkpoint { false }; bool m_performing_a_microtask_checkpoint { false };
Vector<WeakPtr<DOM::Document>> m_documents; Vector<GC::Weak<DOM::Document>> m_documents;
// Used to implement step 4 of "perform a microtask checkpoint". // Used to implement step 4 of "perform a microtask checkpoint".
// NOTE: These are weak references! ESO registers and unregisters itself from the event loop manually. // NOTE: These are weak references! ESO registers and unregisters itself from the event loop manually.

View file

@ -8,7 +8,7 @@
#pragma once #pragma once
#include <AK/String.h> #include <AK/String.h>
#include <AK/WeakPtr.h> #include <LibGC/Weak.h>
#include <LibWeb/Bindings/HTMLFormElementPrototype.h> #include <LibWeb/Bindings/HTMLFormElementPrototype.h>
#include <LibWeb/DOM/InputEventsTarget.h> #include <LibWeb/DOM/InputEventsTarget.h>
#include <LibWeb/Export.h> #include <LibWeb/Export.h>
@ -178,7 +178,7 @@ protected:
private: private:
void reset_form_owner(); void reset_form_owner();
WeakPtr<HTMLFormElement> m_form; GC::Weak<HTMLFormElement> m_form;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#parser-inserted-flag // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#parser-inserted-flag
bool m_parser_inserted { false }; bool m_parser_inserted { false };

View file

@ -380,7 +380,7 @@ static void show_the_picker_if_applicable(HTMLInputElement& element)
// 2. Wait for the user to have made their selection. // 2. Wait for the user to have made their selection.
auto accepted_file_types = element.parse_accept_attribute(); auto accepted_file_types = element.parse_accept_attribute();
auto allow_multiple_files = element.has_attribute(HTML::AttributeNames::multiple) ? AllowMultipleFiles::Yes : AllowMultipleFiles::No; auto allow_multiple_files = element.has_attribute(HTML::AttributeNames::multiple) ? AllowMultipleFiles::Yes : AllowMultipleFiles::No;
auto weak_element = element.make_weak_ptr<HTMLInputElement>(); auto weak_element = GC::Weak<HTMLInputElement> { element };
element.set_is_open(true); element.set_is_open(true);
element.document().browsing_context()->top_level_browsing_context()->page().did_request_file_picker(weak_element, accepted_file_types, allow_multiple_files); element.document().browsing_context()->top_level_browsing_context()->page().did_request_file_picker(weak_element, accepted_file_types, allow_multiple_files);
@ -404,7 +404,7 @@ static void show_the_picker_if_applicable(HTMLInputElement& element)
// events, or a cancel event.) // events, or a cancel event.)
else { else {
if (element.type_state() == HTMLInputElement::TypeAttributeState::Color) { if (element.type_state() == HTMLInputElement::TypeAttributeState::Color) {
auto weak_element = element.make_weak_ptr<HTMLInputElement>(); auto weak_element = GC::Weak<HTMLInputElement> { element };
element.set_is_open(true); element.set_is_open(true);
element.document().browsing_context()->top_level_browsing_context()->page().did_request_color_picker(weak_element, Color::from_utf16_string(element.value()).value_or(Color(0, 0, 0))); element.document().browsing_context()->top_level_browsing_context()->page().did_request_color_picker(weak_element, Color::from_utf16_string(element.value()).value_or(Color(0, 0, 0)));
} }

View file

@ -570,7 +570,7 @@ bool HTMLLinkElement::stylesheet_linked_resource_fetch_setup_steps(Fetch::Infras
void HTMLLinkElement::set_parser_document(Badge<HTMLParser>, GC::Ref<DOM::Document> document) void HTMLLinkElement::set_parser_document(Badge<HTMLParser>, GC::Ref<DOM::Document> document)
{ {
m_parser_document = document->make_weak_ptr<DOM::Document>(); m_parser_document = document;
} }
bool HTMLLinkElement::is_implicitly_potentially_render_blocking() const bool HTMLLinkElement::is_implicitly_potentially_render_blocking() const

View file

@ -167,7 +167,7 @@ private:
Optional<String> m_mime_type; Optional<String> m_mime_type;
WeakPtr<DOM::Document> m_parser_document; GC::Weak<DOM::Document> m_parser_document;
}; };
} }

View file

@ -480,7 +480,7 @@ void HTMLSelectElement::show_the_picker_if_applicable()
} }
// Request select dropdown // Request select dropdown
auto weak_element = make_weak_ptr<HTMLSelectElement>(); auto weak_element = GC::Weak<HTMLSelectElement> { *this };
auto rect = get_bounding_client_rect(); auto rect = get_bounding_client_rect();
auto position = document().navigable()->to_top_level_position(Web::CSSPixelPoint { rect.x(), rect.bottom() }); auto position = document().navigable()->to_top_level_position(Web::CSSPixelPoint { rect.x(), rect.bottom() });
document().page().did_request_select_dropdown(weak_element, position, rect.width(), m_select_items); document().page().did_request_select_dropdown(weak_element, position, rect.width(), m_select_items);

View file

@ -31,10 +31,10 @@ GC_DEFINE_ALLOCATOR(HTMLTextAreaElement);
HTMLTextAreaElement::HTMLTextAreaElement(DOM::Document& document, DOM::QualifiedName qualified_name) HTMLTextAreaElement::HTMLTextAreaElement(DOM::Document& document, DOM::QualifiedName qualified_name)
: HTMLElement(document, move(qualified_name)) : HTMLElement(document, move(qualified_name))
, m_input_event_timer(Core::Timer::create_single_shot(0, [weak_this = make_weak_ptr()]() { , m_input_event_timer(Core::Timer::create_single_shot(0, [weak_this = GC::Weak<HTMLTextAreaElement> { *this }]() {
if (!weak_this) if (!weak_this)
return; return;
static_cast<HTMLTextAreaElement*>(weak_this.ptr())->queue_firing_input_event(); weak_this->queue_firing_input_event();
})) }))
{ {
} }

View file

@ -51,8 +51,7 @@ struct PaintConfig {
}; };
// https://html.spec.whatwg.org/multipage/document-sequences.html#navigable // https://html.spec.whatwg.org/multipage/document-sequences.html#navigable
class WEB_API Navigable : public JS::Cell class WEB_API Navigable : public JS::Cell {
, public Weakable<Navigable> {
GC_CELL(Navigable, JS::Cell); GC_CELL(Navigable, JS::Cell);
GC_DECLARE_ALLOCATOR(Navigable); GC_DECLARE_ALLOCATOR(Navigable);

View file

@ -298,7 +298,7 @@ CSSPixelRect IntersectionObserver::root_intersection_rectangle() const
} else { } else {
document = &intersection_root.get<GC::Root<DOM::Element>>().cell()->document(); document = &intersection_root.get<GC::Root<DOM::Element>>().cell()->document();
} }
if (m_document.has_value() && document->origin().is_same_origin(m_document->origin())) { if (m_document && document->origin().is_same_origin(m_document->origin())) {
if (auto layout_node = intersection_root.visit([&](auto& node) -> GC::Ptr<Layout::Node> { return node->layout_node(); })) { if (auto layout_node = intersection_root.visit([&](auto& node) -> GC::Ptr<Layout::Node> { return node->layout_node(); })) {
rect.inflate( rect.inflate(
m_root_margin[0].to_px(*layout_node, rect.height()), m_root_margin[0].to_px(*layout_node, rect.height()),

View file

@ -106,7 +106,7 @@ private:
Vector<GC::Ref<DOM::Element>> m_observation_targets; Vector<GC::Ref<DOM::Element>> m_observation_targets;
// AD-HOC: This is the document where we've registered the IntersectionObserver. // AD-HOC: This is the document where we've registered the IntersectionObserver.
WeakPtr<DOM::Document> m_document; GC::Weak<DOM::Document> m_document;
}; };
} }

View file

@ -86,7 +86,7 @@ private:
NonnullOwnPtr<DragAndDropEventHandler> m_drag_and_drop_event_handler; NonnullOwnPtr<DragAndDropEventHandler> m_drag_and_drop_event_handler;
WeakPtr<DOM::EventTarget> m_mousedown_target; GC::Weak<DOM::EventTarget> m_mousedown_target;
Optional<CSSPixelPoint> m_mousemove_previous_screen_position; Optional<CSSPixelPoint> m_mousemove_previous_screen_position;

View file

@ -68,7 +68,7 @@ void Page::set_focused_navigable(Badge<EventHandler>, HTML::Navigable& navigable
void Page::navigable_document_destroyed(Badge<DOM::Document>, HTML::Navigable& navigable) void Page::navigable_document_destroyed(Badge<DOM::Document>, HTML::Navigable& navigable)
{ {
if (&navigable == m_focused_navigable.ptr()) if (&navigable == m_focused_navigable.ptr())
m_focused_navigable.clear(); m_focused_navigable = nullptr;
} }
void Page::load(URL::URL const& url) void Page::load(URL::URL const& url)
@ -405,7 +405,7 @@ void Page::on_pending_dialog_closed()
} }
} }
void Page::did_request_color_picker(WeakPtr<HTML::HTMLInputElement> target, Color current_color) void Page::did_request_color_picker(GC::Weak<HTML::HTMLInputElement> target, Color current_color)
{ {
if (m_pending_non_blocking_dialog == PendingNonBlockingDialog::None) { if (m_pending_non_blocking_dialog == PendingNonBlockingDialog::None) {
m_pending_non_blocking_dialog = PendingNonBlockingDialog::ColorPicker; m_pending_non_blocking_dialog = PendingNonBlockingDialog::ColorPicker;
@ -425,12 +425,12 @@ void Page::color_picker_update(Optional<Color> picked_color, HTML::ColorPickerUp
auto& input_element = as<HTML::HTMLInputElement>(*m_pending_non_blocking_dialog_target); auto& input_element = as<HTML::HTMLInputElement>(*m_pending_non_blocking_dialog_target);
input_element.did_pick_color(move(picked_color), state); input_element.did_pick_color(move(picked_color), state);
if (state == HTML::ColorPickerUpdateState::Closed) if (state == HTML::ColorPickerUpdateState::Closed)
m_pending_non_blocking_dialog_target.clear(); m_pending_non_blocking_dialog_target = nullptr;
} }
} }
} }
void Page::did_request_file_picker(WeakPtr<HTML::HTMLInputElement> target, HTML::FileFilter const& accepted_file_types, HTML::AllowMultipleFiles allow_multiple_files) void Page::did_request_file_picker(GC::Weak<HTML::HTMLInputElement> target, HTML::FileFilter const& accepted_file_types, HTML::AllowMultipleFiles allow_multiple_files)
{ {
if (m_pending_non_blocking_dialog == PendingNonBlockingDialog::None) { if (m_pending_non_blocking_dialog == PendingNonBlockingDialog::None) {
m_pending_non_blocking_dialog = PendingNonBlockingDialog::FilePicker; m_pending_non_blocking_dialog = PendingNonBlockingDialog::FilePicker;
@ -449,12 +449,12 @@ void Page::file_picker_closed(Span<HTML::SelectedFile> selected_files)
auto& input_element = as<HTML::HTMLInputElement>(*m_pending_non_blocking_dialog_target); auto& input_element = as<HTML::HTMLInputElement>(*m_pending_non_blocking_dialog_target);
input_element.did_select_files(selected_files); input_element.did_select_files(selected_files);
m_pending_non_blocking_dialog_target.clear(); m_pending_non_blocking_dialog_target = nullptr;
} }
} }
} }
void Page::did_request_select_dropdown(WeakPtr<HTML::HTMLSelectElement> target, Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items) void Page::did_request_select_dropdown(GC::Weak<HTML::HTMLSelectElement> target, Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items)
{ {
if (m_pending_non_blocking_dialog == PendingNonBlockingDialog::None) { if (m_pending_non_blocking_dialog == PendingNonBlockingDialog::None) {
m_pending_non_blocking_dialog = PendingNonBlockingDialog::Select; m_pending_non_blocking_dialog = PendingNonBlockingDialog::Select;
@ -471,7 +471,7 @@ void Page::select_dropdown_closed(Optional<u32> const& selected_item_id)
if (m_pending_non_blocking_dialog_target) { if (m_pending_non_blocking_dialog_target) {
auto& select_element = as<HTML::HTMLSelectElement>(*m_pending_non_blocking_dialog_target); auto& select_element = as<HTML::HTMLSelectElement>(*m_pending_non_blocking_dialog_target);
select_element.did_select_item(selected_item_id); select_element.did_select_item(selected_item_id);
m_pending_non_blocking_dialog_target.clear(); m_pending_non_blocking_dialog_target = nullptr;
} }
} }
} }

View file

@ -9,8 +9,8 @@
#pragma once #pragma once
#include <AK/WeakPtr.h>
#include <LibGC/Root.h> #include <LibGC/Root.h>
#include <LibGC/Weak.h>
#include <LibGfx/Cursor.h> #include <LibGfx/Cursor.h>
#include <LibGfx/Forward.h> #include <LibGfx/Forward.h>
#include <LibGfx/Palette.h> #include <LibGfx/Palette.h>
@ -159,13 +159,13 @@ public:
void dismiss_dialog(GC::Ref<GC::Function<void()>> on_dialog_closed); void dismiss_dialog(GC::Ref<GC::Function<void()>> on_dialog_closed);
void accept_dialog(GC::Ref<GC::Function<void()>> on_dialog_closed); void accept_dialog(GC::Ref<GC::Function<void()>> on_dialog_closed);
void did_request_color_picker(WeakPtr<HTML::HTMLInputElement> target, Color current_color); void did_request_color_picker(GC::Weak<HTML::HTMLInputElement> target, Color current_color);
void color_picker_update(Optional<Color> picked_color, HTML::ColorPickerUpdateState state); void color_picker_update(Optional<Color> picked_color, HTML::ColorPickerUpdateState state);
void did_request_file_picker(WeakPtr<HTML::HTMLInputElement> target, HTML::FileFilter const& accepted_file_types, HTML::AllowMultipleFiles); void did_request_file_picker(GC::Weak<HTML::HTMLInputElement> target, HTML::FileFilter const& accepted_file_types, HTML::AllowMultipleFiles);
void file_picker_closed(Span<HTML::SelectedFile> selected_files); void file_picker_closed(Span<HTML::SelectedFile> selected_files);
void did_request_select_dropdown(WeakPtr<HTML::HTMLSelectElement> target, Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items); void did_request_select_dropdown(GC::Weak<HTML::HTMLSelectElement> target, Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items);
void select_dropdown_closed(Optional<u32> const& selected_item_id); void select_dropdown_closed(Optional<u32> const& selected_item_id);
using ClipboardRequest = GC::Ref<GC::Function<void(Vector<Clipboard::SystemClipboardItem>)>>; using ClipboardRequest = GC::Ref<GC::Function<void(Vector<Clipboard::SystemClipboardItem>)>>;
@ -246,7 +246,7 @@ private:
GC::Ref<PageClient> m_client; GC::Ref<PageClient> m_client;
WeakPtr<HTML::Navigable> m_focused_navigable; GC::Weak<HTML::Navigable> m_focused_navigable;
GC::Ptr<HTML::TraversableNavigable> m_top_level_traversable; GC::Ptr<HTML::TraversableNavigable> m_top_level_traversable;
@ -275,7 +275,7 @@ private:
GC::Ptr<GC::Function<void()>> m_on_pending_dialog_closed; GC::Ptr<GC::Function<void()>> m_on_pending_dialog_closed;
PendingNonBlockingDialog m_pending_non_blocking_dialog { PendingNonBlockingDialog::None }; PendingNonBlockingDialog m_pending_non_blocking_dialog { PendingNonBlockingDialog::None };
WeakPtr<HTML::HTMLElement> m_pending_non_blocking_dialog_target; GC::Weak<HTML::HTMLElement> m_pending_non_blocking_dialog_target;
HashMap<u64, ClipboardRequest> m_pending_clipboard_requests; HashMap<u64, ClipboardRequest> m_pending_clipboard_requests;
u64 m_next_clipboard_request_id { 0 }; u64 m_next_clipboard_request_id { 0 };

View file

@ -25,8 +25,7 @@ namespace Web::Painting {
WEB_API void set_paint_viewport_scrollbars(bool enabled); WEB_API void set_paint_viewport_scrollbars(bool enabled);
class WEB_API PaintableBox : public Paintable class WEB_API PaintableBox : public Paintable {
, public Weakable<PaintableBox> {
GC_CELL(PaintableBox, Paintable); GC_CELL(PaintableBox, Paintable);
public: public:

View file

@ -6,7 +6,7 @@
#pragma once #pragma once
#include <AK/WeakPtr.h> #include <LibGC/Weak.h>
#include <LibWeb/Forward.h> #include <LibWeb/Forward.h>
#include <LibWeb/PixelUnits.h> #include <LibWeb/PixelUnits.h>
@ -40,7 +40,7 @@ public:
} }
private: private:
WeakPtr<PaintableBox> m_paintable_box; GC::Weak<PaintableBox> m_paintable_box;
size_t m_id { 0 }; size_t m_id { 0 };
bool m_sticky { false }; bool m_sticky { false };
RefPtr<ScrollFrame const> m_parent; RefPtr<ScrollFrame const> m_parent;

View file

@ -52,7 +52,7 @@ private:
Vector<GC::Ref<ResizeObservation>> m_skipped_targets; Vector<GC::Ref<ResizeObservation>> m_skipped_targets;
// AD-HOC: This is the document where we've registered the observer. // AD-HOC: This is the document where we've registered the observer.
WeakPtr<DOM::Document> m_document; GC::Weak<DOM::Document> m_document;
IntrusiveListNode<ResizeObserver> m_list_node; IntrusiveListNode<ResizeObserver> m_list_node;

View file

@ -218,25 +218,25 @@ ErrorOr<void> WebSocket::establish_web_socket_connection(URL::URL const& url_rec
m_websocket = request_client->websocket_connect(url_record, origin_string, protocol_byte_strings, {}, additional_headers); m_websocket = request_client->websocket_connect(url_record, origin_string, protocol_byte_strings, {}, additional_headers);
m_websocket->on_open = [weak_this = make_weak_ptr<WebSocket>()] { m_websocket->on_open = [weak_this = GC::Weak { *this }] {
if (!weak_this) if (!weak_this)
return; return;
auto& websocket = const_cast<WebSocket&>(*weak_this); auto& websocket = const_cast<WebSocket&>(*weak_this);
websocket.on_open(); websocket.on_open();
}; };
m_websocket->on_message = [weak_this = make_weak_ptr<WebSocket>()](auto message) { m_websocket->on_message = [weak_this = GC::Weak { *this }](auto message) {
if (!weak_this) if (!weak_this)
return; return;
auto& websocket = const_cast<WebSocket&>(*weak_this); auto& websocket = const_cast<WebSocket&>(*weak_this);
websocket.on_message(move(message.data), message.is_text); websocket.on_message(move(message.data), message.is_text);
}; };
m_websocket->on_close = [weak_this = make_weak_ptr<WebSocket>()](auto code, auto reason, bool was_clean) { m_websocket->on_close = [weak_this = GC::Weak { *this }](auto code, auto reason, bool was_clean) {
if (!weak_this) if (!weak_this)
return; return;
auto& websocket = const_cast<WebSocket&>(*weak_this); auto& websocket = const_cast<WebSocket&>(*weak_this);
websocket.on_close(code, String::from_byte_string(reason).release_value_but_fixme_should_propagate_errors(), was_clean); websocket.on_close(code, String::from_byte_string(reason).release_value_but_fixme_should_propagate_errors(), was_clean);
}; };
m_websocket->on_error = [weak_this = make_weak_ptr<WebSocket>()](auto) { m_websocket->on_error = [weak_this = GC::Weak { *this }](auto) {
if (!weak_this) if (!weak_this)
return; return;
auto& websocket = const_cast<WebSocket&>(*weak_this); auto& websocket = const_cast<WebSocket&>(*weak_this);

View file

@ -4471,7 +4471,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@)
// 1. Append a weak reference to element to elements. // 1. Append a weak reference to element to elements.
// 5. Set this's explicitly set attr-elements to elements. // 5. Set this's explicitly set attr-elements to elements.
attribute_generator.append(R"~~~( attribute_generator.append(R"~~~(
Vector<WeakPtr<DOM::Element>> elements; Vector<GC::Weak<DOM::Element>> elements;
elements.ensure_capacity(cpp_value->size()); elements.ensure_capacity(cpp_value->size());
for (auto const& element : *cpp_value) { for (auto const& element : *cpp_value) {