mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 19:37:35 +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:
parent
512624f31a
commit
e21d1078a0
4 changed files with 107 additions and 5 deletions
37
Userland/Libraries/LibWeb/Bindings/Transferable.h
Normal file
37
Userland/Libraries/LibWeb/Bindings/Transferable.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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())
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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&);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue