
Use a LocalSocket to represent the connection between two message ports. The concept of the port message queue is still missing, however. When that concept is implemented, the "steps" in step 7 of the message port transfer steps will need to send the serialized data over the connected socketpair and run in the event loop of the process that holds onto the other side of the message port. Doing this should allow centralizing the behavior of postMessage for Window, MessagePorts and Workers.
83 lines
2.8 KiB
C++
83 lines
2.8 KiB
C++
/*
|
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/RefCounted.h>
|
|
#include <AK/Weakable.h>
|
|
#include <LibCore/Socket.h>
|
|
#include <LibWeb/Bindings/Transferable.h>
|
|
#include <LibWeb/DOM/EventTarget.h>
|
|
#include <LibWeb/Forward.h>
|
|
|
|
namespace Web::HTML {
|
|
|
|
#define ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(E) \
|
|
E(onmessage, HTML::EventNames::message) \
|
|
E(onmessageerror, HTML::EventNames::messageerror)
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#structuredserializeoptions
|
|
struct StructuredSerializeOptions {
|
|
Vector<JS::Handle<JS::Object>> transfer;
|
|
};
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports
|
|
class MessagePort final : public DOM::EventTarget
|
|
, public Bindings::Transferable {
|
|
WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget);
|
|
JS_DECLARE_ALLOCATOR(MessagePort);
|
|
|
|
public:
|
|
[[nodiscard]] static JS::NonnullGCPtr<MessagePort> create(JS::Realm&);
|
|
|
|
virtual ~MessagePort() override;
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
|
|
void entangle_with(MessagePort&);
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage
|
|
WebIDL::ExceptionOr<void> post_message(JS::Value message, Vector<JS::Handle<JS::Object>> const& transfer);
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage-options
|
|
WebIDL::ExceptionOr<void> post_message(JS::Value message, StructuredSerializeOptions const& options);
|
|
|
|
void start();
|
|
|
|
void close();
|
|
|
|
#undef __ENUMERATE
|
|
#define __ENUMERATE(attribute_name, event_name) \
|
|
void set_##attribute_name(WebIDL::CallbackType*); \
|
|
WebIDL::CallbackType* attribute_name();
|
|
ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
|
|
#undef __ENUMERATE
|
|
|
|
// ^Transferable
|
|
virtual WebIDL::ExceptionOr<void> transfer_steps(HTML::TransferDataHolder&) override;
|
|
virtual WebIDL::ExceptionOr<void> transfer_receiving_steps(HTML::TransferDataHolder&) override;
|
|
virtual HTML::TransferType primary_interface() const override { return HTML::TransferType::MessagePort; }
|
|
|
|
private:
|
|
explicit MessagePort(JS::Realm&);
|
|
|
|
virtual void initialize(JS::Realm&) override;
|
|
virtual void visit_edges(Cell::Visitor&) override;
|
|
|
|
bool is_entangled() const { return static_cast<bool>(m_socket); }
|
|
void disentangle();
|
|
|
|
WebIDL::ExceptionOr<void> message_port_post_message_steps(JS::GCPtr<MessagePort> target_port, JS::Value message, StructuredSerializeOptions const& options);
|
|
|
|
// The HTML spec implies(!) that this is MessagePort.[[RemotePort]]
|
|
JS::GCPtr<MessagePort> m_remote_port;
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
|
|
bool m_has_been_shipped { false };
|
|
|
|
OwnPtr<Core::LocalSocket> m_socket;
|
|
};
|
|
|
|
}
|