mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibWeb: Visit custom element's lifecycle callbacks
...instead of using JS::Handle which causes leaks when object holding the callback can be reached by visiting the callback's dependencies.
This commit is contained in:
parent
3d48c55e50
commit
3b4230e0b0
Notes:
sideshowbarker
2024-07-18 03:20:18 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/3b4230e0b0 Pull-request: https://github.com/SerenityOS/serenity/pull/23553
5 changed files with 26 additions and 5 deletions
|
@ -250,6 +250,7 @@ set(SOURCES
|
|||
HTML/CORSSettingAttribute.cpp
|
||||
HTML/CrossOrigin/AbstractOperations.cpp
|
||||
HTML/CrossOrigin/Reporting.cpp
|
||||
HTML/CustomElements/CustomElementDefinition.cpp
|
||||
HTML/CustomElements/CustomElementName.cpp
|
||||
HTML/CustomElements/CustomElementReactionNames.cpp
|
||||
HTML/CustomElements/CustomElementRegistry.cpp
|
||||
|
|
|
@ -1910,7 +1910,7 @@ void Element::enqueue_a_custom_element_callback_reaction(FlyString const& callba
|
|||
if (callback_iterator == definition->lifecycle_callbacks().end())
|
||||
return;
|
||||
|
||||
if (callback_iterator->value.is_null())
|
||||
if (!callback_iterator->value)
|
||||
return;
|
||||
|
||||
// 4. If callbackName is "attributeChangedCallback", then:
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/HTML/CustomElements/CustomElementDefinition.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
void CustomElementDefinition::visit_edges(Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
for (auto& callback : m_lifecycle_callbacks)
|
||||
visitor.visit(callback.value);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,7 @@ class CustomElementDefinition : public JS::Cell {
|
|||
JS_CELL(CustomElementDefinition, JS::Cell);
|
||||
JS_DECLARE_ALLOCATOR(CustomElementDefinition);
|
||||
|
||||
using LifecycleCallbacksStorage = OrderedHashMap<FlyString, JS::Handle<WebIDL::CallbackType>>;
|
||||
using LifecycleCallbacksStorage = OrderedHashMap<FlyString, JS::GCPtr<WebIDL::CallbackType>>;
|
||||
using ConstructionStackStorage = Vector<Variant<JS::Handle<DOM::Element>, AlreadyConstructedCustomElementMarker>>;
|
||||
|
||||
static JS::NonnullGCPtr<CustomElementDefinition> create(JS::Realm& realm, String const& name, String const& local_name, WebIDL::CallbackType& constructor, Vector<String>&& observed_attributes, LifecycleCallbacksStorage&& lifecycle_callbacks, bool form_associated, bool disable_internals, bool disable_shadow)
|
||||
|
@ -60,6 +60,8 @@ private:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void visit_edges(Visitor& visitor) override;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/custom-elements.html#concept-custom-element-definition-name
|
||||
// A name
|
||||
// A valid custom element name
|
||||
|
|
|
@ -201,14 +201,14 @@ JS::ThrowCompletionOr<void> CustomElementRegistry::define(String const& name, We
|
|||
// 2. If callbackValue is not undefined, then set the value of the entry in lifecycleCallbacks with key callbackName to the result of converting callbackValue to the Web IDL Function callback type. Rethrow any exceptions from the conversion.
|
||||
if (!callback_value.is_undefined()) {
|
||||
auto callback = TRY(convert_value_to_callback_function(vm, callback_value));
|
||||
lifecycle_callbacks.set(callback_name, JS::make_handle(callback));
|
||||
lifecycle_callbacks.set(callback_name, callback);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. If the value of the entry in lifecycleCallbacks with key "attributeChangedCallback" is not null, then:
|
||||
auto attribute_changed_callback_iterator = lifecycle_callbacks.find(CustomElementReactionNames::attributeChangedCallback);
|
||||
VERIFY(attribute_changed_callback_iterator != lifecycle_callbacks.end());
|
||||
if (!attribute_changed_callback_iterator->value.is_null()) {
|
||||
if (attribute_changed_callback_iterator->value) {
|
||||
// 1. Let observedAttributesIterable be ? Get(constructor, "observedAttributes").
|
||||
auto observed_attributes_iterable = TRY(constructor->callback->get(JS::PropertyKey { "observedAttributes" }));
|
||||
|
||||
|
@ -253,7 +253,7 @@ JS::ThrowCompletionOr<void> CustomElementRegistry::define(String const& name, We
|
|||
|
||||
// 2. If callbackValue is not undefined, then set the value of the entry in lifecycleCallbacks with key callbackName to the result of converting callbackValue to the Web IDL Function callback type. Rethrow any exceptions from the conversion.
|
||||
if (!callback_value.is_undefined())
|
||||
lifecycle_callbacks.set(callback_name, JS::make_handle(TRY(convert_value_to_callback_function(vm, callback_value))));
|
||||
lifecycle_callbacks.set(callback_name, TRY(convert_value_to_callback_function(vm, callback_value)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue