Skip to content

Unexpected behaviour with async/await logic in JS host #812

Closed
@yourheropaul

Description

@yourheropaul

I'm building a WASM application that relies upon external, asynchronous operations carried out by the host. The WASM part must initiate an unknown number of requests by means of a function call to the host, and then await responses.

Awaiting promises is causing an issue, where the first value is always ignored

Context

I have this WASM code:

declare namespace operation {
    @external("operation", "call")
    function call(name:string): u32
}

declare namespace console {
    @external("console", "log")
    export function logs(val: u32): void;
}

export function myOperation(): void {
    console.log(1)
    const response = operation.call("some-name")
    console.log(4) // See below
    // Do something with response
}

Correspondingly, operation.call() is provided in the Node.js application using the loader:

export class WASMRumtime {
    protected api: ApiPromiseInterface
    protected module: ASUtil

    constructor(src: Uint8Array, api: ApiPromiseInterface) {
        this.module = instantiateBuffer(src, {
            env: {/* standard env config*/}.
            operation: {
                call: async (name: number) => {
                    console.log(2)
                    // This always returns a 0 value the first time
                    const v = await this.api.somePromiseReturningU32(this.moddule.__getString(name))
                    console.log(3)
                    return v
                }
            },
            console: { log: (value:number) => console.log(value) } }
        })
    }
}

Expected results

When myOperation() is called on the WASM, it should call operation.call() and get some value back. The first call is always a zero value, which is never returned by the promise in this case. Subsequent calls produce the previous value.

To try to understand what's happened, I've included some console.log() statements. I expected them to the called in numeric order, but they're not. The output to the console is:

1 <-- inside the WASM, before call to operation.call()
2 <-- inside the JS callback, before await
4 <-- inside the WASM, after operation.call() should have returned
3 <-- Inside the JS callback, after the await

Any idea why this might be?

Additionally, since function callback references and the table seem to have been disabled, is there any better way to get asynchronous data from the WASM host on demand?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions