From 64eeda6450b7ffc197c7994eaddfd39bd4938f59 Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Sat, 4 Jan 2025 23:12:55 +1300 Subject: [PATCH] LibWeb: Return a representation of an 'Agent' in 'relevant agent' This makes it more convenient to use the 'relvant agent' concept, instead of the awkward dynamic casts we needed to do for every call site. mutation_observers is also changed to hold a GC::Root instead of raw GC::Ptr. Somehow this was not causing problems before, but trips up CI after these changes. --- Libraries/LibWeb/Bindings/MainThreadVM.cpp | 21 ++++----- Libraries/LibWeb/Bindings/MainThreadVM.h | 44 +------------------ Libraries/LibWeb/CMakeLists.txt | 1 + Libraries/LibWeb/DOM/Document.cpp | 5 ++- Libraries/LibWeb/DOM/Element.cpp | 12 +++-- Libraries/LibWeb/DOM/MutationObserver.cpp | 7 ++- Libraries/LibWeb/Forward.h | 1 + .../CustomElementReactionsStack.h | 35 +++++++++++++++ Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp | 6 +-- Libraries/LibWeb/HTML/Parser/HTMLParser.cpp | 14 +++--- Libraries/LibWeb/HTML/Scripting/Agent.cpp | 21 +++++++++ Libraries/LibWeb/HTML/Scripting/Agent.h | 43 ++++++++++++++++++ .../LibWeb/HTML/Scripting/Environments.cpp | 14 ++---- .../LibWeb/HTML/Scripting/Environments.h | 1 - .../BindingsGenerator/IDLGenerators.cpp | 13 ++---- 15 files changed, 140 insertions(+), 98 deletions(-) create mode 100644 Libraries/LibWeb/HTML/CustomElements/CustomElementReactionsStack.h create mode 100644 Libraries/LibWeb/HTML/Scripting/Agent.cpp create mode 100644 Libraries/LibWeb/HTML/Scripting/Agent.h diff --git a/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Libraries/LibWeb/Bindings/MainThreadVM.cpp index b7b894dfe6f..fc5d6655ef0 100644 --- a/Libraries/LibWeb/Bindings/MainThreadVM.cpp +++ b/Libraries/LibWeb/Bindings/MainThreadVM.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,10 @@ ErrorOr initialize_main_thread_vm(HTML::EventLoop::Type type) VERIFY(!s_main_thread_vm); s_main_thread_vm = TRY(JS::VM::create(make())); + + auto& custom_data = verify_cast(*s_main_thread_vm->custom_data()); + custom_data.agent.event_loop = s_main_thread_vm->heap().allocate(type); + s_main_thread_vm->on_unimplemented_property_access = [](auto const& object, auto const& property_key) { dbgln("FIXME: Unimplemented IDL interface: '{}.{}'", object.class_name(), property_key.to_string()); }; @@ -100,9 +105,6 @@ ErrorOr initialize_main_thread_vm(HTML::EventLoop::Type type) // This avoids doing an exhaustive garbage collection on process exit. s_main_thread_vm->ref(); - auto& custom_data = verify_cast(*s_main_thread_vm->custom_data()); - custom_data.event_loop = s_main_thread_vm->heap().allocate(type); - // These strings could potentially live on the VM similar to CommonPropertyNames. DOM::MutationType::initialize_strings(); Editing::CommandNames::initialize_strings(); @@ -692,25 +694,24 @@ JS::VM& main_thread_vm() void queue_mutation_observer_microtask(DOM::Document const& document) { auto& vm = main_thread_vm(); - auto& custom_data = verify_cast(*vm.custom_data()); + auto& surrounding_agent = verify_cast(*vm.custom_data()).agent; // 1. If the surrounding agent’s mutation observer microtask queued is true, then return. - if (custom_data.mutation_observer_microtask_queued) + if (surrounding_agent.mutation_observer_microtask_queued) return; // 2. Set the surrounding agent’s mutation observer microtask queued to true. - custom_data.mutation_observer_microtask_queued = true; + surrounding_agent.mutation_observer_microtask_queued = true; // 3. Queue a microtask to notify mutation observers. // NOTE: This uses the implied document concept. In the case of mutation observers, it is always done in a node context, so document should be that node's document. - // FIXME: Is it safe to pass custom_data through? - HTML::queue_a_microtask(&document, GC::create_function(vm.heap(), [&custom_data, &heap = document.heap()]() { + HTML::queue_a_microtask(&document, GC::create_function(vm.heap(), [&surrounding_agent, &heap = document.heap()]() { // 1. Set the surrounding agent’s mutation observer microtask queued to false. - custom_data.mutation_observer_microtask_queued = false; + surrounding_agent.mutation_observer_microtask_queued = false; // 2. Let notifySet be a clone of the surrounding agent’s mutation observers. GC::RootVector notify_set(heap); - for (auto& observer : custom_data.mutation_observers) + for (auto& observer : surrounding_agent.mutation_observers) notify_set.append(observer); // FIXME: 3. Let signalSet be a clone of the surrounding agent’s signal slots. diff --git a/Libraries/LibWeb/Bindings/MainThreadVM.h b/Libraries/LibWeb/Bindings/MainThreadVM.h index 97ca4ca133b..bc46a89fd66 100644 --- a/Libraries/LibWeb/Bindings/MainThreadVM.h +++ b/Libraries/LibWeb/Bindings/MainThreadVM.h @@ -13,56 +13,16 @@ #include #include #include +#include namespace Web::Bindings { -// https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions-stack -struct CustomElementReactionsStack { - CustomElementReactionsStack() = default; - ~CustomElementReactionsStack() = default; - - // https://html.spec.whatwg.org/multipage/custom-elements.html#element-queue - // Each item in the stack is an element queue, which is initially empty as well. Each item in an element queue is an element. - // (The elements are not necessarily custom yet, since this queue is used for upgrades as well.) - Vector>> element_queue_stack; - - // https://html.spec.whatwg.org/multipage/custom-elements.html#backup-element-queue - // Each custom element reactions stack has an associated backup element queue, which an initially-empty element queue. - Vector> backup_element_queue; - - // https://html.spec.whatwg.org/multipage/custom-elements.html#processing-the-backup-element-queue - // To prevent reentrancy when processing the backup element queue, each custom element reactions stack also has a processing the backup element queue flag, initially unset. - bool processing_the_backup_element_queue { false }; -}; - struct WebEngineCustomData final : public JS::VM::CustomData { virtual ~WebEngineCustomData() override = default; virtual void spin_event_loop_until(GC::Root> goal_condition) override; - GC::Root event_loop; - - // FIXME: These should only be on similar-origin window agents, but we don't currently differentiate agent types. - - // https://dom.spec.whatwg.org/#mutation-observer-compound-microtask-queued-flag - bool mutation_observer_microtask_queued { false }; - - // https://dom.spec.whatwg.org/#mutation-observer-list - // FIXME: This should be a set. - Vector> mutation_observers; - - GC::Root internal_realm; - - OwnPtr root_execution_context; - - // https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions-stack - // Each similar-origin window agent has a custom element reactions stack, which is initially empty. - CustomElementReactionsStack custom_element_reactions_stack {}; - - // https://html.spec.whatwg.org/multipage/custom-elements.html#current-element-queue - // A similar-origin window agent's current element queue is the element queue at the top of its custom element reactions stack. - Vector>& current_element_queue() { return custom_element_reactions_stack.element_queue_stack.last(); } - Vector> const& current_element_queue() const { return custom_element_reactions_stack.element_queue_stack.last(); } + HTML::Agent agent; }; struct WebEngineCustomJobCallbackData final : public JS::JobCallback::CustomData { diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 109bdc40524..5090decc633 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -462,6 +462,7 @@ set(SOURCES HTML/PotentialCORSRequest.cpp HTML/PromiseRejectionEvent.cpp HTML/RadioNodeList.cpp + HTML/Scripting/Agent.cpp HTML/Scripting/ClassicScript.cpp HTML/Scripting/Environments.cpp HTML/Scripting/EnvironmentSettingsSnapshot.cpp diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index feaf8926109..feea9def9b9 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -118,6 +118,7 @@ #include #include #include +#include #include #include #include @@ -3949,7 +3950,7 @@ void Document::unload(GC::Ptr) auto intend_to_store_in_bfcache = false; // 6. Let eventLoop be oldDocument's relevant agent's event loop. - auto& event_loop = *verify_cast(*HTML::relevant_agent(*this).custom_data()).event_loop; + auto& event_loop = *HTML::relevant_agent(*this).event_loop; // 7. Increase eventLoop's termination nesting level by 1. event_loop.increment_termination_nesting_level(); @@ -6096,7 +6097,7 @@ Document::StepsToFireBeforeunloadResult Document::steps_to_fire_beforeunload(boo m_unload_counter++; // 3. Increase document's relevant agent's event loop's termination nesting level by 1. - auto& event_loop = *verify_cast(*HTML::relevant_agent(*this).custom_data()).event_loop; + auto& event_loop = *HTML::relevant_agent(*this).event_loop; event_loop.increment_termination_nesting_level(); // 4. Let eventFiringResult be the result of firing an event named beforeunload at document's relevant global object, diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 1a77f1d8905..efe8ad47dff 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -2088,8 +2089,7 @@ void Element::enqueue_an_element_on_the_appropriate_element_queue() { // 1. Let reactionsStack be element's relevant agent's custom element reactions stack. auto& relevant_agent = HTML::relevant_agent(*this); - auto* custom_data = verify_cast(relevant_agent.custom_data()); - auto& reactions_stack = custom_data->custom_element_reactions_stack; + auto& reactions_stack = relevant_agent.custom_element_reactions_stack; // 2. If reactionsStack is empty, then: if (reactions_stack.element_queue_stack.is_empty()) { @@ -2105,10 +2105,8 @@ void Element::enqueue_an_element_on_the_appropriate_element_queue() // 4. Queue a microtask to perform the following steps: // NOTE: `this` is protected by GC::Function - HTML::queue_a_microtask(&document(), GC::create_function(relevant_agent.heap(), [this]() { - auto& relevant_agent = HTML::relevant_agent(*this); - auto* custom_data = verify_cast(relevant_agent.custom_data()); - auto& reactions_stack = custom_data->custom_element_reactions_stack; + HTML::queue_a_microtask(&document(), GC::create_function(heap(), [this]() { + auto& reactions_stack = HTML::relevant_agent(*this).custom_element_reactions_stack; // 1. Invoke custom element reactions in reactionsStack's backup element queue. Bindings::invoke_custom_element_reactions(reactions_stack.backup_element_queue); @@ -2121,7 +2119,7 @@ void Element::enqueue_an_element_on_the_appropriate_element_queue() } // 3. Otherwise, add element to element's relevant agent's current element queue. - custom_data->current_element_queue().append(*this); + relevant_agent.current_element_queue().append(*this); } // https://html.spec.whatwg.org/multipage/custom-elements.html#enqueue-a-custom-element-upgrade-reaction diff --git a/Libraries/LibWeb/DOM/MutationObserver.cpp b/Libraries/LibWeb/DOM/MutationObserver.cpp index 03a95aa830e..5393670ea59 100644 --- a/Libraries/LibWeb/DOM/MutationObserver.cpp +++ b/Libraries/LibWeb/DOM/MutationObserver.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace Web::DOM { @@ -29,14 +30,12 @@ MutationObserver::MutationObserver(JS::Realm& realm, GC::Ptr(realm.vm().custom_data()); - agent_custom_data->mutation_observers.append(*this); + HTML::relevant_agent(*this).mutation_observers.append(*this); } MutationObserver::~MutationObserver() { - auto* agent_custom_data = verify_cast(vm().custom_data()); - agent_custom_data->mutation_observers.remove_all_matching([this](auto& observer) { + HTML::relevant_agent(*this).mutation_observers.remove_all_matching([this](auto& observer) { return observer.ptr() == this; }); } diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 02dae80b457..07d6692fa9e 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -552,6 +552,7 @@ enum class AllowMultipleFiles; enum class MediaSeekMode; enum class SandboxingFlagSet; +struct Agent; struct EmbedderPolicy; struct Environment; struct EnvironmentSettingsObject; diff --git a/Libraries/LibWeb/HTML/CustomElements/CustomElementReactionsStack.h b/Libraries/LibWeb/HTML/CustomElements/CustomElementReactionsStack.h new file mode 100644 index 00000000000..92656cc6ecd --- /dev/null +++ b/Libraries/LibWeb/HTML/CustomElements/CustomElementReactionsStack.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-2023, Luke Wilde + * Copyright (c) 2025, Shannon Booth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions-stack +struct CustomElementReactionsStack { + CustomElementReactionsStack() = default; + ~CustomElementReactionsStack() = default; + + // https://html.spec.whatwg.org/multipage/custom-elements.html#element-queue + // Each item in the stack is an element queue, which is initially empty as well. Each item in an element queue is an element. + // (The elements are not necessarily custom yet, since this queue is used for upgrades as well.) + Vector>> element_queue_stack; + + // https://html.spec.whatwg.org/multipage/custom-elements.html#backup-element-queue + // Each custom element reactions stack has an associated backup element queue, which an initially-empty element queue. + Vector> backup_element_queue; + + // https://html.spec.whatwg.org/multipage/custom-elements.html#processing-the-backup-element-queue + // To prevent reentrancy when processing the backup element queue, each custom element reactions stack also has a processing the backup element queue flag, initially unset. + bool processing_the_backup_element_queue { false }; +}; + +} diff --git a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index 4a6d370f841..13cc1bca9b8 100644 --- a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +68,7 @@ void EventLoop::schedule() EventLoop& main_thread_event_loop() { - return *static_cast(Bindings::main_thread_vm().custom_data())->event_loop; + return *static_cast(Bindings::main_thread_vm().custom_data())->agent.event_loop; } // https://html.spec.whatwg.org/multipage/webappapis.html#spin-the-event-loop @@ -460,8 +461,7 @@ TaskID queue_a_task(HTML::Task::Source source, GC::Ptr event_loop, GC TaskID queue_global_task(HTML::Task::Source source, JS::Object& global_object, GC::Ref> steps) { // 1. Let event loop be global's relevant agent's event loop. - auto& global_custom_data = verify_cast(*global_object.vm().custom_data()); - auto& event_loop = global_custom_data.event_loop; + auto& event_loop = relevant_agent(global_object).event_loop; // 2. Let document be global's associated Document, if global is a Window object; otherwise null. DOM::Document* document { nullptr }; diff --git a/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index 3f36c6a6ac1..be21f5b48e0 100644 --- a/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -752,8 +753,7 @@ GC::Ref HTMLParser::create_element_for(HTMLToken const& token, Opt perform_a_microtask_checkpoint(); // 3. Push a new element queue onto document's relevant agent's custom element reactions stack. - auto& custom_data = verify_cast(*vm.custom_data()); - custom_data.custom_element_reactions_stack.element_queue_stack.append({}); + relevant_agent(document).custom_element_reactions_stack.element_queue_stack.append({}); } // 9. Let element be the result of creating an element given document, localName, given namespace, null, is, and willExecuteScript. @@ -770,9 +770,7 @@ GC::Ref HTMLParser::create_element_for(HTMLToken const& token, Opt // 11. If willExecuteScript is true: if (will_execute_script) { // 1. Let queue be the result of popping from document's relevant agent's custom element reactions stack. (This will be the same element queue as was pushed above.) - auto& vm = main_thread_event_loop().vm(); - auto& custom_data = verify_cast(*vm.custom_data()); - auto queue = custom_data.custom_element_reactions_stack.element_queue_stack.take_last(); + auto queue = relevant_agent(document).custom_element_reactions_stack.element_queue_stack.take_last(); // 2. Invoke custom element reactions in queue. Bindings::invoke_custom_element_reactions(queue); @@ -5150,8 +5148,7 @@ void HTMLParser::insert_an_element_at_the_adjusted_insertion_location(GC::Ref(*relevant_agent(*element).custom_data()); - custom_data.custom_element_reactions_stack.element_queue_stack.append({}); + relevant_agent(*element).custom_element_reactions_stack.element_queue_stack.append({}); } // 4. Insert element at the adjusted insertion location. @@ -5160,8 +5157,7 @@ void HTMLParser::insert_an_element_at_the_adjusted_insertion_location(GC::Ref(*relevant_agent(*element).custom_data()); - auto queue = custom_data.custom_element_reactions_stack.element_queue_stack.take_last(); + auto queue = relevant_agent(*element).custom_element_reactions_stack.element_queue_stack.take_last(); Bindings::invoke_custom_element_reactions(queue); } } diff --git a/Libraries/LibWeb/HTML/Scripting/Agent.cpp b/Libraries/LibWeb/HTML/Scripting/Agent.cpp new file mode 100644 index 00000000000..d148f7ff718 --- /dev/null +++ b/Libraries/LibWeb/HTML/Scripting/Agent.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025, Shannon Booth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/webappapis.html#relevant-agent +Agent& relevant_agent(JS::Object const& object) +{ + // The relevant agent for a platform object platformObject is platformObject's relevant Realm's agent. + // Spec Note: This pointer is not yet defined in the JavaScript specification; see tc39/ecma262#1357. + return verify_cast(relevant_realm(object).vm().custom_data())->agent; +} + +} diff --git a/Libraries/LibWeb/HTML/Scripting/Agent.h b/Libraries/LibWeb/HTML/Scripting/Agent.h new file mode 100644 index 00000000000..4a69bbda1bb --- /dev/null +++ b/Libraries/LibWeb/HTML/Scripting/Agent.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, Shannon Booth + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/webappapis.html#similar-origin-window-agent +struct Agent { + GC::Root event_loop; + + // FIXME: These should only be on similar-origin window agents, but we don't currently differentiate agent types. + + // https://dom.spec.whatwg.org/#mutation-observer-compound-microtask-queued-flag + bool mutation_observer_microtask_queued { false }; + + // https://dom.spec.whatwg.org/#mutation-observer-list + // FIXME: This should be a set. + Vector> mutation_observers; + + // https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions-stack + // Each similar-origin window agent has a custom element reactions stack, which is initially empty. + CustomElementReactionsStack custom_element_reactions_stack {}; + + // https://html.spec.whatwg.org/multipage/custom-elements.html#current-element-queue + // A similar-origin window agent's current element queue is the element queue at the top of its custom element reactions stack. + Vector>& current_element_queue() { return custom_element_reactions_stack.element_queue_stack.last(); } + Vector> const& current_element_queue() const { return custom_element_reactions_stack.element_queue_stack.last(); } +}; + +Agent& relevant_agent(JS::Object const&); + +} diff --git a/Libraries/LibWeb/HTML/Scripting/Environments.cpp b/Libraries/LibWeb/HTML/Scripting/Environments.cpp index 217711cc0b7..06634c6de90 100644 --- a/Libraries/LibWeb/HTML/Scripting/Environments.cpp +++ b/Libraries/LibWeb/HTML/Scripting/Environments.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -102,10 +103,8 @@ EventLoop& EnvironmentSettingsObject::responsible_event_loop() if (m_responsible_event_loop) return *m_responsible_event_loop; - auto& vm = global_object().vm(); - auto& event_loop = verify_cast(vm.custom_data())->event_loop; - m_responsible_event_loop = event_loop; - return *event_loop; + m_responsible_event_loop = relevant_agent(global_object()).event_loop; + return *m_responsible_event_loop; } // https://html.spec.whatwg.org/multipage/webappapis.html#check-if-we-can-run-script @@ -513,13 +512,6 @@ JS::Object& entry_global_object() return entry_realm().global_object(); } -JS::VM& relevant_agent(JS::Object const& object) -{ - // The relevant agent for a platform object platformObject is platformObject's relevant Realm's agent. - // Spec Note: This pointer is not yet defined in the JavaScript specification; see tc39/ecma262#1357. - return relevant_realm(object).vm(); -} - // https://html.spec.whatwg.org/multipage/webappapis.html#secure-context bool is_secure_context(Environment const& environment) { diff --git a/Libraries/LibWeb/HTML/Scripting/Environments.h b/Libraries/LibWeb/HTML/Scripting/Environments.h index d7adc8d6c74..532d1dc36d7 100644 --- a/Libraries/LibWeb/HTML/Scripting/Environments.h +++ b/Libraries/LibWeb/HTML/Scripting/Environments.h @@ -168,7 +168,6 @@ JS::Object& relevant_principal_global_object(JS::Object const&); JS::Realm& entry_realm(); EnvironmentSettingsObject& entry_settings_object(); JS::Object& entry_global_object(); -JS::VM& relevant_agent(JS::Object const&); [[nodiscard]] bool is_secure_context(Environment const&); [[nodiscard]] bool is_non_secure_context(Environment const&); diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 1b97d142a12..07332287523 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -2077,9 +2077,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@@overload_suffi if (function.extended_attributes.contains("CEReactions")) { // 1. Push a new element queue onto this object's relevant agent's custom element reactions stack. function_generator.append(R"~~~( - auto& relevant_agent = HTML::relevant_agent(*impl); - auto* custom_data = verify_cast(relevant_agent.custom_data()); - auto& reactions_stack = custom_data->custom_element_reactions_stack; + auto& reactions_stack = HTML::relevant_agent(*impl).custom_element_reactions_stack; reactions_stack.element_queue_stack.append({}); )~~~"); } @@ -3566,9 +3564,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.getter_callback@) if (attribute.extended_attributes.contains("CEReactions")) { // 1. Push a new element queue onto this object's relevant agent's custom element reactions stack. attribute_generator.append(R"~~~( - auto& relevant_agent = HTML::relevant_agent(*impl); - auto* custom_data = verify_cast(relevant_agent.custom_data()); - auto& reactions_stack = custom_data->custom_element_reactions_stack; + auto& reactions_stack = HTML::relevant_agent(*impl).custom_element_reactions_stack; reactions_stack.element_queue_stack.append({}); )~~~"); } @@ -3914,9 +3910,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@) if (attribute.extended_attributes.contains("CEReactions")) { // 1. Push a new element queue onto this object's relevant agent's custom element reactions stack. attribute_generator.append(R"~~~( - auto& relevant_agent = HTML::relevant_agent(*impl); - auto* custom_data = verify_cast(relevant_agent.custom_data()); - auto& reactions_stack = custom_data->custom_element_reactions_stack; + auto& reactions_stack = HTML::relevant_agent(*impl).custom_element_reactions_stack; reactions_stack.element_queue_stack.append({}); )~~~"); } @@ -4912,6 +4906,7 @@ void generate_prototype_implementation(IDL::Interface const& interface, StringBu #include #include #include +#include #include #include #include