diff --git a/crates/napi/src/bindgen_runtime/js_values/external.rs b/crates/napi/src/bindgen_runtime/js_values/external.rs index 42ac99da..d26a86f2 100644 --- a/crates/napi/src/bindgen_runtime/js_values/external.rs +++ b/crates/napi/src/bindgen_runtime/js_values/external.rs @@ -3,7 +3,7 @@ use std::{ ops::{Deref, DerefMut}, }; -use super::{FromNapiMutRef, FromNapiRef, ToNapiValue, TypeName, ValidateNapiValue}; +use super::{FromNapiMutRef, FromNapiRef, FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue}; use crate::{check_status, sys, Error, Status}; #[repr(C)] @@ -96,6 +96,18 @@ impl FromNapiRef for External { } } +impl FromNapiValue for &mut External { + unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result { + External::from_napi_mut_ref(env, napi_val) + } +} + +impl FromNapiValue for &External { + unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result { + External::from_napi_ref(env, napi_val) + } +} + impl AsRef for External { fn as_ref(&self) -> &T { &self.obj diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md index 3b9bd06e..09d3d5e1 100644 --- a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md @@ -372,6 +372,8 @@ Generated by [AVA](https://avajs.dev). ␊ export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }␊ ␊ + export function createOptionalExternal(size?: number | undefined | null): ExternalObject | null␊ + ␊ export function createReferenceOnFunction(cb: () => void): Promise␊ ␊ export function createSymbol(): symbol␊ @@ -466,6 +468,8 @@ Generated by [AVA](https://avajs.dev). /** Gets some numbers */␊ export function getNums(): Array␊ ␊ + export function getOptionalExternal(external?: ExternalObject | undefined | null): number | null␊ + ␊ export function getPackageJsonName(packageJson: PackageJson): string␊ ␊ export function getStrFromObject(): void␊ @@ -502,6 +506,8 @@ Generated by [AVA](https://avajs.dev). ␊ export function mutateExternal(external: ExternalObject, newVal: number): void␊ ␊ + export function mutateOptionalExternal(external: ExternalObject | undefined | null, newVal: number): void␊ + ␊ export function mutateTypedArray(input: Float32Array): void␊ ␊ export interface NotUseNullableStruct {␊ diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap index 1a6b9320..fed22a6f 100644 Binary files a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap and b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap differ diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap index 2b1be196..164d8175 100644 Binary files a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap and b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap differ diff --git a/examples/napi/__tests__/values.spec.ts b/examples/napi/__tests__/values.spec.ts index c9d66d86..18c74fbb 100644 --- a/examples/napi/__tests__/values.spec.ts +++ b/examples/napi/__tests__/values.spec.ts @@ -172,6 +172,9 @@ import { type AliasedStruct, returnObjectOnlyToJs, buildThreadsafeFunctionFromFunction, + createOptionalExternal, + getOptionalExternal, + mutateOptionalExternal, } from '../index.cjs' import { test } from './test.framework.js' @@ -908,6 +911,22 @@ test('external', (t) => { t.is(e?.message, ' on `External` is not the type of wrapped object') }) +test('optional external', (t) => { + const FX = 42 + const extEmpty = createOptionalExternal() + t.is(getOptionalExternal(extEmpty), null) + const ext = createOptionalExternal(FX) + t.is(getOptionalExternal(ext), FX) + mutateOptionalExternal(ext, FX + 1) + t.is(getOptionalExternal(ext), FX + 1) + // @ts-expect-error + t.throws(() => getOptionalExternal({})) + const ext2 = createExternalString('wtf') + // @ts-expect-error + const e = t.throws(() => getOptionalExternal(ext2)) + t.is(e?.message, ' on `External` is not the type of wrapped object') +}) + test('should be able to run script', async (t) => { t.is(runScript(`1 + 1`), 2) t.is(await runScript(`Promise.resolve(1)`), 1) diff --git a/examples/napi/index.cjs b/examples/napi/index.cjs index 5f266644..47552aff 100644 --- a/examples/napi/index.cjs +++ b/examples/napi/index.cjs @@ -453,6 +453,7 @@ module.exports.createExternalTypedArray = nativeBinding.createExternalTypedArray module.exports.createObj = nativeBinding.createObj module.exports.createObjectWithClassField = nativeBinding.createObjectWithClassField module.exports.createObjWithProperty = nativeBinding.createObjWithProperty +module.exports.createOptionalExternal = nativeBinding.createOptionalExternal module.exports.createReferenceOnFunction = nativeBinding.createReferenceOnFunction module.exports.createSymbol = nativeBinding.createSymbol module.exports.createSymbolFor = nativeBinding.createSymbolFor @@ -487,6 +488,7 @@ module.exports.getNestedNumArr = nativeBinding.getNestedNumArr module.exports.getNull = nativeBinding.getNull module.exports.getNumArr = nativeBinding.getNumArr module.exports.getNums = nativeBinding.getNums +module.exports.getOptionalExternal = nativeBinding.getOptionalExternal module.exports.getPackageJsonName = nativeBinding.getPackageJsonName module.exports.getStrFromObject = nativeBinding.getStrFromObject module.exports.getterFromObj = nativeBinding.getterFromObj @@ -501,6 +503,7 @@ module.exports.Kind = nativeBinding.Kind module.exports.listObjKeys = nativeBinding.listObjKeys module.exports.mapOption = nativeBinding.mapOption module.exports.mutateExternal = nativeBinding.mutateExternal +module.exports.mutateOptionalExternal = nativeBinding.mutateOptionalExternal module.exports.mutateTypedArray = nativeBinding.mutateTypedArray module.exports.objectGetNamedPropertyShouldPerformTypecheck = nativeBinding.objectGetNamedPropertyShouldPerformTypecheck module.exports.optionEnd = nativeBinding.optionEnd diff --git a/examples/napi/index.d.cts b/examples/napi/index.d.cts index b4959e23..993d69dd 100644 --- a/examples/napi/index.d.cts +++ b/examples/napi/index.d.cts @@ -362,6 +362,8 @@ export function createObjectWithClassField(): ObjectFieldClassInstance export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number } +export function createOptionalExternal(size?: number | undefined | null): ExternalObject | null + export function createReferenceOnFunction(cb: () => void): Promise export function createSymbol(): symbol @@ -456,6 +458,8 @@ export function getNumArr(): number[] /** Gets some numbers */ export function getNums(): Array +export function getOptionalExternal(external?: ExternalObject | undefined | null): number | null + export function getPackageJsonName(packageJson: PackageJson): string export function getStrFromObject(): void @@ -492,6 +496,8 @@ export function mapOption(val?: number | undefined | null): number | null export function mutateExternal(external: ExternalObject, newVal: number): void +export function mutateOptionalExternal(external: ExternalObject | undefined | null, newVal: number): void + export function mutateTypedArray(input: Float32Array): void export interface NotUseNullableStruct { diff --git a/examples/napi/src/external.rs b/examples/napi/src/external.rs index c6aba2e9..f9a869e5 100644 --- a/examples/napi/src/external.rs +++ b/examples/napi/src/external.rs @@ -19,3 +19,20 @@ pub fn get_external(external: &External) -> u32 { pub fn mutate_external(external: &mut External, new_val: u32) { **external = new_val; } + +#[napi] +pub fn create_optional_external(size: Option) -> Option> { + size.map(External::new) +} + +#[napi] +pub fn get_optional_external(external: Option<&External>) -> Option { + external.map(|external| **external) +} + +#[napi] +pub fn mutate_optional_external(external: Option<&mut External>, new_val: u32) { + if let Some(external) = external { + **external = new_val; + } +}