diff options
author | Mark Ladyshau <47859603+mrkldshv@users.noreply.github.com> | 2022-05-26 17:14:38 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-26 17:14:38 +0200 |
commit | 402b497299c04e3b4714842c5caad50197088d0c (patch) | |
tree | b223a24e7a0f680fc8e9e6f6a9de23cb59080733 | |
parent | 3aa6d5d8b0911e9c5fcd38dd856f419692b28085 (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.rs | 32 | ||||
-rw-r--r-- | ext/web/13_message_port.js | 21 | ||||
-rw-r--r-- | tools/wpt/expectation.json | 2 |
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", |