diff options
author | Andreu Botella <andreu@andreubotella.com> | 2022-03-14 19:35:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-14 19:35:15 +0100 |
commit | c6bf07ec6d231d29149a2454d3b5135a41c6cbab (patch) | |
tree | e9252ea7bfba740802826ef26124393f3e0642de | |
parent | b4e42953e1d243f2eda20e5be6b845d60b7bf688 (diff) |
fix(core): Don't override structured clone error messages from V8 (#13942)
In the implementation of structured serialization in
`Deno.core.serialize`, whenever there is a serialization error, an
exception will be thrown with the message "Failed to serialize
response", even though V8 provides a message to use in such cases.
This change instead throws an exception with the V8-provided message,
if there is one.
-rw-r--r-- | cli/tests/unit/structured_clone_test.ts | 13 | ||||
-rw-r--r-- | core/bindings.rs | 22 | ||||
-rw-r--r-- | ext/web/02_structured_clone.js | 2 |
3 files changed, 29 insertions, 8 deletions
diff --git a/cli/tests/unit/structured_clone_test.ts b/cli/tests/unit/structured_clone_test.ts index f25276165..fdad0dba7 100644 --- a/cli/tests/unit/structured_clone_test.ts +++ b/cli/tests/unit/structured_clone_test.ts @@ -1,4 +1,4 @@ -import { assert, assertEquals } from "./test_util.ts"; +import { assert, assertEquals, assertThrows } from "./test_util.ts"; // Basic tests for the structured clone algorithm. Mainly tests TypeScript // typings. Actual functionality is tested in WPT. @@ -17,3 +17,14 @@ Deno.test("self.structuredClone", async () => { channelOriginal.port1.close(); portTransferred.close(); }); + +Deno.test("correct DataCloneError message", () => { + assertThrows( + () => { + const sab = new SharedArrayBuffer(1024); + structuredClone(sab, { transfer: [sab] }); + }, + DOMException, + "Value not transferable", + ); +}); diff --git a/core/bindings.rs b/core/bindings.rs index 4e5c68675..2ab55187d 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -898,7 +898,7 @@ impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> { scope: &mut v8::HandleScope<'s>, message: v8::Local<'s, v8::String>, ) { - let error = v8::Exception::error(scope, message); + let error = v8::Exception::type_error(scope, message); scope.throw_exception(error); } @@ -1101,15 +1101,25 @@ fn serialize( } } - match value_serializer.write_value(scope.get_current_context(), value) { - Some(true) => { + let must_throw = { + let scope = &mut v8::TryCatch::new(scope); + let ret = value_serializer.write_value(scope.get_current_context(), value); + if scope.has_caught() || scope.has_terminated() { + scope.rethrow(); + false + } else if let Some(true) = ret { let vector = value_serializer.release(); let zbuf: ZeroCopyBuf = vector.into(); rv.set(to_v8(scope, zbuf).unwrap()); + false + } else { + // We throw the TypeError outside of the v8::TryCatch scope. + true } - _ => { - throw_type_error(scope, "Failed to serialize response"); - } + }; + + if must_throw { + throw_type_error(scope, "Failed to serialize response"); } } diff --git a/ext/web/02_structured_clone.js b/ext/web/02_structured_clone.js index 058390cfe..62bb48ebd 100644 --- a/ext/web/02_structured_clone.js +++ b/ext/web/02_structured_clone.js @@ -77,7 +77,7 @@ return core.deserialize(core.serialize(value)); } catch (e) { if (ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e)) { - throw new DOMException("Uncloneable value", "DataCloneError"); + throw new DOMException(e.message, "DataCloneError"); } throw e; } |