WebAssembly / WebAssembly/binaryen
wasm2js: function table undefined after calling async function
Nobody has claimed this yet.
- Dominant language
- WebAssembly
- Stars
- 8.6k
- Forks
- 885
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 69
Description
A wasm2js-transpiled JS module is throwing an error after an async call, but the WASM binary is working just fine. The wasm binary is compiled from a rust crate using wasm-bindgen and then built with wasm-pack. For some context, this async call is to a Rust function that then makes a async call back into JS before returning.
The error in particular is
# Unhandled error between tests
-------------------------------
152 | try {
153 | return f(a, state.b, ...args);
154 | } finally {
155 | if (--state.cnt === 0) {
156 | console.debug("In makeMutClosure", {export3: wasm$1.__wbindgen_export_3, wasm1: wasm$1});
157 | wasm$1.__wbindgen_export_3.get(state.dtor)(a, state.b);
^
TypeError: undefined is not an object (evaluating 'wasm$1.__wbindgen_export_3.get')
at real (/Users/joe/git/algorandfoundation/algokit-core/packages/typescript/algokit_utils/dist/algokit_utils.wasm2js.mjs:157:24)
To be clear, the code after the async function still runs, so this seems to be happening async somewhere. Adding a debug statement to this finally block I can see, export 3, which is the function table, is indeed undefined.
In makeMutClosure {
export3: undefined,
wasm1: [Object: null prototype] {
__wbg_composer_free: [Function: $174],
__wbindgen_add_to_stack_pointer: [Function: $413],
__wbindgen_export_0: [Function: $330],
__wbindgen_export_1: [Function: $341],
__wbindgen_export_2: [Function: $390],
__wbindgen_export_4: [Function: $375],
__wbindgen_export_5: [Function: $358],
__wbindgen_export_6: [Function: $354],
addressFromPubKey: [Function: $248],
addressFromString: [Function: $249],
assignFee: [Function: $99],
attachSignature: [Function: $192],
composer_addTransaction: [Function: $138],
composer_encode: [Function: $131],
composer_getSuggestedParams: [Function: $336],
composer_new: [Function: $261],
composer_toJSON: [Function: $215],
composer_toString: [Function: $216],
composer_transactions: [Function: $77],
composer_valueOf: [Function: $214],
decodeTransaction: [Function: $86],
encodeTransaction: [Function: $164],
encodeTransactionRaw: [Function: $165],
estimateTransactionSize: [Function: $199],
getAlgorandConstant: [Function: legalstub$260],
getEncodedTransactionType: [Function: $61],
getTransactionId: [Function: $163],
getTransactionIdRaw: [Function: $162],
memory: {
grow: [Function: __wasm_memory_grow],
buffer: [Getter],
},
},
}
The same debug statement when using the WASM binary:
In makeMutClosure {
export3: Table {
length: 225,
grow: [Function: grow],
get: [Function: get],
set: [Function: set],
type: [Function: type],
},
wasm: [Object: null prototype] {
memory: Memory {
grow: [Function: grow],
buffer: ArrayBuffer(1179648) [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 1179135 more ],
type: [Function: type],
},
composer_addTransaction: [Function: 198],
composer_encode: [Function: 191],
composer_getSuggestedParams: [Function: 396],
composer_transactions: [Function: 137],
__wbg_composer_free: [Function: 234],
composer_new: [Function: 321],
composer_valueOf: [Function: 274],
composer_toJSON: [Function: 275],
composer_toString: [Function: 276],
getEncodedTransactionType: [Function: 121],
encodeTransaction: [Function: 224],
encodeTransactionRaw: [Function: 225],
decodeTransaction: [Function: 146],
attachSignature: [Function: 252],
estimateTransactionSize: [Function: 259],
addressFromPubKey: [Function: 308],
addressFromString: [Function: 309],
getTransactionIdRaw: [Function: 222],
getTransactionId: [Function: 223],
getAlgorandConstant: [Function: 320],
assignFee: [Function: 159],
__wbindgen_export_0: [Function: 390],
__wbindgen_export_1: [Function: 401],
__wbindgen_export_2: [Function: 450],
__wbindgen_export_3: Table {
length: 225,
grow: [Function: grow],
get: [Function: get],
set: [Function: set],
type: [Function: type],
},
__wbindgen_add_to_stack_pointer: [Function: 473],
__wbindgen_export_4: [Function: 435],
__wbindgen_export_5: [Function: 418],
__wbindgen_export_6: [Function: 414],
},
}
The JS files: https://gist.github.com/joe-p/0b12f34e45f5152043f3948d34572e40
The repo: https://github.com/algorandfoundation/algokit-core/tree/2b2eba2c60b0a6d008a4a15bbfa3a76374b04441/packages/typescript/algokit_utils
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the wasm2js-generated JavaScript files in the linked gist and the referenced algokit-core revision, then reproduce the async Rust-to-JavaScript callback path with wasm-pack output. Compare the failing wasm2js module with the working WASM module around makeMutClosure and __wbindgen_export_3. Done means the async path no longer reaches an undefined function table.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, wasm
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100