feat(napi-derive): support return_if_invalid

This commit is contained in:
LongYinan 2022-07-05 18:39:12 +08:00
parent dface0c6a7
commit 2e53bf7f9a
No known key found for this signature in database
GPG key ID: C3666B7FC82ADAD7
9 changed files with 43 additions and 1 deletions

View file

@ -15,6 +15,7 @@ pub struct NapiFn {
pub vis: syn::Visibility, pub vis: syn::Visibility,
pub parent: Option<Ident>, pub parent: Option<Ident>,
pub strict: bool, pub strict: bool,
pub return_if_invalid: bool,
pub js_mod: Option<String>, pub js_mod: Option<String>,
pub ts_generic_types: Option<String>, pub ts_generic_types: Option<String>,
pub ts_args_type: Option<String>, pub ts_args_type: Option<String>,

View file

@ -188,7 +188,17 @@ impl NapiFn {
} }
} }
_ => { _ => {
let type_check = if self.strict { let type_check = if self.return_if_invalid {
quote! {
if let Ok(maybe_promise) = <#ty as napi::bindgen_prelude::ValidateNapiValue>::validate(env, cb.get_arg(#index)) {
if !maybe_promise.is_null() {
return Ok(maybe_promise);
}
} else {
return Ok(std::ptr::null_mut());
}
}
} else if self.strict {
quote! { quote! {
let maybe_promise = <#ty as napi::bindgen_prelude::ValidateNapiValue>::validate(env, cb.get_arg(#index))?; let maybe_promise = <#ty as napi::bindgen_prelude::ValidateNapiValue>::validate(env, cb.get_arg(#index))?;
if !maybe_promise.is_null() { if !maybe_promise.is_null() {

View file

@ -50,6 +50,7 @@ macro_rules! attrgen {
(readonly, Readonly(Span)), (readonly, Readonly(Span)),
(skip, Skip(Span)), (skip, Skip(Span)),
(strict, Strict(Span)), (strict, Strict(Span)),
(return_if_invalid, ReturnIfInvalid(Span)),
(object, Object(Span)), (object, Object(Span)),
(namespace, Namespace(Span, String, Span)), (namespace, Namespace(Span, String, Span)),
(iterator, Iterator(Span)), (iterator, Iterator(Span)),

View file

@ -670,6 +670,7 @@ fn napi_fn_from_decl(
comments: extract_doc_comments(&attrs), comments: extract_doc_comments(&attrs),
attrs, attrs,
strict: opts.strict().is_some(), strict: opts.strict().is_some(),
return_if_invalid: opts.return_if_invalid().is_some(),
js_mod: opts.namespace().map(|(m, _)| m.to_owned()), js_mod: opts.namespace().map(|(m, _)| m.to_owned()),
ts_generic_types: opts.ts_generic_types().map(|(m, _)| m.to_owned()), ts_generic_types: opts.ts_generic_types().map(|(m, _)| m.to_owned()),
ts_args_type: opts.ts_args_type().map(|(m, _)| m.to_owned()), ts_args_type: opts.ts_args_type().map(|(m, _)| m.to_owned()),

View file

@ -17,6 +17,8 @@ import {
validateSymbol, validateSymbol,
validateNull, validateNull,
validateUndefined, validateUndefined,
returnUndefinedIfInvalid,
returnUndefinedIfInvalidPromise,
} from '../index' } from '../index'
test('should validate array', (t) => { test('should validate array', (t) => {
@ -166,3 +168,15 @@ test('should validate undefined', (t) => {
message: 'Expect value to be Undefined, but received Number', message: 'Expect value to be Undefined, but received Number',
}) })
}) })
test('should return undefined if arg is invalid', (t) => {
t.is(returnUndefinedIfInvalid(true), false)
// @ts-expect-error
t.is(returnUndefinedIfInvalid(1), undefined)
})
test('should return Promise.reject() if arg is not Promise', async (t) => {
t.is(await returnUndefinedIfInvalidPromise(Promise.resolve(true)), false)
// @ts-expect-error
await t.throwsAsync(() => returnUndefinedIfInvalidPromise(1))
})

View file

@ -110,6 +110,8 @@ Generated by [AVA](https://avajs.dev).
export function validatePromise(p: Promise<number>): Promise<number> export function validatePromise(p: Promise<number>): Promise<number>
export function validateString(s: string): string␊ export function validateString(s: string): string␊
export function validateSymbol(s: symbol): boolean␊ export function validateSymbol(s: symbol): boolean␊
export function returnUndefinedIfInvalid(input: boolean): boolean␊
export function returnUndefinedIfInvalidPromise(input: Promise<boolean>): Promise<boolean>
export function tsRename(a: { foo: number }): string[]␊ export function tsRename(a: { foo: number }): string[]␊
export function overrideIndividualArgOnFunction(notOverridden: string, f: () => string, notOverridden2: number): string␊ export function overrideIndividualArgOnFunction(notOverridden: string, f: () => string, notOverridden2: number): string␊
export function overrideIndividualArgOnFunctionWithCbArg(callback: (town: string, name?: string | undefined | null) => string, notOverridden: number): object␊ export function overrideIndividualArgOnFunctionWithCbArg(callback: (town: string, name?: string | undefined | null) => string, notOverridden: number): object␊

View file

@ -100,6 +100,8 @@ export function validateNumber(i: number): number
export function validatePromise(p: Promise<number>): Promise<number> export function validatePromise(p: Promise<number>): Promise<number>
export function validateString(s: string): string export function validateString(s: string): string
export function validateSymbol(s: symbol): boolean export function validateSymbol(s: symbol): boolean
export function returnUndefinedIfInvalid(input: boolean): boolean
export function returnUndefinedIfInvalidPromise(input: Promise<boolean>): Promise<boolean>
export function tsRename(a: { foo: number }): string[] export function tsRename(a: { foo: number }): string[]
export function overrideIndividualArgOnFunction(notOverridden: string, f: () => string, notOverridden2: number): string export function overrideIndividualArgOnFunction(notOverridden: string, f: () => string, notOverridden2: number): string
export function overrideIndividualArgOnFunctionWithCbArg(callback: (town: string, name?: string | undefined | null) => string, notOverridden: number): object export function overrideIndividualArgOnFunctionWithCbArg(callback: (town: string, name?: string | undefined | null) => string, notOverridden: number): object

View file

@ -87,3 +87,14 @@ fn validate_string(s: String) -> String {
fn validate_symbol(_s: JsSymbol) -> bool { fn validate_symbol(_s: JsSymbol) -> bool {
true true
} }
#[napi(return_if_invalid)]
fn return_undefined_if_invalid(input: bool) -> bool {
!input
}
#[napi(return_if_invalid)]
async fn return_undefined_if_invalid_promise(input: Promise<bool>) -> Result<bool> {
let input_value = input.await?;
Ok(!input_value)
}