1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 21:50:00 -05:00

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.
This commit is contained in:
Andreu Botella 2022-03-14 19:35:15 +01:00 committed by GitHub
parent b4e42953e1
commit c6bf07ec6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 8 deletions

View file

@ -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 // Basic tests for the structured clone algorithm. Mainly tests TypeScript
// typings. Actual functionality is tested in WPT. // typings. Actual functionality is tested in WPT.
@ -17,3 +17,14 @@ Deno.test("self.structuredClone", async () => {
channelOriginal.port1.close(); channelOriginal.port1.close();
portTransferred.close(); portTransferred.close();
}); });
Deno.test("correct DataCloneError message", () => {
assertThrows(
() => {
const sab = new SharedArrayBuffer(1024);
structuredClone(sab, { transfer: [sab] });
},
DOMException,
"Value not transferable",
);
});

View file

@ -898,7 +898,7 @@ 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>,
) { ) {
let error = v8::Exception::error(scope, message); let error = v8::Exception::type_error(scope, message);
scope.throw_exception(error); scope.throw_exception(error);
} }
@ -1101,15 +1101,25 @@ fn serialize(
} }
} }
match value_serializer.write_value(scope.get_current_context(), value) { let must_throw = {
Some(true) => { 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 vector = value_serializer.release();
let zbuf: ZeroCopyBuf = vector.into(); let zbuf: ZeroCopyBuf = vector.into();
rv.set(to_v8(scope, zbuf).unwrap()); 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");
} }
} }

View file

@ -77,7 +77,7 @@
return core.deserialize(core.serialize(value)); return core.deserialize(core.serialize(value));
} catch (e) { } catch (e) {
if (ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e)) { if (ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e)) {
throw new DOMException("Uncloneable value", "DataCloneError"); throw new DOMException(e.message, "DataCloneError");
} }
throw e; throw e;
} }