Replace TryFrom with custom TryFromJsValue trait (#3709)

This commit is contained in:
Maxim 2023-11-27 18:08:46 +03:00 committed by GitHub
parent 750dfa0c70
commit a65283b3e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 9 deletions

View File

@ -16,6 +16,9 @@
* The DWARF section is now correctly modified instead of leaving it in a broken state.
[#3483](https://github.com/rustwasm/wasm-bindgen/pull/3483)
* Fixed an issue where `#[wasm_bindgen]` automatically derived the `TryFrom` trait for any struct, preventing custom `TryFrom<JsValue>` implementations. It has been updated to utilize a new `TryFromJsValue` trait instead.
[#3709](https://github.com/rustwasm/wasm-bindgen/pull/3709)
* Update the TypeScript signature of `__wbindgen_thread_destroy` to indicate that it's parameters are optional.
[#3703](https://github.com/rustwasm/wasm-bindgen/pull/3703)

View File

@ -297,10 +297,10 @@ impl ToTokens for ast::Struct {
}
#[allow(clippy::all)]
impl #wasm_bindgen::__rt::core::convert::TryFrom<#wasm_bindgen::JsValue> for #name {
impl #wasm_bindgen::convert::TryFromJsValue for #name {
type Error = #wasm_bindgen::JsValue;
fn try_from(value: #wasm_bindgen::JsValue)
fn try_from_js_value(value: #wasm_bindgen::JsValue)
-> #wasm_bindgen::__rt::std::result::Result<Self, Self::Error> {
let idx = #wasm_bindgen::convert::IntoWasmAbi::into_abi(&value);
@ -819,6 +819,7 @@ impl ToTokens for ast::ImportType {
#[automatically_derived]
const _: () = {
use #wasm_bindgen::convert::TryFromJsValue;
use #wasm_bindgen::convert::{IntoWasmAbi, FromWasmAbi};
use #wasm_bindgen::convert::{OptionIntoWasmAbi, OptionFromWasmAbi};
use #wasm_bindgen::convert::{RefFromWasmAbi, LongRefFromWasmAbi};
@ -1452,11 +1453,12 @@ impl ToTokens for ast::Enum {
}
#[allow(clippy::all)]
impl #wasm_bindgen::__rt::core::convert::TryFrom<#wasm_bindgen::JsValue> for #enum_name {
impl #wasm_bindgen::convert::TryFromJsValue for #enum_name {
type Error = #wasm_bindgen::JsValue;
fn try_from(value: #wasm_bindgen::JsValue)
-> #wasm_bindgen::__rt::std::result::Result<Self, <#enum_name as #wasm_bindgen::__rt::core::convert::TryFrom<JsValue>>::Error> {
fn try_from_js_value(value: #wasm_bindgen::JsValue)
-> #wasm_bindgen::__rt::std::result::Result<Self, <#enum_name as #wasm_bindgen::convert::TryFromJsValue>::Error> {
use #wasm_bindgen::__rt::core::convert::TryFrom;
let js = f64::try_from(&value)? as u32;
#wasm_bindgen::__rt::std::result::Result::Ok(

View File

@ -2,13 +2,13 @@ use core::char;
use core::mem::{self, ManuallyDrop};
use crate::convert::traits::{WasmAbi, WasmPrimitive};
use crate::convert::TryFromJsValue;
use crate::convert::{FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, RefFromWasmAbi};
use crate::convert::{OptionFromWasmAbi, OptionIntoWasmAbi, ReturnWasmAbi};
use crate::{Clamped, JsError, JsValue, UnwrapThrowExt};
if_std! {
use std::boxed::Box;
use std::convert::{TryFrom, TryInto};
use std::fmt::Debug;
use std::vec::Vec;
}
@ -415,7 +415,7 @@ if_std! {
js_vals.into_abi()
}
pub unsafe fn js_value_vector_from_abi<T: TryFrom<JsValue>>(js: <Box<[JsValue]> as FromWasmAbi>::Abi) -> Box<[T]> where T::Error: Debug {
pub unsafe fn js_value_vector_from_abi<T: TryFromJsValue>(js: <Box<[JsValue]> as FromWasmAbi>::Abi) -> Box<[T]> where T::Error: Debug {
let js_vals = <Vec<JsValue> as FromWasmAbi>::from_abi(js);
let mut result = Vec::with_capacity(js_vals.len());
@ -430,7 +430,7 @@ if_std! {
// we're talking about, it can only see functions that actually make it to the
// final wasm binary (i.e., not inlined functions). All of those internal
// iterator functions get inlined in release mode, and so they don't show up.
result.push(value.try_into().expect_throw("array contains a value of the wrong type"));
result.push(T::try_from_js_value(value).expect_throw("array contains a value of the wrong type"));
}
result.into_boxed_slice()
}

View File

@ -2,6 +2,7 @@ use core::borrow::Borrow;
use core::ops::{Deref, DerefMut};
use crate::describe::*;
use crate::JsValue;
/// A trait for anything that can be converted into a type that can cross the
/// wasm ABI directly, eg `u32` or `f64`.
@ -249,3 +250,18 @@ impl<T: WasmAbi> WasmRet<T> {
T::join(self.prim1, self.prim2, self.prim3, self.prim4)
}
}
/// [`TryFromJsValue`] is a trait for converting a JavaScript value ([`JsValue`])
/// into a Rust type. It is used by the [`wasm_bindgen`](wasm_bindgen_macro::wasm_bindgen)
/// proc-macro to allow conversion to user types.
///
/// Types implementing this trait must specify their conversion logic from
/// [`JsValue`] to the Rust type, handling any potential errors that may occur
/// during the conversion process.
pub trait TryFromJsValue: Sized {
/// The type returned in the event of a conversion error.
type Error;
/// Performs the conversion.
fn try_from_js_value(value: JsValue) -> Result<Self, Self::Error>;
}

View File

@ -18,7 +18,7 @@ use core::ops::{
};
use core::u32;
use crate::convert::{FromWasmAbi, WasmRet, WasmSlice};
use crate::convert::{FromWasmAbi, TryFromJsValue, WasmRet, WasmSlice};
macro_rules! if_std {
($($i:item)*) => ($(
@ -815,6 +815,17 @@ if_std! {
}
}
}
impl TryFromJsValue for String {
type Error = JsValue;
fn try_from_js_value(value: JsValue) -> Result<Self, Self::Error> {
match value.as_string() {
Some(s) => Ok(s),
None => Err(value),
}
}
}
}
impl From<bool> for JsValue {