mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-02 22:30:31 +00:00
LibWeb: Add and use serialize_enum()
This commit is contained in:
parent
94c6389fc0
commit
49d7719a04
Notes:
sideshowbarker
2024-07-17 23:07:41 +09:00
Author: https://github.com/kennethmyhra
Commit: 49d7719a04
Pull-request: https://github.com/SerenityOS/serenity/pull/23538
Reviewed-by: https://github.com/ADKaster
2 changed files with 32 additions and 25 deletions
|
@ -168,20 +168,20 @@ public:
|
||||||
bool return_primitive_type = true;
|
bool return_primitive_type = true;
|
||||||
// 4. If Type(value) is Undefined, Null, Boolean, Number, BigInt, or String, then return { [[Type]]: "primitive", [[Value]]: value }.
|
// 4. If Type(value) is Undefined, Null, Boolean, Number, BigInt, or String, then return { [[Type]]: "primitive", [[Value]]: value }.
|
||||||
if (value.is_undefined()) {
|
if (value.is_undefined()) {
|
||||||
m_serialized.append(ValueTag::UndefinedPrimitive);
|
serialize_enum(m_serialized, ValueTag::UndefinedPrimitive);
|
||||||
} else if (value.is_null()) {
|
} else if (value.is_null()) {
|
||||||
m_serialized.append(ValueTag::NullPrimitive);
|
serialize_enum(m_serialized, ValueTag::NullPrimitive);
|
||||||
} else if (value.is_boolean()) {
|
} else if (value.is_boolean()) {
|
||||||
m_serialized.append(ValueTag::BooleanPrimitive);
|
serialize_enum(m_serialized, ValueTag::BooleanPrimitive);
|
||||||
serialize_boolean_primitive(m_serialized, value);
|
serialize_boolean_primitive(m_serialized, value);
|
||||||
} else if (value.is_number()) {
|
} else if (value.is_number()) {
|
||||||
m_serialized.append(ValueTag::NumberPrimitive);
|
serialize_enum(m_serialized, ValueTag::NumberPrimitive);
|
||||||
serialize_number_primitive(m_serialized, value);
|
serialize_number_primitive(m_serialized, value);
|
||||||
} else if (value.is_bigint()) {
|
} else if (value.is_bigint()) {
|
||||||
m_serialized.append(ValueTag::BigIntPrimitive);
|
serialize_enum(m_serialized, ValueTag::BigIntPrimitive);
|
||||||
TRY(serialize_big_int_primitive(m_vm, m_serialized, value));
|
TRY(serialize_big_int_primitive(m_vm, m_serialized, value));
|
||||||
} else if (value.is_string()) {
|
} else if (value.is_string()) {
|
||||||
m_serialized.append(ValueTag::StringPrimitive);
|
serialize_enum(m_serialized, ValueTag::StringPrimitive);
|
||||||
TRY(serialize_string_primitive(m_vm, m_serialized, value));
|
TRY(serialize_string_primitive(m_vm, m_serialized, value));
|
||||||
} else {
|
} else {
|
||||||
return_primitive_type = false;
|
return_primitive_type = false;
|
||||||
|
@ -198,31 +198,31 @@ public:
|
||||||
|
|
||||||
// 7. If value has a [[BooleanData]] internal slot, then set serialized to { [[Type]]: "Boolean", [[BooleanData]]: value.[[BooleanData]] }.
|
// 7. If value has a [[BooleanData]] internal slot, then set serialized to { [[Type]]: "Boolean", [[BooleanData]]: value.[[BooleanData]] }.
|
||||||
if (value.is_object() && is<JS::BooleanObject>(value.as_object())) {
|
if (value.is_object() && is<JS::BooleanObject>(value.as_object())) {
|
||||||
m_serialized.append(ValueTag::BooleanObject);
|
serialize_enum(m_serialized, ValueTag::BooleanObject);
|
||||||
serialize_boolean_object(m_serialized, value);
|
serialize_boolean_object(m_serialized, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. Otherwise, if value has a [[NumberData]] internal slot, then set serialized to { [[Type]]: "Number", [[NumberData]]: value.[[NumberData]] }.
|
// 8. Otherwise, if value has a [[NumberData]] internal slot, then set serialized to { [[Type]]: "Number", [[NumberData]]: value.[[NumberData]] }.
|
||||||
else if (value.is_object() && is<JS::NumberObject>(value.as_object())) {
|
else if (value.is_object() && is<JS::NumberObject>(value.as_object())) {
|
||||||
m_serialized.append(ValueTag::NumberObject);
|
serialize_enum(m_serialized, ValueTag::NumberObject);
|
||||||
serialize_number_object(m_serialized, value);
|
serialize_number_object(m_serialized, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. Otherwise, if value has a [[BigIntData]] internal slot, then set serialized to { [[Type]]: "BigInt", [[BigIntData]]: value.[[BigIntData]] }.
|
// 9. Otherwise, if value has a [[BigIntData]] internal slot, then set serialized to { [[Type]]: "BigInt", [[BigIntData]]: value.[[BigIntData]] }.
|
||||||
else if (value.is_object() && is<JS::BigIntObject>(value.as_object())) {
|
else if (value.is_object() && is<JS::BigIntObject>(value.as_object())) {
|
||||||
m_serialized.append(ValueTag::BigIntObject);
|
serialize_enum(m_serialized, ValueTag::BigIntObject);
|
||||||
TRY(serialize_big_int_object(m_vm, m_serialized, value));
|
TRY(serialize_big_int_object(m_vm, m_serialized, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10. Otherwise, if value has a [[StringData]] internal slot, then set serialized to { [[Type]]: "String", [[StringData]]: value.[[StringData]] }.
|
// 10. Otherwise, if value has a [[StringData]] internal slot, then set serialized to { [[Type]]: "String", [[StringData]]: value.[[StringData]] }.
|
||||||
else if (value.is_object() && is<JS::StringObject>(value.as_object())) {
|
else if (value.is_object() && is<JS::StringObject>(value.as_object())) {
|
||||||
m_serialized.append(ValueTag::StringObject);
|
serialize_enum(m_serialized, ValueTag::StringObject);
|
||||||
TRY(serialize_string_object(m_vm, m_serialized, value));
|
TRY(serialize_string_object(m_vm, m_serialized, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 11. Otherwise, if value has a [[DateValue]] internal slot, then set serialized to { [[Type]]: "Date", [[DateValue]]: value.[[DateValue]] }.
|
// 11. Otherwise, if value has a [[DateValue]] internal slot, then set serialized to { [[Type]]: "Date", [[DateValue]]: value.[[DateValue]] }.
|
||||||
else if (value.is_object() && is<JS::Date>(value.as_object())) {
|
else if (value.is_object() && is<JS::Date>(value.as_object())) {
|
||||||
m_serialized.append(ValueTag::DateObject);
|
serialize_enum(m_serialized, ValueTag::DateObject);
|
||||||
serialize_date_object(m_serialized, value);
|
serialize_date_object(m_serialized, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ public:
|
||||||
// { [[Type]]: "RegExp", [[RegExpMatcher]]: value.[[RegExpMatcher]], [[OriginalSource]]: value.[[OriginalSource]],
|
// { [[Type]]: "RegExp", [[RegExpMatcher]]: value.[[RegExpMatcher]], [[OriginalSource]]: value.[[OriginalSource]],
|
||||||
// [[OriginalFlags]]: value.[[OriginalFlags]] }.
|
// [[OriginalFlags]]: value.[[OriginalFlags]] }.
|
||||||
else if (value.is_object() && is<JS::RegExpObject>(value.as_object())) {
|
else if (value.is_object() && is<JS::RegExpObject>(value.as_object())) {
|
||||||
m_serialized.append(ValueTag::RegExpObject);
|
serialize_enum(m_serialized, ValueTag::RegExpObject);
|
||||||
TRY(serialize_reg_exp_object(m_vm, m_serialized, value));
|
TRY(serialize_reg_exp_object(m_vm, m_serialized, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ public:
|
||||||
// 15. Otherwise, if value has [[MapData]] internal slot, then:
|
// 15. Otherwise, if value has [[MapData]] internal slot, then:
|
||||||
else if (value.is_object() && is<JS::Map>(value.as_object())) {
|
else if (value.is_object() && is<JS::Map>(value.as_object())) {
|
||||||
// 1. Set serialized to { [[Type]]: "Map", [[MapData]]: a new empty List }.
|
// 1. Set serialized to { [[Type]]: "Map", [[MapData]]: a new empty List }.
|
||||||
m_serialized.append(ValueTag::MapObject);
|
serialize_enum(m_serialized, ValueTag::MapObject);
|
||||||
// 2. Set deep to true.
|
// 2. Set deep to true.
|
||||||
deep = true;
|
deep = true;
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ public:
|
||||||
// 16. Otherwise, if value has [[SetData]] internal slot, then:
|
// 16. Otherwise, if value has [[SetData]] internal slot, then:
|
||||||
else if (value.is_object() && is<JS::Set>(value.as_object())) {
|
else if (value.is_object() && is<JS::Set>(value.as_object())) {
|
||||||
// 1. Set serialized to { [[Type]]: "Set", [[SetData]]: a new empty List }.
|
// 1. Set serialized to { [[Type]]: "Set", [[SetData]]: a new empty List }.
|
||||||
m_serialized.append(ValueTag::SetObject);
|
serialize_enum(m_serialized, ValueTag::SetObject);
|
||||||
// 2. Set deep to true.
|
// 2. Set deep to true.
|
||||||
deep = true;
|
deep = true;
|
||||||
}
|
}
|
||||||
|
@ -284,8 +284,8 @@ public:
|
||||||
|
|
||||||
// 5. Set serialized to { [[Type]]: "Error", [[Name]]: name, [[Message]]: message }.
|
// 5. Set serialized to { [[Type]]: "Error", [[Name]]: name, [[Message]]: message }.
|
||||||
// FIXME: 6. User agents should attach a serialized representation of any interesting accompanying data which are not yet specified, notably the stack property, to serialized.
|
// FIXME: 6. User agents should attach a serialized representation of any interesting accompanying data which are not yet specified, notably the stack property, to serialized.
|
||||||
m_serialized.append(ValueTag::ErrorObject);
|
serialize_enum(m_serialized, ValueTag::ErrorObject);
|
||||||
m_serialized.append(type);
|
serialize_enum(m_serialized, type);
|
||||||
serialize_primitive_type(m_serialized, message.has_value());
|
serialize_primitive_type(m_serialized, message.has_value());
|
||||||
if (message.has_value())
|
if (message.has_value())
|
||||||
TRY(serialize_string(m_vm, m_serialized, *message));
|
TRY(serialize_string(m_vm, m_serialized, *message));
|
||||||
|
@ -299,7 +299,7 @@ public:
|
||||||
u64 length = MUST(JS::length_of_array_like(m_vm, value.as_object()));
|
u64 length = MUST(JS::length_of_array_like(m_vm, value.as_object()));
|
||||||
|
|
||||||
// 3. Set serialized to { [[Type]]: "Array", [[Length]]: valueLen, [[Properties]]: a new empty List }.
|
// 3. Set serialized to { [[Type]]: "Array", [[Length]]: valueLen, [[Properties]]: a new empty List }.
|
||||||
m_serialized.append(ValueTag::ArrayObject);
|
serialize_enum(m_serialized, ValueTag::ArrayObject);
|
||||||
serialize_primitive_type(m_serialized, length);
|
serialize_primitive_type(m_serialized, length);
|
||||||
|
|
||||||
// 4. Set deep to true.
|
// 4. Set deep to true.
|
||||||
|
@ -310,7 +310,7 @@ public:
|
||||||
else if (value.is_object() && is<Bindings::Serializable>(value.as_object())) {
|
else if (value.is_object() && is<Bindings::Serializable>(value.as_object())) {
|
||||||
auto& serializable = dynamic_cast<Bindings::Serializable&>(value.as_object());
|
auto& serializable = dynamic_cast<Bindings::Serializable&>(value.as_object());
|
||||||
|
|
||||||
m_serialized.append(ValueTag::SerializableObject);
|
serialize_enum(m_serialized, ValueTag::SerializableObject);
|
||||||
|
|
||||||
TRY(serialize_string(m_vm, m_serialized, serializable.interface_name()));
|
TRY(serialize_string(m_vm, m_serialized, serializable.interface_name()));
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ public:
|
||||||
// 24. Otherwise:
|
// 24. Otherwise:
|
||||||
else {
|
else {
|
||||||
// 1. Set serialized to { [[Type]]: "Object", [[Properties]]: a new empty List }.
|
// 1. Set serialized to { [[Type]]: "Object", [[Properties]]: a new empty List }.
|
||||||
m_serialized.append(ValueTag::Object);
|
serialize_enum(m_serialized, ValueTag::Object);
|
||||||
|
|
||||||
// 2. Set deep to true.
|
// 2. Set deep to true.
|
||||||
deep = true;
|
deep = true;
|
||||||
|
@ -593,7 +593,7 @@ WebIDL::ExceptionOr<void> serialize_array_buffer(JS::VM& vm, Vector<u32>& vector
|
||||||
}
|
}
|
||||||
// 6. Otherwise, set serialized to { [[Type]]: "ArrayBuffer", [[ArrayBufferData]]: dataCopy, [[ArrayBufferByteLength]]: size }.
|
// 6. Otherwise, set serialized to { [[Type]]: "ArrayBuffer", [[ArrayBufferData]]: dataCopy, [[ArrayBufferByteLength]]: size }.
|
||||||
else {
|
else {
|
||||||
vector.append(ValueTag::ArrayBuffer);
|
serialize_enum(vector, ValueTag::ArrayBuffer);
|
||||||
TRY(serialize_bytes(vm, vector, data_copy.buffer().bytes()));
|
TRY(serialize_bytes(vm, vector, data_copy.buffer().bytes()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,7 +635,7 @@ WebIDL::ExceptionOr<void> serialize_viewed_array_buffer(JS::VM& vm, Vector<u32>&
|
||||||
// 5. If value has a [[DataView]] internal slot, then set serialized to { [[Type]]: "ArrayBufferView", [[Constructor]]: "DataView",
|
// 5. If value has a [[DataView]] internal slot, then set serialized to { [[Type]]: "ArrayBufferView", [[Constructor]]: "DataView",
|
||||||
// [[ArrayBufferSerialized]]: bufferSerialized, [[ByteLength]]: value.[[ByteLength]], [[ByteOffset]]: value.[[ByteOffset]] }.
|
// [[ArrayBufferSerialized]]: bufferSerialized, [[ByteLength]]: value.[[ByteLength]], [[ByteOffset]]: value.[[ByteOffset]] }.
|
||||||
if constexpr (IsSame<ViewType, JS::DataView>) {
|
if constexpr (IsSame<ViewType, JS::DataView>) {
|
||||||
vector.append(ValueTag::ArrayBufferView);
|
serialize_enum(vector, ValueTag::ArrayBufferView);
|
||||||
vector.extend(move(buffer_serialized)); // [[ArrayBufferSerialized]]
|
vector.extend(move(buffer_serialized)); // [[ArrayBufferSerialized]]
|
||||||
TRY(serialize_string(vm, vector, "DataView"_string)); // [[Constructor]]
|
TRY(serialize_string(vm, vector, "DataView"_string)); // [[Constructor]]
|
||||||
serialize_primitive_type(vector, JS::get_view_byte_length(view_record));
|
serialize_primitive_type(vector, JS::get_view_byte_length(view_record));
|
||||||
|
@ -649,7 +649,7 @@ WebIDL::ExceptionOr<void> serialize_viewed_array_buffer(JS::VM& vm, Vector<u32>&
|
||||||
// 2. Set serialized to { [[Type]]: "ArrayBufferView", [[Constructor]]: value.[[TypedArrayName]],
|
// 2. Set serialized to { [[Type]]: "ArrayBufferView", [[Constructor]]: value.[[TypedArrayName]],
|
||||||
// [[ArrayBufferSerialized]]: bufferSerialized, [[ByteLength]]: value.[[ByteLength]],
|
// [[ArrayBufferSerialized]]: bufferSerialized, [[ByteLength]]: value.[[ByteLength]],
|
||||||
// [[ByteOffset]]: value.[[ByteOffset]], [[ArrayLength]]: value.[[ArrayLength]] }.
|
// [[ByteOffset]]: value.[[ByteOffset]], [[ArrayLength]]: value.[[ArrayLength]] }.
|
||||||
vector.append(ValueTag::ArrayBufferView);
|
serialize_enum(vector, ValueTag::ArrayBufferView);
|
||||||
vector.extend(move(buffer_serialized)); // [[ArrayBufferSerialized]]
|
vector.extend(move(buffer_serialized)); // [[ArrayBufferSerialized]]
|
||||||
TRY(serialize_string(vm, vector, view.element_name())); // [[Constructor]]
|
TRY(serialize_string(vm, vector, view.element_name())); // [[Constructor]]
|
||||||
serialize_primitive_type(vector, JS::typed_array_byte_length(view_record));
|
serialize_primitive_type(vector, JS::typed_array_byte_length(view_record));
|
||||||
|
@ -674,7 +674,7 @@ public:
|
||||||
// https://html.spec.whatwg.org/multipage/structured-data.html#structureddeserialize
|
// https://html.spec.whatwg.org/multipage/structured-data.html#structureddeserialize
|
||||||
WebIDL::ExceptionOr<JS::Value> deserialize()
|
WebIDL::ExceptionOr<JS::Value> deserialize()
|
||||||
{
|
{
|
||||||
auto tag = m_serialized[m_position++];
|
auto tag = deserialize_primitive_type<ValueTag>(m_serialized, m_position);
|
||||||
|
|
||||||
// 2. If memory[serialized] exists, then return memory[serialized].
|
// 2. If memory[serialized] exists, then return memory[serialized].
|
||||||
if (tag == ValueTag::ObjectReference) {
|
if (tag == ValueTag::ObjectReference) {
|
||||||
|
@ -840,7 +840,7 @@ public:
|
||||||
// 21. Otherwise, if serialized.[[Type]] is "Error", then:
|
// 21. Otherwise, if serialized.[[Type]] is "Error", then:
|
||||||
case ValueTag::ErrorObject: {
|
case ValueTag::ErrorObject: {
|
||||||
auto& realm = *m_vm.current_realm();
|
auto& realm = *m_vm.current_realm();
|
||||||
auto type = static_cast<ErrorType>(m_serialized[m_position++]);
|
auto type = deserialize_primitive_type<ErrorType>(m_serialized, m_position);
|
||||||
auto has_message = deserialize_primitive_type<bool>(m_serialized, m_position);
|
auto has_message = deserialize_primitive_type<bool>(m_serialized, m_position);
|
||||||
if (has_message) {
|
if (has_message) {
|
||||||
auto message = TRY(deserialize_string(m_vm, m_serialized, m_position));
|
auto message = TRY(deserialize_string(m_vm, m_serialized, m_position));
|
||||||
|
|
|
@ -74,6 +74,13 @@ void serialize_primitive_type(SerializationRecord& serialized, T value)
|
||||||
serialized.append(bit_cast<u32*>(&value), sizeof(T) / 4);
|
serialized.append(bit_cast<u32*>(&value), sizeof(T) / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
requires(IsEnum<T>)
|
||||||
|
void serialize_enum(SerializationRecord& serialized, T value)
|
||||||
|
{
|
||||||
|
serialize_primitive_type<UnderlyingType<T>>(serialized, to_underlying(value));
|
||||||
|
}
|
||||||
|
|
||||||
WebIDL::ExceptionOr<void> serialize_bytes(JS::VM& vm, Vector<u32>& vector, ReadonlyBytes bytes);
|
WebIDL::ExceptionOr<void> serialize_bytes(JS::VM& vm, Vector<u32>& vector, ReadonlyBytes bytes);
|
||||||
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, DeprecatedFlyString const& string);
|
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, DeprecatedFlyString const& string);
|
||||||
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, String const& string);
|
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, String const& string);
|
||||||
|
@ -92,7 +99,7 @@ JS::NonnullGCPtr<JS::Date> deserialize_date_object(JS::Realm& realm, ReadonlySpa
|
||||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::RegExpObject>> deserialize_reg_exp_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
|
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::RegExpObject>> deserialize_reg_exp_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires(IsIntegral<T> || IsFloatingPoint<T>)
|
requires(IsIntegral<T> || IsFloatingPoint<T> || IsEnum<T>)
|
||||||
T deserialize_primitive_type(ReadonlySpan<u32> const& serialized, size_t& position)
|
T deserialize_primitive_type(ReadonlySpan<u32> const& serialized, size_t& position)
|
||||||
{
|
{
|
||||||
T value;
|
T value;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue