Skip to content

fix: make sure we don't panic when an exception is thrown in an async context #135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mhmd-azeez
Copy link
Contributor

Fixes #134

What's going on?

In this code sample:

import { createHighlighter } from 'shiki'

export function main() {
  try {
    const code = 'const a = 1' // input code
    const highlighter = createHighlighter({
      themes: ['nord'],
      langs: ['javascript'],
    })

    console.log('BAAM!')

    //@ts-ignore - `codeToHtml` doesn't exist, `highlighter` is not awaited, so it's still a Promise
    const html = highlighter.codeToHtml(code, {
      lang: 'javascript',
      theme: 'nord'
    })

    Host.outputString(html);
  } catch (error) {
    console.log('error: ', error)
    throw error
  }
}

highlighter is not awaited, so it's still a Promise so codeToHtml doesn't exist.

And it seems like quickjs can't deal with promise rejections well:

I have made sure we handle this case, and we let the user know async is not supported in Extism functions (see issue_134 example):

➜  issue_134 git:(fix/issue_134) ✗ npm run build && extism call ../issue_134.wasm main --wasi --log-level info

> [email protected] build
> cross-env NODE_ENV=production node esbuild.js && cross-env ../../target/release/extism-js dist/index.js -i src/index.d.ts -o ../issue_134.wasm

2025/05/18 22:42:23 BAAM!
2025/05/18 22:42:23 error:  TypeError: not a function
    at main2 (eval_script:14216:31)
Error: Uncaught exception in async context. Async/Promise operations are not supported in this environment. Please use only synchronous code.
returned non-zero exit code: 4294967295

@mhmd-azeez mhmd-azeez requested review from bhelx and zshipko as code owners May 18, 2025 19:48
@mhmd-azeez
Copy link
Contributor Author

To be clear, normal exception were already being handled properly

@mhmd-azeez
Copy link
Contributor Author

Tried to make the exception more helpful by using set_host_promise_rejection_tracker, but

  1. The version they are exposing doesn't really work: how to handle uncaught errors? DelSkayn/rquickjs#421 (comment), it's fixed here Fix reporting handled promises as unhandled in tracker quickjs-ng/quickjs#1038
  2. couldn't install rquickjs 0.9:
➜  js-pdk git:(main) ✗ make cli  
cd crates/core \
		  && cd src/prelude \
			&& npm install \
			&& npm run build \
			&& npx -y -p typescript tsc src/index.ts --lib es2020 --declaration --emitDeclarationOnly --outDir dist \
			&& cd ../.. \
			&& cargo build --release --target=wasm32-wasip1 \
			&& wasm-opt --enable-reference-types --enable-bulk-memory --strip -O3 ../../target/wasm32-wasip1/release/js_pdk_core.wasm -o ../../target/wasm32-wasip1/release/js_pdk_core.wasm \
			&& cd -

up to date, audited 6 packages in 596ms

1 package is looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

> @extism/[email protected] build
> node esbuild.js && tsc

   Compiling rquickjs-sys v0.9.0
   Compiling js-pdk-core v1.5.1 (/home/mo/work/dylibso/js-pdk/crates/core)
error: failed to run custom build command for `rquickjs-sys v0.9.0`

Caused by:
  process didn't exit successfully: `/home/mo/work/dylibso/js-pdk/target/release/build/rquickjs-sys-1078b1f618b07837/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-changed=build.rs
  cargo:rerun-if-env-changed=CARGO_FEATURE_BINDGEN
  cargo:rerun-if-env-changed=CARGO_FEATURE_UPDATE_BINDINGS
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_BYTECODE
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_GC
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_GC_FREE
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_FREE
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_LEAKS
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_MEM
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_OBJECTS
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_ATOMS
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_SHAPES
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_MODULE_RESOLVE
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_PROMISE
  cargo:rerun-if-env-changed=CARGO_FEATURE_DUMP_READ_OBJECT
  SDK tar: "/home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/wasi-sdk/wasi-sdk-24-0.tar.gz"
  Downloading WASI SDK archive from https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-linux.tar.gz to "/home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/wasi-sdk/wasi-sdk-24-0.tar.gz"
  curl output: 
  curl err:   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                   Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  113M  100  113M    0     0   864k      0  0:02:14  0:02:14 --:--:--  422k


  --- stderr
  Debian clang version 14.0.6
  Target: wasm32-unknown-wasip1
  Thread model: posix
  InstalledDir: 
  ignoring nonexistent directory "lib/clang/14.0.6/include"
  ignoring nonexistent directory "/home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/wasi-sdk/share/wasi-sysroot/local/include/wasm32-wasip1"
  ignoring nonexistent directory "/home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/wasi-sdk/share/wasi-sysroot/local/include"
  ignoring nonexistent directory "/home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/wasi-sdk/share/wasi-sysroot/include/wasm32-wasip1"
  ignoring nonexistent directory "/home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/wasi-sdk/share/wasi-sysroot/include"
  #include "..." search starts here:
  #include <...> search starts here:
   /usr/lib/llvm-14/lib/clang/14.0.6/include
  End of search list.
  /home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/quickjs.h:31:10: fatal error: 'stdio.h' file not found

  thread 'main' panicked at /home/mo/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rquickjs-sys-0.9.0/build.rs:311:39:
  Unable to generate bindings: ClangDiagnostic("/home/mo/work/dylibso/js-pdk/target/wasm32-wasip1/release/build/rquickjs-sys-01c66f6d8f136e1e/out/quickjs.h:31:10: fatal error: 'stdio.h' file not found\n")
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
make: *** [Makefile:18: core] Error 101

@zshipko
Copy link
Contributor

zshipko commented May 19, 2025

something i noticed looking at this example, is that it runs correctly when I make the main function async:

export async function main() {

this leads me to believe that the error is actually related to calling async code in a non-async function or something lower level than the actual exception being raised.

the unreachable error also goes away if I leave the function signature the same, but remove the call returning a promise which kind of supports that idea.

i think we need to investigate this a little more, since async definitely does work, but there is still something weird going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Exceptions throw panic - Option::unwrap() on a None value
2 participants