diff --git a/CHANGELOG.md b/CHANGELOG.md index 32405a47e32..3402f7ae975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # `wasm-bindgen` Change Log -------------------------------------------------------------------------------- +## Unreleased + +### Changed + +* Optional parameters are now typed as `T | undefined | null` to reflect the actual JS behavior. + [#4188](https://github.com/rustwasm/wasm-bindgen/pull/4188) + +-------------------------------------------------------------------------------- + ## [0.2.99](https://github.com/rustwasm/wasm-bindgen/compare/0.2.98...0.2.99) Released 2024-12-07 diff --git a/crates/cli-support/src/js/binding.rs b/crates/cli-support/src/js/binding.rs index 54be1481163..637c3a5edf7 100644 --- a/crates/cli-support/src/js/binding.rs +++ b/crates/cli-support/src/js/binding.rs @@ -321,13 +321,15 @@ impl<'a, 'b> Builder<'a, 'b> { let mut ts = String::new(); match ty { AdapterType::Option(ty) if omittable => { + // e.g. `foo?: string | null` arg.push_str("?: "); - adapter2ts(ty, &mut ts, Some(&mut ts_refs)); + adapter2ts(ty, TypePosition::Argument, &mut ts, Some(&mut ts_refs)); + ts.push_str(" | null"); } ty => { omittable = false; arg.push_str(": "); - adapter2ts(ty, &mut ts, Some(&mut ts_refs)); + adapter2ts(ty, TypePosition::Argument, &mut ts, Some(&mut ts_refs)); } } arg.push_str(&ts); @@ -363,7 +365,12 @@ impl<'a, 'b> Builder<'a, 'b> { let mut ret = String::new(); match result_tys.len() { 0 => ret.push_str("void"), - 1 => adapter2ts(&result_tys[0], &mut ret, Some(&mut ts_refs)), + 1 => adapter2ts( + &result_tys[0], + TypePosition::Return, + &mut ret, + Some(&mut ts_refs), + ), _ => ret.push_str("[any]"), } if asyncness { @@ -395,16 +402,18 @@ impl<'a, 'b> Builder<'a, 'b> { for (name, ty) in fn_arg_names.iter().zip(arg_tys).rev() { let mut arg = "@param {".to_string(); - adapter2ts(ty, &mut arg, None); - arg.push_str("} "); match ty { - AdapterType::Option(..) if omittable => { + AdapterType::Option(ty) if omittable => { + adapter2ts(ty, TypePosition::Argument, &mut arg, None); + arg.push_str(" | null} "); arg.push('['); arg.push_str(name); arg.push(']'); } _ => { omittable = false; + adapter2ts(ty, TypePosition::Argument, &mut arg, None); + arg.push_str("} "); arg.push_str(name); } } @@ -416,7 +425,7 @@ impl<'a, 'b> Builder<'a, 'b> { if let (Some(name), Some(ty)) = (variadic_arg, arg_tys.last()) { ret.push_str("@param {..."); - adapter2ts(ty, &mut ret, None); + adapter2ts(ty, TypePosition::Argument, &mut ret, None); ret.push_str("} "); ret.push_str(name); ret.push('\n'); @@ -1542,7 +1551,18 @@ impl Invocation { } } -fn adapter2ts(ty: &AdapterType, dst: &mut String, refs: Option<&mut HashSet>) { +#[derive(Debug, Clone, Copy)] +enum TypePosition { + Argument, + Return, +} + +fn adapter2ts( + ty: &AdapterType, + position: TypePosition, + dst: &mut String, + refs: Option<&mut HashSet>, +) { match ty { AdapterType::I32 | AdapterType::S8 @@ -1564,8 +1584,11 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String, refs: Option<&mut HashSet dst.push_str("boolean"), AdapterType::Vector(kind) => dst.push_str(&kind.js_ty()), AdapterType::Option(ty) => { - adapter2ts(ty, dst, refs); - dst.push_str(" | undefined"); + adapter2ts(ty, position, dst, refs); + dst.push_str(match position { + TypePosition::Argument => " | null | undefined", + TypePosition::Return => " | undefined", + }); } AdapterType::NamedExternref(name) => dst.push_str(name), AdapterType::Struct(name) => dst.push_str(name), diff --git a/crates/cli/tests/reference/echo.d.ts b/crates/cli/tests/reference/echo.d.ts index c318f636c11..61fd4a7925e 100644 --- a/crates/cli/tests/reference/echo.d.ts +++ b/crates/cli/tests/reference/echo.d.ts @@ -36,42 +36,42 @@ export function echo_vec_uninit_i64(a: BigInt64Array): BigInt64Array; export function echo_vec_string(a: (string)[]): (string)[]; export function echo_struct(a: Foo): Foo; export function echo_vec_struct(a: (Foo)[]): (Foo)[]; -export function echo_option_u8(a?: number): number | undefined; -export function echo_option_i8(a?: number): number | undefined; -export function echo_option_u16(a?: number): number | undefined; -export function echo_option_i16(a?: number): number | undefined; -export function echo_option_u32(a?: number): number | undefined; -export function echo_option_i32(a?: number): number | undefined; -export function echo_option_u64(a?: bigint): bigint | undefined; -export function echo_option_i64(a?: bigint): bigint | undefined; -export function echo_option_u128(a?: bigint): bigint | undefined; -export function echo_option_i128(a?: bigint): bigint | undefined; -export function echo_option_usize(a?: number): number | undefined; -export function echo_option_isize(a?: number): number | undefined; -export function echo_option_f32(a?: number): number | undefined; -export function echo_option_f64(a?: number): number | undefined; -export function echo_option_bool(a?: boolean): boolean | undefined; -export function echo_option_char(a?: string): string | undefined; -export function echo_option_string(a?: string): string | undefined; -export function echo_option_vec_u8(a?: Uint8Array): Uint8Array | undefined; -export function echo_option_vec_i8(a?: Int8Array): Int8Array | undefined; -export function echo_option_vec_u16(a?: Uint16Array): Uint16Array | undefined; -export function echo_option_vec_i16(a?: Int16Array): Int16Array | undefined; -export function echo_option_vec_u32(a?: Uint32Array): Uint32Array | undefined; -export function echo_option_vec_i32(a?: Int32Array): Int32Array | undefined; -export function echo_option_vec_u64(a?: BigUint64Array): BigUint64Array | undefined; -export function echo_option_vec_i64(a?: BigInt64Array): BigInt64Array | undefined; -export function echo_option_vec_uninit_u8(a?: Uint8Array): Uint8Array | undefined; -export function echo_option_vec_uninit_i8(a?: Int8Array): Int8Array | undefined; -export function echo_option_vec_uninit_u16(a?: Uint16Array): Uint16Array | undefined; -export function echo_option_vec_uninit_i16(a?: Int16Array): Int16Array | undefined; -export function echo_option_vec_uninit_u32(a?: Uint32Array): Uint32Array | undefined; -export function echo_option_vec_uninit_i32(a?: Int32Array): Int32Array | undefined; -export function echo_option_vec_uninit_u64(a?: BigUint64Array): BigUint64Array | undefined; -export function echo_option_vec_uninit_i64(a?: BigInt64Array): BigInt64Array | undefined; -export function echo_option_vec_string(a?: (string)[]): (string)[] | undefined; -export function echo_option_struct(a?: Foo): Foo | undefined; -export function echo_option_vec_struct(a?: (Foo)[]): (Foo)[] | undefined; +export function echo_option_u8(a?: number | null): number | undefined; +export function echo_option_i8(a?: number | null): number | undefined; +export function echo_option_u16(a?: number | null): number | undefined; +export function echo_option_i16(a?: number | null): number | undefined; +export function echo_option_u32(a?: number | null): number | undefined; +export function echo_option_i32(a?: number | null): number | undefined; +export function echo_option_u64(a?: bigint | null): bigint | undefined; +export function echo_option_i64(a?: bigint | null): bigint | undefined; +export function echo_option_u128(a?: bigint | null): bigint | undefined; +export function echo_option_i128(a?: bigint | null): bigint | undefined; +export function echo_option_usize(a?: number | null): number | undefined; +export function echo_option_isize(a?: number | null): number | undefined; +export function echo_option_f32(a?: number | null): number | undefined; +export function echo_option_f64(a?: number | null): number | undefined; +export function echo_option_bool(a?: boolean | null): boolean | undefined; +export function echo_option_char(a?: string | null): string | undefined; +export function echo_option_string(a?: string | null): string | undefined; +export function echo_option_vec_u8(a?: Uint8Array | null): Uint8Array | undefined; +export function echo_option_vec_i8(a?: Int8Array | null): Int8Array | undefined; +export function echo_option_vec_u16(a?: Uint16Array | null): Uint16Array | undefined; +export function echo_option_vec_i16(a?: Int16Array | null): Int16Array | undefined; +export function echo_option_vec_u32(a?: Uint32Array | null): Uint32Array | undefined; +export function echo_option_vec_i32(a?: Int32Array | null): Int32Array | undefined; +export function echo_option_vec_u64(a?: BigUint64Array | null): BigUint64Array | undefined; +export function echo_option_vec_i64(a?: BigInt64Array | null): BigInt64Array | undefined; +export function echo_option_vec_uninit_u8(a?: Uint8Array | null): Uint8Array | undefined; +export function echo_option_vec_uninit_i8(a?: Int8Array | null): Int8Array | undefined; +export function echo_option_vec_uninit_u16(a?: Uint16Array | null): Uint16Array | undefined; +export function echo_option_vec_uninit_i16(a?: Int16Array | null): Int16Array | undefined; +export function echo_option_vec_uninit_u32(a?: Uint32Array | null): Uint32Array | undefined; +export function echo_option_vec_uninit_i32(a?: Int32Array | null): Int32Array | undefined; +export function echo_option_vec_uninit_u64(a?: BigUint64Array | null): BigUint64Array | undefined; +export function echo_option_vec_uninit_i64(a?: BigInt64Array | null): BigInt64Array | undefined; +export function echo_option_vec_string(a?: (string)[] | null): (string)[] | undefined; +export function echo_option_struct(a?: Foo | null): Foo | undefined; +export function echo_option_vec_struct(a?: (Foo)[] | null): (Foo)[] | undefined; export class Foo { private constructor(); free(): void; diff --git a/crates/cli/tests/reference/echo.js b/crates/cli/tests/reference/echo.js index 1809b0e8618..c3e9c47f835 100644 --- a/crates/cli/tests/reference/echo.js +++ b/crates/cli/tests/reference/echo.js @@ -727,7 +727,7 @@ export function echo_vec_struct(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_u8(a) { @@ -736,7 +736,7 @@ export function echo_option_u8(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_i8(a) { @@ -745,7 +745,7 @@ export function echo_option_i8(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_u16(a) { @@ -754,7 +754,7 @@ export function echo_option_u16(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_i16(a) { @@ -763,7 +763,7 @@ export function echo_option_i16(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_u32(a) { @@ -772,7 +772,7 @@ export function echo_option_u32(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_i32(a) { @@ -781,7 +781,7 @@ export function echo_option_i32(a) { } /** - * @param {bigint | undefined} [a] + * @param {bigint | null} [a] * @returns {bigint | undefined} */ export function echo_option_u64(a) { @@ -790,7 +790,7 @@ export function echo_option_u64(a) { } /** - * @param {bigint | undefined} [a] + * @param {bigint | null} [a] * @returns {bigint | undefined} */ export function echo_option_i64(a) { @@ -799,7 +799,7 @@ export function echo_option_i64(a) { } /** - * @param {bigint | undefined} [a] + * @param {bigint | null} [a] * @returns {bigint | undefined} */ export function echo_option_u128(a) { @@ -808,7 +808,7 @@ export function echo_option_u128(a) { } /** - * @param {bigint | undefined} [a] + * @param {bigint | null} [a] * @returns {bigint | undefined} */ export function echo_option_i128(a) { @@ -817,7 +817,7 @@ export function echo_option_i128(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_usize(a) { @@ -826,7 +826,7 @@ export function echo_option_usize(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_isize(a) { @@ -835,7 +835,7 @@ export function echo_option_isize(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_f32(a) { @@ -844,7 +844,7 @@ export function echo_option_f32(a) { } /** - * @param {number | undefined} [a] + * @param {number | null} [a] * @returns {number | undefined} */ export function echo_option_f64(a) { @@ -853,7 +853,7 @@ export function echo_option_f64(a) { } /** - * @param {boolean | undefined} [a] + * @param {boolean | null} [a] * @returns {boolean | undefined} */ export function echo_option_bool(a) { @@ -862,7 +862,7 @@ export function echo_option_bool(a) { } /** - * @param {string | undefined} [a] + * @param {string | null} [a] * @returns {string | undefined} */ export function echo_option_char(a) { @@ -873,7 +873,7 @@ export function echo_option_char(a) { } /** - * @param {string | undefined} [a] + * @param {string | null} [a] * @returns {string | undefined} */ export function echo_option_string(a) { @@ -889,7 +889,7 @@ export function echo_option_string(a) { } /** - * @param {Uint8Array | undefined} [a] + * @param {Uint8Array | null} [a] * @returns {Uint8Array | undefined} */ export function echo_option_vec_u8(a) { @@ -905,7 +905,7 @@ export function echo_option_vec_u8(a) { } /** - * @param {Int8Array | undefined} [a] + * @param {Int8Array | null} [a] * @returns {Int8Array | undefined} */ export function echo_option_vec_i8(a) { @@ -921,7 +921,7 @@ export function echo_option_vec_i8(a) { } /** - * @param {Uint16Array | undefined} [a] + * @param {Uint16Array | null} [a] * @returns {Uint16Array | undefined} */ export function echo_option_vec_u16(a) { @@ -937,7 +937,7 @@ export function echo_option_vec_u16(a) { } /** - * @param {Int16Array | undefined} [a] + * @param {Int16Array | null} [a] * @returns {Int16Array | undefined} */ export function echo_option_vec_i16(a) { @@ -953,7 +953,7 @@ export function echo_option_vec_i16(a) { } /** - * @param {Uint32Array | undefined} [a] + * @param {Uint32Array | null} [a] * @returns {Uint32Array | undefined} */ export function echo_option_vec_u32(a) { @@ -969,7 +969,7 @@ export function echo_option_vec_u32(a) { } /** - * @param {Int32Array | undefined} [a] + * @param {Int32Array | null} [a] * @returns {Int32Array | undefined} */ export function echo_option_vec_i32(a) { @@ -985,7 +985,7 @@ export function echo_option_vec_i32(a) { } /** - * @param {BigUint64Array | undefined} [a] + * @param {BigUint64Array | null} [a] * @returns {BigUint64Array | undefined} */ export function echo_option_vec_u64(a) { @@ -1001,7 +1001,7 @@ export function echo_option_vec_u64(a) { } /** - * @param {BigInt64Array | undefined} [a] + * @param {BigInt64Array | null} [a] * @returns {BigInt64Array | undefined} */ export function echo_option_vec_i64(a) { @@ -1017,7 +1017,7 @@ export function echo_option_vec_i64(a) { } /** - * @param {Uint8Array | undefined} [a] + * @param {Uint8Array | null} [a] * @returns {Uint8Array | undefined} */ export function echo_option_vec_uninit_u8(a) { @@ -1033,7 +1033,7 @@ export function echo_option_vec_uninit_u8(a) { } /** - * @param {Int8Array | undefined} [a] + * @param {Int8Array | null} [a] * @returns {Int8Array | undefined} */ export function echo_option_vec_uninit_i8(a) { @@ -1049,7 +1049,7 @@ export function echo_option_vec_uninit_i8(a) { } /** - * @param {Uint16Array | undefined} [a] + * @param {Uint16Array | null} [a] * @returns {Uint16Array | undefined} */ export function echo_option_vec_uninit_u16(a) { @@ -1065,7 +1065,7 @@ export function echo_option_vec_uninit_u16(a) { } /** - * @param {Int16Array | undefined} [a] + * @param {Int16Array | null} [a] * @returns {Int16Array | undefined} */ export function echo_option_vec_uninit_i16(a) { @@ -1081,7 +1081,7 @@ export function echo_option_vec_uninit_i16(a) { } /** - * @param {Uint32Array | undefined} [a] + * @param {Uint32Array | null} [a] * @returns {Uint32Array | undefined} */ export function echo_option_vec_uninit_u32(a) { @@ -1097,7 +1097,7 @@ export function echo_option_vec_uninit_u32(a) { } /** - * @param {Int32Array | undefined} [a] + * @param {Int32Array | null} [a] * @returns {Int32Array | undefined} */ export function echo_option_vec_uninit_i32(a) { @@ -1113,7 +1113,7 @@ export function echo_option_vec_uninit_i32(a) { } /** - * @param {BigUint64Array | undefined} [a] + * @param {BigUint64Array | null} [a] * @returns {BigUint64Array | undefined} */ export function echo_option_vec_uninit_u64(a) { @@ -1129,7 +1129,7 @@ export function echo_option_vec_uninit_u64(a) { } /** - * @param {BigInt64Array | undefined} [a] + * @param {BigInt64Array | null} [a] * @returns {BigInt64Array | undefined} */ export function echo_option_vec_uninit_i64(a) { @@ -1145,7 +1145,7 @@ export function echo_option_vec_uninit_i64(a) { } /** - * @param {(string)[] | undefined} [a] + * @param {(string)[] | null} [a] * @returns {(string)[] | undefined} */ export function echo_option_vec_string(a) { @@ -1161,7 +1161,7 @@ export function echo_option_vec_string(a) { } /** - * @param {Foo | undefined} [a] + * @param {Foo | null} [a] * @returns {Foo | undefined} */ export function echo_option_struct(a) { @@ -1175,7 +1175,7 @@ export function echo_option_struct(a) { } /** - * @param {(Foo)[] | undefined} [a] + * @param {(Foo)[] | null} [a] * @returns {(Foo)[] | undefined} */ export function echo_option_vec_struct(a) { diff --git a/crates/cli/tests/reference/enums.d.ts b/crates/cli/tests/reference/enums.d.ts index da84bbb7740..8d1b955c1f9 100644 --- a/crates/cli/tests/reference/enums.d.ts +++ b/crates/cli/tests/reference/enums.d.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ export function enum_echo(color: Color): Color; -export function option_enum_echo(color?: Color): Color | undefined; +export function option_enum_echo(color?: Color | null): Color | undefined; export function get_name(color: Color): ColorName; -export function option_string_enum_echo(color?: ColorName): ColorName | undefined; -export function option_order(order?: Ordering): Ordering | undefined; +export function option_string_enum_echo(color?: ColorName | null): ColorName | undefined; +export function option_order(order?: Ordering | null): Ordering | undefined; /** * A color. */ diff --git a/crates/cli/tests/reference/enums.js b/crates/cli/tests/reference/enums.js index 13459b9c77e..10d698dc7e5 100644 --- a/crates/cli/tests/reference/enums.js +++ b/crates/cli/tests/reference/enums.js @@ -36,7 +36,7 @@ function isLikeNone(x) { return x === undefined || x === null; } /** - * @param {Color | undefined} [color] + * @param {Color | null} [color] * @returns {Color | undefined} */ export function option_enum_echo(color) { @@ -54,7 +54,7 @@ export function get_name(color) { } /** - * @param {ColorName | undefined} [color] + * @param {ColorName | null} [color] * @returns {ColorName | undefined} */ export function option_string_enum_echo(color) { @@ -63,7 +63,7 @@ export function option_string_enum_echo(color) { } /** - * @param {Ordering | undefined} [order] + * @param {Ordering | null} [order] * @returns {Ordering | undefined} */ export function option_order(order) { diff --git a/crates/cli/tests/reference/getter-setter.d.ts b/crates/cli/tests/reference/getter-setter.d.ts index 8222ca2a462..789fb0f279f 100644 --- a/crates/cli/tests/reference/getter-setter.d.ts +++ b/crates/cli/tests/reference/getter-setter.d.ts @@ -4,10 +4,12 @@ export class Foo { private constructor(); free(): void; x: number; - y?: number; - z?: number; + get y(): number | undefined; + set y(value: number | null | undefined); + get z(): number | undefined; + set z(value: number | null | undefined); readonly lone_getter: number | undefined; - set lone_setter(value: number | undefined); + set lone_setter(value: number | null | undefined); /** * You will only read numbers. */ @@ -17,10 +19,11 @@ export class Foo { * * Yes, this is totally fine in JS. */ - set weird(value: string | undefined); + set weird(value: string | null | undefined); /** * There can be static getters and setters too, and they can even have the * same name as instance getters and setters. */ - static x?: boolean; + static get x(): boolean | undefined; + static set x(value: boolean | null | undefined); } diff --git a/crates/cli/tests/reference/getter-setter.js b/crates/cli/tests/reference/getter-setter.js index fc0ce4820dd..a9df5536a5b 100644 --- a/crates/cli/tests/reference/getter-setter.js +++ b/crates/cli/tests/reference/getter-setter.js @@ -124,7 +124,7 @@ export class Foo { return ret === 0x100000001 ? undefined : ret; } /** - * @param {number | undefined} [arg0] + * @param {number | null} [arg0] */ set y(arg0) { wasm.__wbg_set_foo_y(this.__wbg_ptr, isLikeNone(arg0) ? 0x100000001 : (arg0) >>> 0); @@ -137,7 +137,7 @@ export class Foo { return ret === 0x100000001 ? undefined : ret; } /** - * @param {number | undefined} [z] + * @param {number | null} [z] */ set z(z) { wasm.foo_set_z(this.__wbg_ptr, isLikeNone(z) ? 0x100000001 : (z) >>> 0); @@ -150,7 +150,7 @@ export class Foo { return ret === 0x100000001 ? undefined : ret; } /** - * @param {number | undefined} [value] + * @param {number | null} [value] */ set lone_setter(value) { wasm.foo_set_lone_setter(this.__wbg_ptr, isLikeNone(value) ? 0x100000001 : (value) >>> 0); @@ -167,7 +167,7 @@ export class Foo { * But you must write strings. * * Yes, this is totally fine in JS. - * @param {string | undefined} [value] + * @param {string | null} [value] */ set weird(value) { var ptr0 = isLikeNone(value) ? 0 : passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); @@ -184,7 +184,7 @@ export class Foo { return ret === 0xFFFFFF ? undefined : ret !== 0; } /** - * @param {boolean | undefined} [value] + * @param {boolean | null} [value] */ static set x(value) { wasm.foo_set_x_static(isLikeNone(value) ? 0xFFFFFF : value ? 1 : 0); diff --git a/crates/cli/tests/reference/int128.d.ts b/crates/cli/tests/reference/int128.d.ts index 183cef4758a..ff5bfb22910 100644 --- a/crates/cli/tests/reference/int128.d.ts +++ b/crates/cli/tests/reference/int128.d.ts @@ -2,6 +2,6 @@ /* eslint-disable */ export function echo_i128(a: bigint): bigint; export function echo_u128(a: bigint): bigint; -export function echo_option_i128(a?: bigint): bigint | undefined; -export function echo_option_u128(a?: bigint): bigint | undefined; +export function echo_option_i128(a?: bigint | null): bigint | undefined; +export function echo_option_u128(a?: bigint | null): bigint | undefined; export function throw_i128(): bigint; diff --git a/crates/cli/tests/reference/int128.js b/crates/cli/tests/reference/int128.js index 1df6bb28c26..32de778621c 100644 --- a/crates/cli/tests/reference/int128.js +++ b/crates/cli/tests/reference/int128.js @@ -45,7 +45,7 @@ function isLikeNone(x) { return x === undefined || x === null; } /** - * @param {bigint | undefined} [a] + * @param {bigint | null} [a] * @returns {bigint | undefined} */ export function echo_option_i128(a) { @@ -54,7 +54,7 @@ export function echo_option_i128(a) { } /** - * @param {bigint | undefined} [a] + * @param {bigint | null} [a] * @returns {bigint | undefined} */ export function echo_option_u128(a) { diff --git a/crates/cli/tests/reference/optional-args.d.ts b/crates/cli/tests/reference/optional-args.d.ts new file mode 100644 index 00000000000..4f156949356 --- /dev/null +++ b/crates/cli/tests/reference/optional-args.d.ts @@ -0,0 +1,4 @@ +/* tslint:disable */ +/* eslint-disable */ +export function all_optional(a?: number | null, b?: number | null, c?: number | null): void; +export function some_optional(a: number | null | undefined, b: number, c?: number | null): void; diff --git a/crates/cli/tests/reference/optional-args.js b/crates/cli/tests/reference/optional-args.js new file mode 100644 index 00000000000..43ead5d86c1 --- /dev/null +++ b/crates/cli/tests/reference/optional-args.js @@ -0,0 +1,38 @@ +let wasm; +export function __wbg_set_wasm(val) { + wasm = val; +} + + +function isLikeNone(x) { + return x === undefined || x === null; +} +/** + * @param {number | null} [a] + * @param {number | null} [b] + * @param {number | null} [c] + */ +export function all_optional(a, b, c) { + wasm.all_optional(isLikeNone(a) ? 0x100000001 : (a) >>> 0, isLikeNone(b) ? 0x100000001 : (b) >>> 0, isLikeNone(c) ? 0x100000001 : (c) >>> 0); +} + +/** + * @param {number | null | undefined} a + * @param {number} b + * @param {number | null} [c] + */ +export function some_optional(a, b, c) { + wasm.some_optional(isLikeNone(a) ? 0x100000001 : (a) >>> 0, b, isLikeNone(c) ? 0x100000001 : (c) >>> 0); +} + +export function __wbindgen_init_externref_table() { + const table = wasm.__wbindgen_export_0; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + ; +}; + diff --git a/crates/cli/tests/reference/optional-args.rs b/crates/cli/tests/reference/optional-args.rs new file mode 100644 index 00000000000..bbc0fa81e39 --- /dev/null +++ b/crates/cli/tests/reference/optional-args.rs @@ -0,0 +1,7 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn all_optional(a: Option, b: Option, c: Option) {} + +#[wasm_bindgen] +pub fn some_optional(a: Option, b: u32, c: Option) {} diff --git a/crates/cli/tests/reference/optional-args.wat b/crates/cli/tests/reference/optional-args.wat new file mode 100644 index 00000000000..a0f6061efbe --- /dev/null +++ b/crates/cli/tests/reference/optional-args.wat @@ -0,0 +1,17 @@ +(module $reference_test.wasm + (type (;0;) (func)) + (type (;1;) (func (param f64 i32 f64))) + (type (;2;) (func (param f64 f64 f64))) + (import "./reference_test_bg.js" "__wbindgen_init_externref_table" (func (;0;) (type 0))) + (func $all_optional (;1;) (type 2) (param f64 f64 f64)) + (func $some_optional (;2;) (type 1) (param f64 i32 f64)) + (table (;0;) 128 externref) + (memory (;0;) 17) + (export "memory" (memory 0)) + (export "all_optional" (func $all_optional)) + (export "some_optional" (func $some_optional)) + (export "__wbindgen_export_0" (table 0)) + (export "__wbindgen_start" (func 0)) + (@custom "target_features" (after code) "\04+\0amultivalue+\0fmutable-globals+\0freference-types+\08sign-ext") +) + diff --git a/crates/typescript-tests/src/optional_fields.ts b/crates/typescript-tests/src/optional_fields.ts index 61e1fc05b1b..8d1cf90c64c 100644 --- a/crates/typescript-tests/src/optional_fields.ts +++ b/crates/typescript-tests/src/optional_fields.ts @@ -1,3 +1,10 @@ import * as wbg from '../pkg/typescript_tests'; -const fields: wbg.Fields = { spaceboy: true, free: () => { } }; +const fields: wbg.Fields = null as unknown as wbg.Fields; + +// optional fields read T | undefined +const _hallo: boolean | undefined = fields.hallo; + +// and allow writing T | null | undefined +fields.hallo = undefined; +fields.hallo = null;