mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 19:38:12 +00:00
LibWeb: Rewrite EventTarget to more closely match the spec
This isn't perfect (especially the global object situation in activate_event_handler), but I believe it's in a much more complete state now :^) This fixes the issue of crashing in prepare_for_ordinary_call with the `i < m_size` crash, as it now uses the IDL callback functions which requires the Environment Settings Object. The environment settings object for the callback is fetched at the time the callback is created, for example, WrapperGenerator gets the incumbent settings object for the callback at the time of wrapping. This allows us to remove passing in ScriptExecutionContext into EventTarget's constructor. With this, we can now drop ScriptExecutionContext.
This commit is contained in:
parent
3bb5c6207f
commit
5aacec65ab
39 changed files with 874 additions and 300 deletions
|
@ -8,6 +8,7 @@
|
|||
#include <LibGUI/DisplayLink.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h>
|
||||
#include <LibWeb/Crypto/Crypto.h>
|
||||
|
@ -109,7 +110,7 @@ NonnullRefPtr<Window> Window::create_with_document(Document& document)
|
|||
}
|
||||
|
||||
Window::Window(Document& document)
|
||||
: EventTarget(static_cast<Bindings::ScriptExecutionContext&>(document))
|
||||
: EventTarget()
|
||||
, m_associated_document(document)
|
||||
, m_performance(make<HighResolutionTime::Performance>(*this))
|
||||
, m_crypto(Crypto::Crypto::create())
|
||||
|
@ -146,16 +147,16 @@ String Window::prompt(String const& message, String const& default_)
|
|||
return {};
|
||||
}
|
||||
|
||||
i32 Window::set_interval(JS::FunctionObject& callback, i32 interval)
|
||||
i32 Window::set_interval(NonnullOwnPtr<Bindings::CallbackType> callback, i32 interval)
|
||||
{
|
||||
auto timer = Timer::create_interval(*this, interval, callback);
|
||||
auto timer = Timer::create_interval(*this, interval, move(callback));
|
||||
m_timers.set(timer->id(), timer);
|
||||
return timer->id();
|
||||
}
|
||||
|
||||
i32 Window::set_timeout(JS::FunctionObject& callback, i32 interval)
|
||||
i32 Window::set_timeout(NonnullOwnPtr<Bindings::CallbackType> callback, i32 interval)
|
||||
{
|
||||
auto timer = Timer::create_timeout(*this, interval, callback);
|
||||
auto timer = Timer::create_timeout(*this, interval, move(callback));
|
||||
m_timers.set(timer->id(), timer);
|
||||
return timer->id();
|
||||
}
|
||||
|
@ -172,7 +173,7 @@ void Window::timer_did_fire(Badge<Timer>, Timer& timer)
|
|||
VERIFY(wrapper());
|
||||
|
||||
HTML::queue_global_task(HTML::Task::Source::TimerTask, *wrapper(), [this, strong_this = NonnullRefPtr(*this), strong_timer = NonnullRefPtr(timer)]() mutable {
|
||||
auto result = JS::call(wrapper()->global_object(), strong_timer->callback(), wrapper());
|
||||
auto result = Bindings::IDL::invoke_callback(strong_timer->callback(), wrapper());
|
||||
if (result.is_error())
|
||||
HTML::report_exception(result);
|
||||
});
|
||||
|
@ -199,17 +200,15 @@ void Window::clear_interval(i32 timer_id)
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#run-the-animation-frame-callbacks
|
||||
i32 Window::request_animation_frame(JS::FunctionObject& js_callback)
|
||||
i32 Window::request_animation_frame(NonnullOwnPtr<Bindings::CallbackType> js_callback)
|
||||
{
|
||||
auto callback = request_animation_frame_driver().add([this, handle = JS::make_handle(&js_callback)](i32 id) mutable {
|
||||
auto& function = *handle.cell();
|
||||
auto callback = request_animation_frame_driver().add([this, js_callback = move(js_callback)](i32 id) mutable {
|
||||
// 3. Invoke callback, passing now as the only argument,
|
||||
auto result = JS::call(function.global_object(), function, JS::js_undefined(), JS::Value(performance().now()));
|
||||
auto result = Bindings::IDL::invoke_callback(*js_callback, {}, JS::Value(performance().now()));
|
||||
|
||||
// and if an exception is thrown, report the exception.
|
||||
if (result.is_error())
|
||||
HTML::report_exception(result);
|
||||
|
||||
m_request_animation_frame_callbacks.remove(id);
|
||||
});
|
||||
m_request_animation_frame_callbacks.set(callback->id(), callback);
|
||||
|
@ -399,10 +398,11 @@ void Window::fire_a_page_transition_event(FlyString const& event_name, bool pers
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-queuemicrotask
|
||||
void Window::queue_microtask(JS::FunctionObject& callback)
|
||||
void Window::queue_microtask(NonnullOwnPtr<Bindings::CallbackType> callback)
|
||||
{
|
||||
HTML::queue_a_microtask(&associated_document(), [&callback, handle = JS::make_handle(&callback)]() {
|
||||
auto result = JS::call(callback.global_object(), callback, JS::js_null());
|
||||
// The queueMicrotask(callback) method must queue a microtask to invoke callback,
|
||||
HTML::queue_a_microtask(&associated_document(), [callback = move(callback)]() mutable {
|
||||
auto result = Bindings::IDL::invoke_callback(*callback, {});
|
||||
// and if callback throws an exception, report the exception.
|
||||
if (result.is_error())
|
||||
HTML::report_exception(result);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue