From 0d018a547010b71c059ca34f5826a7f7fd406339 Mon Sep 17 00:00:00 2001 From: forehalo Date: Fri, 24 Sep 2021 09:46:27 +0800 Subject: [PATCH] impl ToNapiValue for Result --- crates/backend/src/typegen.rs | 4 +- crates/napi/src/bindgen_runtime/js_values.rs | 41 +++++++++++++----- .../napi/src/bindgen_runtime/js_values/nil.rs | 19 -------- examples/napi/__test__/typegen.spec.ts.md | 5 ++- examples/napi/__test__/typegen.spec.ts.snap | Bin 578 -> 586 bytes examples/napi/__test__/values.spec.ts | 11 ++++- examples/napi/index.d.ts | 5 ++- examples/napi/src/error.rs | 6 +++ examples/napi/src/lib.rs | 1 + 9 files changed, 53 insertions(+), 39 deletions(-) create mode 100644 examples/napi/src/error.rs diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index 81f9fdf0..39e77169 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -64,7 +64,7 @@ pub fn ty_to_ts_type(ty: &Type) -> String { pub fn str_to_ts_type(ty: &str) -> String { match ty { - "()" => "null".to_owned(), + "()" => "undefined".to_owned(), "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" => "number".to_owned(), "i128" | "isize" | "u64" | "u128" | "usize" => "BigInt".to_owned(), "bool" => "boolean".to_owned(), @@ -82,7 +82,7 @@ pub fn str_to_ts_type(ty: &str) -> String { let captures = TYPE_REGEXES["Option"].captures(s).unwrap(); let inner = captures.get(1).unwrap().as_str(); - format!("{} | undefined", str_to_ts_type(inner)) + format!("{} | null", str_to_ts_type(inner)) } s if s.starts_with("Result") && TYPE_REGEXES["Result"].is_match(s) => { let captures = TYPE_REGEXES["Result"].captures(s).unwrap(); diff --git a/crates/napi/src/bindgen_runtime/js_values.rs b/crates/napi/src/bindgen_runtime/js_values.rs index 7561c044..8946ad54 100644 --- a/crates/napi/src/bindgen_runtime/js_values.rs +++ b/crates/napi/src/bindgen_runtime/js_values.rs @@ -95,10 +95,7 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName { } } -impl TypeName for Option -where - T: TypeName, -{ +impl TypeName for Option { fn type_name() -> &'static str { "Option" } @@ -106,19 +103,18 @@ where impl FromNapiValue for Option where - T: FromNapiValue + TypeName, + T: FromNapiValue, { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { let mut val_type = 0; check_status!( sys::napi_typeof(env, napi_val, &mut val_type), - "Failed to convert napi value into rust type `Option<{}>`", - T::type_name() + "Failed to convert napi value into rust type `Option`", )?; match val_type { - sys::ValueType::napi_undefined => Ok(None), + sys::ValueType::napi_undefined | sys::ValueType::napi_null => Ok(None), _ => Ok(Some(T::from_napi_value(env, napi_val)?)), } } @@ -126,7 +122,7 @@ where impl ToNapiValue for Option where - T: ToNapiValue + TypeName, + T: ToNapiValue, { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { match val { @@ -134,12 +130,33 @@ where None => { let mut ptr = ptr::null_mut(); check_status!( - sys::napi_get_undefined(env, &mut ptr), - "Failed to convert rust type `Option<{}>` into napi value", - T::type_name(), + sys::napi_get_null(env, &mut ptr), + "Failed to convert rust type `Option` into napi value", )?; Ok(ptr) } } } } + +impl ToNapiValue for Result +where + T: ToNapiValue, +{ + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { + match val { + Ok(v) => T::to_napi_value(env, v), + Err(e) => { + let error_code = String::to_napi_value(env, format!("{:?}", e.status))?; + let reason = String::to_napi_value(env, e.reason)?; + let mut error = ptr::null_mut(); + check_status!( + sys::napi_create_error(env, error_code, reason, &mut error), + "Failed to create napi error" + )?; + + Ok(error) + } + } + } +} diff --git a/crates/napi/src/bindgen_runtime/js_values/nil.rs b/crates/napi/src/bindgen_runtime/js_values/nil.rs index 05bd00f0..50177192 100644 --- a/crates/napi/src/bindgen_runtime/js_values/nil.rs +++ b/crates/napi/src/bindgen_runtime/js_values/nil.rs @@ -79,22 +79,3 @@ impl ToNapiValue for Undefined { Ok(ret) } } - -impl ToNapiValue for Result<()> { - unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { - match val { - Ok(_) => Ok(Null::to_napi_value(env, Null).unwrap_or_else(|_| ptr::null_mut())), - Err(e) => { - let error_code = String::to_napi_value(env, format!("{:?}", e.status))?; - let reason = String::to_napi_value(env, e.reason)?; - let mut error = ptr::null_mut(); - check_status!( - sys::napi_create_error(env, error_code, reason, &mut error), - "Failed to create napi error" - )?; - - Ok(error) - } - } - } -} diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index b17746ee..ae4d3aaf 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -12,11 +12,12 @@ Generated by [AVA](https://avajs.dev). export function getNums(): Array␊ export function sumNums(nums: Array): number␊ export function getCwd(callback: (arg0: string) => void): void␊ - export function readFile(callback: (arg0: Error | null, arg1: string | undefined) => void): void␊ + export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void␊ export enum Kind { Dog = 0, Cat = 1, Duck = 2 }␊ export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 }␊ export function enumToI32(e: CustomNumEnum): number␊ - export function mapOption(val: number | undefined): number | undefined␊ + export function getError(): Error | undefined␊ + export function mapOption(val: number | null): number | null␊ export function add(a: number, b: number): number␊ export function fibonacci(n: number): number␊ export function listObjKeys(obj: object): Array␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 81dd14dd3ad083fcb9deac1aa813bc5f96f453e1..39980d0c783c255ac03ba96c0c393609f8f7c631 100644 GIT binary patch literal 586 zcmV-Q0=4}?RzVLhwF29~AZDHUfvqDK2a{Er{)R0yL$6C|bD`T~g!=vT~^4#Sspmce{ zbsaP=FF@QkcUbh6YE$*@G$o8?Swh)30z&n$9YJ}T791YIl@ciy@P9SC<}^JO8Lt=U zX{|KefRia72+7kBaHCUI#vSRhY+C@wlA#|xl(Fx(iu`#MWxLxDB z&RFGp(DSP~^d&F(i>dNBijn62-hK$D%4t+jLx{ySih~e(VmR^%FG4sMh4&>|xb#KZ z%dEx2`_K#ZdVi1bXg&PD{VqD=UuUgFH9Du0{=_SCMYF1A)w(nTKBc~(|ijBltFvg4hliZ{ox zj2Z*SQsgv)c@v87N6BmkW1RJF00000000Ap zlRt0MKp4gyT7;C1iS->Xl82;)0v4@QrKyBkHA9LJ-)Dajllmt z?FPY4@Fdrb$HCJ_A9wl9R2v7wOfe_4f)RJ`wMi^#MR05koxicp2sJutZXqwSbPZHl z8go+xZIKZBlMEugP>!C%g_$5D(8_qF{HPIYEbJr7|ZZcrSA&=aGvPk0r=g~+|H(ZZE) z(q3gPAKr&v>bLuQgh!j<_2-?^X@BY!xu&wDHcn()vC@Vn385t!LR`xF;Gu}MqKpZm z9)_i`t{-2W@wp{BzKQ@ZoVf>QmEk-%j!r+Vg{R7B<)~1WSbPJFms1gf!y(~rIeHPq zT1!sVwhoNCfion{++fX6h#LN#8+Hx|ei^wKl%BO!jq#j1p*r4KsKNF)CaJY>tVBvB zESivi8(PUZOmL2)e44SUXu5o6Tw(<3j5%${iVHWe7IM~MHUq_H^;q;T9r4*%(^Qbv QChwYm0qH@R*0BTt0E+Pxc>n+a diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index f87f1144..c7487f0a 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -19,6 +19,7 @@ import { createObj, mapOption, readFile, + getError, } from '../' test('number', (t) => { @@ -81,7 +82,7 @@ test('callback', (t) => { ) readFile((err, content) => { - t.is(err, null) + t.is(err, undefined) t.is(content, 'hello world') }) }) @@ -92,6 +93,12 @@ test('object', (t) => { }) test('Option', (t) => { - t.is(mapOption(undefined), undefined) + t.is(mapOption(null), null) t.is(mapOption(3), 4) }) + +test('Result', (t) => { + const error = getError() + t.not(error, undefined) + t.is(error!.message, 'Manual Error') +}) diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 7cdb1527..7cbb680f 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -2,11 +2,12 @@ export function getWords(): Array export function getNums(): Array export function sumNums(nums: Array): number export function getCwd(callback: (arg0: string) => void): void -export function readFile(callback: (arg0: Error | null, arg1: string | undefined) => void): void +export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void export enum Kind { Dog = 0, Cat = 1, Duck = 2 } export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 } export function enumToI32(e: CustomNumEnum): number -export function mapOption(val: number | undefined): number | undefined +export function getError(): Error | undefined +export function mapOption(val: number | null): number | null export function add(a: number, b: number): number export function fibonacci(n: number): number export function listObjKeys(obj: object): Array diff --git a/examples/napi/src/error.rs b/examples/napi/src/error.rs new file mode 100644 index 00000000..31ce7e4b --- /dev/null +++ b/examples/napi/src/error.rs @@ -0,0 +1,6 @@ +use napi::bindgen_prelude::*; + +#[napi] +fn get_error() -> Result<()> { + Err(Error::new(Status::InvalidArg, "Manual Error".to_owned())) +} diff --git a/examples/napi/src/lib.rs b/examples/napi/src/lib.rs index e982cfba..b688315e 100644 --- a/examples/napi/src/lib.rs +++ b/examples/napi/src/lib.rs @@ -5,6 +5,7 @@ mod array; mod callback; mod class; mod r#enum; +mod error; mod nullable; mod number; mod object;