Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add enum types for function parameters and return types #3647

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;