Skip to content

Commit d289b1d

Browse files
legendecasrichardlau
authored andcommitted
deps: V8: cherry-pick e3df60f3f5ab
Original commit message: [objects] allow host defined serializer of JSError Allow host defined serializer and deserializer of JSError in ValueSerializer API. This allows hosts that implement DOMException in JS to support `Error.isError` proposal and `structuredClone`. Refs: #58691 Change-Id: I022821c9abd659970c4d449b3c69c5fb54d0618a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6637876 Reviewed-by: Camillo Bruni <[email protected]> Commit-Queue: Chengzhong Wu <[email protected]> Cr-Commit-Position: refs/heads/main@{#100894} Refs: v8/v8@e3df60f PR-URL: #58691 Backport-PR-URL: #59957 Fixes: #56497 Refs: #58138 Reviewed-By: Jason Zhang <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Ethan Arrowood <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent da6e8cb commit d289b1d

File tree

3 files changed

+75
-3
lines changed

3 files changed

+75
-3
lines changed

common.gypi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
# Reset this number to 0 on major V8 upgrades.
4040
# Increment by one for each non-official patch applied to deps/v8.
41-
'v8_embedder_string': '-node.32',
41+
'v8_embedder_string': '-node.33',
4242

4343
##### V8 defaults for Node.js #####
4444

deps/v8/src/objects/value-serializer.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,17 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
643643
case JS_DATA_VIEW_TYPE:
644644
case JS_RAB_GSAB_DATA_VIEW_TYPE:
645645
return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver));
646-
case JS_ERROR_TYPE:
647-
return WriteJSError(Handle<JSObject>::cast(receiver));
646+
case JS_ERROR_TYPE: {
647+
Handle<JSObject> js_error = Handle<JSObject>::cast(receiver);
648+
Maybe<bool> is_host_object = IsHostObject(js_error);
649+
if (is_host_object.IsNothing()) {
650+
return is_host_object;
651+
}
652+
if (is_host_object.FromJust()) {
653+
return WriteHostObject(js_error);
654+
}
655+
return WriteJSError(js_error);
656+
}
648657
case JS_SHARED_ARRAY_TYPE:
649658
return WriteJSSharedArray(Handle<JSSharedArray>::cast(receiver));
650659
case JS_SHARED_STRUCT_TYPE:

deps/v8/test/unittests/objects/value-serializer-unittest.cc

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3139,6 +3139,69 @@ TEST_F(ValueSerializerTestWithHostObject, RoundTripHostJSObject) {
31393139
ExpectScriptTrue("result.a === result.b");
31403140
}
31413141

3142+
TEST_F(ValueSerializerTestWithHostObject, RoundTripJSErrorObject) {
3143+
i::DisableHandleChecksForMockingScope mocking_scope;
3144+
3145+
EXPECT_CALL(serializer_delegate_, HasCustomHostObject(isolate()))
3146+
.WillOnce(Invoke([](Isolate* isolate) { return true; }));
3147+
EXPECT_CALL(serializer_delegate_, IsHostObject(isolate(), _))
3148+
.WillRepeatedly(Invoke([this](Isolate* isolate, Local<Object> object) {
3149+
EXPECT_TRUE(object->IsObject());
3150+
Local<Context> context = isolate->GetCurrentContext();
3151+
return object->Has(context, StringFromUtf8("my_host_object"));
3152+
}));
3153+
// Read/Write HostObject methods are not invoked for non-host JSErrors.
3154+
EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _)).Times(0);
3155+
EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate())).Times(0);
3156+
3157+
RoundTripTest(
3158+
"var e = new Error('before serialize');"
3159+
"({ a: e, get b() { return this.a; } })");
3160+
ExpectScriptTrue("!('my_host_object' in result)");
3161+
ExpectScriptTrue("!('my_host_object' in result.a)");
3162+
ExpectScriptTrue("result.a.message === 'before serialize'");
3163+
ExpectScriptTrue("result.a instanceof Error");
3164+
ExpectScriptTrue("result.a === result.b");
3165+
}
3166+
3167+
TEST_F(ValueSerializerTestWithHostObject, RoundTripHostJSErrorObject) {
3168+
i::DisableHandleChecksForMockingScope mocking_scope;
3169+
3170+
EXPECT_CALL(serializer_delegate_, HasCustomHostObject(isolate()))
3171+
.WillOnce(Invoke([](Isolate* isolate) { return true; }));
3172+
EXPECT_CALL(serializer_delegate_, IsHostObject(isolate(), _))
3173+
.WillRepeatedly(Invoke([this](Isolate* isolate, Local<Object> object) {
3174+
EXPECT_TRUE(object->IsObject());
3175+
Local<Context> context = isolate->GetCurrentContext();
3176+
return object->Has(context, StringFromUtf8("my_host_object"));
3177+
}));
3178+
EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
3179+
.WillOnce(Invoke([this](Isolate*, Local<Object> object) {
3180+
EXPECT_TRUE(object->IsObject());
3181+
WriteExampleHostObjectTag();
3182+
return Just(true);
3183+
}));
3184+
EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
3185+
.WillOnce(Invoke([this](Isolate* isolate) {
3186+
EXPECT_TRUE(ReadExampleHostObjectTag());
3187+
Local<Context> context = isolate->GetCurrentContext();
3188+
Local<Object> obj =
3189+
v8::Exception::Error(StringFromUtf8("deserialized")).As<Object>();
3190+
obj->Set(context, StringFromUtf8("my_host_object"), v8::True(isolate))
3191+
.Check();
3192+
return obj;
3193+
}));
3194+
RoundTripTest(
3195+
"var e = new Error('before serialize');"
3196+
"e.my_host_object = true;"
3197+
"({ a: e, get b() { return this.a; } })");
3198+
ExpectScriptTrue("!('my_host_object' in result)");
3199+
ExpectScriptTrue("result.a.my_host_object");
3200+
ExpectScriptTrue("result.a.message === 'deserialized'");
3201+
ExpectScriptTrue("result.a instanceof Error");
3202+
ExpectScriptTrue("result.a === result.b");
3203+
}
3204+
31423205
class ValueSerializerTestWithHostArrayBufferView
31433206
: public ValueSerializerTestWithHostObject {
31443207
protected:

0 commit comments

Comments
 (0)