Merge pull request #929 from napi-rs/async-error-handling
fix(napi): ThreadsafeFunction with ErrorStrategy::Fatal should throw fatal exception
This commit is contained in:
commit
5860d8ce4f
10 changed files with 58 additions and 4 deletions
|
@ -382,7 +382,7 @@ unsafe extern "C" fn call_js_cb<T: 'static, V: NapiRaw, R, ES>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(e) if ES::VALUE == ErrorStrategy::Fatal::VALUE => {
|
Err(e) if ES::VALUE == ErrorStrategy::Fatal::VALUE => {
|
||||||
panic!("{}", e);
|
status = sys::napi_fatal_exception(raw_env, JsError::from(e).into_value(raw_env));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
status = sys::napi_call_function(
|
status = sys::napi_call_function(
|
||||||
|
|
3
examples/napi/__test__/tsfn-error.js
Normal file
3
examples/napi/__test__/tsfn-error.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
const { threadsafeFunctionFatalModeError } = require('../index.node')
|
||||||
|
|
||||||
|
threadsafeFunctionFatalModeError(() => {})
|
|
@ -109,6 +109,7 @@ Generated by [AVA](https://avajs.dev).
|
||||||
export function callThreadsafeFunction(callback: (...args: any[]) => any): void␊
|
export function callThreadsafeFunction(callback: (...args: any[]) => any): void␊
|
||||||
export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void␊
|
export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void␊
|
||||||
export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void␊
|
export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void␊
|
||||||
|
export function threadsafeFunctionFatalModeError(cb: (...args: any[]) => any): void␊
|
||||||
export function getBuffer(): Buffer␊
|
export function getBuffer(): Buffer␊
|
||||||
export function convertU32Array(input: Uint32Array): Array<number>␊
|
export function convertU32Array(input: Uint32Array): Array<number>␊
|
||||||
export function createExternalTypedArray(): Uint32Array␊
|
export function createExternalTypedArray(): Uint32Array␊
|
||||||
|
|
Binary file not shown.
|
@ -1,3 +1,4 @@
|
||||||
|
import { exec } from 'child_process'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
import test from 'ava'
|
import test from 'ava'
|
||||||
|
@ -390,13 +391,34 @@ Napi4Test('throw error from thread safe function', async (t) => {
|
||||||
t.is(err.message, 'ThrowFromNative')
|
t.is(err.message, 'ThrowFromNative')
|
||||||
})
|
})
|
||||||
|
|
||||||
Napi4Test('throw error from thread safe function fatal mode', async (t) => {
|
Napi4Test('resolve value from thread safe function fatal mode', async (t) => {
|
||||||
const tsfnFatalMode = new Promise<boolean>((resolve) => {
|
const tsfnFatalMode = new Promise<boolean>((resolve) => {
|
||||||
threadsafeFunctionFatalMode(resolve)
|
threadsafeFunctionFatalMode(resolve)
|
||||||
})
|
})
|
||||||
t.true(await tsfnFatalMode)
|
t.true(await tsfnFatalMode)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Napi4Test('throw error from thread safe function fatal mode', (t) => {
|
||||||
|
const p = exec('node ./tsfn-error.js', {
|
||||||
|
cwd: __dirname,
|
||||||
|
})
|
||||||
|
let stderr = Buffer.from([])
|
||||||
|
p.stderr?.on('data', (data) => {
|
||||||
|
stderr = Buffer.concat([stderr, Buffer.from(data)])
|
||||||
|
})
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
p.on('exit', (code) => {
|
||||||
|
t.is(code, 1)
|
||||||
|
t.true(
|
||||||
|
stderr
|
||||||
|
.toString('utf8')
|
||||||
|
.includes(`[Error: Generic tsfn error] { code: 'GenericFailure' }`),
|
||||||
|
)
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Napi4Test('await Promise in rust', async (t) => {
|
Napi4Test('await Promise in rust', async (t) => {
|
||||||
const fx = 20
|
const fx = 20
|
||||||
const result = await asyncPlus100(
|
const result = await asyncPlus100(
|
||||||
|
|
1
examples/napi/index.d.ts
vendored
1
examples/napi/index.d.ts
vendored
|
@ -99,6 +99,7 @@ export function withAbortController(a: number, b: number, signal: AbortSignal):
|
||||||
export function callThreadsafeFunction(callback: (...args: any[]) => any): void
|
export function callThreadsafeFunction(callback: (...args: any[]) => any): void
|
||||||
export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void
|
export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void
|
||||||
export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void
|
export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void
|
||||||
|
export function threadsafeFunctionFatalModeError(cb: (...args: any[]) => any): void
|
||||||
export function getBuffer(): Buffer
|
export function getBuffer(): Buffer
|
||||||
export function convertU32Array(input: Uint32Array): Array<number>
|
export function convertU32Array(input: Uint32Array): Array<number>
|
||||||
export function createExternalTypedArray(): Uint32Array
|
export function createExternalTypedArray(): Uint32Array
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "napi-examples",
|
"name": "napi-examples",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
"main": "./index.node",
|
"main": "./index.node",
|
||||||
"types": "./index.d.ts",
|
"types": "./index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -10,5 +11,9 @@
|
||||||
"build-i686": "node ../../cli/scripts/index.js build --js false --target i686-pc-windows-msvc",
|
"build-i686": "node ../../cli/scripts/index.js build --js false --target i686-pc-windows-msvc",
|
||||||
"build-i686-release": "node ../../cli/scripts/index.js build --js false --release --target i686-pc-windows-msvc",
|
"build-i686-release": "node ../../cli/scripts/index.js build --js false --release --target i686-pc-windows-msvc",
|
||||||
"build-release": "node ../../cli/scripts/index.js build --js false --release"
|
"build-release": "node ../../cli/scripts/index.js build --js false --release"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/lodash": "^4.14.178",
|
||||||
|
"lodash": "4.17.21"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::thread;
|
||||||
use napi::{
|
use napi::{
|
||||||
bindgen_prelude::*,
|
bindgen_prelude::*,
|
||||||
threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode},
|
threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode},
|
||||||
|
JsBoolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
|
@ -45,3 +46,18 @@ pub fn threadsafe_function_fatal_mode(cb: JsFunction) -> Result<()> {
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
pub fn threadsafe_function_fatal_mode_error(cb: JsFunction) -> Result<()> {
|
||||||
|
let tsfn: ThreadsafeFunction<bool, ErrorStrategy::Fatal> =
|
||||||
|
cb.create_threadsafe_function(0, |_ctx| {
|
||||||
|
Err::<Vec<JsBoolean>, Error>(Error::new(
|
||||||
|
Status::GenericFailure,
|
||||||
|
"Generic tsfn error".to_owned(),
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
thread::spawn(move || {
|
||||||
|
tsfn.call(true, ThreadsafeFunctionCallMode::Blocking);
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"cli",
|
"cli",
|
||||||
"triples",
|
"triples",
|
||||||
"memory-testing"
|
"memory-testing",
|
||||||
|
"examples/napi"
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -1189,6 +1189,11 @@
|
||||||
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz#f70c0d19c30fab101cad46b52be60363c43c4578"
|
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz#f70c0d19c30fab101cad46b52be60363c43c4578"
|
||||||
integrity sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==
|
integrity sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==
|
||||||
|
|
||||||
|
"@types/lodash@^4.14.178":
|
||||||
|
version "4.14.178"
|
||||||
|
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8"
|
||||||
|
integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==
|
||||||
|
|
||||||
"@types/minimatch@^3.0.3":
|
"@types/minimatch@^3.0.3":
|
||||||
version "3.0.5"
|
version "3.0.5"
|
||||||
resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
|
resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
|
||||||
|
@ -4388,7 +4393,7 @@ lodash.truncate@^4.4.2:
|
||||||
resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||||
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
||||||
|
|
||||||
lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
|
lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
|
Loading…
Reference in a new issue