/src/serenity/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2022, Daniel Ehrenberg <dan@littledan.dev> |
3 | | * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org> |
4 | | * Copyright (c) 2024, Kenneth Myhra <kennethmyhra@serenityos.org> |
5 | | * |
6 | | * SPDX-License-Identifier: BSD-2-Clause |
7 | | */ |
8 | | |
9 | | #pragma once |
10 | | |
11 | | #include <AK/Result.h> |
12 | | #include <AK/Types.h> |
13 | | #include <AK/Vector.h> |
14 | | #include <LibIPC/Forward.h> |
15 | | #include <LibJS/Forward.h> |
16 | | #include <LibWeb/WebIDL/ExceptionOr.h> |
17 | | |
18 | | // Structured serialize is an entirely different format from IPC because: |
19 | | // - It contains representation of type information |
20 | | // - It may contain circularities |
21 | | // - It is restricted to JS values |
22 | | |
23 | | namespace Web::HTML { |
24 | | |
25 | | using SerializationRecord = Vector<u32>; |
26 | | using SerializationMemory = HashMap<JS::Handle<JS::Value>, u32>; |
27 | | using DeserializationMemory = JS::MarkedVector<JS::Value>; |
28 | | |
29 | | struct TransferDataHolder { |
30 | | Vector<u8> data; |
31 | | Vector<IPC::File> fds; |
32 | | }; |
33 | | |
34 | | struct SerializedTransferRecord { |
35 | | SerializationRecord serialized; |
36 | | Vector<TransferDataHolder> transfer_data_holders; |
37 | | }; |
38 | | |
39 | | struct DeserializedTransferRecord { |
40 | | JS::Value deserialized; |
41 | | Vector<JS::Handle<JS::Object>> transferred_values; |
42 | | }; |
43 | | |
44 | | struct DeserializedRecord { |
45 | | Optional<JS::Value> value; |
46 | | size_t position; |
47 | | }; |
48 | | |
49 | | enum class TransferType : u8 { |
50 | | MessagePort, |
51 | | }; |
52 | | |
53 | | WebIDL::ExceptionOr<SerializationRecord> structured_serialize(JS::VM& vm, JS::Value); |
54 | | WebIDL::ExceptionOr<SerializationRecord> structured_serialize_for_storage(JS::VM& vm, JS::Value); |
55 | | WebIDL::ExceptionOr<SerializationRecord> structured_serialize_internal(JS::VM& vm, JS::Value, bool for_storage, SerializationMemory&); |
56 | | |
57 | | WebIDL::ExceptionOr<JS::Value> structured_deserialize(JS::VM& vm, SerializationRecord const& serialized, JS::Realm& target_realm, Optional<DeserializationMemory>); |
58 | | WebIDL::ExceptionOr<DeserializedRecord> structured_deserialize_internal(JS::VM& vm, ReadonlySpan<u32> const& serialized, JS::Realm& target_realm, DeserializationMemory& memory, Optional<size_t> position = {}); |
59 | | |
60 | | void serialize_boolean_primitive(SerializationRecord& serialized, JS::Value& value); |
61 | | void serialize_number_primitive(SerializationRecord& serialized, JS::Value& value); |
62 | | WebIDL::ExceptionOr<void> serialize_big_int_primitive(JS::VM& vm, SerializationRecord& serialized, JS::Value& value); |
63 | | WebIDL::ExceptionOr<void> serialize_string_primitive(JS::VM& vm, SerializationRecord& serialized, JS::Value& value); |
64 | | void serialize_boolean_object(SerializationRecord& serialized, JS::Value& value); |
65 | | void serialize_number_object(SerializationRecord& serialized, JS::Value& value); |
66 | | WebIDL::ExceptionOr<void> serialize_big_int_object(JS::VM& vm, SerializationRecord& serialized, JS::Value& value); |
67 | | WebIDL::ExceptionOr<void> serialize_string_object(JS::VM& vm, SerializationRecord& serialized, JS::Value& value); |
68 | | void serialize_date_object(SerializationRecord& serialized, JS::Value& value); |
69 | | WebIDL::ExceptionOr<void> serialize_reg_exp_object(JS::VM& vm, SerializationRecord& serialized, JS::Value& value); |
70 | | |
71 | | template<typename T> |
72 | | requires(IsIntegral<T> || IsFloatingPoint<T>) |
73 | | void serialize_primitive_type(SerializationRecord& serialized, T value) |
74 | 0 | { |
75 | 0 | if constexpr (sizeof(T) < sizeof(u32)) { |
76 | | // NOTE: If the value is smaller than a u32, we can just store it directly. |
77 | 0 | serialized.append(static_cast<u32>(value)); |
78 | 0 | return; |
79 | 0 | } |
80 | 0 | serialized.append(bit_cast<u32*>(&value), sizeof(T) / 4); |
81 | 0 | } Unexecuted instantiation: _ZN3Web4HTML24serialize_primitive_typeIjQoo10IsIntegralIT_E15IsFloatingPointIS2_EEEvRN2AK6VectorIjLm0EEES2_ Unexecuted instantiation: _ZN3Web4HTML24serialize_primitive_typeIbQoo10IsIntegralIT_E15IsFloatingPointIS2_EEEvRN2AK6VectorIjLm0EEES2_ Unexecuted instantiation: _ZN3Web4HTML24serialize_primitive_typeIdQoo10IsIntegralIT_E15IsFloatingPointIS2_EEEvRN2AK6VectorIjLm0EEES2_ Unexecuted instantiation: _ZN3Web4HTML24serialize_primitive_typeIlQoo10IsIntegralIT_E15IsFloatingPointIS2_EEEvRN2AK6VectorIjLm0EEES2_ Unexecuted instantiation: _ZN3Web4HTML24serialize_primitive_typeImQoo10IsIntegralIT_E15IsFloatingPointIS2_EEEvRN2AK6VectorIjLm0EEES2_ |
82 | | |
83 | | template<typename T> |
84 | | requires(IsEnum<T>) |
85 | | void serialize_enum(SerializationRecord& serialized, T value) |
86 | 0 | { |
87 | 0 | serialize_primitive_type<UnderlyingType<T>>(serialized, to_underlying(value)); |
88 | 0 | } Unexecuted instantiation: _ZN3Web4HTML14serialize_enumINS0_9ErrorTypeEQ6IsEnumIT_EEEvRN2AK6VectorIjLm0EEES3_ Unexecuted instantiation: _ZN3Web4HTML14serialize_enumINS0_8ValueTagEQ6IsEnumIT_EEEvRN2AK6VectorIjLm0EEES3_ |
89 | | |
90 | | WebIDL::ExceptionOr<void> serialize_bytes(JS::VM& vm, Vector<u32>& vector, ReadonlyBytes bytes); |
91 | | WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, DeprecatedFlyString const& string); |
92 | | WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, String const& string); |
93 | | WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, JS::PrimitiveString const& primitive_string); |
94 | | WebIDL::ExceptionOr<void> serialize_array_buffer(JS::VM& vm, Vector<u32>& vector, JS::ArrayBuffer const& array_buffer, bool for_storage); |
95 | | template<OneOf<JS::TypedArrayBase, JS::DataView> ViewType> |
96 | | WebIDL::ExceptionOr<void> serialize_viewed_array_buffer(JS::VM& vm, Vector<u32>& vector, ViewType const& view, bool for_storage, SerializationMemory& memory); |
97 | | |
98 | | bool deserialize_boolean_primitive(ReadonlySpan<u32> const& serialized, size_t& position); |
99 | | double deserialize_number_primitive(ReadonlySpan<u32> const& serialized, size_t& position); |
100 | | JS::NonnullGCPtr<JS::BooleanObject> deserialize_boolean_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position); |
101 | | JS::NonnullGCPtr<JS::NumberObject> deserialize_number_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position); |
102 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::BigIntObject>> deserialize_big_int_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position); |
103 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::StringObject>> deserialize_string_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position); |
104 | | JS::NonnullGCPtr<JS::Date> deserialize_date_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position); |
105 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::RegExpObject>> deserialize_reg_exp_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position); |
106 | | |
107 | | template<typename T> |
108 | | requires(IsIntegral<T> || IsFloatingPoint<T> || IsEnum<T>) |
109 | | T deserialize_primitive_type(ReadonlySpan<u32> const& serialized, size_t& position) |
110 | 0 | { |
111 | 0 | T value; |
112 | | // NOTE: Make sure we always round up, otherwise Ts that are less than 32 bit will end up with a size of 0. |
113 | 0 | auto size = 1 + ((sizeof(value) - 1) / 4); |
114 | 0 | VERIFY(position + size <= serialized.size()); |
115 | 0 | memcpy(&value, serialized.offset_pointer(position), sizeof(value)); |
116 | 0 | position += size; |
117 | 0 | return value; |
118 | 0 | } Unexecuted instantiation: _ZN3Web4HTML26deserialize_primitive_typeIjQoooo10IsIntegralIT_E15IsFloatingPointIS2_E6IsEnumIS2_EEES2_RKN2AK4SpanIKjEERm Unexecuted instantiation: _ZN3Web4HTML26deserialize_primitive_typeIbQoooo10IsIntegralIT_E15IsFloatingPointIS2_E6IsEnumIS2_EEES2_RKN2AK4SpanIKjEERm Unexecuted instantiation: _ZN3Web4HTML26deserialize_primitive_typeIdQoooo10IsIntegralIT_E15IsFloatingPointIS2_E6IsEnumIS2_EEES2_RKN2AK4SpanIKjEERm Unexecuted instantiation: _ZN3Web4HTML26deserialize_primitive_typeIlQoooo10IsIntegralIT_E15IsFloatingPointIS2_E6IsEnumIS2_EEES2_RKN2AK4SpanIKjEERm Unexecuted instantiation: _ZN3Web4HTML26deserialize_primitive_typeImQoooo10IsIntegralIT_E15IsFloatingPointIS2_E6IsEnumIS2_EEES2_RKN2AK4SpanIKjEERm Unexecuted instantiation: _ZN3Web4HTML26deserialize_primitive_typeINS0_8ValueTagEQoooo10IsIntegralIT_E15IsFloatingPointIS3_E6IsEnumIS3_EEES3_RKN2AK4SpanIKjEERm Unexecuted instantiation: _ZN3Web4HTML26deserialize_primitive_typeINS0_9ErrorTypeEQoooo10IsIntegralIT_E15IsFloatingPointIS3_E6IsEnumIS3_EEES3_RKN2AK4SpanIKjEERm |
119 | | |
120 | | WebIDL::ExceptionOr<ByteBuffer> deserialize_bytes(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position); |
121 | | WebIDL::ExceptionOr<String> deserialize_string(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position); |
122 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::PrimitiveString>> deserialize_string_primitive(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position); |
123 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::BigInt>> deserialize_big_int_primitive(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position); |
124 | | |
125 | | WebIDL::ExceptionOr<SerializedTransferRecord> structured_serialize_with_transfer(JS::VM& vm, JS::Value value, Vector<JS::Handle<JS::Object>> const& transfer_list); |
126 | | WebIDL::ExceptionOr<DeserializedTransferRecord> structured_deserialize_with_transfer(JS::VM& vm, SerializedTransferRecord&); |
127 | | |
128 | | } |
129 | | |
130 | | namespace IPC { |
131 | | |
132 | | template<> |
133 | | ErrorOr<void> encode(Encoder&, ::Web::HTML::SerializedTransferRecord const&); |
134 | | |
135 | | template<> |
136 | | ErrorOr<void> encode(Encoder&, ::Web::HTML::TransferDataHolder const&); |
137 | | |
138 | | template<> |
139 | | ErrorOr<::Web::HTML::SerializedTransferRecord> decode(Decoder&); |
140 | | |
141 | | template<> |
142 | | ErrorOr<::Web::HTML::TransferDataHolder> decode(Decoder&); |
143 | | |
144 | | } |