mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 09:39:39 +00:00
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.
This commit is contained in:
parent
5bed8f4055
commit
64eeda6450
Notes:
github-actions[bot]
2025-01-11 15:40:39 +00:00
Author: https://github.com/shannonbooth
Commit: 64eeda6450
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3142
15 changed files with 140 additions and 98 deletions
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2023, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGC/Root.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
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<Vector<GC::Root<DOM::Element>>> 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<GC::Root<DOM::Element>> 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 };
|
||||
};
|
||||
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
||||
#include <LibWeb/HTML/Scripting/Agent.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||
|
@ -67,7 +68,7 @@ void EventLoop::schedule()
|
|||
|
||||
EventLoop& main_thread_event_loop()
|
||||
{
|
||||
return *static_cast<Bindings::WebEngineCustomData*>(Bindings::main_thread_vm().custom_data())->event_loop;
|
||||
return *static_cast<Bindings::WebEngineCustomData*>(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<EventLoop> event_loop, GC
|
|||
TaskID queue_global_task(HTML::Task::Source source, JS::Object& global_object, GC::Ref<GC::Function<void()>> steps)
|
||||
{
|
||||
// 1. Let event loop be global's relevant agent's event loop.
|
||||
auto& global_custom_data = verify_cast<Bindings::WebEngineCustomData>(*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 };
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <LibWeb/HTML/Parser/HTMLEncodingDetection.h>
|
||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||
#include <LibWeb/HTML/Parser/HTMLToken.h>
|
||||
#include <LibWeb/HTML/Scripting/Agent.h>
|
||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
#include <LibWeb/HighResolutionTime/TimeOrigin.h>
|
||||
|
@ -752,8 +753,7 @@ GC::Ref<DOM::Element> 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<Bindings::WebEngineCustomData>(*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<DOM::Element> 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<Bindings::WebEngineCustomData>(*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<DO
|
|||
// 3. If the parser was not created as part of the HTML fragment parsing algorithm,
|
||||
// then push a new element queue onto element's relevant agent's custom element reactions stack.
|
||||
if (!m_parsing_fragment) {
|
||||
auto& custom_data = verify_cast<Bindings::WebEngineCustomData>(*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<DO
|
|||
// 5. If the parser was not created as part of the HTML fragment parsing algorithm,
|
||||
// then pop the element queue from element's relevant agent's custom element reactions stack, and invoke custom element reactions in that queue.
|
||||
if (!m_parsing_fragment) {
|
||||
auto& custom_data = verify_cast<Bindings::WebEngineCustomData>(*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);
|
||||
}
|
||||
}
|
||||
|
|
21
Libraries/LibWeb/HTML/Scripting/Agent.cpp
Normal file
21
Libraries/LibWeb/HTML/Scripting/Agent.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/HTML/Scripting/Agent.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
|
||||
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<Bindings::WebEngineCustomData>(relevant_realm(object).vm().custom_data())->agent;
|
||||
}
|
||||
|
||||
}
|
43
Libraries/LibWeb/HTML/Scripting/Agent.h
Normal file
43
Libraries/LibWeb/HTML/Scripting/Agent.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGC/Root.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/HTML/CustomElements/CustomElementReactionsStack.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#similar-origin-window-agent
|
||||
struct Agent {
|
||||
GC::Root<HTML::EventLoop> 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<GC::Root<DOM::MutationObserver>> 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<GC::Root<DOM::Element>>& current_element_queue() { return custom_element_reactions_stack.element_queue_stack.last(); }
|
||||
Vector<GC::Root<DOM::Element>> const& current_element_queue() const { return custom_element_reactions_stack.element_queue_stack.last(); }
|
||||
};
|
||||
|
||||
Agent& relevant_agent(JS::Object const&);
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOMURL/DOMURL.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/FetchRecord.h>
|
||||
#include <LibWeb/HTML/Scripting/Agent.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||
#include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h>
|
||||
|
@ -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<Bindings::WebEngineCustomData>(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)
|
||||
{
|
||||
|
|
|
@ -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&);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue