diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index e45d4e50ba19..cda345eb1833 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1427,6 +1427,65 @@ impl ToTokens for ast::Enum { inform(#hole); } } + + #[automatically_derived] + impl #wasm_bindgen::__rt::core::convert::From<#enum_name> for + #wasm_bindgen::JsValue + { + fn from(value: #enum_name) -> Self { + #wasm_bindgen::JsValue::from_f64((value as u32).into()) + } + } + + #[allow(clippy::all)] + impl #wasm_bindgen::__rt::core::convert::TryFrom<#wasm_bindgen::JsValue> for #enum_name { + type Error = #wasm_bindgen::JsValue; + + fn try_from(value: #wasm_bindgen::JsValue) + -> #wasm_bindgen::__rt::std::result::Result { + let val = f64::try_from(value)? as u32; + + unsafe { + #wasm_bindgen::__rt::std::result::Result::Ok( + ::from_abi(val) + ) + } + } + } + + impl #wasm_bindgen::describe::WasmDescribeVector for #enum_name { + fn describe_vector() { + use #wasm_bindgen::describe::*; + inform(VECTOR); + <#wasm_bindgen::JsValue as #wasm_bindgen::describe::WasmDescribe>::describe(); + } + } + + impl #wasm_bindgen::convert::VectorIntoWasmAbi for #enum_name { + type Abi = < + #wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]> + as #wasm_bindgen::convert::IntoWasmAbi + >::Abi; + + fn vector_into_abi( + vector: #wasm_bindgen::__rt::std::boxed::Box<[#enum_name]> + ) -> Self::Abi { + #wasm_bindgen::convert::js_value_vector_into_abi(vector) + } + } + + impl #wasm_bindgen::convert::VectorFromWasmAbi for #enum_name { + type Abi = < + #wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]> + as #wasm_bindgen::convert::FromWasmAbi + >::Abi; + + unsafe fn vector_from_abi( + js: Self::Abi + ) -> #wasm_bindgen::__rt::std::boxed::Box<[#enum_name]> { + #wasm_bindgen::convert::js_value_vector_from_abi(js) + } + } }) .to_tokens(into); } diff --git a/tests/wasm/enum_vecs.js b/tests/wasm/enum_vecs.js new file mode 100644 index 000000000000..bef43b3e417a --- /dev/null +++ b/tests/wasm/enum_vecs.js @@ -0,0 +1,23 @@ +const wasm = require('wasm-bindgen-test.js'); +const assert = require('assert'); + +exports.pass_enum_vec = () => { + const el1 = wasm.EnumArrayElement.Unit; + const el2 = wasm.EnumArrayElement.Unit; + const ret = wasm.consume_enum_vec([el1, el2]); + assert.strictEqual(ret.length, 3); + + const ret2 = wasm.consume_optional_enum_vec(ret); + assert.strictEqual(ret2.length, 4); + + assert.strictEqual(wasm.consume_optional_enum_vec(undefined), undefined); +}; + +exports.pass_invalid_enum_vec = () => { + try { + wasm.consume_enum_vec(['not an enum value']); + } catch (e) { + assert.match(e.message, /invalid enum value passed/) + assert.match(e.stack, /consume_enum_vec/) + } +}; diff --git a/tests/wasm/enum_vecs.rs b/tests/wasm/enum_vecs.rs new file mode 100644 index 000000000000..7266e046144c --- /dev/null +++ b/tests/wasm/enum_vecs.rs @@ -0,0 +1,34 @@ +use wasm_bindgen::prelude::*; +use wasm_bindgen_test::*; + +#[wasm_bindgen(module = "tests/wasm/enum_vecs.js")] +extern "C" { + fn pass_enum_vec(); + fn pass_invalid_enum_vec(); +} + +#[wasm_bindgen] +pub enum EnumArrayElement { + Unit, +} + +#[wasm_bindgen] +pub fn consume_enum_vec(mut vec: Vec) -> Vec { + vec.push(EnumArrayElement::Unit); + vec +} + +#[wasm_bindgen] +pub fn consume_optional_enum_vec(vec: Option>) -> Option> { + vec.map(consume_enum_vec) +} + +#[wasm_bindgen_test] +fn test_valid() { + pass_enum_vec(); +} + +#[wasm_bindgen_test] +fn test_invalid() { + pass_invalid_enum_vec(); +} diff --git a/tests/wasm/main.rs b/tests/wasm/main.rs index eebde19677e1..9da381f78981 100644 --- a/tests/wasm/main.rs +++ b/tests/wasm/main.rs @@ -24,6 +24,7 @@ pub mod comments; pub mod duplicate_deps; pub mod duplicates; pub mod enums; +pub mod enum_vecs; #[path = "final.rs"] pub mod final_; pub mod futures;