fix(napi): nested Either and Promise validate logic (#2625)

- Close https://github.com/napi-rs/napi-rs/issues/2578
This commit is contained in:
LongYinan 2025-05-12 00:33:14 +08:00 committed by GitHub
parent 1c0f127178
commit 7a972425b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 42 additions and 1 deletions

View File

@ -99,7 +99,16 @@ macro_rules! either_n {
$(
if unsafe {
ret = $parameter::validate(env, napi_val);
ret.is_ok()
if let Ok(maybe_rejected_promise) = ret.as_ref() {
if maybe_rejected_promise.is_null() {
true
} else {
silence_rejected_promise(env, *maybe_rejected_promise)?;
false
}
} else {
false
}
} {
ret
} else

View File

@ -540,6 +540,8 @@ Generated by [AVA](https://avajs.dev).
export declare function eitherFromOption(): JsClassForEither | undefined␊
export declare function eitherPromiseInEitherA(input: Promise<number> | number | string): Promise<boolean>
export declare function eitherStringOrNumber(input: string | number): number␊
export declare const enum Empty {␊

View File

@ -72,6 +72,7 @@ import {
returnEither,
either3,
either4,
eitherPromiseInEitherA,
withoutAbortController,
withAbortController,
asyncMultiTwo,
@ -1107,6 +1108,14 @@ test('either4', (t) => {
t.is(either4({ v: 'world' }), 'world'.length)
})
test('either promise in either a', async (t) => {
t.is(await eitherPromiseInEitherA(1), false)
t.is(await eitherPromiseInEitherA(20), true)
t.is(await eitherPromiseInEitherA(Promise.resolve(1)), false)
t.is(await eitherPromiseInEitherA(Promise.resolve(20)), true)
t.is(await eitherPromiseInEitherA('abc'), false)
})
test('external', (t) => {
const FX = 42
const ext = createExternal(FX)

View File

@ -197,6 +197,7 @@ export const eitherBoolOrFunction = __napiModule.exports.eitherBoolOrFunction
export const eitherBoolOrTuple = __napiModule.exports.eitherBoolOrTuple
export const eitherFromObjects = __napiModule.exports.eitherFromObjects
export const eitherFromOption = __napiModule.exports.eitherFromOption
export const eitherPromiseInEitherA = __napiModule.exports.eitherPromiseInEitherA
export const eitherStringOrNumber = __napiModule.exports.eitherStringOrNumber
export const Empty = __napiModule.exports.Empty
export const enumToI32 = __napiModule.exports.enumToI32

View File

@ -221,6 +221,7 @@ module.exports.eitherBoolOrFunction = __napiModule.exports.eitherBoolOrFunction
module.exports.eitherBoolOrTuple = __napiModule.exports.eitherBoolOrTuple
module.exports.eitherFromObjects = __napiModule.exports.eitherFromObjects
module.exports.eitherFromOption = __napiModule.exports.eitherFromOption
module.exports.eitherPromiseInEitherA = __napiModule.exports.eitherPromiseInEitherA
module.exports.eitherStringOrNumber = __napiModule.exports.eitherStringOrNumber
module.exports.Empty = __napiModule.exports.Empty
module.exports.enumToI32 = __napiModule.exports.enumToI32

View File

@ -511,6 +511,7 @@ module.exports.eitherBoolOrFunction = nativeBinding.eitherBoolOrFunction
module.exports.eitherBoolOrTuple = nativeBinding.eitherBoolOrTuple
module.exports.eitherFromObjects = nativeBinding.eitherFromObjects
module.exports.eitherFromOption = nativeBinding.eitherFromOption
module.exports.eitherPromiseInEitherA = nativeBinding.eitherPromiseInEitherA
module.exports.eitherStringOrNumber = nativeBinding.eitherStringOrNumber
module.exports.Empty = nativeBinding.Empty
module.exports.enumToI32 = nativeBinding.enumToI32

View File

@ -502,6 +502,8 @@ export declare function eitherFromObjects(input: A | B | C): string
export declare function eitherFromOption(): JsClassForEither | undefined
export declare function eitherPromiseInEitherA(input: Promise<number> | number | string): Promise<boolean>
export declare function eitherStringOrNumber(input: string | number): number
export declare const enum Empty {

View File

@ -146,3 +146,19 @@ pub async fn promise_in_either(input: Either<u32, Promise<u32>>) -> Result<bool>
#[napi]
pub fn either_bool_or_tuple(_input: Either<bool, (bool, String)>) {}
#[napi]
pub async fn either_promise_in_either_a(
input: Either<Either<Promise<u32>, u32>, String>,
) -> Result<bool> {
match input {
Either::A(a) => match a {
Either::A(b) => {
let r = b.await?;
Ok(r > 10)
}
Either::B(b) => Ok(b > 10),
},
Either::B(a) => Ok(a.len() > 10),
}
}