feat(napi): allow &External to be created from napi value (#2037)

This commit is contained in:
翠 / green 2024-04-15 18:54:10 +09:00 committed by GitHub
parent af625fc7df
commit 923b82aee9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 64 additions and 1 deletions

View file

@ -3,7 +3,7 @@ use std::{
ops::{Deref, DerefMut}, 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}; use crate::{check_status, sys, Error, Status};
#[repr(C)] #[repr(C)]
@ -96,6 +96,18 @@ impl<T: 'static> FromNapiRef for External<T> {
} }
} }
impl<T: 'static> FromNapiValue for &mut External<T> {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
External::from_napi_mut_ref(env, napi_val)
}
}
impl<T: 'static> FromNapiValue for &External<T> {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
External::from_napi_ref(env, napi_val)
}
}
impl<T: 'static> AsRef<T> for External<T> { impl<T: 'static> AsRef<T> for External<T> {
fn as_ref(&self) -> &T { fn as_ref(&self) -> &T {
&self.obj &self.obj

View file

@ -372,6 +372,8 @@ Generated by [AVA](https://avajs.dev).
export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }␊ export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }␊
export function createOptionalExternal(size?: number | undefined | null): ExternalObject<number> | null␊
export function createReferenceOnFunction(cb: () => void): Promise<void> export function createReferenceOnFunction(cb: () => void): Promise<void>
export function createSymbol(): symbol␊ export function createSymbol(): symbol␊
@ -466,6 +468,8 @@ Generated by [AVA](https://avajs.dev).
/** Gets some numbers */␊ /** Gets some numbers */␊
export function getNums(): Array<number> export function getNums(): Array<number>
export function getOptionalExternal(external?: ExternalObject<number> | undefined | null): number | null␊
export function getPackageJsonName(packageJson: PackageJson): string␊ export function getPackageJsonName(packageJson: PackageJson): string␊
export function getStrFromObject(): void␊ export function getStrFromObject(): void␊
@ -502,6 +506,8 @@ Generated by [AVA](https://avajs.dev).
export function mutateExternal(external: ExternalObject<number>, newVal: number): void␊ export function mutateExternal(external: ExternalObject<number>, newVal: number): void␊
export function mutateOptionalExternal(external: ExternalObject<number> | undefined | null, newVal: number): void␊
export function mutateTypedArray(input: Float32Array): void␊ export function mutateTypedArray(input: Float32Array): void␊
export interface NotUseNullableStruct {␊ export interface NotUseNullableStruct {␊

View file

@ -172,6 +172,9 @@ import {
type AliasedStruct, type AliasedStruct,
returnObjectOnlyToJs, returnObjectOnlyToJs,
buildThreadsafeFunctionFromFunction, buildThreadsafeFunctionFromFunction,
createOptionalExternal,
getOptionalExternal,
mutateOptionalExternal,
} from '../index.cjs' } from '../index.cjs'
import { test } from './test.framework.js' import { test } from './test.framework.js'
@ -908,6 +911,22 @@ test('external', (t) => {
t.is(e?.message, '<u32> on `External` is not the type of wrapped object') t.is(e?.message, '<u32> 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, '<u32> on `External` is not the type of wrapped object')
})
test('should be able to run script', async (t) => { test('should be able to run script', async (t) => {
t.is(runScript(`1 + 1`), 2) t.is(runScript(`1 + 1`), 2)
t.is(await runScript(`Promise.resolve(1)`), 1) t.is(await runScript(`Promise.resolve(1)`), 1)

View file

@ -453,6 +453,7 @@ module.exports.createExternalTypedArray = nativeBinding.createExternalTypedArray
module.exports.createObj = nativeBinding.createObj module.exports.createObj = nativeBinding.createObj
module.exports.createObjectWithClassField = nativeBinding.createObjectWithClassField module.exports.createObjectWithClassField = nativeBinding.createObjectWithClassField
module.exports.createObjWithProperty = nativeBinding.createObjWithProperty module.exports.createObjWithProperty = nativeBinding.createObjWithProperty
module.exports.createOptionalExternal = nativeBinding.createOptionalExternal
module.exports.createReferenceOnFunction = nativeBinding.createReferenceOnFunction module.exports.createReferenceOnFunction = nativeBinding.createReferenceOnFunction
module.exports.createSymbol = nativeBinding.createSymbol module.exports.createSymbol = nativeBinding.createSymbol
module.exports.createSymbolFor = nativeBinding.createSymbolFor module.exports.createSymbolFor = nativeBinding.createSymbolFor
@ -487,6 +488,7 @@ module.exports.getNestedNumArr = nativeBinding.getNestedNumArr
module.exports.getNull = nativeBinding.getNull module.exports.getNull = nativeBinding.getNull
module.exports.getNumArr = nativeBinding.getNumArr module.exports.getNumArr = nativeBinding.getNumArr
module.exports.getNums = nativeBinding.getNums module.exports.getNums = nativeBinding.getNums
module.exports.getOptionalExternal = nativeBinding.getOptionalExternal
module.exports.getPackageJsonName = nativeBinding.getPackageJsonName module.exports.getPackageJsonName = nativeBinding.getPackageJsonName
module.exports.getStrFromObject = nativeBinding.getStrFromObject module.exports.getStrFromObject = nativeBinding.getStrFromObject
module.exports.getterFromObj = nativeBinding.getterFromObj module.exports.getterFromObj = nativeBinding.getterFromObj
@ -501,6 +503,7 @@ module.exports.Kind = nativeBinding.Kind
module.exports.listObjKeys = nativeBinding.listObjKeys module.exports.listObjKeys = nativeBinding.listObjKeys
module.exports.mapOption = nativeBinding.mapOption module.exports.mapOption = nativeBinding.mapOption
module.exports.mutateExternal = nativeBinding.mutateExternal module.exports.mutateExternal = nativeBinding.mutateExternal
module.exports.mutateOptionalExternal = nativeBinding.mutateOptionalExternal
module.exports.mutateTypedArray = nativeBinding.mutateTypedArray module.exports.mutateTypedArray = nativeBinding.mutateTypedArray
module.exports.objectGetNamedPropertyShouldPerformTypecheck = nativeBinding.objectGetNamedPropertyShouldPerformTypecheck module.exports.objectGetNamedPropertyShouldPerformTypecheck = nativeBinding.objectGetNamedPropertyShouldPerformTypecheck
module.exports.optionEnd = nativeBinding.optionEnd module.exports.optionEnd = nativeBinding.optionEnd

View file

@ -362,6 +362,8 @@ export function createObjectWithClassField(): ObjectFieldClassInstance
export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number } export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }
export function createOptionalExternal(size?: number | undefined | null): ExternalObject<number> | null
export function createReferenceOnFunction(cb: () => void): Promise<void> export function createReferenceOnFunction(cb: () => void): Promise<void>
export function createSymbol(): symbol export function createSymbol(): symbol
@ -456,6 +458,8 @@ export function getNumArr(): number[]
/** Gets some numbers */ /** Gets some numbers */
export function getNums(): Array<number> export function getNums(): Array<number>
export function getOptionalExternal(external?: ExternalObject<number> | undefined | null): number | null
export function getPackageJsonName(packageJson: PackageJson): string export function getPackageJsonName(packageJson: PackageJson): string
export function getStrFromObject(): void export function getStrFromObject(): void
@ -492,6 +496,8 @@ export function mapOption(val?: number | undefined | null): number | null
export function mutateExternal(external: ExternalObject<number>, newVal: number): void export function mutateExternal(external: ExternalObject<number>, newVal: number): void
export function mutateOptionalExternal(external: ExternalObject<number> | undefined | null, newVal: number): void
export function mutateTypedArray(input: Float32Array): void export function mutateTypedArray(input: Float32Array): void
export interface NotUseNullableStruct { export interface NotUseNullableStruct {

View file

@ -19,3 +19,20 @@ pub fn get_external(external: &External<u32>) -> u32 {
pub fn mutate_external(external: &mut External<u32>, new_val: u32) { pub fn mutate_external(external: &mut External<u32>, new_val: u32) {
**external = new_val; **external = new_val;
} }
#[napi]
pub fn create_optional_external(size: Option<u32>) -> Option<External<u32>> {
size.map(External::new)
}
#[napi]
pub fn get_optional_external(external: Option<&External<u32>>) -> Option<u32> {
external.map(|external| **external)
}
#[napi]
pub fn mutate_optional_external(external: Option<&mut External<u32>>, new_val: u32) {
if let Some(external) = external {
**external = new_val;
}
}