
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.
123 lines
4.4 KiB
C++
123 lines
4.4 KiB
C++
/*
|
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWeb/Bindings/MessagePortWrapper.h>
|
|
#include <LibWeb/DOM/EventDispatcher.h>
|
|
#include <LibWeb/HTML/EventHandler.h>
|
|
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
|
#include <LibWeb/HTML/EventNames.h>
|
|
#include <LibWeb/HTML/MessageEvent.h>
|
|
#include <LibWeb/HTML/MessagePort.h>
|
|
|
|
namespace Web::HTML {
|
|
|
|
MessagePort::MessagePort()
|
|
: DOM::EventTarget()
|
|
{
|
|
}
|
|
|
|
MessagePort::~MessagePort()
|
|
{
|
|
}
|
|
|
|
void MessagePort::disentangle()
|
|
{
|
|
m_remote_port->m_remote_port = nullptr;
|
|
m_remote_port = nullptr;
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
|
|
void MessagePort::entangle_with(Badge<MessageChannel>, MessagePort& remote_port)
|
|
{
|
|
if (m_remote_port == &remote_port)
|
|
return;
|
|
|
|
// 1. If one of the ports is already entangled, then disentangle it and the port that it was entangled with.
|
|
if (is_entangled())
|
|
disentangle();
|
|
if (remote_port.is_entangled())
|
|
remote_port.disentangle();
|
|
|
|
// 2. Associate the two ports to be entangled, so that they form the two parts of a new channel.
|
|
// (There is no MessageChannel object that represents this channel.)
|
|
remote_port.m_remote_port = *this;
|
|
m_remote_port = &remote_port;
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage
|
|
void MessagePort::post_message(JS::Value message)
|
|
{
|
|
// 1. Let targetPort be the port with which this MessagePort is entangled, if any; otherwise let it be null.
|
|
auto* target_port = m_remote_port.ptr();
|
|
|
|
// FIXME: 2. Let options be «[ "transfer" → transfer ]».
|
|
|
|
// 3. Run the message port post message steps providing targetPort, message and options.
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-port-post-message-steps
|
|
|
|
// FIXME: 1. Let transfer be options["transfer"].
|
|
|
|
// FIXME: 2. If transfer contains this MessagePort, then throw a "DataCloneError" DOMException.
|
|
|
|
// 3. Let doomed be false.
|
|
bool doomed = false;
|
|
|
|
// FIXME: 4. If targetPort is not null and transfer contains targetPort, then set doomed to true and optionally report to a developer console that the target port was posted to itself, causing the communication channel to be lost.
|
|
|
|
// FIXME: 5. Let serializeWithTransferResult be StructuredSerializeWithTransfer(message, transfer). Rethrow any exceptions.
|
|
|
|
// 6. If targetPort is null, or if doomed is true, then return.
|
|
if (!target_port || doomed)
|
|
return;
|
|
|
|
// FIXME: 7. Add a task that runs the following steps to the port message queue of targetPort:
|
|
|
|
// FIXME: This is an ad-hoc hack implementation instead, since we don't currently
|
|
// have serialization and deserialization of messages.
|
|
main_thread_event_loop().task_queue().add(HTML::Task::create(HTML::Task::Source::PostedMessage, nullptr, [strong_port = NonnullRefPtr { *target_port }, message]() mutable {
|
|
MessageEventInit event_init {};
|
|
event_init.data = message;
|
|
event_init.origin = "<origin>";
|
|
strong_port->dispatch_event(MessageEvent::create(HTML::EventNames::message, event_init));
|
|
}));
|
|
}
|
|
|
|
JS::Object* MessagePort::create_wrapper(JS::GlobalObject& global_object)
|
|
{
|
|
return wrap(global_object, *this);
|
|
}
|
|
|
|
void MessagePort::start()
|
|
{
|
|
// FIXME: Message ports are supposed to be disabled by default.
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-close
|
|
void MessagePort::close()
|
|
{
|
|
// 1. Set this MessagePort object's [[Detached]] internal slot value to true.
|
|
m_detached = true;
|
|
|
|
// 2. If this MessagePort object is entangled, disentangle it.
|
|
if (is_entangled())
|
|
disentangle();
|
|
}
|
|
|
|
#undef __ENUMERATE
|
|
#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
|
|
|
|
}
|