Skip to content

Problems encountered using asyncify and promises. #217

Open
@pxbos13

Description

@pxbos13

Hello, thank you for providing this tool.

I'm having issues using asyncify and promises. The following code is an example of a usage scenario.

import variant from "@jitl/quickjs-wasmfile-release-asyncify"
import {
  newQuickJSAsyncWASMModuleFromVariant,
  QuickJSAsyncContext,
  QuickJSHandle,
} from "quickjs-emscripten-core"

async function init() {
  const qjsModule = await newQuickJSAsyncWASMModuleFromVariant(variant)
  const runtime = qjsModule.newRuntime()
  const ctx = runtime.newContext()

  defineObj(ctx)
  defineLogger(ctx)
  exposeEval(ctx)
}

init()
function sleep(ms: number) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(undefined)
    }, ms)
  })
}

function defineObj(ctx: QuickJSAsyncContext) {
  const _obj = ctx.newObject()
  const asyncHandle = ctx.newFunction("getAsync", function () {
    const _prom = ctx.newPromise()
    setTimeout(() => {
      _prom.resolve(ctx.newString(""))
    }, 10)
    _prom.settled.then(ctx.runtime.executePendingJobs)
    return _prom.handle
  })
  asyncHandle.consume((handle) => ctx.setProp(_obj, "getAsync", handle))

  ctx.defineProp(_obj, "name", {
    get: async function name() {
      await sleep(10)
      return ctx.newString("QuickJs")
    } as any,
  })
  ctx.setProp(ctx.global, "temp", _obj)
}

function defineLogger(ctx: QuickJSAsyncContext) {
  const logHandle = ctx.newFunction("log", function (...args: QuickJSHandle[]) {
    const nativeArgs = args.map(ctx.dump)
    console.log("[sandbox]", ...nativeArgs)
  })
  ctx.setProp(ctx.global, "log", logHandle)
}

function exposeEval(ctx: QuickJSAsyncContext) {
  ;(window as any)._eval = async function (script: string) {
    const res = await ctx.evalCodeAsync(script)
    ctx.runtime.executePendingJobs()
    console.log("result", res)
  }
}

Then when I use the asyncify method and promise in the sandbox, an error will be reported. The following example:

_eval(`
    async function test(i){
        log("start", i)
        await temp.getAsync();
        const name = temp.name;
        log(i, name);
    }
    for( let i = 0; i < 2; i ++){
        test(i)
    }
`)

Snipaste_2025-01-14_15-41-35

In another scenario, I changed it to await Promise.resolve(0).

_eval(`
    async function test(i){
        log("start", i)
        await Promise.resolve(0);
        const name = temp.name;
        log(i, name);
    }
    for( let i = 0; i < 2; i ++){
        test(i)
    }
`)

When _eval was executed for the first time, no error was reported; another error was reported for the second execution.

Snipaste_2025-01-14_15-49-59

Please help me how to deal with this problem. Many thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions