LibWeb: Add {de}serialization steps for RegExpObjects

We skip serializing any of the internal state of the Regex<ECMA262>
object, because that state is all computable from the input pattern
and flags. If it turns out that this is really, really slow, we can add
some optimizations to serialize more of the regex parse result.
This commit is contained in:
Andrew Kaster 2023-09-11 16:32:13 -06:00 committed by Andreas Kling
parent 3a74bd2509
commit 267074cd81
3 changed files with 25 additions and 1 deletions

View file

@ -5,4 +5,5 @@ false
This is a String object
9007199254740991
1692748800000
/abc/gimsuy
ERROR: DataCloneError: Cannot serialize Symbol

View file

@ -8,6 +8,7 @@
println(structuredClone(new String("This is a String object")));
println(structuredClone(BigInt("0x1fffffffffffff")));
println(structuredClone(Date.UTC(2023, 7, 23)));
println(structuredClone(/abc/gimsuy));
try {
structuredClone(Symbol("foo"));

View file

@ -16,6 +16,7 @@
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/NumberObject.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/RegExpObject.h>
#include <LibJS/Runtime/StringObject.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
@ -67,6 +68,8 @@ enum ValueTag {
DateObject,
RegExpObject,
// TODO: Define many more types
// This tag or higher are understood to be errors
@ -171,7 +174,20 @@ public:
m_serialized.append(bit_cast<u32*>(&date_value), 2);
}
// 12 - 24: FIXME: Serialize other data types
// 12. Otherwise, if value has a [[RegExpMatcher]] internal slot, then set serialized to
// { [[Type]]: "RegExp", [[RegExpMatcher]]: value.[[RegExpMatcher]], [[OriginalSource]]: value.[[OriginalSource]],
// [[OriginalFlags]]: value.[[OriginalFlags]] }.
else if (value.is_object() && is<JS::RegExpObject>(value.as_object())) {
m_serialized.append(ValueTag::RegExpObject);
auto& regexp_object = static_cast<JS::RegExpObject&>(value.as_object());
// Note: A Regex<ECMA262> object is perfectly happy to be reconstructed with just the source+flags
// In the future, we could optimize the work being done on the deserialize step by serializing
// more of the internal state (the [[RegExpMatcher]] internal slot)
TRY(serialize_string(m_serialized, TRY_OR_THROW_OOM(m_vm, String::from_deprecated_string(regexp_object.pattern()))));
TRY(serialize_string(m_serialized, TRY_OR_THROW_OOM(m_vm, String::from_deprecated_string(regexp_object.flags()))));
}
// 13 - 24: FIXME: Serialize other data types
else {
return throw_completion(WebIDL::DataCloneError::create(*m_vm.current_realm(), "Unsupported type"_fly_string));
}
@ -301,6 +317,12 @@ public:
m_memory.append(JS::Date::create(*realm, value));
break;
}
case ValueTag::RegExpObject: {
auto pattern = TRY(deserialize_string_primitive(m_vm, m_vector, position));
auto flags = TRY(deserialize_string_primitive(m_vm, m_vector, position));
m_memory.append(TRY(JS::regexp_create(m_vm, move(pattern), move(flags))));
break;
}
default:
m_error = "Unsupported type"_fly_string;
break;