diff --git a/crates/napi/src/task.rs b/crates/napi/src/task.rs index be8dddb7..05489e8b 100644 --- a/crates/napi/src/task.rs +++ b/crates/napi/src/task.rs @@ -31,15 +31,19 @@ impl<'a, T: Task> ScopedTask<'a> for T { type JsValue = T::JsValue; fn compute(&mut self) -> Result { - Task::compute(self) + T::compute(self) } fn resolve(&mut self, env: &'a Env, output: Self::Output) -> Result { - Task::resolve(self, Env::from_raw(env.raw()), output) + T::resolve(self, Env::from_raw(env.raw()), output) } fn reject(&mut self, env: &'a Env, err: Error) -> Result { - Task::reject(self, Env::from_raw(env.raw()), err) + T::reject(self, Env::from_raw(env.raw()), err) + } + + fn finally(self, env: Env) -> Result<()> { + T::finally(self, env) } } diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.md b/examples/napi/__tests__/__snapshots__/values.spec.ts.md index 6f50b4a2..5284748a 100644 --- a/examples/napi/__tests__/__snapshots__/values.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/values.spec.ts.md @@ -394,6 +394,8 @@ Generated by [AVA](https://avajs.dev). ␊ export declare function asyncResolveArray(inner: number): Promise␊ ␊ + export declare function asyncTaskFinally(inner: object): Promise␊ + ␊ export declare function asyncTaskOptionalReturn(): Promise␊ ␊ export declare function asyncTaskReadFile(path: string): Promise␊ diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap index 9250edfd..86b50884 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 f6476e1d..092f89a6 100644 --- a/examples/napi/__tests__/values.spec.ts +++ b/examples/napi/__tests__/values.spec.ts @@ -79,6 +79,7 @@ import { withAbortController, asyncTaskReadFile, asyncTaskOptionalReturn, + asyncTaskFinally, asyncResolveArray, asyncMultiTwo, bigintAdd, @@ -1342,7 +1343,7 @@ test('should be able to return object from shared crate', (t) => { const AbortSignalTest = typeof AbortController !== 'undefined' ? test : test.skip -AbortSignalTest('async task without abort controller', async (t) => { +test('async task without abort controller', async (t) => { t.is(await withoutAbortController(1, 2), 3) }) @@ -1394,6 +1395,16 @@ test('abort signal should be able to reuse with different tasks', async (t) => { }) }) +test('async task finally must be called', async (t) => { + const obj = { + finally: false, + resolve: false, + } + await asyncTaskFinally(obj) + t.is(obj.finally, true) + t.is(obj.resolve, true) +}) + const BigIntTest = typeof BigInt !== 'undefined' ? test : test.skip BigIntTest('BigInt add', (t) => { diff --git a/examples/napi/example.wasi-browser.js b/examples/napi/example.wasi-browser.js index eadf4772..10913a71 100644 --- a/examples/napi/example.wasi-browser.js +++ b/examples/napi/example.wasi-browser.js @@ -137,6 +137,7 @@ export const asyncMultiTwo = __napiModule.exports.asyncMultiTwo export const asyncPlus100 = __napiModule.exports.asyncPlus100 export const asyncReduceBuffer = __napiModule.exports.asyncReduceBuffer export const asyncResolveArray = __napiModule.exports.asyncResolveArray +export const asyncTaskFinally = __napiModule.exports.asyncTaskFinally export const asyncTaskOptionalReturn = __napiModule.exports.asyncTaskOptionalReturn export const asyncTaskReadFile = __napiModule.exports.asyncTaskReadFile export const asyncTaskVoidReturn = __napiModule.exports.asyncTaskVoidReturn diff --git a/examples/napi/example.wasi.cjs b/examples/napi/example.wasi.cjs index 4c406d0b..93604b57 100644 --- a/examples/napi/example.wasi.cjs +++ b/examples/napi/example.wasi.cjs @@ -182,6 +182,7 @@ module.exports.asyncMultiTwo = __napiModule.exports.asyncMultiTwo module.exports.asyncPlus100 = __napiModule.exports.asyncPlus100 module.exports.asyncReduceBuffer = __napiModule.exports.asyncReduceBuffer module.exports.asyncResolveArray = __napiModule.exports.asyncResolveArray +module.exports.asyncTaskFinally = __napiModule.exports.asyncTaskFinally module.exports.asyncTaskOptionalReturn = __napiModule.exports.asyncTaskOptionalReturn module.exports.asyncTaskReadFile = __napiModule.exports.asyncTaskReadFile module.exports.asyncTaskVoidReturn = __napiModule.exports.asyncTaskVoidReturn diff --git a/examples/napi/index.cjs b/examples/napi/index.cjs index 8cf1d696..30cb15b5 100644 --- a/examples/napi/index.cjs +++ b/examples/napi/index.cjs @@ -467,6 +467,7 @@ module.exports.asyncMultiTwo = nativeBinding.asyncMultiTwo module.exports.asyncPlus100 = nativeBinding.asyncPlus100 module.exports.asyncReduceBuffer = nativeBinding.asyncReduceBuffer module.exports.asyncResolveArray = nativeBinding.asyncResolveArray +module.exports.asyncTaskFinally = nativeBinding.asyncTaskFinally module.exports.asyncTaskOptionalReturn = nativeBinding.asyncTaskOptionalReturn module.exports.asyncTaskReadFile = nativeBinding.asyncTaskReadFile module.exports.asyncTaskVoidReturn = nativeBinding.asyncTaskVoidReturn diff --git a/examples/napi/index.d.cts b/examples/napi/index.d.cts index 99d8e4c9..0ebf0011 100644 --- a/examples/napi/index.d.cts +++ b/examples/napi/index.d.cts @@ -355,6 +355,8 @@ export declare function asyncReduceBuffer(buf: Buffer): Promise export declare function asyncResolveArray(inner: number): Promise +export declare function asyncTaskFinally(inner: object): Promise + export declare function asyncTaskOptionalReturn(): Promise export declare function asyncTaskReadFile(path: string): Promise diff --git a/examples/napi/src/task.rs b/examples/napi/src/task.rs index 758b59d8..be8a7352 100644 --- a/examples/napi/src/task.rs +++ b/examples/napi/src/task.rs @@ -17,6 +17,10 @@ impl napi::Task for DelaySum { fn resolve(&mut self, _env: napi::Env, output: Self::Output) -> Result { Ok(output) } + + fn finally(self, _env: Env) -> Result<()> { + Ok(()) + } } #[napi] @@ -122,3 +126,35 @@ pub fn async_resolve_array(inner: u32) -> AsyncTask { inner: inner as usize, }) } + +pub struct AsyncTaskFinally { + inner: ObjectRef, +} + +#[napi] +impl Task for AsyncTaskFinally { + type Output = (); + type JsValue = (); + + fn compute(&mut self) -> Result { + Ok(()) + } + + fn resolve(&mut self, env: Env, _output: Self::Output) -> Result { + let mut obj = self.inner.get_value(&env)?; + obj.set("resolve", true)?; + Ok(()) + } + + fn finally(self, env: Env) -> Result<()> { + let mut obj = self.inner.get_value(&env)?; + obj.set("finally", true)?; + self.inner.unref(&env)?; + Ok(()) + } +} + +#[napi] +pub fn async_task_finally(inner: ObjectRef) -> AsyncTask { + AsyncTask::new(AsyncTaskFinally { inner }) +}