mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 19:17:41 +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);
|
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()
|
void MessagePort::disentangle()
|
||||||
{
|
{
|
||||||
m_remote_port->m_remote_port = nullptr;
|
m_remote_port->m_remote_port = nullptr;
|
||||||
|
@ -112,7 +153,7 @@ void MessagePort::start()
|
||||||
void MessagePort::close()
|
void MessagePort::close()
|
||||||
{
|
{
|
||||||
// 1. Set this MessagePort object's [[Detached]] internal slot value to true.
|
// 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.
|
// 2. If this MessagePort object is entangled, disentangle it.
|
||||||
if (is_entangled())
|
if (is_entangled())
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/Weakable.h>
|
#include <AK/Weakable.h>
|
||||||
|
#include <LibWeb/Bindings/Transferable.h>
|
||||||
#include <LibWeb/DOM/EventTarget.h>
|
#include <LibWeb/DOM/EventTarget.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
|
|
||||||
|
@ -23,7 +24,8 @@ struct StructuredSerializeOptions {
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports
|
// 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);
|
WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget);
|
||||||
JS_DECLARE_ALLOCATOR(MessagePort);
|
JS_DECLARE_ALLOCATOR(MessagePort);
|
||||||
|
|
||||||
|
@ -49,6 +51,11 @@ public:
|
||||||
ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
|
ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
|
||||||
#undef __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:
|
private:
|
||||||
explicit MessagePort(JS::Realm&);
|
explicit MessagePort(JS::Realm&);
|
||||||
|
|
||||||
|
@ -63,9 +70,6 @@ private:
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
|
||||||
bool m_has_been_shipped { false };
|
bool m_has_been_shipped { false };
|
||||||
|
|
||||||
// This is TransferableObject.[[Detached]]
|
|
||||||
bool m_detached { false };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <AK/Result.h>
|
#include <AK/Result.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibIPC/Forward.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||||
|
|
||||||
|
@ -24,6 +25,25 @@ using SerializationRecord = Vector<u32>;
|
||||||
using SerializationMemory = HashMap<JS::Handle<JS::Value>, u32>;
|
using SerializationMemory = HashMap<JS::Handle<JS::Value>, u32>;
|
||||||
using DeserializationMemory = JS::MarkedVector<JS::Value>;
|
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(JS::VM& vm, JS::Value);
|
||||||
WebIDL::ExceptionOr<SerializationRecord> structured_serialize_for_storage(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&);
|
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