0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

fix(core): rethrow exception during structured cloning serialization (#14671)

- Introduced optional callback for Deno.core.serialize API, that returns
cloning error if there is one.
- Removed try/catch in seralize structured clone function and throw error from
callback.
- Removed "Object with a getter that throws" assertion from WPT.
This commit is contained in:
Mark Ladyshau 2022-05-26 17:14:38 +02:00 committed by GitHub
parent 3aa6d5d8b0
commit 402b497299
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 16 deletions

View file

@ -937,6 +937,7 @@ fn decode(
struct SerializeDeserialize<'a> { struct SerializeDeserialize<'a> {
host_objects: Option<v8::Local<'a, v8::Array>>, host_objects: Option<v8::Local<'a, v8::Array>>,
error_callback: Option<v8::Local<'a, v8::Function>>,
} }
impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> { impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
@ -946,6 +947,15 @@ impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
scope: &mut v8::HandleScope<'s>, scope: &mut v8::HandleScope<'s>,
message: v8::Local<'s, v8::String>, message: v8::Local<'s, v8::String>,
) { ) {
if let Some(cb) = self.error_callback {
let scope = &mut v8::TryCatch::new(scope);
let undefined = v8::undefined(scope).into();
cb.call(scope, undefined, &[message.into()]);
if scope.has_caught() || scope.has_terminated() {
scope.rethrow();
return;
};
}
let error = v8::Exception::type_error(scope, message); let error = v8::Exception::type_error(scope, message);
scope.throw_exception(error); scope.throw_exception(error);
} }
@ -1078,6 +1088,17 @@ fn serialize(
} }
}; };
let arg2_to_error_callback = match !args.get(2).is_undefined() {
true => match v8::Local::<v8::Function>::try_from(args.get(2)) {
Ok(cb) => Some(v8::Local::new(scope, cb)),
Err(_) => {
throw_type_error(scope, "Invalid argument 3");
return;
}
},
false => None,
};
let options = options.unwrap_or(SerializeDeserializeOptions { let options = options.unwrap_or(SerializeDeserializeOptions {
host_objects: None, host_objects: None,
transfered_array_buffers: None, transfered_array_buffers: None,
@ -1105,7 +1126,11 @@ fn serialize(
None => None, None => None,
}; };
let serialize_deserialize = Box::new(SerializeDeserialize { host_objects }); let serialize_deserialize = Box::new(SerializeDeserialize {
host_objects,
error_callback: arg2_to_error_callback,
});
let mut value_serializer = let mut value_serializer =
v8::ValueSerializer::new(scope, serialize_deserialize); v8::ValueSerializer::new(scope, serialize_deserialize);
@ -1227,7 +1252,10 @@ fn deserialize(
None => None, None => None,
}; };
let serialize_deserialize = Box::new(SerializeDeserialize { host_objects }); let serialize_deserialize = Box::new(SerializeDeserialize {
host_objects,
error_callback: None,
});
let mut value_deserializer = let mut value_deserializer =
v8::ValueDeserializer::new(scope, serialize_deserialize, &zero_copy); v8::ValueDeserializer::new(scope, serialize_deserialize, &zero_copy);

View file

@ -265,18 +265,15 @@
WeakSetPrototypeAdd(detachedArrayBuffers, arrayBuffer); WeakSetPrototypeAdd(detachedArrayBuffers, arrayBuffer);
} }
let serializedData; const serializedData = core.serialize(data, {
try { hostObjects: ArrayPrototypeFilter(
serializedData = core.serialize(data, { transferables,
hostObjects: ArrayPrototypeFilter( (a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a),
transferables, ),
(a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a), transferedArrayBuffers,
), }, (err) => {
transferedArrayBuffers, throw new DOMException(err, "DataCloneError");
}); });
} catch (err) {
throw new DOMException(err.message, "DataCloneError");
}
/** @type {globalThis.__bootstrap.messagePort.Transferable[]} */ /** @type {globalThis.__bootstrap.messagePort.Transferable[]} */
const serializedTransferables = []; const serializedTransferables = [];

View file

@ -3655,7 +3655,6 @@
"Object Blob object, Blob empty", "Object Blob object, Blob empty",
"Object Blob object, Blob NUL", "Object Blob object, Blob NUL",
"File basic", "File basic",
"Object with a getter that throws",
"Serializing a non-serializable platform object fails", "Serializing a non-serializable platform object fails",
"An object whose interface is deleted from the global must still deserialize", "An object whose interface is deleted from the global must still deserialize",
"A subclass instance will deserialize as its closest serializable superclass", "A subclass instance will deserialize as its closest serializable superclass",
@ -3682,7 +3681,6 @@
"Object Blob object, Blob empty", "Object Blob object, Blob empty",
"Object Blob object, Blob NUL", "Object Blob object, Blob NUL",
"File basic", "File basic",
"Object with a getter that throws",
"Serializing a non-serializable platform object fails", "Serializing a non-serializable platform object fails",
"An object whose interface is deleted from the global must still deserialize", "An object whose interface is deleted from the global must still deserialize",
"A subclass instance will deserialize as its closest serializable superclass", "A subclass instance will deserialize as its closest serializable superclass",