summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Ladyshau <47859603+mrkldshv@users.noreply.github.com>2022-05-26 17:14:38 +0200
committerGitHub <noreply@github.com>2022-05-26 17:14:38 +0200
commit402b497299c04e3b4714842c5caad50197088d0c (patch)
treeb223a24e7a0f680fc8e9e6f6a9de23cb59080733
parent3aa6d5d8b0911e9c5fcd38dd856f419692b28085 (diff)
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.
-rw-r--r--core/bindings.rs32
-rw-r--r--ext/web/13_message_port.js21
-rw-r--r--tools/wpt/expectation.json2
3 files changed, 39 insertions, 16 deletions
diff --git a/core/bindings.rs b/core/bindings.rs
index cb57b43fe..6fb0153a1 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -937,6 +937,7 @@ fn decode(
struct SerializeDeserialize<'a> {
host_objects: Option<v8::Local<'a, v8::Array>>,
+ error_callback: Option<v8::Local<'a, v8::Function>>,
}
impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
@@ -946,6 +947,15 @@ impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
scope: &mut v8::HandleScope<'s>,
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);
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 {
host_objects: None,
transfered_array_buffers: None,
@@ -1105,7 +1126,11 @@ fn serialize(
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 =
v8::ValueSerializer::new(scope, serialize_deserialize);
@@ -1227,7 +1252,10 @@ fn deserialize(
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 =
v8::ValueDeserializer::new(scope, serialize_deserialize, &zero_copy);
diff --git a/ext/web/13_message_port.js b/ext/web/13_message_port.js
index 8242f85f3..01ed92d9a 100644
--- a/ext/web/13_message_port.js
+++ b/ext/web/13_message_port.js
@@ -265,18 +265,15 @@
WeakSetPrototypeAdd(detachedArrayBuffers, arrayBuffer);
}
- let serializedData;
- try {
- serializedData = core.serialize(data, {
- hostObjects: ArrayPrototypeFilter(
- transferables,
- (a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a),
- ),
- transferedArrayBuffers,
- });
- } catch (err) {
- throw new DOMException(err.message, "DataCloneError");
- }
+ const serializedData = core.serialize(data, {
+ hostObjects: ArrayPrototypeFilter(
+ transferables,
+ (a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a),
+ ),
+ transferedArrayBuffers,
+ }, (err) => {
+ throw new DOMException(err, "DataCloneError");
+ });
/** @type {globalThis.__bootstrap.messagePort.Transferable[]} */
const serializedTransferables = [];
diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json
index aa168a88b..f13bf39d8 100644
--- a/tools/wpt/expectation.json
+++ b/tools/wpt/expectation.json
@@ -3655,7 +3655,6 @@
"Object Blob object, Blob empty",
"Object Blob object, Blob NUL",
"File basic",
- "Object with a getter that throws",
"Serializing a non-serializable platform object fails",
"An object whose interface is deleted from the global must still deserialize",
"A subclass instance will deserialize as its closest serializable superclass",
@@ -3682,7 +3681,6 @@
"Object Blob object, Blob empty",
"Object Blob object, Blob NUL",
"File basic",
- "Object with a getter that throws",
"Serializing a non-serializable platform object fails",
"An object whose interface is deleted from the global must still deserialize",
"A subclass instance will deserialize as its closest serializable superclass",