Skip to content

Commit 4c66da3

Browse files
committed
fix: make sure we don't panic when an exception is thrown in an async context
1 parent 06bd074 commit 4c66da3

File tree

9 files changed

+1155
-4
lines changed

9 files changed

+1155
-4
lines changed

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ test: compile-examples
7171
echo "Got: $$error_msg"; \
7272
exit 1; \
7373
fi
74+
@output=$$(extism call examples/async_exception.wasm main --wasi --log-level info 2>&1); \
75+
if echo "$$output" | grep -q "wasm error: unreachable"; then \
76+
echo "Test failed - found 'wasm error: unreachable' in output"; \
77+
echo "Output: $$output"; \
78+
exit 1; \
79+
else \
80+
echo "Test passed - no unreachable error in async_exception"; \
81+
fi
7482

7583
compile-examples: cli
7684
cd examples/react && npm install && npm run build && cd ../..
@@ -82,6 +90,7 @@ compile-examples: cli
8290
./target/release/extism-js examples/console/script.js -i examples/console/script.d.ts -o examples/console.wasm
8391
./target/release/extism-js examples/base64/script.js -i examples/base64/script.d.ts -o examples/base64.wasm
8492
./target/release/extism-js examples/try-catch/script.js -i examples/try-catch/script.d.ts -o examples/try-catch.wasm
93+
cd examples/async_exception && npm install && npm run build && cd ../..
8594

8695
kitchen:
8796
cd examples/kitchen-sink && npm install && npm run build && cd ../..

crates/core/src/lib.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,26 @@ static CALL_ARGS: std::sync::Mutex<Vec<Vec<ArgType>>> = std::sync::Mutex::new(ve
1818
fn check_exception(this: &Ctx, err: rquickjs::Error) -> anyhow::Error {
1919
let s = match err {
2020
rquickjs::Error::Exception => {
21-
let err = this.catch().into_exception().unwrap();
22-
let msg = err.message().unwrap_or_default();
23-
format!("Exception: {}\n{}", msg, err.stack().unwrap_or_default())
21+
// Check if we got a valid exception or if it's uninitialized (possibly due to async code)
22+
// - https://github.com/DelSkayn/rquickjs/issues/421
23+
// - https://github.com/DelSkayn/rquickjs/pull/422
24+
// - https://github.com/quickjs-ng/quickjs/issues/39
25+
// - https://github.com/quickjs-ng/quickjs/pull/1038
26+
27+
match this.catch().into_exception() {
28+
Some(err) => {
29+
let msg = err.message().unwrap_or_default();
30+
let stack = err.stack().unwrap_or_default();
31+
format!("Exception: {}\n{}", msg, stack)
32+
}
33+
None => {
34+
format!(
35+
"Uncaught exception in async context. \
36+
Async/Promise operations are not supported in this environment. \
37+
Please use only synchronous code."
38+
)
39+
}
40+
}
2441
}
2542
err => err.to_string(),
2643
};
@@ -102,7 +119,7 @@ fn invoke<'a, T, F: for<'b> Fn(Ctx<'b>, Value<'b>) -> T>(
102119
let function_invocation_result = function.call_arg(args);
103120

104121
while ctx.execute_pending_job() {
105-
continue
122+
continue;
106123
}
107124

108125
match function_invocation_result {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
dist/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const esbuild = require('esbuild');
2+
3+
esbuild
4+
.build({
5+
entryPoints: ['src/index.ts'],
6+
outdir: 'dist',
7+
bundle: true,
8+
sourcemap: true,
9+
minify: false, // might want to use true for production build
10+
format: 'cjs', // needs to be CJS for now
11+
target: ['es2020'] // don't go over es2020 because quickjs doesn't support it
12+
})

0 commit comments

Comments
 (0)