2021-09-19 22:12:31 +02:00
/*
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2021 , Andreas Kling < andreas @ ladybird . org >
2023-12-19 15:28:56 -07:00
* Copyright ( c ) 2023 , Andrew Kaster < akaster @ serenityos . org >
2025-04-07 04:17:36 +02:00
* Copyright ( c ) 2025 , Aliaksandr Kalenik < kalenik . aliaksandr @ gmail . com >
2021-09-19 22:12:31 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2024-04-17 16:46:24 -06:00
# include <AK/ByteReader.h>
2023-12-19 15:28:56 -07:00
# include <AK/MemoryStream.h>
2023-12-18 17:24:31 -07:00
# include <LibCore/Socket.h>
# include <LibCore/System.h>
2023-12-19 15:28:56 -07:00
# include <LibIPC/Decoder.h>
# include <LibIPC/Encoder.h>
2023-12-18 17:24:31 -07:00
# include <LibIPC/File.h>
2024-10-22 15:47:33 -06:00
# include <LibIPC/Transport.h>
2023-12-18 17:24:31 -07:00
# include <LibWeb/Bindings/ExceptionOrUtils.h>
2022-09-25 16:38:21 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2023-12-18 17:24:31 -07:00
# include <LibWeb/Bindings/MessagePortPrototype.h>
2021-09-19 22:12:31 +02:00
# include <LibWeb/DOM/EventDispatcher.h>
# include <LibWeb/HTML/EventNames.h>
# include <LibWeb/HTML/MessageEvent.h>
# include <LibWeb/HTML/MessagePort.h>
2023-12-18 17:24:31 -07:00
# include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
2025-07-17 13:40:50 -04:00
# include <LibWeb/HTML/StructuredSerialize.h>
2024-10-17 08:46:48 -04:00
# include <LibWeb/HTML/StructuredSerializeOptions.h>
2023-12-20 13:47:01 -07:00
# include <LibWeb/HTML/WorkerGlobalScope.h>
2021-09-19 22:12:31 +02:00
namespace Web : : HTML {
2023-12-18 17:24:31 -07:00
constexpr u8 IPC_FILE_TAG = 0xA5 ;
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( MessagePort ) ;
2023-11-19 19:47:52 +01:00
2024-11-15 04:01:23 +13:00
static HashTable < GC : : RawPtr < MessagePort > > & all_message_ports ( )
2024-10-17 07:59:04 -04:00
{
2024-11-15 04:01:23 +13:00
static HashTable < GC : : RawPtr < MessagePort > > ports ;
2024-10-17 07:59:04 -04:00
return ports ;
}
2025-07-17 09:52:25 -04:00
GC : : Ref < MessagePort > MessagePort : : create ( JS : : Realm & realm )
2021-09-19 22:12:31 +02:00
{
2025-07-17 09:52:25 -04:00
return realm . create < MessagePort > ( realm ) ;
2022-08-28 13:42:07 +02:00
}
2025-07-17 09:52:25 -04:00
MessagePort : : MessagePort ( JS : : Realm & realm )
2022-09-25 16:38:21 -06:00
: DOM : : EventTarget ( realm )
2022-08-28 13:42:07 +02:00
{
2024-10-17 07:59:04 -04:00
all_message_ports ( ) . set ( this ) ;
2021-09-19 22:12:31 +02:00
}
2025-01-01 01:20:37 +13:00
MessagePort : : ~ MessagePort ( ) = default ;
2021-09-19 22:12:31 +02:00
2024-10-17 07:59:04 -04:00
void MessagePort : : for_each_message_port ( Function < void ( MessagePort & ) > callback )
{
for ( auto port : all_message_ports ( ) )
callback ( * port ) ;
}
2023-08-07 08:41:28 +02:00
void MessagePort : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( MessagePort ) ;
2025-04-20 16:22:57 +02:00
Base : : initialize ( realm ) ;
2023-01-10 06:28:20 -05:00
}
2025-01-01 01:20:37 +13:00
void MessagePort : : finalize ( )
{
Base : : finalize ( ) ;
all_message_ports ( ) . remove ( this ) ;
disentangle ( ) ;
}
2022-08-28 13:42:07 +02:00
void MessagePort : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
2023-11-19 16:18:00 +13:00
visitor . visit ( m_remote_port ) ;
2024-10-16 19:51:05 -04:00
visitor . visit ( m_worker_event_target ) ;
2022-08-28 13:42:07 +02:00
}
2024-10-22 15:47:33 -06:00
bool MessagePort : : is_entangled ( ) const
{
2025-04-08 22:01:46 +02:00
return m_transport ;
2024-10-22 15:47:33 -06:00
}
2024-11-15 04:01:23 +13:00
void MessagePort : : set_worker_event_target ( GC : : Ref < DOM : : EventTarget > target )
2023-12-20 13:47:01 -07:00
{
m_worker_event_target = target ;
}
2023-12-07 15:52:08 -07:00
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports:transfer-steps
2025-07-17 09:51:04 -04:00
WebIDL : : ExceptionOr < void > MessagePort : : transfer_steps ( HTML : : TransferDataEncoder & data_holder )
2023-12-07 15:52:08 -07:00
{
// 1. Set value's has been shipped flag to true.
m_has_been_shipped = true ;
// FIXME: 2. Set dataHolder.[[PortMessageQueue]] to value's port message queue.
// FIXME: Support delivery of messages that haven't been delivered yet on the other side
// 3. If value is entangled with another port remotePort, then:
if ( is_entangled ( ) ) {
// 1. Set remotePort's has been shipped flag to true.
m_remote_port - > m_has_been_shipped = true ;
2024-12-21 10:03:51 +05:00
auto fd = MUST ( m_transport - > release_underlying_transport_for_transfer ( ) ) ;
2025-04-08 22:01:46 +02:00
m_transport . clear ( ) ;
2023-12-07 15:52:08 -07:00
2025-07-17 09:51:04 -04:00
// 2. Set dataHolder.[[RemotePort]] to remotePort.
// TODO: Mach IPC
data_holder . encode ( IPC_FILE_TAG ) ;
data_holder . encode ( IPC : : File : : adopt_fd ( fd ) ) ;
}
2023-12-07 15:52:08 -07:00
// 4. Otherwise, set dataHolder.[[RemotePort]] to null.
else {
2025-07-17 09:51:04 -04:00
data_holder . encode < u8 > ( 0 ) ;
2023-12-07 15:52:08 -07:00
}
return { } ;
}
2025-07-17 09:51:04 -04:00
WebIDL : : ExceptionOr < void > MessagePort : : transfer_receiving_steps ( HTML : : TransferDataDecoder & data_holder )
2023-12-07 15:52:08 -07:00
{
// 1. Set value's has been shipped flag to true.
m_has_been_shipped = true ;
// FIXME 2. Move all the tasks that are to fire message events in dataHolder.[[PortMessageQueue]] to the port message queue of value,
// if any, leaving value's port message queue in its initial disabled state, and, if value's relevant global object is a Window,
// associating the moved tasks with value's relevant global object's associated Document.
2023-12-18 17:24:31 -07:00
// 3. If dataHolder.[[RemotePort]] is not null, then entangle dataHolder.[[RemotePort]] and value.
2023-12-07 15:52:08 -07:00
// (This will disentangle dataHolder.[[RemotePort]] from the original port that was transferred.)
2025-07-17 09:51:04 -04:00
if ( auto fd_tag = data_holder . decode < u8 > ( ) ; fd_tag = = IPC_FILE_TAG ) {
2024-12-21 10:03:51 +05:00
// TODO: Mach IPC
2025-07-17 09:51:04 -04:00
auto fd = data_holder . decode < IPC : : File > ( ) ;
2025-04-08 22:01:46 +02:00
m_transport = make < IPC : : Transport > ( MUST ( Core : : LocalSocket : : adopt_fd ( fd . take_fd ( ) ) ) ) ;
2024-12-21 10:03:51 +05:00
m_transport - > set_up_read_hook ( [ strong_this = GC : : make_root ( this ) ] ( ) {
2025-06-07 23:57:17 +02:00
if ( strong_this - > m_enabled )
strong_this - > read_from_transport ( ) ;
2024-12-21 10:03:51 +05:00
} ) ;
2023-12-18 17:24:31 -07:00
} else if ( fd_tag ! = 0 ) {
dbgln ( " Unexpected byte {:x} in MessagePort transfer data " , fd_tag ) ;
VERIFY_NOT_REACHED ( ) ;
}
2023-12-07 15:52:08 -07:00
return { } ;
}
2021-09-19 22:12:31 +02:00
void MessagePort : : disentangle ( )
{
2025-05-23 15:16:23 -04:00
if ( auto remote_port = m_remote_port ) {
// Set the pointers to null before disentangling the remote port to prevent infinite recursion here.
2023-12-19 15:28:56 -07:00
m_remote_port - > m_remote_port = nullptr ;
2025-05-20 16:21:17 -04:00
m_remote_port = nullptr ;
2025-05-23 15:16:23 -04:00
if ( remote_port )
remote_port - > disentangle ( ) ;
2025-05-20 16:21:17 -04:00
}
2023-12-18 17:24:31 -07:00
2025-05-20 16:21:17 -04:00
if ( m_transport ) {
m_transport - > close_after_sending_all_pending_messages ( ) ;
m_transport . clear ( ) ;
}
2024-10-17 07:57:20 -04:00
m_worker_event_target = nullptr ;
2021-09-19 22:12:31 +02:00
}
// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
2022-02-17 13:31:09 +01:00
void MessagePort : : entangle_with ( MessagePort & remote_port )
2021-09-19 22:12:31 +02:00
{
2022-08-28 13:42:07 +02:00
if ( m_remote_port . ptr ( ) = = & remote_port )
2021-09-19 22:12:31 +02:00
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.)
2022-08-28 13:42:07 +02:00
remote_port . m_remote_port = this ;
2021-09-19 22:12:31 +02:00
m_remote_port = & remote_port ;
2023-12-18 17:24:31 -07:00
2024-10-22 15:47:33 -06:00
// FIXME: Abstract such that we can entangle different transport types
2023-12-19 15:28:56 -07:00
auto create_paired_sockets = [ ] ( ) - > Array < NonnullOwnPtr < Core : : LocalSocket > , 2 > {
int fds [ 2 ] = { } ;
MUST ( Core : : System : : socketpair ( AF_LOCAL , SOCK_STREAM , 0 , fds ) ) ;
2024-04-05 00:07:32 +02:00
auto socket0 = MUST ( Core : : LocalSocket : : adopt_fd ( fds [ 0 ] ) ) ;
2023-12-19 15:28:56 -07:00
MUST ( socket0 - > set_blocking ( false ) ) ;
MUST ( socket0 - > set_close_on_exec ( true ) ) ;
2024-04-05 00:07:32 +02:00
auto socket1 = MUST ( Core : : LocalSocket : : adopt_fd ( fds [ 1 ] ) ) ;
2023-12-19 15:28:56 -07:00
MUST ( socket1 - > set_blocking ( false ) ) ;
MUST ( socket1 - > set_close_on_exec ( true ) ) ;
return Array { move ( socket0 ) , move ( socket1 ) } ;
} ;
auto sockets = create_paired_sockets ( ) ;
2025-04-08 22:01:46 +02:00
m_transport = make < IPC : : Transport > ( move ( sockets [ 0 ] ) ) ;
m_remote_port - > m_transport = make < IPC : : Transport > ( move ( sockets [ 1 ] ) ) ;
2023-12-19 15:28:56 -07:00
2024-11-15 04:01:23 +13:00
m_transport - > set_up_read_hook ( [ strong_this = GC : : make_root ( this ) ] ( ) {
2025-06-07 23:57:17 +02:00
if ( strong_this - > m_enabled )
strong_this - > read_from_transport ( ) ;
2024-10-22 15:47:33 -06:00
} ) ;
2023-12-19 15:28:56 -07:00
2024-11-15 04:01:23 +13:00
m_remote_port - > m_transport - > set_up_read_hook ( [ remote_port = GC : : make_root ( m_remote_port ) ] ( ) {
2025-06-07 23:57:17 +02:00
if ( remote_port - > m_enabled )
remote_port - > read_from_transport ( ) ;
2024-10-22 15:47:33 -06:00
} ) ;
2021-09-19 22:12:31 +02:00
}
2023-12-18 17:24:31 -07:00
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage-options
2024-11-15 04:01:23 +13:00
WebIDL : : ExceptionOr < void > MessagePort : : post_message ( JS : : Value message , Vector < GC : : Root < JS : : Object > > const & transfer )
2021-09-19 22:12:31 +02:00
{
// 1. Let targetPort be the port with which this MessagePort is entangled, if any; otherwise let it be null.
2024-11-15 04:01:23 +13:00
GC : : Ptr < MessagePort > target_port = m_remote_port ;
2021-09-19 22:12:31 +02:00
2023-12-18 17:24:31 -07:00
// 2. Let options be «[ "transfer" → transfer ]».
auto options = StructuredSerializeOptions { transfer } ;
// 3. Run the message port post message steps providing this, targetPort, message and options.
return message_port_post_message_steps ( target_port , message , options ) ;
}
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage
WebIDL : : ExceptionOr < void > MessagePort : : post_message ( JS : : Value message , StructuredSerializeOptions const & options )
{
// 1. Let targetPort be the port with which this MessagePort is entangled, if any; otherwise let it be null.
2024-11-15 04:01:23 +13:00
GC : : Ptr < MessagePort > target_port = m_remote_port ;
2021-09-19 22:12:31 +02:00
2023-12-18 17:24:31 -07:00
// 2. Run the message port post message steps providing targetPort, message and options.
return message_port_post_message_steps ( target_port , message , options ) ;
}
2021-09-19 22:12:31 +02:00
2023-12-18 17:24:31 -07:00
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-port-post-message-steps
2024-11-15 04:01:23 +13:00
WebIDL : : ExceptionOr < void > MessagePort : : message_port_post_message_steps ( GC : : Ptr < MessagePort > target_port , JS : : Value message , StructuredSerializeOptions const & options )
2023-12-18 17:24:31 -07:00
{
auto & realm = this - > realm ( ) ;
auto & vm = this - > vm ( ) ;
2021-09-19 22:12:31 +02:00
2023-12-18 17:24:31 -07:00
// 1. Let transfer be options["transfer"].
auto const & transfer = options . transfer ;
2021-09-19 22:12:31 +02:00
2023-12-18 17:24:31 -07:00
// 2. If transfer contains this MessagePort, then throw a "DataCloneError" DOMException.
for ( auto const & handle : transfer ) {
if ( handle = = this )
2024-10-12 20:56:21 +02:00
return WebIDL : : DataCloneError : : create ( realm , " Cannot transfer a MessagePort to itself " _string ) ;
2023-12-18 17:24:31 -07:00
}
2021-09-19 22:12:31 +02:00
// 3. Let doomed be false.
bool doomed = false ;
2023-12-18 17:24:31 -07:00
// 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.
if ( target_port ) {
for ( auto const & handle : transfer ) {
if ( handle = = target_port . ptr ( ) ) {
doomed = true ;
dbgln ( " FIXME: Report to a developer console that the target port was posted to itself, causing the communication channel to be lost " ) ;
}
}
}
2021-09-19 22:12:31 +02:00
2023-12-18 17:24:31 -07:00
// 5. Let serializeWithTransferResult be StructuredSerializeWithTransfer(message, transfer). Rethrow any exceptions.
auto serialize_with_transfer_result = TRY ( structured_serialize_with_transfer ( vm , message , transfer ) ) ;
2021-09-19 22:12:31 +02:00
// 6. If targetPort is null, or if doomed is true, then return.
2023-12-19 15:28:56 -07:00
// IMPLEMENTATION DEFINED: Actually check the socket here, not the target port.
// If there's no target message port in the same realm, we still want to send the message over IPC
2025-04-08 22:01:46 +02:00
if ( ! m_transport | | doomed ) {
2023-12-18 17:24:31 -07:00
return { } ;
2023-12-19 15:28:56 -07:00
}
2021-09-19 22:12:31 +02:00
2023-12-19 15:28:56 -07:00
// 7. Add a task that runs the following steps to the port message queue of targetPort:
2025-07-17 13:40:50 -04:00
post_port_message ( serialize_with_transfer_result ) ;
2023-12-19 15:28:56 -07:00
return { } ;
}
2023-12-18 17:24:31 -07:00
2024-10-22 15:47:33 -06:00
ErrorOr < void > MessagePort : : send_message_on_transport ( SerializedTransferRecord const & serialize_with_transfer_result )
2023-12-19 15:28:56 -07:00
{
IPC : : MessageBuffer buffer ;
IPC : : Encoder encoder ( buffer ) ;
MUST ( encoder . encode ( serialize_with_transfer_result ) ) ;
2024-10-22 15:47:33 -06:00
TRY ( buffer . transfer_message ( * m_transport ) ) ;
2023-12-19 15:28:56 -07:00
return { } ;
}
2025-07-17 13:40:50 -04:00
void MessagePort : : post_port_message ( SerializedTransferRecord const & serialize_with_transfer_result )
2023-12-19 15:28:56 -07:00
{
2025-04-08 22:01:46 +02:00
if ( ! m_transport | | ! m_transport - > is_open ( ) )
2024-11-08 17:02:31 -07:00
return ;
if ( auto result = send_message_on_transport ( serialize_with_transfer_result ) ; result . is_error ( ) ) {
dbgln ( " Failed to post message: {} " , result . error ( ) ) ;
disentangle ( ) ;
}
2023-12-19 15:28:56 -07:00
}
2025-04-07 04:17:36 +02:00
void MessagePort : : read_from_transport ( )
2023-12-19 15:28:56 -07:00
{
2025-06-07 23:57:17 +02:00
VERIFY ( m_enabled ) ;
2025-07-15 12:38:24 +01:00
if ( ! is_entangled ( ) )
return ;
2025-04-10 20:26:46 +02:00
auto schedule_shutdown = m_transport - > read_as_many_messages_as_possible_without_blocking ( [ this ] ( auto & & raw_message ) {
FixedMemoryStream stream { raw_message . bytes . span ( ) , FixedMemoryStream : : Mode : : ReadOnly } ;
IPC : : Decoder decoder { stream , raw_message . fds } ;
2024-01-05 14:50:01 -07:00
2025-04-07 04:17:36 +02:00
auto serialized_transfer_record = MUST ( decoder . decode < SerializedTransferRecord > ( ) ) ;
2024-04-17 16:46:24 -06:00
2024-11-15 04:01:23 +13:00
queue_global_task ( Task : : Source : : PostedMessage , relevant_global_object ( * this ) , GC : : create_function ( heap ( ) , [ this , serialized_transfer_record = move ( serialized_transfer_record ) ] ( ) mutable {
2024-11-08 17:02:31 -07:00
this - > post_message_task_steps ( serialized_transfer_record ) ;
} ) ) ;
2025-04-07 04:17:36 +02:00
} ) ;
2024-04-17 16:46:24 -06:00
2025-06-27 22:14:03 -07:00
if ( schedule_shutdown = = IPC : : Transport : : ShouldShutdown : : Yes ) {
2024-11-15 04:01:23 +13:00
queue_global_task ( Task : : Source : : PostedMessage , relevant_global_object ( * this ) , GC : : create_function ( heap ( ) , [ this ] {
2024-10-22 15:47:33 -06:00
this - > close ( ) ;
} ) ) ;
2023-12-19 15:28:56 -07:00
}
}
void MessagePort : : post_message_task_steps ( SerializedTransferRecord & serialize_with_transfer_result )
{
2025-06-07 23:57:17 +02:00
VERIFY ( m_enabled ) ;
2023-12-19 15:28:56 -07:00
// 1. Let finalTargetPort be the MessagePort in whose port message queue the task now finds itself.
// NOTE: This can be different from targetPort, if targetPort itself was transferred and thus all its tasks moved along with it.
auto * final_target_port = this ;
2023-12-20 13:47:01 -07:00
// IMPLEMENTATION DEFINED:
// https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface
// Worker objects act as if they had an implicit MessagePort associated with them.
// All messages received by that port must immediately be retargeted at the Worker object.
// We therefore set a special event target for those implicit ports on the Worker and the WorkerGlobalScope objects
EventTarget * message_event_target = final_target_port ;
if ( m_worker_event_target ! = nullptr ) {
message_event_target = m_worker_event_target ;
}
2023-12-19 15:28:56 -07:00
// 2. Let targetRealm be finalTargetPort's relevant realm.
auto & target_realm = relevant_realm ( * final_target_port ) ;
2025-04-17 08:57:55 -04:00
TemporaryExecutionContext context { target_realm } ;
2023-12-19 15:28:56 -07:00
// 3. Let deserializeRecord be StructuredDeserializeWithTransfer(serializeWithTransferResult, targetRealm).
2025-04-17 08:57:55 -04:00
auto deserialize_record_or_error = structured_deserialize_with_transfer ( serialize_with_transfer_result , target_realm ) ;
2023-12-19 15:28:56 -07:00
if ( deserialize_record_or_error . is_error ( ) ) {
// If this throws an exception, catch it, fire an event named messageerror at finalTargetPort, using MessageEvent, and then return.
auto exception = deserialize_record_or_error . release_error ( ) ;
2021-10-01 18:39:03 +03:00
MessageEventInit event_init { } ;
2023-12-20 13:47:01 -07:00
message_event_target - > dispatch_event ( MessageEvent : : create ( target_realm , HTML : : EventNames : : messageerror , event_init ) ) ;
2023-12-19 15:28:56 -07:00
return ;
}
auto deserialize_record = deserialize_record_or_error . release_value ( ) ;
2023-12-18 17:24:31 -07:00
2023-12-19 15:28:56 -07:00
// 4. Let messageClone be deserializeRecord.[[Deserialized]].
auto message_clone = deserialize_record . deserialized ;
// 5. Let newPorts be a new frozen array consisting of all MessagePort objects in deserializeRecord.[[TransferredValues]], if any, maintaining their relative order.
// FIXME: Use a FrozenArray
2024-11-15 04:01:23 +13:00
Vector < GC : : Root < MessagePort > > new_ports ;
2023-12-19 15:28:56 -07:00
for ( auto const & object : deserialize_record . transferred_values ) {
if ( is < HTML : : MessagePort > ( * object ) ) {
2025-01-21 09:12:05 -05:00
new_ports . append ( as < MessagePort > ( * object ) ) ;
2023-12-19 15:28:56 -07:00
}
}
// 6. Fire an event named message at finalTargetPort, using MessageEvent, with the data attribute initialized to messageClone and the ports attribute initialized to newPorts.
MessageEventInit event_init { } ;
event_init . data = message_clone ;
event_init . ports = move ( new_ports ) ;
2024-11-15 17:15:34 +00:00
auto event = MessageEvent : : create ( target_realm , HTML : : EventNames : : message , event_init ) ;
event - > set_is_trusted ( true ) ;
message_event_target - > dispatch_event ( event ) ;
2021-09-19 22:12:31 +02:00
}
2025-06-07 23:57:17 +02:00
void MessagePort : : enable ( )
{
if ( ! m_enabled ) {
m_enabled = true ;
read_from_transport ( ) ;
}
}
2023-12-18 17:24:31 -07:00
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-start
2021-09-19 22:12:31 +02:00
void MessagePort : : start ( )
{
2024-03-12 10:53:21 +01:00
if ( ! is_entangled ( ) )
return ;
2025-04-08 22:01:46 +02:00
VERIFY ( m_transport ) ;
2023-12-18 17:24:31 -07:00
2025-06-07 23:57:17 +02:00
// The start() method steps are to enable this's port message queue, if it is not already enabled.
enable ( ) ;
2021-09-19 22:12:31 +02:00
}
// 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.
2023-12-07 15:52:08 -07:00
set_detached ( true ) ;
2021-09-19 22:12:31 +02:00
// 2. If this MessagePort object is entangled, disentangle it.
if ( is_entangled ( ) )
disentangle ( ) ;
}
2024-12-15 01:17:08 +13:00
// https://html.spec.whatwg.org/multipage/web-messaging.html#handler-messageeventtarget-onmessageerror
void MessagePort : : set_onmessageerror ( GC : : Ptr < WebIDL : : CallbackType > value )
{
set_event_handler_attribute ( EventNames : : messageerror , value ) ;
}
// https://html.spec.whatwg.org/multipage/web-messaging.html#handler-messageeventtarget-onmessageerror
GC : : Ptr < WebIDL : : CallbackType > MessagePort : : onmessageerror ( )
{
return event_handler_attribute ( EventNames : : messageerror ) ;
}
// https://html.spec.whatwg.org/multipage/web-messaging.html#handler-messageeventtarget-onmessage
void MessagePort : : set_onmessage ( GC : : Ptr < WebIDL : : CallbackType > value )
{
set_event_handler_attribute ( EventNames : : message , value ) ;
2024-12-15 22:11:19 +13:00
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports:handler-messageeventtarget-onmessage
// The first time a MessagePort object's onmessage IDL attribute is set, the port's port message queue must be enabled,
// as if the start() method had been called.
start ( ) ;
2024-12-15 01:17:08 +13:00
}
// https://html.spec.whatwg.org/multipage/web-messaging.html#handler-messageeventtarget-onmessage
GC : : Ptr < WebIDL : : CallbackType > MessagePort : : onmessage ( )
{
return event_handler_attribute ( EventNames : : message ) ;
}
2021-09-19 22:12:31 +02:00
}