1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:07:34 +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:
Luke Wilde 2021-10-14 18:03:08 +01:00 committed by Linus Groh
parent 3bb5c6207f
commit 5aacec65ab
39 changed files with 874 additions and 300 deletions

View file

@ -7,28 +7,34 @@
#pragma once
#include <AK/String.h>
#include <AK/Variant.h>
#include <LibJS/Heap/Handle.h>
#include <LibJS/Runtime/FunctionObject.h>
#include <LibWeb/Bindings/CallbackType.h>
#include <LibWeb/DOM/EventListener.h>
namespace Web::HTML {
struct EventHandler {
EventHandler()
{
}
EventHandler(String s)
: string(move(s))
: value(move(s))
{
}
EventHandler(JS::Handle<JS::FunctionObject> c)
: callback(move(c))
EventHandler(Bindings::CallbackType c)
: value(move(c))
{
}
String string;
JS::Handle<JS::FunctionObject> callback;
// Either uncompiled source code or a callback.
// https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-value
// NOTE: This does not contain Empty as part of the optimization of not allocating all event handler attributes up front.
// FIXME: The string should actually be an "internal raw uncompiled handler" struct. This struct is just the uncompiled source code plus a source location for reporting parse errors.
// https://html.spec.whatwg.org/multipage/webappapis.html#internal-raw-uncompiled-handler
Variant<String, Bindings::CallbackType> value;
// https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-listener
RefPtr<DOM::EventListener> listener;
};
}

View file

@ -17,11 +17,11 @@ namespace Web::HTML {
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void GlobalEventHandlers::set_##attribute_name(HTML::EventHandler value) \
void GlobalEventHandlers::set_##attribute_name(Optional<Bindings::CallbackType> value) \
{ \
global_event_handlers_to_event_target().set_event_handler_attribute(event_name, move(value)); \
} \
HTML::EventHandler GlobalEventHandlers::attribute_name() \
Bindings::CallbackType* GlobalEventHandlers::attribute_name() \
{ \
return global_event_handlers_to_event_target().event_handler_attribute(event_name); \
}

View file

@ -84,9 +84,9 @@ public:
virtual ~GlobalEventHandlers();
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void set_##attribute_name(HTML::EventHandler); \
HTML::EventHandler attribute_name();
#define __ENUMERATE(attribute_name, event_name) \
void set_##attribute_name(Optional<Bindings::CallbackType>); \
Bindings::CallbackType* attribute_name();
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE

View file

@ -172,10 +172,12 @@ void HTMLElement::parse_attribute(const FlyString& name, const String& value)
{
Element::parse_attribute(name, value);
// 1. If namespace is not null, or localName is not the name of an event handler content attribute on element, then return.
// FIXME: Add the namespace part once we support attribute namespaces.
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
if (name == HTML::AttributeNames::attribute_name) { \
set_event_handler_attribute(event_name, EventHandler { value }); \
#define __ENUMERATE(attribute_name, event_name) \
if (name == HTML::AttributeNames::attribute_name) { \
element_event_handler_attribute_changed(event_name, value); \
}
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE

View file

@ -10,15 +10,13 @@
namespace Web::HTML {
MessageChannel::MessageChannel(Bindings::WindowObject& global_object)
MessageChannel::MessageChannel()
{
auto& context = global_object.impl().associated_document();
// 1. Set this's port 1 to a new MessagePort in this's relevant Realm.
m_port1 = MessagePort::create(context);
m_port1 = MessagePort::create();
// 2. Set this's port 2 to a new MessagePort in this's relevant Realm.
m_port2 = MessagePort::create(context);
m_port2 = MessagePort::create();
// 3. Entangle this's port 1 and this's port 2.
m_port1->entangle_with({}, *m_port2);

View file

@ -24,9 +24,9 @@ public:
using RefCounted::ref;
using RefCounted::unref;
static NonnullRefPtr<MessageChannel> create_with_global_object(Bindings::WindowObject& global_object)
static NonnullRefPtr<MessageChannel> create_with_global_object(Bindings::WindowObject&)
{
return adopt_ref(*new MessageChannel(global_object));
return adopt_ref(*new MessageChannel());
}
virtual ~MessageChannel() override;
@ -38,7 +38,7 @@ public:
MessagePort const* port2() const { return m_port2; }
private:
explicit MessageChannel(Bindings::WindowObject&);
MessageChannel();
RefPtr<MessagePort> m_port1;
RefPtr<MessagePort> m_port2;

View file

@ -5,7 +5,6 @@
*/
#include <LibWeb/Bindings/MessagePortWrapper.h>
#include <LibWeb/Bindings/ScriptExecutionContext.h>
#include <LibWeb/DOM/EventDispatcher.h>
#include <LibWeb/HTML/EventHandler.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
@ -15,8 +14,8 @@
namespace Web::HTML {
MessagePort::MessagePort(Bindings::ScriptExecutionContext& context)
: DOM::EventTarget(context)
MessagePort::MessagePort()
: DOM::EventTarget()
{
}
@ -109,14 +108,14 @@ void MessagePort::close()
}
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void MessagePort::set_##attribute_name(HTML::EventHandler value) \
{ \
set_event_handler_attribute(event_name, move(value)); \
} \
HTML::EventHandler MessagePort::attribute_name() \
{ \
return event_handler_attribute(event_name); \
#define __ENUMERATE(attribute_name, event_name) \
void MessagePort::set_##attribute_name(Optional<Bindings::CallbackType> value) \
{ \
set_event_handler_attribute(event_name, move(value)); \
} \
Bindings::CallbackType* MessagePort::attribute_name() \
{ \
return event_handler_attribute(event_name); \
}
ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE

View file

@ -30,9 +30,9 @@ public:
using RefCounted::ref;
using RefCounted::unref;
static NonnullRefPtr<MessagePort> create(Bindings::ScriptExecutionContext& context)
static NonnullRefPtr<MessagePort> create()
{
return adopt_ref(*new MessagePort(context));
return adopt_ref(*new MessagePort());
}
virtual ~MessagePort() override;
@ -53,14 +53,14 @@ public:
void close();
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void set_##attribute_name(HTML::EventHandler); \
HTML::EventHandler attribute_name();
#define __ENUMERATE(attribute_name, event_name) \
void set_##attribute_name(Optional<Bindings::CallbackType>); \
Bindings::CallbackType* attribute_name();
ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE
private:
explicit MessagePort(Bindings::ScriptExecutionContext&);
MessagePort();
bool is_entangled() const { return m_remote_port; }
void disentangle();

View file

@ -67,7 +67,7 @@ DOM::ExceptionOr<NonnullRefPtr<WebSocket>> WebSocket::create_with_global_object(
}
WebSocket::WebSocket(DOM::Window& window, AK::URL& url)
: EventTarget(static_cast<Bindings::ScriptExecutionContext&>(window.associated_document()))
: EventTarget()
, m_window(window)
{
// FIXME: Integrate properly with FETCH as per https://fetch.spec.whatwg.org/#websocket-opening-handshake
@ -226,14 +226,14 @@ JS::Object* WebSocket::create_wrapper(JS::GlobalObject& global_object)
}
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void WebSocket::set_##attribute_name(HTML::EventHandler value) \
{ \
set_event_handler_attribute(event_name, move(value)); \
} \
HTML::EventHandler WebSocket::attribute_name() \
{ \
return event_handler_attribute(event_name); \
#define __ENUMERATE(attribute_name, event_name) \
void WebSocket::set_##attribute_name(Optional<Bindings::CallbackType> value) \
{ \
set_event_handler_attribute(event_name, move(value)); \
} \
Bindings::CallbackType* WebSocket::attribute_name() \
{ \
return event_handler_attribute(event_name); \
}
ENUMERATE_WEBSOCKET_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE

View file

@ -74,9 +74,9 @@ public:
String url() const { return m_url.to_string(); }
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void set_##attribute_name(HTML::EventHandler); \
HTML::EventHandler attribute_name();
#define __ENUMERATE(attribute_name, event_name) \
void set_##attribute_name(Optional<Bindings::CallbackType>); \
Bindings::CallbackType* attribute_name();
ENUMERATE_WEBSOCKET_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE