From 92b094e4875ebbd2f62ae5c597927a91d936bb5d Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sun, 18 May 2025 23:16:40 +0800 Subject: [PATCH] feat(napi): new handle scope API (#2650) --- crates/napi/src/bindgen_runtime/js_values.rs | 2 + .../src/bindgen_runtime/js_values/scope.rs | 201 ++++++++++++++++++ .../__tests__/__snapshots__/values.spec.ts.md | 2 + .../__snapshots__/values.spec.ts.snap | Bin 6511 -> 6527 bytes examples/napi/__tests__/values.spec.ts | 6 + examples/napi/example.wasi-browser.js | 1 + examples/napi/example.wasi.cjs | 1 + examples/napi/index.cjs | 1 + examples/napi/index.d.cts | 2 + examples/napi/src/lib.rs | 1 + examples/napi/src/scope.rs | 21 ++ 11 files changed, 238 insertions(+) create mode 100644 crates/napi/src/bindgen_runtime/js_values/scope.rs create mode 100644 examples/napi/src/scope.rs diff --git a/crates/napi/src/bindgen_runtime/js_values.rs b/crates/napi/src/bindgen_runtime/js_values.rs index 371db93d..0fac92d3 100644 --- a/crates/napi/src/bindgen_runtime/js_values.rs +++ b/crates/napi/src/bindgen_runtime/js_values.rs @@ -25,6 +25,7 @@ mod object; #[cfg(all(feature = "tokio_rt", feature = "napi4"))] mod promise; mod promise_raw; +mod scope; #[cfg(feature = "serde-json")] mod serde; mod set; @@ -52,6 +53,7 @@ pub use object::*; #[cfg(all(feature = "tokio_rt", feature = "napi4"))] pub use promise::*; pub use promise_raw::*; +pub use scope::*; #[cfg(feature = "web_stream")] pub use stream::*; pub use string::*; diff --git a/crates/napi/src/bindgen_runtime/js_values/scope.rs b/crates/napi/src/bindgen_runtime/js_values/scope.rs new file mode 100644 index 00000000..034927fe --- /dev/null +++ b/crates/napi/src/bindgen_runtime/js_values/scope.rs @@ -0,0 +1,201 @@ +use std::ptr; + +use crate::{check_status, sys, Env, JsValue, Result}; + +pub struct HandleScope { + pub(crate) scope: sys::napi_handle_scope, +} + +impl HandleScope { + pub fn create(env: &Env) -> Result { + let mut scope = ptr::null_mut(); + check_status!( + unsafe { sys::napi_open_handle_scope(env.0, &mut scope) }, + "Failed to open handle scope" + )?; + Ok(Self { scope }) + } + + pub fn run(self, arg: A, f: impl FnOnce(A) -> Result) -> Result + where + A: JsValuesTuple, + { + let env = arg.env(); + let ret = f(arg); + check_status!( + unsafe { sys::napi_close_handle_scope(env, self.scope) }, + "Failed to close handle scope" + )?; + ret + } +} + +pub trait JsValuesTuple { + fn env(&self) -> sys::napi_env; +} + +impl<'env, T: JsValue<'env>> JsValuesTuple for T { + fn env(&self) -> sys::napi_env { + self.value().env + } +} + +impl<'env, T1: JsValue<'env>, T2: JsValue<'env>> JsValuesTuple for (T1, T2) { + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl<'env, T1: JsValue<'env>, T2: JsValue<'env>, T3: JsValue<'env>> JsValuesTuple for (T1, T2, T3) { + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl<'env, T1: JsValue<'env>, T2: JsValue<'env>, T3: JsValue<'env>, T4: JsValue<'env>> JsValuesTuple + for (T1, T2, T3, T4) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + T6: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5, T6) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + T6: JsValue<'env>, + T7: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5, T6, T7) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + T6: JsValue<'env>, + T7: JsValue<'env>, + T8: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5, T6, T7, T8) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + T6: JsValue<'env>, + T7: JsValue<'env>, + T8: JsValue<'env>, + T9: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5, T6, T7, T8, T9) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + T6: JsValue<'env>, + T7: JsValue<'env>, + T8: JsValue<'env>, + T9: JsValue<'env>, + T10: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + T6: JsValue<'env>, + T7: JsValue<'env>, + T8: JsValue<'env>, + T9: JsValue<'env>, + T10: JsValue<'env>, + T11: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} + +impl< + 'env, + T1: JsValue<'env>, + T2: JsValue<'env>, + T3: JsValue<'env>, + T4: JsValue<'env>, + T5: JsValue<'env>, + T6: JsValue<'env>, + T7: JsValue<'env>, + T8: JsValue<'env>, + T9: JsValue<'env>, + T10: JsValue<'env>, + T11: JsValue<'env>, + T12: JsValue<'env>, + > JsValuesTuple for (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) +{ + fn env(&self) -> sys::napi_env { + self.0.value().env + } +} diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.md b/examples/napi/__tests__/__snapshots__/values.spec.ts.md index a03296e4..80be2855 100644 --- a/examples/napi/__tests__/__snapshots__/values.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/values.spec.ts.md @@ -824,6 +824,8 @@ Generated by [AVA](https://avajs.dev). value: number␊ }␊ ␊ + export declare function shorterScope(arr: unknown[]): Array␊ + ␊ export declare function shutdownRuntime(): void␊ ␊ export declare function spawnThreadInThread(tsfn: ((err: Error | null, arg: number) => number)): void␊ diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap index cfd2ad4463e85830ecf2d1ba392cffbd994afc32..e68529266037344b965d37a7eac3258954a43f7f 100644 GIT binary patch delta 6396 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 Kc3ku-bN~R@*oV9T delta 6382 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 diff --git a/examples/napi/__tests__/values.spec.ts b/examples/napi/__tests__/values.spec.ts index d3fcb088..a00a5d60 100644 --- a/examples/napi/__tests__/values.spec.ts +++ b/examples/napi/__tests__/values.spec.ts @@ -232,6 +232,7 @@ import { extendsJavascriptError, shutdownRuntime, callAsyncWithUnknownReturnValue, + shorterScope, } from '../index.cjs' // import other stuff in `#[napi(module_exports)]` import nativeAddon from '../index.cjs' @@ -1660,3 +1661,8 @@ test('extends javascript error', (t) => { test('module exports', (t) => { t.is(nativeAddon.NAPI_RS_SYMBOL, Symbol.for('NAPI_RS_SYMBOL')) }) + +test('shorter scope', (t) => { + const result = shorterScope(['hello', { foo: 'bar' }, 'world', true]) + t.deepEqual(result, [5, 1, 5, 0]) +}) diff --git a/examples/napi/example.wasi-browser.js b/examples/napi/example.wasi-browser.js index e7f885c6..c42fba5b 100644 --- a/examples/napi/example.wasi-browser.js +++ b/examples/napi/example.wasi-browser.js @@ -292,6 +292,7 @@ export const roundtripStr = __napiModule.exports.roundtripStr export const runScript = __napiModule.exports.runScript export const setNullByteProperty = __napiModule.exports.setNullByteProperty export const setSymbolInObj = __napiModule.exports.setSymbolInObj +export const shorterScope = __napiModule.exports.shorterScope export const shutdownRuntime = __napiModule.exports.shutdownRuntime export const spawnThreadInThread = __napiModule.exports.spawnThreadInThread export const Status = __napiModule.exports.Status diff --git a/examples/napi/example.wasi.cjs b/examples/napi/example.wasi.cjs index e94d7b69..53280515 100644 --- a/examples/napi/example.wasi.cjs +++ b/examples/napi/example.wasi.cjs @@ -316,6 +316,7 @@ module.exports.roundtripStr = __napiModule.exports.roundtripStr module.exports.runScript = __napiModule.exports.runScript module.exports.setNullByteProperty = __napiModule.exports.setNullByteProperty module.exports.setSymbolInObj = __napiModule.exports.setSymbolInObj +module.exports.shorterScope = __napiModule.exports.shorterScope module.exports.shutdownRuntime = __napiModule.exports.shutdownRuntime module.exports.spawnThreadInThread = __napiModule.exports.spawnThreadInThread module.exports.Status = __napiModule.exports.Status diff --git a/examples/napi/index.cjs b/examples/napi/index.cjs index e2a9e2ed..b400ec22 100644 --- a/examples/napi/index.cjs +++ b/examples/napi/index.cjs @@ -606,6 +606,7 @@ module.exports.roundtripStr = nativeBinding.roundtripStr module.exports.runScript = nativeBinding.runScript module.exports.setNullByteProperty = nativeBinding.setNullByteProperty module.exports.setSymbolInObj = nativeBinding.setSymbolInObj +module.exports.shorterScope = nativeBinding.shorterScope module.exports.shutdownRuntime = nativeBinding.shutdownRuntime module.exports.spawnThreadInThread = nativeBinding.spawnThreadInThread module.exports.Status = nativeBinding.Status diff --git a/examples/napi/index.d.cts b/examples/napi/index.d.cts index 027c4529..6163d2fc 100644 --- a/examples/napi/index.d.cts +++ b/examples/napi/index.d.cts @@ -786,6 +786,8 @@ export interface Shared { value: number } +export declare function shorterScope(arr: unknown[]): Array + export declare function shutdownRuntime(): void export declare function spawnThreadInThread(tsfn: ((err: Error | null, arg: number) => number)): void diff --git a/examples/napi/src/lib.rs b/examples/napi/src/lib.rs index bca8f0b5..9ce5cad7 100644 --- a/examples/napi/src/lib.rs +++ b/examples/napi/src/lib.rs @@ -80,6 +80,7 @@ mod number; mod object; mod promise; mod reference; +mod scope; mod serde; mod set; mod shared; diff --git a/examples/napi/src/scope.rs b/examples/napi/src/scope.rs new file mode 100644 index 00000000..0fa8fd07 --- /dev/null +++ b/examples/napi/src/scope.rs @@ -0,0 +1,21 @@ +use napi::{bindgen_prelude::*, JsString}; + +#[napi] +pub fn shorter_scope(env: &Env, arr: Array) -> Result> { + let len = arr.len(); + let mut result = Vec::with_capacity(len as usize); + for i in 0..len { + let scope = HandleScope::create(env)?; + let value: Unknown = arr.get_element(i)?; + let len = scope.run(value, |v| match v.get_type()? { + ValueType::String => { + let string = unsafe { v.cast::() }?; + Ok(string.utf8_len()? as u32) + } + ValueType::Object => Ok(1), + _ => Ok(0), + })?; + result.push(len); + } + Ok(result) +}