diff options
-rw-r--r-- | core/runtime.rs | 2 | ||||
-rw-r--r-- | serde_v8/de.rs | 21 | ||||
-rw-r--r-- | serde_v8/error.rs | 145 | ||||
-rw-r--r-- | serde_v8/magic/bigint.rs | 3 | ||||
-rw-r--r-- | serde_v8/magic/bytestring.rs | 3 | ||||
-rw-r--r-- | serde_v8/magic/detached_buffer.rs | 7 | ||||
-rw-r--r-- | serde_v8/magic/external_pointer.rs | 4 | ||||
-rw-r--r-- | serde_v8/magic/string_or_buffer.rs | 3 | ||||
-rw-r--r-- | serde_v8/magic/u16string.rs | 3 | ||||
-rw-r--r-- | serde_v8/magic/v8slice.rs | 4 | ||||
-rw-r--r-- | serde_v8/tests/de.rs | 2 |
11 files changed, 152 insertions, 45 deletions
diff --git a/core/runtime.rs b/core/runtime.rs index 3723a917a..9ead489af 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -4385,7 +4385,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { let sum = Deno.core.ops.op_sum_take(w32.subarray(0, 2)); return false; } catch(e) { - return e.message.includes('invalid type, expected: detachable'); + return e.message.includes('invalid type; expected: detachable'); } }); if (!assertWasmThrow()) { diff --git a/serde_v8/de.rs b/serde_v8/de.rs index d593ffbc5..edb1263eb 100644 --- a/serde_v8/de.rs +++ b/serde_v8/de.rs @@ -4,6 +4,7 @@ use serde::de::Visitor; use serde::de::{self}; use serde::Deserialize; +use crate::error::value_to_type_str; use crate::error::Error; use crate::error::Result; use crate::keys::v8_struct_key; @@ -84,7 +85,7 @@ macro_rules! deserialize_signed { } else if let Some(x) = self.input.to_big_int(self.scope) { x.i64_value().0 as $t } else { - return Err(Error::ExpectedInteger); + return Err(Error::ExpectedInteger(value_to_type_str(self.input))); }, ) } @@ -107,7 +108,7 @@ macro_rules! deserialize_unsigned { } else if let Some(x) = self.input.to_big_int(self.scope) { x.u64_value().0 as $t } else { - return Err(Error::ExpectedInteger); + return Err(Error::ExpectedInteger(value_to_type_str(self.input))); }, ) } @@ -188,7 +189,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> } else if let Some(x) = self.input.to_big_int(self.scope) { bigint_to_f64(x) } else { - return Err(Error::ExpectedNumber); + return Err(Error::ExpectedNumber(value_to_type_str(self.input))); }, ) } @@ -216,7 +217,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> let string = to_utf8(v8_string, self.scope); visitor.visit_string(string) } else { - Err(Error::ExpectedString) + Err(Error::ExpectedString(value_to_type_str(self.input))) } } @@ -268,7 +269,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> V: Visitor<'de>, { let arr = v8::Local::<v8::Array>::try_from(self.input) - .map_err(|_| Error::ExpectedArray)?; + .map_err(|_| Error::ExpectedArray(value_to_type_str(self.input)))?; visitor.visit_seq(SeqAccess::new(arr.into(), self.scope, 0..arr.length())) } @@ -308,7 +309,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> { // Assume object, then get_own_property_names let obj = v8::Local::<v8::Object>::try_from(self.input) - .map_err(|_| Error::ExpectedObject)?; + .map_err(|_| Error::ExpectedObject(value_to_type_str(self.input)))?; if v8::Local::<v8::Map>::try_from(self.input).is_ok() { let pairs_array = v8::Local::<v8::Map>::try_from(self.input) @@ -363,7 +364,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> _ => { // Regular struct let obj = v8::Local::<v8::Object>::try_from(self.input) - .or(Err(Error::ExpectedObject))?; + .map_err(|_| Error::ExpectedObject(value_to_type_str(self.input)))?; // Fields names are a hint and must be inferred when not provided if fields.is_empty() { @@ -409,7 +410,8 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> let tag = { let prop_names = obj.get_own_property_names(self.scope, Default::default()); - let prop_names = prop_names.ok_or(Error::ExpectedEnum)?; + let prop_names = prop_names + .ok_or_else(|| Error::ExpectedEnum(value_to_type_str(self.input)))?; let prop_names_len = prop_names.length(); if prop_names_len != 1 { return Err(Error::LengthMismatch(prop_names_len as usize, 1)); @@ -424,8 +426,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> payload, }) } else { - // TODO: improve error - Err(Error::ExpectedEnum) + Err(Error::ExpectedEnum(value_to_type_str(self.input))) } } diff --git a/serde_v8/error.rs b/serde_v8/error.rs index 94ac3c0a5..aa2d92bf8 100644 --- a/serde_v8/error.rs +++ b/serde_v8/error.rs @@ -9,30 +9,41 @@ pub enum Error { #[error("{0}")] Message(String), - #[error("serde_v8 error: invalid type, expected: boolean")] - ExpectedBoolean, - #[error("serde_v8 error: invalid type, expected: integer")] - ExpectedInteger, - #[error("serde_v8 error: invalid type, expected: number")] - ExpectedNumber, - #[error("serde_v8 error: invalid type, expected: string")] - ExpectedString, - #[error("serde_v8 error: invalid type, expected: array")] - ExpectedArray, - #[error("serde_v8 error: invalid type, expected: map")] - ExpectedMap, - #[error("serde_v8 error: invalid type, expected: enum")] - ExpectedEnum, - #[error("serde_v8 error: invalid type, expected: object")] - ExpectedObject, - #[error("serde_v8 error: invalid type, expected: buffer")] - ExpectedBuffer, - #[error("serde_v8 error: invalid type, expected: detachable")] - ExpectedDetachable, - #[error("serde_v8 error: invalid type, expected: external")] - ExpectedExternal, - #[error("serde_v8 error: invalid type, expected: bigint")] - ExpectedBigInt, + #[error("serde_v8 error: invalid type; expected: boolean, got: {0}")] + ExpectedBoolean(&'static str), + + #[error("serde_v8 error: invalid type; expected: integer, got: {0}")] + ExpectedInteger(&'static str), + + #[error("serde_v8 error: invalid type; expected: number, got: {0}")] + ExpectedNumber(&'static str), + + #[error("serde_v8 error: invalid type; expected: string, got: {0}")] + ExpectedString(&'static str), + + #[error("serde_v8 error: invalid type; expected: array, got: {0}")] + ExpectedArray(&'static str), + + #[error("serde_v8 error: invalid type; expected: map, got: {0}")] + ExpectedMap(&'static str), + + #[error("serde_v8 error: invalid type; expected: enum, got: {0}")] + ExpectedEnum(&'static str), + + #[error("serde_v8 error: invalid type; expected: object, got: {0}")] + ExpectedObject(&'static str), + + #[error("serde_v8 error: invalid type; expected: buffer, got: {0}")] + ExpectedBuffer(&'static str), + + #[error("serde_v8 error: invalid type; expected: detachable, got: {0}")] + ExpectedDetachable(&'static str), + + #[error("serde_v8 error: invalid type; expected: external, got: {0}")] + ExpectedExternal(&'static str), + + #[error("serde_v8 error: invalid type; expected: bigint, got: {0}")] + ExpectedBigInt(&'static str), #[error("serde_v8 error: invalid type, expected: utf8")] ExpectedUtf8, @@ -57,3 +68,89 @@ impl serde::de::Error for Error { Error::Message(msg.to_string()) } } + +pub(crate) fn value_to_type_str(value: v8::Local<v8::Value>) -> &'static str { + if value.is_module_namespace_object() { + "Module" + } else if value.is_wasm_module_object() { + "WASM module" + } else if value.is_wasm_memory_object() { + "WASM memory object" + } else if value.is_proxy() { + "Proxy" + } else if value.is_shared_array_buffer() { + "SharedArrayBuffer" + } else if value.is_data_view() { + "DataView" + } else if value.is_big_uint64_array() { + "BigUint64Array" + } else if value.is_big_int64_array() { + "BigInt64Array" + } else if value.is_float64_array() { + "Float64Array" + } else if value.is_float32_array() { + "Float32Array" + } else if value.is_int32_array() { + "Int32Array" + } else if value.is_uint32_array() { + "Uint32Array" + } else if value.is_int16_array() { + "Int16Array" + } else if value.is_uint16_array() { + "Uint16Array" + } else if value.is_int8_array() { + "Int8Array" + } else if value.is_uint8_clamped_array() { + "Uint8ClampedArray" + } else if value.is_uint8_array() { + "Uint8Array" + } else if value.is_typed_array() { + "TypedArray" + } else if value.is_array_buffer_view() { + "ArrayBufferView" + } else if value.is_array_buffer() { + "ArrayBuffer" + } else if value.is_weak_set() { + "WeakSet" + } else if value.is_weak_map() { + "WeakMap" + } else if value.is_set_iterator() { + "Set Iterator" + } else if value.is_map_iterator() { + "Map Iterator" + } else if value.is_set() { + "Set" + } else if value.is_map() { + "Map" + } else if value.is_promise() { + "Promise" + } else if value.is_generator_function() { + "Generator function" + } else if value.is_async_function() { + "Async function" + } else if value.is_reg_exp() { + "RegExp" + } else if value.is_date() { + "Date" + } else if value.is_number() { + "Number" + } else if value.is_boolean() { + "Boolean" + } else if value.is_big_int() { + "bigint" + } else if value.is_array() { + "array" + } else if value.is_function() { + "function" + } else if value.is_symbol() { + "symbol" + } else if value.is_string() { + "string" + } else if value.is_null() { + "null" + } else if value.is_undefined() { + "undefined" + } else { + "unknown" + } +} diff --git a/serde_v8/magic/bigint.rs b/serde_v8/magic/bigint.rs index 69828747f..330803daf 100644 --- a/serde_v8/magic/bigint.rs +++ b/serde_v8/magic/bigint.rs @@ -5,6 +5,7 @@ use smallvec::SmallVec; use super::transl8::FromV8; use super::transl8::ToV8; +use crate::error::value_to_type_str; use crate::magic::transl8::impl_magic; use crate::Error; @@ -42,7 +43,7 @@ impl FromV8 for BigInt { value: v8::Local<v8::Value>, ) -> Result<Self, crate::Error> { let v8bigint = v8::Local::<v8::BigInt>::try_from(value) - .map_err(|_| Error::ExpectedBigInt)?; + .map_err(|_| Error::ExpectedBigInt(value_to_type_str(value)))?; let word_count = v8bigint.word_count(); let mut words: SmallVec<[u64; 1]> = smallvec![0u64; word_count]; let (sign_bit, _words) = v8bigint.to_words_array(&mut words); diff --git a/serde_v8/magic/bytestring.rs b/serde_v8/magic/bytestring.rs index 77771698f..3baa704e5 100644 --- a/serde_v8/magic/bytestring.rs +++ b/serde_v8/magic/bytestring.rs @@ -1,6 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use super::transl8::FromV8; use super::transl8::ToV8; +use crate::error::value_to_type_str; use crate::magic::transl8::impl_magic; use crate::Error; use smallvec::SmallVec; @@ -49,7 +50,7 @@ impl FromV8 for ByteString { value: v8::Local<v8::Value>, ) -> Result<Self, crate::Error> { let v8str = v8::Local::<v8::String>::try_from(value) - .map_err(|_| Error::ExpectedString)?; + .map_err(|_| Error::ExpectedString(value_to_type_str(value)))?; if !v8str.contains_only_onebyte() { return Err(Error::ExpectedLatin1); } diff --git a/serde_v8/magic/detached_buffer.rs b/serde_v8/magic/detached_buffer.rs index 7ee4dfb21..bc4b3de67 100644 --- a/serde_v8/magic/detached_buffer.rs +++ b/serde_v8/magic/detached_buffer.rs @@ -8,6 +8,7 @@ use super::transl8::FromV8; use super::transl8::ToV8; use super::v8slice::to_ranged_buffer; use super::v8slice::V8Slice; +use crate::error::value_to_type_str; use crate::magic::transl8::impl_magic; // A buffer that detaches when deserialized from JS @@ -57,10 +58,10 @@ impl FromV8 for DetachedBuffer { scope: &mut v8::HandleScope, value: v8::Local<v8::Value>, ) -> Result<Self, crate::Error> { - let (b, range) = - to_ranged_buffer(scope, value).or(Err(crate::Error::ExpectedBuffer))?; + let (b, range) = to_ranged_buffer(scope, value) + .map_err(|_| crate::Error::ExpectedBuffer(value_to_type_str(value)))?; if !b.is_detachable() { - return Err(crate::Error::ExpectedDetachable); + return Err(crate::Error::ExpectedDetachable(value_to_type_str(value))); } let store = b.get_backing_store(); b.detach(None); // Detach diff --git a/serde_v8/magic/external_pointer.rs b/serde_v8/magic/external_pointer.rs index fca6028d6..e22e41a01 100644 --- a/serde_v8/magic/external_pointer.rs +++ b/serde_v8/magic/external_pointer.rs @@ -2,6 +2,8 @@ use std::ffi::c_void; +use crate::error::value_to_type_str; + use super::transl8::impl_magic; use super::transl8::FromV8; use super::transl8::ToV8; @@ -38,7 +40,7 @@ impl FromV8 for ExternalPointer { } else if let Ok(external) = v8::Local::<v8::External>::try_from(value) { Ok(ExternalPointer(external.value())) } else { - Err(crate::Error::ExpectedExternal) + Err(crate::Error::ExpectedExternal(value_to_type_str(value))) } } } diff --git a/serde_v8/magic/string_or_buffer.rs b/serde_v8/magic/string_or_buffer.rs index 04ce08be2..8b1a06dbc 100644 --- a/serde_v8/magic/string_or_buffer.rs +++ b/serde_v8/magic/string_or_buffer.rs @@ -2,6 +2,7 @@ use super::buffer::ZeroCopyBuf; use super::transl8::FromV8; use super::transl8::ToV8; +use crate::error::value_to_type_str; use crate::magic::transl8::impl_magic; use crate::Error; use std::ops::Deref; @@ -73,7 +74,7 @@ impl FromV8 for StringOrBuffer { } else if let Ok(s) = crate::from_v8(scope, value) { return Ok(Self::String(s)); } - Err(Error::ExpectedBuffer) + Err(Error::ExpectedBuffer(value_to_type_str(value))) } } diff --git a/serde_v8/magic/u16string.rs b/serde_v8/magic/u16string.rs index 57e3fd0f6..04d742da9 100644 --- a/serde_v8/magic/u16string.rs +++ b/serde_v8/magic/u16string.rs @@ -1,5 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use crate::error::value_to_type_str; use crate::Error; use super::transl8::impl_magic; @@ -37,7 +38,7 @@ impl FromV8 for U16String { value: v8::Local<v8::Value>, ) -> Result<Self, crate::Error> { let v8str = v8::Local::<v8::String>::try_from(value) - .map_err(|_| Error::ExpectedString)?; + .map_err(|_| Error::ExpectedString(value_to_type_str(value)))?; let len = v8str.length(); let mut buffer = Vec::with_capacity(len); #[allow(clippy::uninit_vec)] diff --git a/serde_v8/magic/v8slice.rs b/serde_v8/magic/v8slice.rs index 384ccf5c5..073e75235 100644 --- a/serde_v8/magic/v8slice.rs +++ b/serde_v8/magic/v8slice.rs @@ -5,6 +5,8 @@ use std::ops::DerefMut; use std::ops::Range; use std::rc::Rc; +use crate::error::value_to_type_str; + use super::rawbytes; use super::transl8::FromV8; @@ -91,7 +93,7 @@ impl FromV8 for V8Slice { ) -> Result<Self, crate::Error> { to_ranged_buffer(scope, value) .and_then(|(b, r)| Self::from_buffer(b, r)) - .map_err(|_| crate::Error::ExpectedBuffer) + .map_err(|_| crate::Error::ExpectedBuffer(value_to_type_str(value))) } } diff --git a/serde_v8/tests/de.rs b/serde_v8/tests/de.rs index eae30f540..4e5e1e4b9 100644 --- a/serde_v8/tests/de.rs +++ b/serde_v8/tests/de.rs @@ -408,7 +408,7 @@ detest!( ); defail!(defail_struct, MathOp, "123", |e| e - == Err(Error::ExpectedObject)); + == Err(Error::ExpectedObject("Number"))); #[derive(Eq, PartialEq, Debug, Deserialize)] pub struct SomeThing { |