diff --git a/crates/backend/src/codegen/struct.rs b/crates/backend/src/codegen/struct.rs index 06302a43..4e1ef477 100644 --- a/crates/backend/src/codegen/struct.rs +++ b/crates/backend/src/codegen/struct.rs @@ -322,7 +322,12 @@ impl NapiStruct { if is_optional_field { obj_field_getters.push(quote! { let #ident: #ty = obj.get(#field_js_name)?; }); } else { - obj_field_getters.push(quote! { let #ident: #ty = obj.get(#field_js_name)?.expect(&format!("Field {} should exist", #field_js_name)); }); + obj_field_getters.push(quote! { + let #ident: #ty = obj.get(#field_js_name)?.ok_or_else(|| napi::bindgen_prelude::Error::new( + napi::bindgen_prelude::Status::InvalidArg, + format!("Missing field `{}`", #field_js_name), + ))?; + }); } } syn::Member::Unnamed(i) => { @@ -339,7 +344,12 @@ impl NapiStruct { if is_optional_field { obj_field_getters.push(quote! { let arg #i: #ty = obj.get(#field_js_name)?; }); } else { - obj_field_getters.push(quote! { let arg #i: #ty = obj.get(#field_js_name)?.expect(&format!("Field {} should exist", #field_js_name)); }); + obj_field_getters.push(quote! { + let arg #i: #ty = obj.get(#field_js_name)?.ok_or_else(|| napi::bindgen_prelude::Error::new( + napi::bindgen_prelude::Status::InvalidArg, + format!("Missing field `{}`", #field_js_name), + ))?; + }); } } } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 23907a13..55b92aca 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -94,6 +94,10 @@ Generated by [AVA](https://avajs.dev). b: number␊ }␊ export function fnReceivedAliased(s: AliasedStruct, e: ALIAS): void␊ + export interface StrictObject {␊ + name: string␊ + }␊ + export function receiveStrictObject(strictObject: StrictObject): void␊ export function asyncPlus100(p: Promise): Promise␊ /** This is an interface for package.json */␊ export interface PackageJson {␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 1730c624..36b7e036 100644 Binary files a/examples/napi/__test__/typegen.spec.ts.snap and b/examples/napi/__test__/typegen.spec.ts.snap differ diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index 2745b850..395f0719 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -72,6 +72,7 @@ import { Dog, Bird, Assets, + receiveStrictObject, } from '../' test('export const', (t) => { @@ -245,6 +246,15 @@ test('option object', (t) => { t.notThrows(() => receiveAllOptionalObject({})) }) +test('should throw if object type is not matched', (t) => { + // @ts-expect-error + const err1 = t.throws(() => receiveStrictObject({ name: 1 })) + t.is(err1!.message, 'Failed to convert napi `string` into rust type `String`') + // @ts-expect-error + const err2 = t.throws(() => receiveStrictObject({ bar: 1 })) + t.is(err2!.message, 'Missing field `name`') +}) + test('aliased rust struct and enum', (t) => { const a: ALIAS = ALIAS.A const b: AliasedStruct = { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 3453c31c..cd2e9b02 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -84,6 +84,10 @@ export interface AliasedStruct { b: number } export function fnReceivedAliased(s: AliasedStruct, e: ALIAS): void +export interface StrictObject { + name: string +} +export function receiveStrictObject(strictObject: StrictObject): void export function asyncPlus100(p: Promise): Promise /** This is an interface for package.json */ export interface PackageJson { diff --git a/examples/napi/src/object.rs b/examples/napi/src/object.rs index 741c74cf..6ae0fa5b 100644 --- a/examples/napi/src/object.rs +++ b/examples/napi/src/object.rs @@ -59,3 +59,13 @@ pub struct StructContainsAliasedEnum { fn fn_received_aliased(mut s: StructContainsAliasedEnum, e: AliasedEnum) { s.a = e; } + +#[napi(object)] +pub struct StrictObject { + pub name: String, +} + +#[napi] +pub fn receive_strict_object(strict_object: StrictObject) { + assert_eq!(strict_object.name, "strict"); +}