Skip to content

Commit

Permalink
Add enum types for function parameters and return types (#3647)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianIvicevic authored Oct 7, 2023
1 parent 277b20f commit 5b42ffc
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@
as normal exceptions rather than as rejected promises.
[#3611](https://github.com/rustwasm/wasm-bindgen/pull/3611)

* Improved TypeScript bindings to accurately reference Rust enum types in function signatures,
enhancing type safety and compatibility.
[#3647](https://github.com/rustwasm/wasm-bindgen/pull/3647)

### Fixed

* Fixed `wasm_bindgen` macro to handle raw identifiers in field names.
Expand Down
5 changes: 5 additions & 0 deletions crates/backend/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1382,6 +1382,9 @@ impl<'a> ToTokens for DescribeImport<'a> {
impl ToTokens for ast::Enum {
fn to_tokens(&self, into: &mut TokenStream) {
let enum_name = &self.rust_name;
let name_str = self.js_name.to_string();
let name_len = name_str.len() as u32;
let name_chars = name_str.chars().map(|c| c as u32);
let hole = &self.hole;
let cast_clauses = self.variants.iter().map(|variant| {
let variant_name = &variant.name;
Expand Down Expand Up @@ -1433,6 +1436,8 @@ impl ToTokens for ast::Enum {
fn describe() {
use #wasm_bindgen::describe::*;
inform(ENUM);
inform(#name_len);
#(inform(#name_chars);)*
inform(#hole);
}
}
Expand Down
8 changes: 6 additions & 2 deletions crates/cli-support/src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub enum Descriptor {
String,
Externref,
NamedExternref(String),
Enum { hole: u32 },
Enum { name: String, hole: u32 },
RustStruct(String),
Char,
Option(Box<Descriptor>),
Expand Down Expand Up @@ -149,7 +149,11 @@ impl Descriptor {
CACHED_STRING => Descriptor::CachedString,
STRING => Descriptor::String,
EXTERNREF => Descriptor::Externref,
ENUM => Descriptor::Enum { hole: get(data) },
ENUM => {
let name = get_string(data);
let hole = get(data);
Descriptor::Enum { name, hole }
}
RUST_STRUCT => {
let name = get_string(data);
Descriptor::RustStruct(name)
Expand Down
1 change: 1 addition & 0 deletions crates/cli-support/src/js/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,7 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String) {
}
AdapterType::NamedExternref(name) => dst.push_str(name),
AdapterType::Struct(name) => dst.push_str(name),
AdapterType::Enum(name) => dst.push_str(name),
AdapterType::Function => dst.push_str("any"),
}
}
15 changes: 12 additions & 3 deletions crates/cli-support/src/wit/incoming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,16 @@ impl InstructionBuilder<'_, '_> {
self.get(AdapterType::F64);
self.output.push(AdapterType::F64);
}
Descriptor::Enum { .. } => self.number(AdapterType::U32, WasmVT::I32),
Descriptor::Enum { name, .. } => {
self.instruction(
&[AdapterType::Enum(name.clone())],
Instruction::IntToWasm {
input: AdapterType::U32,
output: ValType::I32,
},
&[AdapterType::I32],
);
},
Descriptor::Ref(d) => self.incoming_ref(false, d)?,
Descriptor::RefMut(d) => self.incoming_ref(true, d)?,
Descriptor::Option(d) => self.incoming_option(d)?,
Expand Down Expand Up @@ -274,9 +283,9 @@ impl InstructionBuilder<'_, '_> {
&[AdapterType::I32],
);
}
Descriptor::Enum { hole } => {
Descriptor::Enum { name, hole } => {
self.instruction(
&[AdapterType::U32.option()],
&[AdapterType::Enum(name.clone()).option()],
Instruction::I32FromOptionEnum { hole: *hole },
&[AdapterType::I32],
);
Expand Down
6 changes: 3 additions & 3 deletions crates/cli-support/src/wit/outgoing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl InstructionBuilder<'_, '_> {
self.get(AdapterType::F64);
self.output.push(AdapterType::F64);
}
Descriptor::Enum { .. } => self.outgoing_i32(AdapterType::U32),
Descriptor::Enum { name, .. } => self.outgoing_i32(AdapterType::Enum(name.clone())),

Descriptor::Char => {
self.instruction(
Expand Down Expand Up @@ -278,11 +278,11 @@ impl InstructionBuilder<'_, '_> {
&[AdapterType::String.option()],
);
}
Descriptor::Enum { hole } => {
Descriptor::Enum { name, hole } => {
self.instruction(
&[AdapterType::I32],
Instruction::OptionEnumFromI32 { hole: *hole },
&[AdapterType::U32.option()],
&[AdapterType::Enum(name.clone()).option()],
);
}
Descriptor::RustStruct(name) => {
Expand Down
2 changes: 2 additions & 0 deletions crates/cli-support/src/wit/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub enum AdapterType {
Vector(VectorKind),
Option(Box<AdapterType>),
Struct(String),
Enum(String),
NamedExternref(String),
Function,
}
Expand Down Expand Up @@ -327,6 +328,7 @@ impl AdapterType {
AdapterType::I64 => walrus::ValType::I64,
AdapterType::F32 => walrus::ValType::F32,
AdapterType::F64 => walrus::ValType::F64,
AdapterType::Enum(_) => walrus::ValType::I32,
AdapterType::Externref | AdapterType::NamedExternref(_) => walrus::ValType::Externref,
_ => return None,
})
Expand Down
16 changes: 16 additions & 0 deletions crates/typescript-tests/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,19 @@ pub enum Foo {
A = 1,
B = 3,
}

#[wasm_bindgen]
pub fn fn_expects_enum(_: Foo) {}

#[wasm_bindgen]
pub fn fn_returns_enum() -> Foo {
Foo::A
}

#[wasm_bindgen]
pub fn fn_expects_option_enum(_: Option<Foo>) {}

#[wasm_bindgen]
pub fn fn_returns_option_enum() -> Option<Foo> {
Some(Foo::A)
}
5 changes: 5 additions & 0 deletions crates/typescript-tests/src/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ const a3: wbg.Foo.A = 1;
const b1: wbg.Foo = wbg.Foo.B;
const b2: wbg.Foo.B = wbg.Foo.B;
const b3: wbg.Foo.B = 3;

const fn_expects_enum: (_: wbg.Foo) => void = wbg.fn_expects_enum;
const fn_returns_enum: () => wbg.Foo = wbg.fn_returns_enum;
const fn_expects_option_enum: (_?: wbg.Foo) => void = wbg.fn_expects_option_enum;
const fn_returns_option_enum: () => wbg.Foo | undefined = wbg.fn_returns_option_enum;

0 comments on commit 5b42ffc

Please sign in to comment.