Summary
When a sync import returns a Promise that the runtime refuses with NeedsJspi, the runtime abandons its adapted Promise without a rejection handler. Catching the export refusal does not prevent a later unhandled Trap rejection.
Priority: medium. Reproduced with real Wasm on fd4266b516632e80943456a45aa64b95ea42f36f, Deno 2.9.5 / V8 15.0, Linux aarch64.
Reproduction
Instantiate the committed runtime/tests/embedder/host-result.wasm fixture using the normal translator/artifact helper, with this provider:
{
"host:api/fallible": {
check: () => Promise.reject(new Error("late host failure")),
},
}
The sync import is deliberately unmarked. Call and catch await instance.exports.run(), then allow an event-loop turn.
Observed:
entry refused NeedsJspi
Uncaught (in promise) Trap: import 'host:api/fallible/check' threw Error: late host failure ...
Deno terminates the test module due to the uncaught rejection, despite the application catching the entry refusal.
Cause and authority
- instantiate.ts:782–790 constructs an adapted Promise whose rejection becomes a Trap.
- boundary.ts:1790–1806 rejects the capability request without observing the adapted Promise.
contracts/embedder-api.md:206–215 specifies a call-site refusal for unsupported Promise returns. Although the invalid import signature is a host error, the runtime must handle the intermediate Promise it created when refusing it.
The existing refusal test using a branded ComponentException misses this: adaptation turns that rejection into a fulfilled err value.
Acceptance criteria
- Observe rejected adapted Promises on capability-refusal paths while preserving the specified call-site error.
- Cover an unbranded rejected Promise after catching NeedsJspi, plus marked imports with
jspi:false.
- Check late fulfillment with ownership-bearing values so draining does not introduce abandoned conversion effects.
- No unhandled rejection or test-module termination; run
just gates for the repair.
Summary
When a sync import returns a Promise that the runtime refuses with
NeedsJspi, the runtime abandons its adapted Promise without a rejection handler. Catching the export refusal does not prevent a later unhandledTraprejection.Priority: medium. Reproduced with real Wasm on
fd4266b516632e80943456a45aa64b95ea42f36f, Deno 2.9.5 / V8 15.0, Linux aarch64.Reproduction
Instantiate the committed
runtime/tests/embedder/host-result.wasmfixture using the normal translator/artifact helper, with this provider:The sync import is deliberately unmarked. Call and catch
await instance.exports.run(), then allow an event-loop turn.Observed:
Deno terminates the test module due to the uncaught rejection, despite the application catching the entry refusal.
Cause and authority
contracts/embedder-api.md:206–215specifies a call-site refusal for unsupported Promise returns. Although the invalid import signature is a host error, the runtime must handle the intermediate Promise it created when refusing it.The existing refusal test using a branded ComponentException misses this: adaptation turns that rejection into a fulfilled err value.
Acceptance criteria
jspi:false.just gatesfor the repair.