From 9d38689426fdb0fa3b7b539daf156acbb8f14fb7 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 18 Dec 2020 11:32:07 +0800 Subject: [PATCH] feat(napi): provide reject method in Task trait Do some cleanup logic if needed --- napi/src/async_work.rs | 11 +++++++---- napi/src/task.rs | 12 +++++++++--- test_module/__test__/spawn.spec.ts | 11 +++++++++++ test_module/src/task.rs | 12 +++++++++++- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/napi/src/async_work.rs b/napi/src/async_work.rs index 913ee454..9f6b3c55 100644 --- a/napi/src/async_work.rs +++ b/napi/src/async_work.rs @@ -93,10 +93,13 @@ unsafe extern "C" fn complete( let value_ptr = mem::replace(&mut work.value, Ok(mem::MaybeUninit::zeroed())); let deferred = mem::replace(&mut work.deferred, ptr::null_mut()); let napi_async_work = mem::replace(&mut work.napi_async_work, ptr::null_mut()); - let value = value_ptr.and_then(move |v| { - let output = v.assume_init(); - work.inner_task.resolve(Env::from_raw(env), output) - }); + let value = match value_ptr { + Ok(v) => { + let output = v.assume_init(); + work.inner_task.resolve(Env::from_raw(env), output) + } + Err(e) => work.inner_task.reject(Env::from_raw(env), e), + }; match check_status!(status).and_then(move |_| value) { Ok(v) => { let status = sys::napi_resolve_deferred(env, deferred, v.raw()); diff --git a/napi/src/task.rs b/napi/src/task.rs index 428f0d41..c7372940 100644 --- a/napi/src/task.rs +++ b/napi/src/task.rs @@ -1,11 +1,17 @@ -use crate::js_values::NapiValue; -use crate::{Env, Result}; +use crate::{js_values::NapiValue, Env, Error, Result}; -pub trait Task: Send { +pub trait Task: Send + Sized { type Output: Send + Sized + 'static; type JsValue: NapiValue; + /// Compute logic in libuv thread fn compute(&mut self) -> Result; + /// Into this method if `compute` return `Ok` fn resolve(self, env: Env, output: Self::Output) -> Result; + + /// Into this method if `compute` return `Err` + fn reject(self, _env: Env, err: Error) -> Result { + Err(err) + } } diff --git a/test_module/__test__/spawn.spec.ts b/test_module/__test__/spawn.spec.ts index 70420ba5..7a8683e6 100644 --- a/test_module/__test__/spawn.spec.ts +++ b/test_module/__test__/spawn.spec.ts @@ -12,3 +12,14 @@ test('should be able to spawn thread with ref value', async (t) => { const result = await bindings.testSpawnThreadWithRef(Buffer.from(fixture)) t.is(result, fixture.length) }) + +test('should be able to spawn with error', async (t) => { + const fixture = Array.from({ length: 10 }).fill('0').join('') + const err = new Error('Unreachable') + try { + await bindings.testSpawnThreadWithRef(Buffer.from(fixture)) + throw err + } catch (e) { + t.not(e, err) + } +}) diff --git a/test_module/src/task.rs b/test_module/src/task.rs index 54380167..9e58be08 100644 --- a/test_module/src/task.rs +++ b/test_module/src/task.rs @@ -1,6 +1,8 @@ use std::convert::TryInto; -use napi::{CallContext, Env, JsBuffer, JsBufferValue, JsNumber, JsObject, Ref, Result, Task}; +use napi::{ + CallContext, Env, Error, JsBuffer, JsBufferValue, JsNumber, JsObject, Ref, Result, Task, +}; struct ComputeFib { n: u32, @@ -56,6 +58,9 @@ impl Task for CountBufferLength { type JsValue = JsNumber; fn compute(&mut self) -> Result { + if self.data.len() == 10 { + return Err(Error::from_reason("len can't be 5".to_string())); + } Ok((&self.data).len()) } @@ -63,6 +68,11 @@ impl Task for CountBufferLength { self.data.unref(env)?; env.create_uint32(output as _) } + + fn reject(self, env: Env, err: Error) -> Result { + self.data.unref(env)?; + Err(err) + } } #[js_function(1)]