1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

fix(node): Fix node IPC serialization for objects with undefined values (#24894)

We were serializing `{ a: undefined }` to `{ a: null }` instead of `{}`
This commit is contained in:
Nathan Whitaker 2024-08-05 18:42:26 +02:00 committed by GitHub
parent 649725442a
commit ae8d048b6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -90,8 +90,14 @@ mod impl_ {
let str = deno_core::serde_v8::to_utf8(value.try_into().unwrap(), scope);
ser.serialize_str(&str)
} else if value.is_string_object() {
let str =
deno_core::serde_v8::to_utf8(value.to_string(scope).unwrap(), scope);
let str = deno_core::serde_v8::to_utf8(
value.to_string(scope).ok_or_else(|| {
S::Error::custom(deno_core::error::generic_error(
"toString on string object failed",
))
})?,
scope,
);
ser.serialize_str(&str)
} else if value.is_boolean() {
ser.serialize_bool(value.is_true())
@ -99,7 +105,7 @@ mod impl_ {
ser.serialize_bool(value.boolean_value(scope))
} else if value.is_array() {
use serde::ser::SerializeSeq;
let array = v8::Local::<v8::Array>::try_from(value).unwrap();
let array = value.cast::<v8::Array>();
let length = array.length();
let mut seq = ser.serialize_seq(Some(length as usize))?;
for i in 0..length {
@ -111,13 +117,13 @@ mod impl_ {
} else if value.is_object() {
use serde::ser::SerializeMap;
if value.is_array_buffer_view() {
let buffer = v8::Local::<v8::ArrayBufferView>::try_from(value).unwrap();
let buffer = value.cast::<v8::ArrayBufferView>();
let mut buf = vec![0u8; buffer.byte_length()];
let copied = buffer.copy_contents(&mut buf);
assert_eq!(copied, buf.len());
debug_assert_eq!(copied, buf.len());
return ser.serialize_bytes(&buf);
}
let object = value.to_object(scope).unwrap();
let object = value.cast::<v8::Object>();
// node uses `JSON.stringify`, so to match its behavior (and allow serializing custom objects)
// we need to respect the `toJSON` method if it exists.
let to_json_key = v8::String::new_from_utf8(
@ -128,8 +134,7 @@ mod impl_ {
.unwrap()
.into();
if let Some(to_json) = object.get(scope, to_json_key) {
if to_json.is_function() {
let to_json = v8::Local::<v8::Function>::try_from(to_json).unwrap();
if let Ok(to_json) = to_json.try_cast::<v8::Function>() {
let json_value = to_json.call(scope, object.into(), &[]).unwrap();
return serialize_v8_value(scope, json_value, ser);
}
@ -149,6 +154,9 @@ mod impl_ {
let key = keys.get_index(scope, i).unwrap();
let key_str = key.to_rust_string_lossy(scope);
let value = object.get(scope, key).unwrap();
if value.is_undefined() {
continue;
}
map.serialize_entry(
&key_str,
&SerializeWrapper(RefCell::new(scope), value),
@ -157,9 +165,10 @@ mod impl_ {
map.end()
} else {
// TODO(nathanwhit): better error message
Err(S::Error::custom(deno_core::error::type_error(
"Unsupported type",
)))
Err(S::Error::custom(deno_core::error::type_error(format!(
"Unsupported type: {}",
value.type_repr()
))))
}
}
@ -869,6 +878,7 @@ mod impl_ {
r#"{ a: "field", toJSON() { return "custom"; } }"#,
"\"custom\"",
),
(r#"{ a: undefined, b: 1 }"#, "{\"b\":1}"),
];
for (input, expect) in cases {