Skip to content

Commit

Permalink
Replace TryFrom with custom TryFromJsValue trait (#3709)
Browse files Browse the repository at this point in the history
  • Loading branch information
biryukovmaxim committed Nov 27, 2023
1 parent 750dfa0 commit a65283b
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
12 changes: 7 additions & 5 deletions crates/backend/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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(
Expand Down
6 changes: 3 additions & 3 deletions src/convert/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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());
Expand All @@ -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()
}
Expand Down
16 changes: 16 additions & 0 deletions src/convert/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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>;
}
13 changes: 12 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)*) => ($(
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit a65283b

Please sign in to comment.