Skip to content

Commit

Permalink
Replace TryFrom with custom TryFromJsValue trait
Browse files Browse the repository at this point in the history
This commit replaces the usage of the standard library's TryFrom trait with a custom TryFromJsValue trait added for handling the conversion from JavaScript values in WASM. This trait has been implemented for different types across multiple modules to ensure consistent error handling on failed conversions.

fixes rustwasm#3685
  • Loading branch information
biryukovmaxim committed Nov 16, 2023
1 parent fe88e39 commit 93610cb
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 8 deletions.
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 @@ -822,6 +822,7 @@ impl ToTokens for ast::ImportType {
use #wasm_bindgen::convert::{IntoWasmAbi, FromWasmAbi};
use #wasm_bindgen::convert::{OptionIntoWasmAbi, OptionFromWasmAbi};
use #wasm_bindgen::convert::{RefFromWasmAbi, LongRefFromWasmAbi};
use #wasm_bindgen::convert::TryFromJsValue;
use #wasm_bindgen::describe::WasmDescribe;
use #wasm_bindgen::{JsValue, JsCast, JsObject};
use #wasm_bindgen::__rt::core;
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
9 changes: 9 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,11 @@ impl<T: WasmAbi> WasmRet<T> {
T::join(self.prim1, self.prim2, self.prim3, self.prim4)
}
}

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>;
}
11 changes: 11 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,17 @@ if_std! {
}
}
}

impl crate::convert::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 93610cb

Please sign in to comment.