1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 22:17:42 +00:00

LibWeb: Add a Transferable interface to model the transferable property

This property is only shared by MessagePort and a few Image related APIs
but is important for the Structured{De}SerializeWithTransfer AOs.
This commit is contained in:
Andrew Kaster 2023-12-07 15:52:08 -07:00 committed by Andreas Kling
parent 512624f31a
commit e21d1078a0
4 changed files with 107 additions and 5 deletions

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Vector.h>
#include <LibIPC/Forward.h>
#include <LibWeb/HTML/StructuredSerialize.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::Bindings {
// https://html.spec.whatwg.org/multipage/structured-data.html#transferable-objects
class Transferable {
public:
virtual ~Transferable() = default;
// NOTE: It is an error to call Base::transfer_steps in your impl
virtual WebIDL::ExceptionOr<void> transfer_steps(HTML::TransferDataHolder&) = 0;
// NOTE: It is an error to call Base::transfer_receiving_steps in your impl
virtual WebIDL::ExceptionOr<void> transfer_receiving_steps(HTML::TransferDataHolder const&) = 0;
virtual HTML::TransferType primary_interface() const = 0;
bool is_detached() const { return m_detached; }
void set_detached(bool b) { m_detached = b; }
private:
// https://html.spec.whatwg.org/multipage/structured-data.html#detached
bool m_detached = false;
};
}

View file

@ -40,6 +40,47 @@ void MessagePort::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_remote_port);
}
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports:transfer-steps
WebIDL::ExceptionOr<void> MessagePort::transfer_steps(HTML::TransferDataHolder&)
{
// 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;
// 2. Set dataHolder.[[RemotePort]] to remotePort.
// FIXME: Append an IPC::File to the dataHolder
}
// 4. Otherwise, set dataHolder.[[RemotePort]] to null.
else {
// FIXME: Note in the dataHolder that there are no fds
}
return {};
}
WebIDL::ExceptionOr<void> MessagePort::transfer_receiving_steps(HTML::TransferDataHolder const&)
{
// 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.
// FIXME: 3. If dataHolder.[[RemotePort]] is not null, then entangle dataHolder.[[RemotePort]] and value.
// (This will disentangle dataHolder.[[RemotePort]] from the original port that was transferred.)
return {};
}
void MessagePort::disentangle()
{
m_remote_port->m_remote_port = nullptr;
@ -112,7 +153,7 @@ void MessagePort::start()
void MessagePort::close()
{
// 1. Set this MessagePort object's [[Detached]] internal slot value to true.
m_detached = true;
set_detached(true);
// 2. If this MessagePort object is entangled, disentangle it.
if (is_entangled())

View file

@ -8,6 +8,7 @@
#include <AK/RefCounted.h>
#include <AK/Weakable.h>
#include <LibWeb/Bindings/Transferable.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/Forward.h>
@ -23,7 +24,8 @@ struct StructuredSerializeOptions {
};
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports
class MessagePort final : public DOM::EventTarget {
class MessagePort final : public DOM::EventTarget
, public Bindings::Transferable {
WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget);
JS_DECLARE_ALLOCATOR(MessagePort);
@ -49,6 +51,11 @@ public:
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 const&) override;
virtual HTML::TransferType primary_interface() const override { return HTML::TransferType::MessagePort; }
private:
explicit MessagePort(JS::Realm&);
@ -63,9 +70,6 @@ private:
// https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
bool m_has_been_shipped { false };
// This is TransferableObject.[[Detached]]
bool m_detached { false };
};
}

View file

@ -10,6 +10,7 @@
#include <AK/Result.h>
#include <AK/Types.h>
#include <AK/Vector.h>
#include <LibIPC/Forward.h>
#include <LibJS/Forward.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
@ -24,6 +25,25 @@ using SerializationRecord = Vector<u32>;
using SerializationMemory = HashMap<JS::Handle<JS::Value>, u32>;
using DeserializationMemory = JS::MarkedVector<JS::Value>;
struct TransferDataHolder {
Vector<u8> data;
Vector<IPC::File> fds;
};
struct SerializedTransferRecord {
SerializationRecord serialized;
Vector<TransferDataHolder> transfer_data_holders;
};
struct DeserializedTransferRecord {
JS::Value deserialized;
JS::MarkedVector<JS::Value> transferred_values;
};
enum class TransferType : u8 {
MessagePort,
};
WebIDL::ExceptionOr<SerializationRecord> structured_serialize(JS::VM& vm, JS::Value);
WebIDL::ExceptionOr<SerializationRecord> structured_serialize_for_storage(JS::VM& vm, JS::Value);
WebIDL::ExceptionOr<SerializationRecord> structured_serialize_internal(JS::VM& vm, JS::Value, bool for_storage, SerializationMemory&);