summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreu Botella <andreu@andreubotella.com>2022-03-14 19:35:15 +0100
committerGitHub <noreply@github.com>2022-03-14 19:35:15 +0100
commitc6bf07ec6d231d29149a2454d3b5135a41c6cbab (patch)
treee9252ea7bfba740802826ef26124393f3e0642de
parentb4e42953e1d243f2eda20e5be6b845d60b7bf688 (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.ts13
-rw-r--r--core/bindings.rs22
-rw-r--r--ext/web/02_structured_clone.js2
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;
}