Skip to content

Commit e14a7ad

Browse files
authored
Allow creating Vecs of exported enums (#3624)
1 parent 4bafdbe commit e14a7ad

File tree

4 files changed

+120
-0
lines changed

4 files changed

+120
-0
lines changed

crates/backend/src/codegen.rs

+60
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,7 @@ impl ToTokens for ast::Enum {
13911391
}
13921392
}
13931393
});
1394+
let try_from_cast_clauses = cast_clauses.clone();
13941395
let wasm_bindgen = &self.wasm_bindgen;
13951396
(quote! {
13961397
#[automatically_derived]
@@ -1435,6 +1436,65 @@ impl ToTokens for ast::Enum {
14351436
inform(#hole);
14361437
}
14371438
}
1439+
1440+
#[automatically_derived]
1441+
impl #wasm_bindgen::__rt::core::convert::From<#enum_name> for
1442+
#wasm_bindgen::JsValue
1443+
{
1444+
fn from(value: #enum_name) -> Self {
1445+
#wasm_bindgen::JsValue::from_f64((value as u32).into())
1446+
}
1447+
}
1448+
1449+
#[allow(clippy::all)]
1450+
impl #wasm_bindgen::__rt::core::convert::TryFrom<#wasm_bindgen::JsValue> for #enum_name {
1451+
type Error = #wasm_bindgen::JsValue;
1452+
1453+
fn try_from(value: #wasm_bindgen::JsValue)
1454+
-> #wasm_bindgen::__rt::std::result::Result<Self, Self::Error> {
1455+
let js = f64::try_from(&value)? as u32;
1456+
1457+
#wasm_bindgen::__rt::std::result::Result::Ok(
1458+
#(#try_from_cast_clauses else)* {
1459+
return #wasm_bindgen::__rt::std::result::Result::Err(value)
1460+
}
1461+
)
1462+
}
1463+
}
1464+
1465+
impl #wasm_bindgen::describe::WasmDescribeVector for #enum_name {
1466+
fn describe_vector() {
1467+
use #wasm_bindgen::describe::*;
1468+
inform(VECTOR);
1469+
<#wasm_bindgen::JsValue as #wasm_bindgen::describe::WasmDescribe>::describe();
1470+
}
1471+
}
1472+
1473+
impl #wasm_bindgen::convert::VectorIntoWasmAbi for #enum_name {
1474+
type Abi = <
1475+
#wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]>
1476+
as #wasm_bindgen::convert::IntoWasmAbi
1477+
>::Abi;
1478+
1479+
fn vector_into_abi(
1480+
vector: #wasm_bindgen::__rt::std::boxed::Box<[#enum_name]>
1481+
) -> Self::Abi {
1482+
#wasm_bindgen::convert::js_value_vector_into_abi(vector)
1483+
}
1484+
}
1485+
1486+
impl #wasm_bindgen::convert::VectorFromWasmAbi for #enum_name {
1487+
type Abi = <
1488+
#wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]>
1489+
as #wasm_bindgen::convert::FromWasmAbi
1490+
>::Abi;
1491+
1492+
unsafe fn vector_from_abi(
1493+
js: Self::Abi
1494+
) -> #wasm_bindgen::__rt::std::boxed::Box<[#enum_name]> {
1495+
#wasm_bindgen::convert::js_value_vector_from_abi(js)
1496+
}
1497+
}
14381498
})
14391499
.to_tokens(into);
14401500
}

tests/wasm/enum_vecs.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const wasm = require('wasm-bindgen-test.js');
2+
const assert = require('assert');
3+
4+
exports.pass_enum_vec = () => {
5+
const el1 = wasm.EnumArrayElement.Unit;
6+
const el2 = wasm.EnumArrayElement.Unit;
7+
const ret = wasm.consume_enum_vec([el1, el2]);
8+
assert.strictEqual(ret.length, 3);
9+
10+
const ret2 = wasm.consume_optional_enum_vec(ret);
11+
assert.strictEqual(ret2.length, 4);
12+
13+
assert.strictEqual(wasm.consume_optional_enum_vec(undefined), undefined);
14+
};
15+
16+
exports.pass_invalid_enum_vec = () => {
17+
try {
18+
wasm.consume_enum_vec(['not an enum value']);
19+
} catch (e) {
20+
assert.match(e.message, /invalid enum value passed/)
21+
assert.match(e.stack, /consume_enum_vec/)
22+
}
23+
};

tests/wasm/enum_vecs.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use wasm_bindgen::prelude::*;
2+
use wasm_bindgen_test::*;
3+
4+
#[wasm_bindgen(module = "tests/wasm/enum_vecs.js")]
5+
extern "C" {
6+
fn pass_enum_vec();
7+
fn pass_invalid_enum_vec();
8+
}
9+
10+
#[wasm_bindgen]
11+
pub enum EnumArrayElement {
12+
Unit,
13+
}
14+
15+
#[wasm_bindgen]
16+
pub fn consume_enum_vec(mut vec: Vec<EnumArrayElement>) -> Vec<EnumArrayElement> {
17+
vec.push(EnumArrayElement::Unit);
18+
vec
19+
}
20+
21+
#[wasm_bindgen]
22+
pub fn consume_optional_enum_vec(
23+
vec: Option<Vec<EnumArrayElement>>,
24+
) -> Option<Vec<EnumArrayElement>> {
25+
vec.map(consume_enum_vec)
26+
}
27+
28+
#[wasm_bindgen_test]
29+
fn test_valid() {
30+
pass_enum_vec();
31+
}
32+
33+
#[wasm_bindgen_test]
34+
fn test_invalid() {
35+
pass_invalid_enum_vec();
36+
}

tests/wasm/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub mod closures;
2323
pub mod comments;
2424
pub mod duplicate_deps;
2525
pub mod duplicates;
26+
pub mod enum_vecs;
2627
pub mod enums;
2728
#[path = "final.rs"]
2829
pub mod final_;

0 commit comments

Comments
 (0)