diff --git a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp index 84811b897f..90439b0792 100644 --- a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp +++ b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp @@ -701,16 +701,12 @@ public: break; } case ValueTag::BooleanPrimitive: { - value = JS::Value(static_cast(m_serialized[m_position++])); + value = JS::Value { deserialize_boolean_primitive(m_serialized, m_position) }; is_primitive = true; break; } case ValueTag::NumberPrimitive: { - u32 bits[2] = {}; - bits[0] = m_serialized[m_position++]; - bits[1] = m_serialized[m_position++]; - auto double_value = *bit_cast(&bits); - value = JS::Value(double_value); + value = JS::Value { deserialize_number_primitive(m_serialized, m_position) }; is_primitive = true; break; } @@ -728,51 +724,33 @@ public: } // 6. Otherwise, if serialized.[[Type]] is "Boolean", then set value to a new Boolean object in targetRealm whose [[BooleanData]] internal slot value is serialized.[[BooleanData]]. case BooleanObject: { - auto* realm = m_vm.current_realm(); - auto bool_value = static_cast(m_serialized[m_position++]); - value = JS::BooleanObject::create(*realm, bool_value); + value = deserialize_boolean_object(*m_vm.current_realm(), m_serialized, m_position); break; } // 7. Otherwise, if serialized.[[Type]] is "Number", then set value to a new Number object in targetRealm whose [[NumberData]] internal slot value is serialized.[[NumberData]]. case ValueTag::NumberObject: { - auto* realm = m_vm.current_realm(); - u32 bits[2]; - bits[0] = m_serialized[m_position++]; - bits[1] = m_serialized[m_position++]; - auto double_value = *bit_cast(&bits); - value = JS::NumberObject::create(*realm, double_value); + value = deserialize_number_object(*m_vm.current_realm(), m_serialized, m_position); break; } // 8. Otherwise, if serialized.[[Type]] is "BigInt", then set value to a new BigInt object in targetRealm whose [[BigIntData]] internal slot value is serialized.[[BigIntData]]. case ValueTag::BigIntObject: { - auto* realm = m_vm.current_realm(); - auto big_int = TRY(deserialize_big_int_primitive(m_vm, m_serialized, m_position)); - value = JS::BigIntObject::create(*realm, big_int); + value = TRY(deserialize_big_int_object(*m_vm.current_realm(), m_serialized, m_position)); break; } // 9. Otherwise, if serialized.[[Type]] is "String", then set value to a new String object in targetRealm whose [[StringData]] internal slot value is serialized.[[StringData]]. case ValueTag::StringObject: { - auto* realm = m_vm.current_realm(); - auto string = TRY(deserialize_string_primitive(m_vm, m_serialized, m_position)); - value = JS::StringObject::create(*realm, string, realm->intrinsics().string_prototype()); + value = TRY(deserialize_string_object(*m_vm.current_realm(), m_serialized, m_position)); break; } // 10. Otherwise, if serialized.[[Type]] is "Date", then set value to a new Date object in targetRealm whose [[DateValue]] internal slot value is serialized.[[DateValue]]. case ValueTag::DateObject: { - auto* realm = m_vm.current_realm(); - u32 bits[2]; - bits[0] = m_serialized[m_position++]; - bits[1] = m_serialized[m_position++]; - auto double_value = *bit_cast(&bits); - value = JS::Date::create(*realm, double_value); + value = deserialize_date_object(*m_vm.current_realm(), m_serialized, m_position); break; } // 11. Otherwise, if serialized.[[Type]] is "RegExp", then set value to a new RegExp object in targetRealm whose [[RegExpMatcher]] internal slot value is serialized.[[RegExpMatcher]], // whose [[OriginalSource]] internal slot value is serialized.[[OriginalSource]], and whose [[OriginalFlags]] internal slot value is serialized.[[OriginalFlags]]. case ValueTag::RegExpObject: { - auto pattern = TRY(deserialize_string_primitive(m_vm, m_serialized, m_position)); - auto flags = TRY(deserialize_string_primitive(m_vm, m_serialized, m_position)); - value = TRY(JS::regexp_create(m_vm, move(pattern), move(flags))); + value = TRY(deserialize_reg_exp_object(*m_vm.current_realm(), m_serialized, m_position)); break; } // FIXME: 12. Otherwise, if serialized.[[Type]] is "SharedArrayBuffer", then: @@ -1008,8 +986,67 @@ private: } }; +bool deserialize_boolean_primitive(ReadonlySpan const& serialized, size_t& position) +{ + VERIFY(position < serialized.size()); + return static_cast(serialized[position++]); +} + +double deserialize_number_primitive(ReadonlySpan const& serialized, size_t& position) +{ + VERIFY(position + 2 <= serialized.size()); + u32 const bits[2] { + serialized[position++], + serialized[position++], + }; + return *bit_cast(&bits); +} + +JS::NonnullGCPtr deserialize_boolean_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position) +{ + auto boolean_primitive = deserialize_boolean_primitive(serialized, position); + return JS::BooleanObject::create(realm, boolean_primitive); +} + +JS::NonnullGCPtr deserialize_number_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position) +{ + auto number_primitive = deserialize_number_primitive(serialized, position); + return JS::NumberObject::create(realm, number_primitive); +} + +WebIDL::ExceptionOr> deserialize_big_int_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position) +{ + auto big_int_primitive = TRY(deserialize_big_int_primitive(realm.vm(), serialized, position)); + return JS::BigIntObject::create(realm, big_int_primitive); +} + +WebIDL::ExceptionOr> deserialize_string_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position) +{ + auto string_primitive = TRY(deserialize_string_primitive(realm.vm(), serialized, position)); + return JS::StringObject::create(realm, string_primitive, realm.intrinsics().string_prototype()); +} + +JS::NonnullGCPtr deserialize_date_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position) +{ + VERIFY(position + 2 <= serialized.size()); + u32 const bits[2] { + serialized[position++], + serialized[position++], + }; + auto double_value = *bit_cast(&bits); + return JS::Date::create(realm, double_value); +} + +WebIDL::ExceptionOr> deserialize_reg_exp_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position) +{ + auto pattern = TRY(deserialize_string_primitive(realm.vm(), serialized, position)); + auto flags = TRY(deserialize_string_primitive(realm.vm(), serialized, position)); + return TRY(JS::regexp_create(realm.vm(), move(pattern), move(flags))); +} + WebIDL::ExceptionOr deserialize_bytes(JS::VM& vm, ReadonlySpan vector, size_t& position) { + VERIFY(position + 2 <= vector.size()); u32 size_bits[2]; size_bits[0] = vector[position++]; size_bits[1] = vector[position++]; diff --git a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h index dc0b5c45e4..74f549cd6e 100644 --- a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h +++ b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h @@ -70,6 +70,15 @@ WebIDL::ExceptionOr serialize_array_buffer(JS::VM& vm, Vector& vector template ViewType> WebIDL::ExceptionOr serialize_viewed_array_buffer(JS::VM& vm, Vector& vector, ViewType const& view, bool for_storage, SerializationMemory& memory); +bool deserialize_boolean_primitive(ReadonlySpan const& serialized, size_t& position); +double deserialize_number_primitive(ReadonlySpan const& serialized, size_t& position); +JS::NonnullGCPtr deserialize_boolean_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); +JS::NonnullGCPtr deserialize_number_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); +WebIDL::ExceptionOr> deserialize_big_int_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); +WebIDL::ExceptionOr> deserialize_string_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); +JS::NonnullGCPtr deserialize_date_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); +WebIDL::ExceptionOr> deserialize_reg_exp_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); + WebIDL::ExceptionOr deserialize_bytes(JS::VM& vm, ReadonlySpan vector, size_t& position); WebIDL::ExceptionOr deserialize_string(JS::VM& vm, ReadonlySpan vector, size_t& position); WebIDL::ExceptionOr> deserialize_string_primitive(JS::VM& vm, ReadonlySpan vector, size_t& position);