feat(napi): implement AsyncTask with AbortSignal support
This commit is contained in:
parent
d36c303dec
commit
e74fe2fb94
17 changed files with 114 additions and 98 deletions
examples
napi-compat-mode/src
napi
|
@ -154,15 +154,16 @@ pub fn test_tsfn_with_ref(ctx: CallContext) -> Result<JsUndefined> {
|
|||
let callback = ctx.get::<JsFunction>(0)?;
|
||||
let options = ctx.get::<JsObject>(1)?;
|
||||
let options_ref = ctx.env.create_reference(options)?;
|
||||
let tsfn =
|
||||
ctx
|
||||
.env
|
||||
.create_threadsafe_function(&callback, 0, |ctx: ThreadSafeCallContext<Ref<()>>| {
|
||||
ctx
|
||||
.env
|
||||
.get_reference_value_unchecked::<JsObject>(&ctx.value)
|
||||
.and_then(|obj| ctx.value.unref(ctx.env).map(|_| vec![obj]))
|
||||
})?;
|
||||
let tsfn = ctx.env.create_threadsafe_function(
|
||||
&callback,
|
||||
0,
|
||||
|mut ctx: ThreadSafeCallContext<Ref<()>>| {
|
||||
ctx
|
||||
.env
|
||||
.get_reference_value_unchecked::<JsObject>(&ctx.value)
|
||||
.and_then(|obj| ctx.value.unref(ctx.env).map(|_| vec![obj]))
|
||||
},
|
||||
)?;
|
||||
|
||||
thread::spawn(move || {
|
||||
tsfn.call(Ok(options_ref), ThreadsafeFunctionCallMode::Blocking);
|
||||
|
|
|
@ -22,7 +22,7 @@ impl Task for ComputeFib {
|
|||
Ok(fibonacci_native(self.n))
|
||||
}
|
||||
|
||||
fn resolve(self, env: Env, output: Self::Output) -> Result<Self::JsValue> {
|
||||
fn resolve(&mut self, env: Env, output: Self::Output) -> Result<Self::JsValue> {
|
||||
env.create_uint32(output)
|
||||
}
|
||||
}
|
||||
|
@ -63,15 +63,18 @@ impl Task for CountBufferLength {
|
|||
Ok((&self.data).len())
|
||||
}
|
||||
|
||||
fn resolve(self, env: Env, output: Self::Output) -> Result<Self::JsValue> {
|
||||
self.data.unref(env)?;
|
||||
fn resolve(&mut self, env: Env, output: Self::Output) -> Result<Self::JsValue> {
|
||||
env.create_uint32(output as _)
|
||||
}
|
||||
|
||||
fn reject(self, env: Env, err: Error) -> Result<Self::JsValue> {
|
||||
self.data.unref(env)?;
|
||||
fn reject(&mut self, env: Env, err: Error) -> Result<Self::JsValue> {
|
||||
Err(err)
|
||||
}
|
||||
|
||||
fn finally(&mut self, env: Env) -> Result<()> {
|
||||
self.data.unref(env)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
|
|
|
@ -43,7 +43,7 @@ Generated by [AVA](https://avajs.dev).
|
|||
export function concatUtf16(s: string): string␊
|
||||
export function concatLatin1(s: string): string␊
|
||||
export function withoutAbortController(a: number, b: number): Promise<number>␊
|
||||
export function withAbortController(a: number, b: number, ctrl: AbortController): Promise<number>␊
|
||||
export function withAbortController(a: number, b: number, signal: AbortSignal): Promise<number>␊
|
||||
export function getBuffer(): Buffer␊
|
||||
export class Animal {␊
|
||||
readonly kind: Kind␊
|
||||
|
|
Binary file not shown.
|
@ -167,9 +167,11 @@ test('async task without abort controller', async (t) => {
|
|||
t.is(await withoutAbortController(1, 2), 3)
|
||||
})
|
||||
|
||||
test('async task with abort controller', async (t) => {
|
||||
const MaybeTest = typeof AbortController !== 'undefined' ? test : test.skip
|
||||
|
||||
MaybeTest('async task with abort controller', async (t) => {
|
||||
const ctrl = new AbortController()
|
||||
const promise = withAbortController(1, 2, ctrl)
|
||||
const promise = withAbortController(1, 2, ctrl.signal)
|
||||
try {
|
||||
ctrl.abort()
|
||||
await promise
|
||||
|
@ -178,3 +180,9 @@ test('async task with abort controller', async (t) => {
|
|||
t.is((err as Error).message, 'AbortError')
|
||||
}
|
||||
})
|
||||
|
||||
MaybeTest('abort resolved task', async (t) => {
|
||||
const ctrl = new AbortController()
|
||||
await withAbortController(1, 2, ctrl.signal).then(() => ctrl.abort())
|
||||
t.pass('should not throw')
|
||||
})
|
||||
|
|
2
examples/napi/index.d.ts
vendored
2
examples/napi/index.d.ts
vendored
|
@ -33,7 +33,7 @@ export function concatStr(mutS: string): string
|
|||
export function concatUtf16(s: string): string
|
||||
export function concatLatin1(s: string): string
|
||||
export function withoutAbortController(a: number, b: number): Promise<number>
|
||||
export function withAbortController(a: number, b: number, ctrl: AbortController): Promise<number>
|
||||
export function withAbortController(a: number, b: number, signal: AbortSignal): Promise<number>
|
||||
export function getBuffer(): Buffer
|
||||
export class Animal {
|
||||
readonly kind: Kind
|
||||
|
|
|
@ -5,17 +5,17 @@ use napi::Task;
|
|||
|
||||
struct DelaySum(u32, u32);
|
||||
|
||||
#[napi]
|
||||
#[napi(task)]
|
||||
impl Task for DelaySum {
|
||||
type Output = u32;
|
||||
type JsValue = u32;
|
||||
|
||||
fn compute(&mut self) -> Result<Self::Output> {
|
||||
sleep(std::time::Duration::from_secs(1));
|
||||
sleep(std::time::Duration::from_millis(100));
|
||||
Ok(self.0 + self.1)
|
||||
}
|
||||
|
||||
fn resolve(self, _env: napi::Env, output: Self::Output) -> Result<Self::JsValue> {
|
||||
fn resolve(&mut self, _env: napi::Env, output: Self::Output) -> Result<Self::JsValue> {
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,6 @@ fn without_abort_controller(a: u32, b: u32) -> AsyncTask<DelaySum> {
|
|||
}
|
||||
|
||||
#[napi]
|
||||
fn with_abort_controller(a: u32, b: u32, ctrl: AsyncTaskAbortController) -> AsyncTask<DelaySum> {
|
||||
AsyncTask::with_abort_controller(DelaySum(a, b), ctrl)
|
||||
fn with_abort_controller(a: u32, b: u32, signal: AbortSignal) -> AsyncTask<DelaySum> {
|
||||
AsyncTask::with_signal(DelaySum(a, b), signal)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue