{"version":3,"sources":["../src/context-asyncify.ts","../src/runtime-asyncify.ts","../src/module-asyncify.ts"],"sourcesContent":["import type {\n  QuickJSAsyncEmscriptenModule,\n  QuickJSAsyncFFI,\n  EvalDetectModule,\n  EvalFlags,\n  JSRuntimePointer,\n  JSValuePointer,\n} from \"@jitl/quickjs-ffi-types\"\nimport type { QuickJSContextResult } from \"./context\"\nimport { QuickJSContext } from \"./context\"\nimport type { Lifetime } from \"./lifetime\"\nimport type { QuickJSModuleCallbacks } from \"./module\"\nimport type { QuickJSAsyncRuntime } from \"./runtime-asyncify\"\nimport type { ContextEvalOptions, QuickJSHandle } from \"./types\"\nimport { evalOptionsToFlags } from \"./types\"\nimport type { VmCallResult } from \"./vm-interface\"\n\nexport type AsyncFunctionImplementation = (\n  this: QuickJSHandle,\n  ...args: QuickJSHandle[]\n) => Promise<QuickJSHandle | VmCallResult<QuickJSHandle> | void>\n\n/**\n * Asyncified version of {@link QuickJSContext}.\n *\n * *Asyncify* allows normally synchronous code to wait for asynchronous Promises\n * or callbacks. The asyncified version of QuickJSContext can wait for async\n * host functions as though they were synchronous.\n */\nexport class QuickJSAsyncContext extends QuickJSContext {\n  public declare runtime: QuickJSAsyncRuntime\n  /** @private */\n  protected declare module: QuickJSAsyncEmscriptenModule\n  /** @private */\n  protected declare ffi: QuickJSAsyncFFI\n  /** @private */\n  protected declare rt: Lifetime<JSRuntimePointer>\n  /** @private */\n  protected declare callbacks: QuickJSModuleCallbacks\n\n  /**\n   * Asyncified version of {@link evalCode}.\n   */\n  async evalCodeAsync(\n    code: string,\n    filename: string = \"eval.js\",\n    /** See {@link EvalFlags} for number semantics */\n    options?: number | ContextEvalOptions,\n  ): Promise<QuickJSContextResult<QuickJSHandle>> {\n    const detectModule = (options === undefined ? 1 : 0) as EvalDetectModule\n    const flags = evalOptionsToFlags(options) as EvalFlags\n    let resultPtr = 0 as JSValuePointer\n    try {\n      resultPtr = await this.memory\n        .newHeapCharPointer(code)\n        .consume((charHandle) =>\n          this.ffi.QTS_Eval_MaybeAsync(\n            this.ctx.value,\n            charHandle.value.ptr,\n            charHandle.value.strlen,\n            filename,\n            detectModule,\n            flags,\n          ),\n        )\n    } catch (error) {\n      this.runtime.debugLog(\"QTS_Eval_MaybeAsync threw\", error)\n      throw error\n    }\n    const errorPtr = this.ffi.QTS_ResolveException(this.ctx.value, resultPtr)\n    if (errorPtr) {\n      this.ffi.QTS_FreeValuePointer(this.ctx.value, resultPtr)\n      return this.fail(this.memory.heapValueHandle(errorPtr))\n    }\n    return this.success(this.memory.heapValueHandle(resultPtr))\n  }\n\n  /**\n   * Similar to {@link newFunction}.\n   * Convert an async host Javascript function into a synchronous QuickJS function value.\n   *\n   * Whenever QuickJS calls this function, the VM's stack will be unwound while\n   * waiting the async function to complete, and then restored when the returned\n   * promise resolves.\n   *\n   * Asyncified functions must never call other asyncified functions or\n   * `import`, even indirectly, because the stack cannot be unwound twice.\n   *\n   * See [Emscripten's docs on Asyncify](https://emscripten.org/docs/porting/asyncify.html).\n   */\n  newAsyncifiedFunction(name: string, fn: AsyncFunctionImplementation): QuickJSHandle {\n    return this.newFunction(name, fn as any)\n  }\n}\n","import type {\n  QuickJSAsyncEmscriptenModule,\n  QuickJSAsyncFFI,\n  JSContextPointer,\n  JSRuntimePointer,\n} from \"@jitl/quickjs-ffi-types\"\nimport { QuickJSAsyncContext } from \"./context-asyncify\"\nimport type {\n  // Used in doc\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  QuickJSAsyncWASMModule,\n} from \"./module-asyncify\"\nimport type { QuickJSModuleCallbacks } from \"./module\"\nimport { QuickJSRuntime } from \"./runtime\"\nimport type {\n  ContextOptions,\n  JSModuleLoader,\n  JSModuleLoaderAsync,\n  JSModuleNormalizer,\n  JSModuleNormalizerAsync,\n} from \"./types\"\nimport { intrinsicsToFlags } from \"./types\"\nimport { Lifetime } from \"./lifetime\"\n\nexport class QuickJSAsyncRuntime extends QuickJSRuntime {\n  public declare context: QuickJSAsyncContext | undefined\n\n  /** @private */\n  protected declare module: QuickJSAsyncEmscriptenModule\n  /** @private */\n  protected declare ffi: QuickJSAsyncFFI\n  /** @private */\n  protected declare rt: Lifetime<JSRuntimePointer>\n  /** @private */\n  protected declare callbacks: QuickJSModuleCallbacks\n  /** @private */\n  protected declare contextMap: Map<JSContextPointer, QuickJSAsyncContext>\n\n  /** @private */\n  constructor(args: {\n    module: QuickJSAsyncEmscriptenModule\n    ffi: QuickJSAsyncFFI\n    rt: Lifetime<JSRuntimePointer>\n    callbacks: QuickJSModuleCallbacks\n  }) {\n    super(args)\n  }\n\n  override newContext(options: ContextOptions = {}): QuickJSAsyncContext {\n    const intrinsics = intrinsicsToFlags(options.intrinsics)\n    const ctx = new Lifetime(\n      this.ffi.QTS_NewContext(this.rt.value, intrinsics),\n      undefined,\n      (ctx_ptr) => {\n        this.contextMap.delete(ctx_ptr)\n        this.callbacks.deleteContext(ctx_ptr)\n        this.ffi.QTS_FreeContext(ctx_ptr)\n      },\n    )\n\n    const context = new QuickJSAsyncContext({\n      module: this.module,\n      ctx,\n      ffi: this.ffi,\n      rt: this.rt,\n      ownedLifetimes: [],\n      runtime: this,\n      callbacks: this.callbacks,\n    })\n    this.contextMap.set(ctx.value, context)\n\n    return context\n  }\n\n  public override setModuleLoader(\n    moduleLoader: JSModuleLoaderAsync,\n    moduleNormalizer?: JSModuleNormalizerAsync,\n  ): void {\n    super.setModuleLoader(\n      moduleLoader as JSModuleLoader,\n      moduleNormalizer as JSModuleNormalizer | undefined,\n    )\n  }\n\n  /**\n   * Set the max stack size for this runtime in bytes.\n   * To remove the limit, set to `0`.\n   *\n   * Setting this limit also adjusts the global `ASYNCIFY_STACK_SIZE` for the entire {@link QuickJSAsyncWASMModule}.\n   * See the [pull request](https://github.com/justjake/quickjs-emscripten/pull/114) for more details.\n   */\n  public override setMaxStackSize(stackSize: number): void {\n    return super.setMaxStackSize(stackSize)\n  }\n}\n","import type { QuickJSAsyncEmscriptenModule, QuickJSAsyncFFI } from \"@jitl/quickjs-ffi-types\"\nimport type { QuickJSAsyncContext } from \"./context-asyncify\"\nimport { QuickJSNotImplemented } from \"./errors\"\nimport { Lifetime, Scope } from \"./lifetime\"\nimport type { ModuleEvalOptions } from \"./module\"\nimport { applyBaseRuntimeOptions, applyModuleEvalRuntimeOptions, QuickJSWASMModule } from \"./module\"\nimport { QuickJSAsyncRuntime } from \"./runtime-asyncify\"\nimport type { AsyncRuntimeOptions, ContextOptions } from \"./types\"\n\n/**\n * Asyncified version of {@link QuickJSWASMModule}.\n *\n * Due to limitations of Emscripten's ASYNCIFY process, only a single async\n * function call can happen at a time across the entire WebAssembly module.\n *\n * That means that all runtimes, contexts, functions, etc created inside this\n * WebAssembly are limited to a single concurrent async action.\n * **Multiple concurrent async actions is an error.**\n *\n * To allow for multiple concurrent async actions, you must create multiple WebAssembly\n * modules.\n */\nexport class QuickJSAsyncWASMModule extends QuickJSWASMModule {\n  /** @private */\n  protected ffi: QuickJSAsyncFFI\n  /** @private */\n  protected module: QuickJSAsyncEmscriptenModule\n\n  /** @private */\n  constructor(module: QuickJSAsyncEmscriptenModule, ffi: QuickJSAsyncFFI) {\n    super(module, ffi)\n    this.ffi = ffi\n    this.module = module\n  }\n\n  /**\n   * Create a new async runtime inside this WebAssembly module. All runtimes inside a\n   * module are limited to a single async call at a time. For multiple\n   * concurrent async actions, create multiple WebAssembly modules.\n   */\n  override newRuntime(options: AsyncRuntimeOptions = {}): QuickJSAsyncRuntime {\n    const rt = new Lifetime(this.ffi.QTS_NewRuntime(), undefined, (rt_ptr) => {\n      this.callbacks.deleteRuntime(rt_ptr)\n      this.ffi.QTS_FreeRuntime(rt_ptr)\n    })\n    const runtime = new QuickJSAsyncRuntime({\n      module: this.module,\n      ffi: this.ffi,\n      rt,\n      callbacks: this.callbacks,\n    })\n\n    applyBaseRuntimeOptions(runtime, options)\n\n    if (options.moduleLoader) {\n      runtime.setModuleLoader(options.moduleLoader)\n    }\n\n    return runtime\n  }\n\n  /**\n   * A simplified API to create a new {@link QuickJSAsyncRuntime} and a\n   * {@link QuickJSAsyncContext} inside that runtime at the same time. The runtime will\n   * be disposed when the context is disposed.\n   */\n  override newContext(options: ContextOptions = {}): QuickJSAsyncContext {\n    const runtime = this.newRuntime()\n    const lifetimes = options.ownedLifetimes ? options.ownedLifetimes.concat([runtime]) : [runtime]\n    const context = runtime.newContext({ ...options, ownedLifetimes: lifetimes })\n    runtime.context = context\n    return context\n  }\n\n  /** Synchronous evalCode is not supported. */\n  override evalCode(): never {\n    throw new QuickJSNotImplemented(\"QuickJSWASMModuleAsyncify.evalCode: use evalCodeAsync instead\")\n  }\n\n  /**\n   * One-off evaluate code without needing to create a {@link QuickJSAsyncRuntime} or\n   * {@link QuickJSAsyncContext} explicitly.\n   *\n   * This version allows for asynchronous Ecmascript module loading.\n   *\n   * Note that only a single async action can occur at a time inside the entire WebAssembly module.\n   * **Multiple concurrent async actions is an error.**\n   *\n   * See the documentation for {@link QuickJSWASMModule#evalCode} for more details.\n   */\n  evalCodeAsync(code: string, options: ModuleEvalOptions): Promise<unknown> {\n    // TODO: we should really figure out generator for the Promise monad...\n    return Scope.withScopeAsync(async (scope) => {\n      const vm = scope.manage(this.newContext())\n      applyModuleEvalRuntimeOptions(vm.runtime, options)\n      const result = await vm.evalCodeAsync(code, \"eval.js\")\n\n      if (options.memoryLimitBytes !== undefined) {\n        // Remove memory limit so we can dump the result without exceeding it.\n        vm.runtime.setMemoryLimit(-1)\n      }\n\n      if (result.error) {\n        const error = vm.dump(scope.manage(result.error))\n        throw error\n      }\n\n      const value = vm.dump(scope.manage(result.value))\n      return value\n    })\n  }\n}\n"],"mappings":"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","names":[]}