@execbox/quickjs 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +2 -8
  2. package/dist/index.cjs +2 -2
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +51 -3
  5. package/dist/index.d.cts.map +1 -1
  6. package/dist/index.d.ts +51 -3
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -2
  9. package/dist/index.js.map +1 -1
  10. package/dist/{runner-DRLfwiqY.cjs → runner-BeRzBTrn.cjs} +92 -74
  11. package/dist/runner-BeRzBTrn.cjs.map +1 -0
  12. package/dist/{runner-oZXbguX3.js → runner-DJd4Bh8V.js} +92 -74
  13. package/dist/runner-DJd4Bh8V.js.map +1 -0
  14. package/dist/workerEntry.cjs +105 -3
  15. package/dist/workerEntry.cjs.map +1 -1
  16. package/dist/workerEntry.js +104 -2
  17. package/dist/workerEntry.js.map +1 -1
  18. package/package.json +2 -29
  19. package/dist/protocolEndpoint-BGyrwlr_.cjs +0 -112
  20. package/dist/protocolEndpoint-BGyrwlr_.cjs.map +0 -1
  21. package/dist/protocolEndpoint-Ceadcq_L.js +0 -107
  22. package/dist/protocolEndpoint-Ceadcq_L.js.map +0 -1
  23. package/dist/remoteEndpoint.cjs +0 -45
  24. package/dist/remoteEndpoint.cjs.map +0 -1
  25. package/dist/remoteEndpoint.d.cts +0 -29
  26. package/dist/remoteEndpoint.d.cts.map +0 -1
  27. package/dist/remoteEndpoint.d.ts +0 -29
  28. package/dist/remoteEndpoint.d.ts.map +0 -1
  29. package/dist/remoteEndpoint.js +0 -45
  30. package/dist/remoteEndpoint.js.map +0 -1
  31. package/dist/runner/index.cjs +0 -3
  32. package/dist/runner/index.d.cts +0 -45
  33. package/dist/runner/index.d.cts.map +0 -1
  34. package/dist/runner/index.d.ts +0 -45
  35. package/dist/runner/index.d.ts.map +0 -1
  36. package/dist/runner/index.js +0 -3
  37. package/dist/runner/protocolEndpoint.cjs +0 -4
  38. package/dist/runner/protocolEndpoint.d.cts +0 -22
  39. package/dist/runner/protocolEndpoint.d.cts.map +0 -1
  40. package/dist/runner/protocolEndpoint.d.ts +0 -22
  41. package/dist/runner/protocolEndpoint.d.ts.map +0 -1
  42. package/dist/runner/protocolEndpoint.js +0 -4
  43. package/dist/runner-DRLfwiqY.cjs.map +0 -1
  44. package/dist/runner-oZXbguX3.js.map +0 -1
  45. package/dist/types-C-XfFJ7u.d.cts +0 -58
  46. package/dist/types-C-XfFJ7u.d.cts.map +0 -1
  47. package/dist/types-CE7SvejR.d.ts +0 -58
  48. package/dist/types-CE7SvejR.d.ts.map +0 -1
package/README.md CHANGED
@@ -62,17 +62,11 @@ const executor = new QuickJsExecutor({
62
62
  await executor.prewarm();
63
63
  ```
64
64
 
65
- ## Advanced Imports
66
-
67
- - `@execbox/quickjs/runner` exports the reusable QuickJS runner
68
- - `@execbox/quickjs/runner/protocol-endpoint` exports the low-level QuickJS protocol loop used by worker-hosted integrations
69
- - `@execbox/quickjs/remote-endpoint` adapts the QuickJS protocol loop to `@execbox/remote` runner ports
70
-
71
65
  ## Operational Notes
72
66
 
73
67
  - Each execution gets a fresh QuickJS runtime with JSON-only tool and result boundaries.
74
- - This package is the default deployment path, not a hard security boundary for hostile or multi-tenant code.
75
- - If you need a stronger deployment boundary, move execution behind `@execbox/remote` and a process, container, VM, or network boundary your application owns.
68
+ - Inline mode and worker mode are execution placement choices, not hard security boundaries for hostile or multi-tenant code.
69
+ - Worker mode moves QuickJS off the main thread but still shares the same host process.
76
70
 
77
71
  ## Read Next
78
72
 
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_runner = require('./runner-DRLfwiqY.cjs');
1
+ const require_runner = require('./runner-BeRzBTrn.cjs');
2
2
  let __execbox_core_runtime = require("@execbox/core/runtime");
3
3
  let node_os = require("node:os");
4
4
  let node_worker_threads = require("node:worker_threads");
@@ -309,7 +309,7 @@ var QuickJsExecutor = class {
309
309
  */
310
310
  constructor(options = {}) {
311
311
  const unsupportedHost = getUnsupportedHost(options);
312
- if (unsupportedHost !== void 0) throw new Error(`QuickJsExecutor host "${unsupportedHost}" is no longer supported. Use host "worker" for local hosted execution, or @execbox/remote for process, container, or VM boundaries.`);
312
+ if (unsupportedHost !== void 0) throw new Error(`QuickJsExecutor host "${unsupportedHost}" is no longer supported. Use host "worker" for local hosted execution.`);
313
313
  if (isWorkerOptions(options)) {
314
314
  this.hostedExecutor = new WorkerHostedQuickJsExecutor(options);
315
315
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions>","closeReason: TransportCloseReason | undefined","Worker","leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }>","runQuickJsSession"],"sources":["../src/hosted/shared.ts","../src/hosted/workerHostedExecutor.ts","../src/quickjsExecutor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n runHostTransportSession,\n type HostTransport,\n} from \"@execbox/core/protocol\";\nimport type { ExecutorPoolOptions } from \"@execbox/core\";\nimport { resolveExecutorRuntimeOptions } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n ExecutorRuntimeOptions,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\n/**\n * Default grace period before a worker-hosted shell is forcefully terminated.\n */\nconst DEFAULT_CANCEL_GRACE_MS = 25;\n\n/**\n * Default pooling limits shared by worker-hosted QuickJS executors.\n */\nconst DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions> = {\n idleTimeoutMs: 30_000,\n maxSize: 1,\n minSize: 0,\n prewarm: false,\n};\n\n/**\n * Minimal code used to warm a worker shell without touching user providers.\n */\nconst DEFAULT_PREWARM_CODE = \"undefined\";\n\nexport { DEFAULT_CANCEL_GRACE_MS, DEFAULT_POOL_OPTIONS, DEFAULT_PREWARM_CODE };\n\n/**\n * Wraps a transport so warmup and pooled execution can borrow it without\n * taking ownership of its lifecycle.\n */\nexport function createBorrowedTransport(\n transport: HostTransport,\n): HostTransport {\n return {\n dispose() {},\n onClose: transport.onClose,\n onError: transport.onError,\n onMessage: transport.onMessage,\n send: transport.send,\n terminate: transport.terminate,\n };\n}\n\n/**\n * Resolves how many pooled shells should be prewarmed from the pool settings.\n */\nexport function getPrewarmCount(pool: ExecutorPoolOptions | undefined): number {\n if (!pool?.prewarm) {\n return 0;\n }\n\n if (typeof pool.prewarm === \"number\") {\n return Math.max(0, Math.min(pool.prewarm, pool.maxSize));\n }\n\n return Math.max(1, Math.min(pool.minSize ?? 1, pool.maxSize));\n}\n\n/**\n * Caps an explicit warmup request to the configured pool boundaries.\n */\nexport function getWarmupTarget(\n count: number | undefined,\n poolOptions: ExecutorPoolOptions,\n): number {\n return Math.max(\n 0,\n Math.min(count ?? poolOptions.minSize ?? 0, poolOptions.maxSize),\n );\n}\n\n/**\n * Returns whether a hosted execution result is safe to return to a pool.\n */\nexport function isReusableResult(result: ExecuteResult): boolean {\n return (\n result.ok || ![\"internal_error\", \"timeout\"].includes(result.error.code)\n );\n}\n\n/**\n * Normalizes a failed warmup result into an actionable host-side error.\n */\nexport function toWarmupError(label: string, result: ExecuteResult): Error {\n if (result.ok) {\n return new Error(`Failed to prewarm pooled ${label}`);\n }\n\n return new Error(\n `Failed to prewarm pooled ${label}: ${result.error.message}`,\n );\n}\n\n/**\n * Runs one transport-backed execution session with resolved runtime limits and\n * a fresh execution identifier.\n */\nexport async function runHostedTransportSession(options: {\n cancelGraceMs: number;\n code: string;\n executorOptions: ExecutorRuntimeOptions;\n onSettled?: (result: ExecuteResult) => Promise<void> | void;\n providers: ResolvedToolProvider[];\n requestOptions?: ExecutionOptions;\n transport: HostTransport;\n}): Promise<ExecuteResult> {\n return await runHostTransportSession({\n cancelGraceMs: options.cancelGraceMs,\n code: options.code,\n executionId: randomUUID(),\n onSettled: options.onSettled,\n providers: options.providers,\n runtimeOptions: resolveExecutorRuntimeOptions(\n options.executorOptions,\n options.requestOptions,\n ),\n signal: options.requestOptions?.signal,\n transport: options.transport,\n });\n}\n\n/**\n * Exercises a set of leased shells with a warmup run and releases each lease\n * according to the warmup result.\n */\nexport async function warmHostedPool<Shell>(options: {\n count: number;\n getTransport: (shell: Shell) => HostTransport;\n label: string;\n onRelease: (shell: Shell, reusable: boolean) => Promise<void>;\n runSession: (\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n ) => Promise<ExecuteResult>;\n shells: Shell[];\n}): Promise<void> {\n const results = await Promise.allSettled(\n options.shells.map(async (shell) => {\n let reusable = false;\n\n try {\n const result = await options.runSession(\n createBorrowedTransport(options.getTransport(shell)),\n DEFAULT_PREWARM_CODE,\n [],\n );\n reusable = result.ok;\n if (!result.ok) {\n throw toWarmupError(options.label, result);\n }\n } finally {\n await options.onRelease(shell, reusable);\n }\n }),\n );\n\n const rejected = results.find((result) => result.status === \"rejected\");\n if (rejected?.status === \"rejected\") {\n throw rejected.reason;\n }\n}\n","import { availableParallelism } from \"node:os\";\nimport { Worker } from \"node:worker_threads\";\n\nimport {\n createResourcePool,\n getNodeTransportExecArgv,\n type HostTransport,\n type ResourcePool,\n type RunnerMessage,\n type TransportCloseReason,\n} from \"@execbox/core/protocol\";\nimport { createTimeoutExecuteResult } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n Executor,\n ExecutorPoolOptions,\n ExecuteResult,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport type { QuickJsWorkerExecutorOptions } from \"../types.ts\";\nimport {\n DEFAULT_CANCEL_GRACE_MS,\n DEFAULT_POOL_OPTIONS,\n createBorrowedTransport,\n getPrewarmCount,\n getWarmupTarget,\n isReusableResult,\n runHostedTransportSession,\n warmHostedPool,\n} from \"./shared.ts\";\n\nconst DEFAULT_POOLED_WORKER_MAX_SIZE = 4;\n\ninterface WorkerShell {\n transport: HostTransport;\n worker: Worker;\n}\n\nfunction resolveWorkerEntryUrl(): URL {\n const extension = import.meta.url.endsWith(\".ts\") ? \".ts\" : \".js\";\n return new URL(`../workerEntry${extension}`, import.meta.url);\n}\n\nfunction createWorkerTransport(worker: Worker): HostTransport {\n let terminated = false;\n let closeReason: TransportCloseReason | undefined;\n const closeHandlers = new Set<(reason?: TransportCloseReason) => void>();\n const errorHandlers = new Set<(error: Error) => void>();\n const messageHandlers = new Set<(message: RunnerMessage) => void>();\n\n const terminateWorker = async () => {\n if (terminated) {\n return;\n }\n\n terminated = true;\n await worker.terminate().catch(() => {});\n };\n\n const notifyClose = (reason: TransportCloseReason) => {\n if (closeReason) {\n return;\n }\n\n closeReason = reason;\n for (const handler of closeHandlers) {\n handler(reason);\n }\n };\n\n const onExit = (code: number) => {\n notifyClose({\n code,\n message: `Worker exited unexpectedly with code ${code}`,\n });\n };\n const onError = (error: Error) => {\n for (const handler of errorHandlers) {\n handler(error);\n }\n };\n const onMessage = (message: unknown) => {\n for (const handler of messageHandlers) {\n handler(message as RunnerMessage);\n }\n };\n\n worker.on(\"exit\", onExit);\n worker.on(\"error\", onError);\n worker.on(\"message\", onMessage);\n\n return {\n dispose: async () => {\n worker.off(\"exit\", onExit);\n worker.off(\"error\", onError);\n worker.off(\"message\", onMessage);\n await terminateWorker();\n },\n onClose: (handler) => {\n closeHandlers.add(handler);\n if (closeReason) {\n queueMicrotask(() => {\n if (closeHandlers.has(handler)) {\n handler(closeReason);\n }\n });\n }\n return () => closeHandlers.delete(handler);\n },\n onError: (handler) => {\n errorHandlers.add(handler);\n return () => errorHandlers.delete(handler);\n },\n onMessage: (handler) => {\n messageHandlers.add(handler);\n return () => messageHandlers.delete(handler);\n },\n send: (message) => {\n worker.postMessage(message);\n },\n terminate: async () => {\n await terminateWorker();\n },\n };\n}\n\nfunction createWorkerShell(options: QuickJsWorkerExecutorOptions): WorkerShell {\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: options.workerResourceLimits,\n });\n\n return {\n transport: createWorkerTransport(worker),\n worker,\n };\n}\n\nfunction getDefaultPoolMaxSize(): number {\n try {\n return Math.max(\n 1,\n Math.min(availableParallelism(), DEFAULT_POOLED_WORKER_MAX_SIZE),\n );\n } catch {\n return 1;\n }\n}\n\nfunction resolvePoolOptions(\n options: QuickJsWorkerExecutorOptions,\n): ExecutorPoolOptions | undefined {\n if (options.mode === \"ephemeral\") {\n return undefined;\n }\n\n return {\n ...DEFAULT_POOL_OPTIONS,\n maxSize: getDefaultPoolMaxSize(),\n ...options.pool,\n };\n}\n\n/**\n * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.\n */\nexport class WorkerHostedQuickJsExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: QuickJsWorkerExecutorOptions;\n private readonly pool: ResourcePool<WorkerShell> | undefined;\n private readonly poolOptions: ExecutorPoolOptions | undefined;\n private readonly warmup: Promise<void> | undefined;\n\n /**\n * Creates a QuickJS executor that launches worker-thread shells on demand.\n */\n constructor(options: QuickJsWorkerExecutorOptions) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n const poolOptions = resolvePoolOptions(options);\n this.poolOptions = poolOptions;\n\n if (poolOptions) {\n this.pool = createResourcePool({\n create: async () => createWorkerShell(options),\n destroy: async (shell) => {\n await shell.transport.dispose();\n },\n idleTimeoutMs: poolOptions.idleTimeoutMs,\n maxSize: poolOptions.maxSize,\n minSize: poolOptions.minSize,\n });\n const prewarmCount = getPrewarmCount(poolOptions);\n if (prewarmCount > 0) {\n this.warmup = this.warmPool(prewarmCount);\n }\n }\n }\n\n /**\n * Disposes any pooled worker-thread shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.pool?.dispose();\n }\n\n /**\n * Prewarms pooled worker-thread shells up to the requested count.\n */\n async prewarm(count?: number): Promise<void> {\n if (!this.pool || !this.poolOptions) {\n return;\n }\n\n const target = getWarmupTarget(count, this.poolOptions);\n if (target <= 0) {\n return;\n }\n\n await this.warmPool(target);\n }\n\n private async runTransportSession(\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n onSettled?: (result: ExecuteResult) => Promise<void> | void,\n ): Promise<ExecuteResult> {\n return await runHostedTransportSession({\n cancelGraceMs: this.cancelGraceMs,\n code,\n executorOptions: this.options,\n onSettled,\n providers,\n requestOptions: options,\n transport,\n });\n }\n\n private async warmPool(count: number): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n await this.pool.prewarm(count);\n\n const leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }> = [];\n try {\n for (let index = 0; index < count; index += 1) {\n leases.push(await this.pool.acquire());\n }\n } catch (error) {\n await Promise.allSettled(\n leases.map(async (lease) => await lease.release(false)),\n );\n throw error;\n }\n\n await warmHostedPool({\n count,\n getTransport: (lease) => lease.value.transport,\n label: \"worker shell\",\n onRelease: async (lease, reusable) => await lease.release(reusable),\n runSession: async (transport, code, providers) =>\n await this.runTransportSession(transport, code, providers),\n shells: leases,\n });\n }\n\n /**\n * Executes guest code in a worker-thread-hosted QuickJS shell.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n await this.warmup;\n if (this.pool) {\n const lease = await this.pool.acquire();\n\n return await this.runTransportSession(\n createBorrowedTransport(lease.value.transport),\n code,\n providers,\n options,\n async (result) => {\n await lease.release(isReusableResult(result));\n },\n );\n }\n\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: this.options.workerResourceLimits,\n });\n\n return await this.runTransportSession(\n createWorkerTransport(worker),\n code,\n providers,\n options,\n );\n }\n}\n","import {\n createTimeoutExecuteResult,\n createToolCallDispatcher,\n extractProviderManifests,\n} from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n Executor,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport { WorkerHostedQuickJsExecutor } from \"./hosted/workerHostedExecutor.ts\";\nimport { runQuickJsSession } from \"./runner/index.ts\";\nimport type {\n QuickJsExecutorOptions,\n QuickJsInlineExecutorOptions,\n QuickJsWorkerExecutorOptions,\n} from \"./types\";\n\nfunction isWorkerOptions(\n options: QuickJsExecutorOptions,\n): options is QuickJsWorkerExecutorOptions {\n return options.host === \"worker\";\n}\n\nfunction getUnsupportedHost(\n options: QuickJsExecutorOptions,\n): string | undefined {\n const host = (options as { host?: unknown }).host;\n if (host === undefined || host === \"inline\" || host === \"worker\") {\n return undefined;\n }\n\n return String(host);\n}\n\n/**\n * QuickJS-backed executor for inline or worker-backed JavaScript runs.\n */\nexport class QuickJsExecutor implements Executor {\n private readonly hostedExecutor: Executor | undefined;\n private readonly options: QuickJsInlineExecutorOptions | undefined;\n\n /**\n * Creates a QuickJS executor with inline QuickJS by default, or a hosted\n * worker shell when `host` is explicitly set.\n */\n constructor(options: QuickJsExecutorOptions = {}) {\n const unsupportedHost = getUnsupportedHost(options);\n if (unsupportedHost !== undefined) {\n throw new Error(\n `QuickJsExecutor host \"${unsupportedHost}\" is no longer supported. ` +\n 'Use host \"worker\" for local hosted execution, or @execbox/remote ' +\n \"for process, container, or VM boundaries.\",\n );\n }\n\n if (isWorkerOptions(options)) {\n this.hostedExecutor = new WorkerHostedQuickJsExecutor(options);\n return;\n }\n\n this.options = options;\n }\n\n /**\n * Disposes any pooled hosted shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.hostedExecutor?.dispose?.();\n }\n\n /**\n * Prewarms pooled hosted shells when the executor is running in worker mode.\n * Inline mode treats this as a no-op.\n */\n async prewarm(count?: number): Promise<void> {\n await this.hostedExecutor?.prewarm?.(count);\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh QuickJS runtime.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (this.hostedExecutor) {\n return await this.hostedExecutor.execute(code, providers, options);\n }\n\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const abortController = new AbortController();\n const onToolCall = createToolCallDispatcher(\n providers,\n abortController.signal,\n );\n const onAbort = () => {\n abortController.abort();\n };\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n return await runQuickJsSession(\n {\n abortController,\n code,\n onToolCall,\n providers: extractProviderManifests(providers),\n },\n {\n ...this.options,\n ...options,\n },\n );\n } finally {\n options.signal?.removeEventListener(\"abort\", onAbort);\n abortController.abort();\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions>","closeReason: TransportCloseReason | undefined","Worker","leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }>","runQuickJsSession"],"sources":["../src/hosted/shared.ts","../src/hosted/workerHostedExecutor.ts","../src/quickjsExecutor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n runHostTransportSession,\n type HostTransport,\n} from \"@execbox/core/protocol\";\nimport type { ExecutorPoolOptions } from \"@execbox/core\";\nimport { resolveExecutorRuntimeOptions } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n ExecutorRuntimeOptions,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\n/**\n * Default grace period before a worker-hosted shell is forcefully terminated.\n */\nconst DEFAULT_CANCEL_GRACE_MS = 25;\n\n/**\n * Default pooling limits shared by worker-hosted QuickJS executors.\n */\nconst DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions> = {\n idleTimeoutMs: 30_000,\n maxSize: 1,\n minSize: 0,\n prewarm: false,\n};\n\n/**\n * Minimal code used to warm a worker shell without touching user providers.\n */\nconst DEFAULT_PREWARM_CODE = \"undefined\";\n\nexport { DEFAULT_CANCEL_GRACE_MS, DEFAULT_POOL_OPTIONS, DEFAULT_PREWARM_CODE };\n\n/**\n * Wraps a transport so warmup and pooled execution can borrow it without\n * taking ownership of its lifecycle.\n */\nexport function createBorrowedTransport(\n transport: HostTransport,\n): HostTransport {\n return {\n dispose() {},\n onClose: transport.onClose,\n onError: transport.onError,\n onMessage: transport.onMessage,\n send: transport.send,\n terminate: transport.terminate,\n };\n}\n\n/**\n * Resolves how many pooled shells should be prewarmed from the pool settings.\n */\nexport function getPrewarmCount(pool: ExecutorPoolOptions | undefined): number {\n if (!pool?.prewarm) {\n return 0;\n }\n\n if (typeof pool.prewarm === \"number\") {\n return Math.max(0, Math.min(pool.prewarm, pool.maxSize));\n }\n\n return Math.max(1, Math.min(pool.minSize ?? 1, pool.maxSize));\n}\n\n/**\n * Caps an explicit warmup request to the configured pool boundaries.\n */\nexport function getWarmupTarget(\n count: number | undefined,\n poolOptions: ExecutorPoolOptions,\n): number {\n return Math.max(\n 0,\n Math.min(count ?? poolOptions.minSize ?? 0, poolOptions.maxSize),\n );\n}\n\n/**\n * Returns whether a hosted execution result is safe to return to a pool.\n */\nexport function isReusableResult(result: ExecuteResult): boolean {\n return (\n result.ok || ![\"internal_error\", \"timeout\"].includes(result.error.code)\n );\n}\n\n/**\n * Normalizes a failed warmup result into an actionable host-side error.\n */\nexport function toWarmupError(label: string, result: ExecuteResult): Error {\n if (result.ok) {\n return new Error(`Failed to prewarm pooled ${label}`);\n }\n\n return new Error(\n `Failed to prewarm pooled ${label}: ${result.error.message}`,\n );\n}\n\n/**\n * Runs one transport-backed execution session with resolved runtime limits and\n * a fresh execution identifier.\n */\nexport async function runHostedTransportSession(options: {\n cancelGraceMs: number;\n code: string;\n executorOptions: ExecutorRuntimeOptions;\n onSettled?: (result: ExecuteResult) => Promise<void> | void;\n providers: ResolvedToolProvider[];\n requestOptions?: ExecutionOptions;\n transport: HostTransport;\n}): Promise<ExecuteResult> {\n return await runHostTransportSession({\n cancelGraceMs: options.cancelGraceMs,\n code: options.code,\n executionId: randomUUID(),\n onSettled: options.onSettled,\n providers: options.providers,\n runtimeOptions: resolveExecutorRuntimeOptions(\n options.executorOptions,\n options.requestOptions,\n ),\n signal: options.requestOptions?.signal,\n transport: options.transport,\n });\n}\n\n/**\n * Exercises a set of leased shells with a warmup run and releases each lease\n * according to the warmup result.\n */\nexport async function warmHostedPool<Shell>(options: {\n count: number;\n getTransport: (shell: Shell) => HostTransport;\n label: string;\n onRelease: (shell: Shell, reusable: boolean) => Promise<void>;\n runSession: (\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n ) => Promise<ExecuteResult>;\n shells: Shell[];\n}): Promise<void> {\n const results = await Promise.allSettled(\n options.shells.map(async (shell) => {\n let reusable = false;\n\n try {\n const result = await options.runSession(\n createBorrowedTransport(options.getTransport(shell)),\n DEFAULT_PREWARM_CODE,\n [],\n );\n reusable = result.ok;\n if (!result.ok) {\n throw toWarmupError(options.label, result);\n }\n } finally {\n await options.onRelease(shell, reusable);\n }\n }),\n );\n\n const rejected = results.find((result) => result.status === \"rejected\");\n if (rejected?.status === \"rejected\") {\n throw rejected.reason;\n }\n}\n","import { availableParallelism } from \"node:os\";\nimport { Worker } from \"node:worker_threads\";\n\nimport {\n createResourcePool,\n getNodeTransportExecArgv,\n type HostTransport,\n type ResourcePool,\n type RunnerMessage,\n type TransportCloseReason,\n} from \"@execbox/core/protocol\";\nimport { createTimeoutExecuteResult } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n Executor,\n ExecutorPoolOptions,\n ExecuteResult,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport type { QuickJsWorkerExecutorOptions } from \"../types.ts\";\nimport {\n DEFAULT_CANCEL_GRACE_MS,\n DEFAULT_POOL_OPTIONS,\n createBorrowedTransport,\n getPrewarmCount,\n getWarmupTarget,\n isReusableResult,\n runHostedTransportSession,\n warmHostedPool,\n} from \"./shared.ts\";\n\nconst DEFAULT_POOLED_WORKER_MAX_SIZE = 4;\n\ninterface WorkerShell {\n transport: HostTransport;\n worker: Worker;\n}\n\nfunction resolveWorkerEntryUrl(): URL {\n const extension = import.meta.url.endsWith(\".ts\") ? \".ts\" : \".js\";\n return new URL(`../workerEntry${extension}`, import.meta.url);\n}\n\nfunction createWorkerTransport(worker: Worker): HostTransport {\n let terminated = false;\n let closeReason: TransportCloseReason | undefined;\n const closeHandlers = new Set<(reason?: TransportCloseReason) => void>();\n const errorHandlers = new Set<(error: Error) => void>();\n const messageHandlers = new Set<(message: RunnerMessage) => void>();\n\n const terminateWorker = async () => {\n if (terminated) {\n return;\n }\n\n terminated = true;\n await worker.terminate().catch(() => {});\n };\n\n const notifyClose = (reason: TransportCloseReason) => {\n if (closeReason) {\n return;\n }\n\n closeReason = reason;\n for (const handler of closeHandlers) {\n handler(reason);\n }\n };\n\n const onExit = (code: number) => {\n notifyClose({\n code,\n message: `Worker exited unexpectedly with code ${code}`,\n });\n };\n const onError = (error: Error) => {\n for (const handler of errorHandlers) {\n handler(error);\n }\n };\n const onMessage = (message: unknown) => {\n for (const handler of messageHandlers) {\n handler(message as RunnerMessage);\n }\n };\n\n worker.on(\"exit\", onExit);\n worker.on(\"error\", onError);\n worker.on(\"message\", onMessage);\n\n return {\n dispose: async () => {\n worker.off(\"exit\", onExit);\n worker.off(\"error\", onError);\n worker.off(\"message\", onMessage);\n await terminateWorker();\n },\n onClose: (handler) => {\n closeHandlers.add(handler);\n if (closeReason) {\n queueMicrotask(() => {\n if (closeHandlers.has(handler)) {\n handler(closeReason);\n }\n });\n }\n return () => closeHandlers.delete(handler);\n },\n onError: (handler) => {\n errorHandlers.add(handler);\n return () => errorHandlers.delete(handler);\n },\n onMessage: (handler) => {\n messageHandlers.add(handler);\n return () => messageHandlers.delete(handler);\n },\n send: (message) => {\n worker.postMessage(message);\n },\n terminate: async () => {\n await terminateWorker();\n },\n };\n}\n\nfunction createWorkerShell(options: QuickJsWorkerExecutorOptions): WorkerShell {\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: options.workerResourceLimits,\n });\n\n return {\n transport: createWorkerTransport(worker),\n worker,\n };\n}\n\nfunction getDefaultPoolMaxSize(): number {\n try {\n return Math.max(\n 1,\n Math.min(availableParallelism(), DEFAULT_POOLED_WORKER_MAX_SIZE),\n );\n } catch {\n return 1;\n }\n}\n\nfunction resolvePoolOptions(\n options: QuickJsWorkerExecutorOptions,\n): ExecutorPoolOptions | undefined {\n if (options.mode === \"ephemeral\") {\n return undefined;\n }\n\n return {\n ...DEFAULT_POOL_OPTIONS,\n maxSize: getDefaultPoolMaxSize(),\n ...options.pool,\n };\n}\n\n/**\n * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.\n */\nexport class WorkerHostedQuickJsExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: QuickJsWorkerExecutorOptions;\n private readonly pool: ResourcePool<WorkerShell> | undefined;\n private readonly poolOptions: ExecutorPoolOptions | undefined;\n private readonly warmup: Promise<void> | undefined;\n\n /**\n * Creates a QuickJS executor that launches worker-thread shells on demand.\n */\n constructor(options: QuickJsWorkerExecutorOptions) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n const poolOptions = resolvePoolOptions(options);\n this.poolOptions = poolOptions;\n\n if (poolOptions) {\n this.pool = createResourcePool({\n create: async () => createWorkerShell(options),\n destroy: async (shell) => {\n await shell.transport.dispose();\n },\n idleTimeoutMs: poolOptions.idleTimeoutMs,\n maxSize: poolOptions.maxSize,\n minSize: poolOptions.minSize,\n });\n const prewarmCount = getPrewarmCount(poolOptions);\n if (prewarmCount > 0) {\n this.warmup = this.warmPool(prewarmCount);\n }\n }\n }\n\n /**\n * Disposes any pooled worker-thread shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.pool?.dispose();\n }\n\n /**\n * Prewarms pooled worker-thread shells up to the requested count.\n */\n async prewarm(count?: number): Promise<void> {\n if (!this.pool || !this.poolOptions) {\n return;\n }\n\n const target = getWarmupTarget(count, this.poolOptions);\n if (target <= 0) {\n return;\n }\n\n await this.warmPool(target);\n }\n\n private async runTransportSession(\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n onSettled?: (result: ExecuteResult) => Promise<void> | void,\n ): Promise<ExecuteResult> {\n return await runHostedTransportSession({\n cancelGraceMs: this.cancelGraceMs,\n code,\n executorOptions: this.options,\n onSettled,\n providers,\n requestOptions: options,\n transport,\n });\n }\n\n private async warmPool(count: number): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n await this.pool.prewarm(count);\n\n const leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }> = [];\n try {\n for (let index = 0; index < count; index += 1) {\n leases.push(await this.pool.acquire());\n }\n } catch (error) {\n await Promise.allSettled(\n leases.map(async (lease) => await lease.release(false)),\n );\n throw error;\n }\n\n await warmHostedPool({\n count,\n getTransport: (lease) => lease.value.transport,\n label: \"worker shell\",\n onRelease: async (lease, reusable) => await lease.release(reusable),\n runSession: async (transport, code, providers) =>\n await this.runTransportSession(transport, code, providers),\n shells: leases,\n });\n }\n\n /**\n * Executes guest code in a worker-thread-hosted QuickJS shell.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n await this.warmup;\n if (this.pool) {\n const lease = await this.pool.acquire();\n\n return await this.runTransportSession(\n createBorrowedTransport(lease.value.transport),\n code,\n providers,\n options,\n async (result) => {\n await lease.release(isReusableResult(result));\n },\n );\n }\n\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: this.options.workerResourceLimits,\n });\n\n return await this.runTransportSession(\n createWorkerTransport(worker),\n code,\n providers,\n options,\n );\n }\n}\n","import {\n createTimeoutExecuteResult,\n createToolCallDispatcher,\n extractProviderManifests,\n} from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n Executor,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport { WorkerHostedQuickJsExecutor } from \"./hosted/workerHostedExecutor.ts\";\nimport { runQuickJsSession } from \"./runner/index.ts\";\nimport type {\n QuickJsExecutorOptions,\n QuickJsInlineExecutorOptions,\n QuickJsWorkerExecutorOptions,\n} from \"./types\";\n\nfunction isWorkerOptions(\n options: QuickJsExecutorOptions,\n): options is QuickJsWorkerExecutorOptions {\n return options.host === \"worker\";\n}\n\nfunction getUnsupportedHost(\n options: QuickJsExecutorOptions,\n): string | undefined {\n const host = (options as { host?: unknown }).host;\n if (host === undefined || host === \"inline\" || host === \"worker\") {\n return undefined;\n }\n\n return String(host);\n}\n\n/**\n * QuickJS-backed executor for inline or worker-backed JavaScript runs.\n */\nexport class QuickJsExecutor implements Executor {\n private readonly hostedExecutor: Executor | undefined;\n private readonly options: QuickJsInlineExecutorOptions | undefined;\n\n /**\n * Creates a QuickJS executor with inline QuickJS by default, or a hosted\n * worker shell when `host` is explicitly set.\n */\n constructor(options: QuickJsExecutorOptions = {}) {\n const unsupportedHost = getUnsupportedHost(options);\n if (unsupportedHost !== undefined) {\n throw new Error(\n `QuickJsExecutor host \"${unsupportedHost}\" is no longer supported. ` +\n 'Use host \"worker\" for local hosted execution.',\n );\n }\n\n if (isWorkerOptions(options)) {\n this.hostedExecutor = new WorkerHostedQuickJsExecutor(options);\n return;\n }\n\n this.options = options;\n }\n\n /**\n * Disposes any pooled hosted shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.hostedExecutor?.dispose?.();\n }\n\n /**\n * Prewarms pooled hosted shells when the executor is running in worker mode.\n * Inline mode treats this as a no-op.\n */\n async prewarm(count?: number): Promise<void> {\n await this.hostedExecutor?.prewarm?.(count);\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh QuickJS runtime.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (this.hostedExecutor) {\n return await this.hostedExecutor.execute(code, providers, options);\n }\n\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const abortController = new AbortController();\n const onToolCall = createToolCallDispatcher(\n providers,\n abortController.signal,\n );\n const onAbort = () => {\n abortController.abort();\n };\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n return await runQuickJsSession(\n {\n abortController,\n code,\n onToolCall,\n providers: extractProviderManifests(providers),\n },\n {\n ...this.options,\n ...options,\n },\n );\n } finally {\n options.signal?.removeEventListener(\"abort\", onAbort);\n abortController.abort();\n }\n }\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -2,11 +2,59 @@
2
2
  * @packageDocumentation
3
3
  * Public TypeScript declarations for this package entrypoint.
4
4
  */
5
- import { a as QuickJsWorkerExecutorOptions, i as QuickJsInlineExecutorOptions, n as QuickJsExecutorOptions, o as WorkerResourceLimits, r as QuickJsHostedMode, t as QuickJsExecutorHost } from "./types-C-XfFJ7u.cjs";
6
- import { ExecuteResult, ExecutionOptions, Executor, ResolvedToolProvider } from "@execbox/core";
5
+ import { ExecuteResult, ExecutionOptions, Executor, ExecutorPoolOptions, ExecutorRuntimeOptions, ResolvedToolProvider } from "@execbox/core";
7
6
 
8
- //#region src/quickjsExecutor.d.ts
7
+ //#region src/types.d.ts
9
8
 
9
+ /**
10
+ * Host boundary options available to the QuickJS executor.
11
+ */
12
+ type QuickJsExecutorHost = "inline" | "worker";
13
+ /**
14
+ * Lifecycle modes for worker-hosted QuickJS shells.
15
+ */
16
+ type QuickJsHostedMode = "pooled" | "ephemeral";
17
+ /**
18
+ * Optional V8 heap limits used only as a backstop for worker thread safety.
19
+ */
20
+ interface WorkerResourceLimits {
21
+ /** Maximum size of the old generation heap in megabytes. */
22
+ maxOldGenerationSizeMb?: number;
23
+ /** Maximum size of the young generation heap in megabytes. */
24
+ maxYoungGenerationSizeMb?: number;
25
+ /** Maximum V8 stack size in megabytes. */
26
+ stackSizeMb?: number;
27
+ }
28
+ /**
29
+ * Options for constructing an inline QuickJS executor.
30
+ */
31
+ interface QuickJsInlineExecutorOptions extends ExecutorRuntimeOptions {
32
+ /** Uses inline QuickJS execution inside the current process. */
33
+ host?: "inline";
34
+ /** Optional QuickJS module loader override for tests or custom builds. */
35
+ loadModule?: () => Promise<unknown> | unknown;
36
+ }
37
+ /**
38
+ * Options for constructing a worker-backed QuickJS executor.
39
+ */
40
+ interface QuickJsWorkerExecutorOptions extends ExecutorRuntimeOptions {
41
+ /** Uses a worker thread to host each QuickJS runtime. */
42
+ host: "worker";
43
+ /** Time to wait before forcefully tearing down a hung worker shell. */
44
+ cancelGraceMs?: number;
45
+ /** Whether to reuse worker shells or spawn a fresh one per execution. */
46
+ mode?: QuickJsHostedMode;
47
+ /** Pool sizing and idle-eviction settings for pooled worker shells. */
48
+ pool?: ExecutorPoolOptions;
49
+ /** Optional worker thread V8 limits used as a coarse safety backstop. */
50
+ workerResourceLimits?: WorkerResourceLimits;
51
+ }
52
+ /**
53
+ * Options for constructing a QuickJS executor.
54
+ */
55
+ type QuickJsExecutorOptions = QuickJsInlineExecutorOptions | QuickJsWorkerExecutorOptions;
56
+ //#endregion
57
+ //#region src/quickjsExecutor.d.ts
10
58
  /**
11
59
  * QuickJS-backed executor for inline or worker-backed JavaScript runs.
12
60
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/quickjsExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AAwCA,CAAA,CAAA;AAQuB,OAAA,CAAA,KAAA,CARV,eAAA,CAAA,UAAA,CAA2B,QAQjB,CAAA;EAqBJ,OAAA,CAAA,QAAA,CAAA,cAAA;EAQc,OAAA,CAAA,QAAA,CAAA,OAAA;EASlB,CAAA,CAAA;;;;EA9CyB,WAAA,CAAA,OAAA,CAAA,CAAA,CAQjB,sBARiB,CAAA;EAAQ,CAAA,CAAA;;;aA6B7B;;;;;2BAQc;;;;mCASlB,kCACF,mBACR,QAAQ"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/quickjsExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAQA,CAAA,CAAA;AAKY,IAAA,CALA,mBAAA,CAAA,CAAA,CAKiB,CAAA,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA,MAAA,CAAA;AAK7B,CAAA,CAAA;AAYA,CAAA,CAAA,CAAA,SAAA,CAAA,KAAA,CAAA,GAAA,CAAA,MAAA,CAAA,MAAA,CAAA,OAAA,CAAA,MAAA;AAWA,CAAA,CAAA;AAQS,IAAA,CApCG,iBAAA,CAAA,CAAA,CAoCH,CAAA,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA,SAAA,CAAA;;;;AARmE,SAAA,CAvB3D,oBAAA,CAuB2D;EAoBhE,CAAA,CAAA,CAAA,CAAA,OAAA,CAAA,IAAA,CAAA,EAAA,CAAA,GAAA,CAAA,GAAA,CAAA,UAAA,CAAA,IAAA,CAAA,EAAA,CAAA,SAAA,CAAA,CAAA,CAAA;;;;ECrBC,CAAA,CAAA,CAAA,CAAA,OAAA,CAAA,EAAA,CAAA,KAAA,CAAA,IAAA,CAAA,EAAA,CAAA,SAAA,CAAA,CAAA,CAAA;EAQU,WAAA,CAAA,CAAA,CAAA,MAAA;;;;;AAuCV,SAAA,CDzDI,4BAAA,CAAA,OAAA,CAAqC,sBCyDzC,CAAA;EAAR,CAAA,CAAA,CAAA,CAAA,IAAA,CAAA,MAAA,CAAA,OAAA,CAAA,SAAA,CAAA,MAAA,CAAA,GAAA,CAAA,OAAA,CAAA,OAAA,CAAA,CAAA,CAAA;EA/CmC,IAAA,CAAA,CAAA,CAAA,CAAA,MAAA,CAAA;EAAQ,CAAA,CAAA,CAAA,CAAA,QAAA,CAAA,OAAA,CAAA,MAAA,CAAA,MAAA,CAAA,QAAA,CAAA,GAAA,CAAA,KAAA,CAAA,EAAA,CAAA,MAAA,CAAA,MAAA,CAAA,CAAA,CAAA;qBDL3B;;;;;UAMJ,4BAAA,CAAA,OAAA,CAAqC;;;;;;SAQ7C;;SAGA;;yBAGgB;;;;;KAMb,sBAAA,CAAA,CAAA,CACR,+BACA;;;;AAvDJ,CAAA,CAAA,CAAA,OAAA,CAAA,MAAA,CAAA,QAAA,CAAA,GAAA,CAAA,MAAA,CAAA,EAAA,CAAA,MAAA,CAAA,MAAA,CAAA,UAAA,CAAA,IAAA;AAKA,CAAA,CAAA;AAKiB,OAAA,CAAA,KAAA,CCsBJ,eAAA,CAAA,UAAA,CAA2B,QDtBH,CAAA;EAYpB,OAAA,CAAA,QAAA,CAAA,cAA6B;EAW7B,OAAA,CAAA,QAAA,CAAA,OAAA;EAQR,CAAA,CAAA;;;;EARmE,WAAA,CAAA,OAAA,CAAA,CAAA,CCOrD,sBDPqD,CAAA;EAoBhE,CAAA,CAAA;;;aCOO;EA5BN,CAAA,CAAA;;;;EA6CE,OAAA,CAAA,KAAA,CAAA,CAAA,CAAA,MAAA,CAAA,CAAA,CATkB,OASlB,CAAA,IAAA,CAAA;EACF,CAAA,CAAA;;;EA9C2B,OAAA,CAAA,IAAA,CAAA,CAAA,MAAA,CAAA,CAAA,SAAA,CAAA,CA6CzB,oBA7CyB,CAAA,CAAA,CAAA,CAAA,OAAA,CAAA,CAAA,CA8C3B,gBA9C2B,CAAA,CAAA,CA+CnC,OA/CmC,CA+C3B,aA/C2B,CAAA"}
package/dist/index.d.ts CHANGED
@@ -2,11 +2,59 @@
2
2
  * @packageDocumentation
3
3
  * Public TypeScript declarations for this package entrypoint.
4
4
  */
5
- import { a as QuickJsWorkerExecutorOptions, i as QuickJsInlineExecutorOptions, n as QuickJsExecutorOptions, o as WorkerResourceLimits, r as QuickJsHostedMode, t as QuickJsExecutorHost } from "./types-CE7SvejR.js";
6
- import { ExecuteResult, ExecutionOptions, Executor, ResolvedToolProvider } from "@execbox/core";
5
+ import { ExecuteResult, ExecutionOptions, Executor, ExecutorPoolOptions, ExecutorRuntimeOptions, ResolvedToolProvider } from "@execbox/core";
7
6
 
8
- //#region src/quickjsExecutor.d.ts
7
+ //#region src/types.d.ts
9
8
 
9
+ /**
10
+ * Host boundary options available to the QuickJS executor.
11
+ */
12
+ type QuickJsExecutorHost = "inline" | "worker";
13
+ /**
14
+ * Lifecycle modes for worker-hosted QuickJS shells.
15
+ */
16
+ type QuickJsHostedMode = "pooled" | "ephemeral";
17
+ /**
18
+ * Optional V8 heap limits used only as a backstop for worker thread safety.
19
+ */
20
+ interface WorkerResourceLimits {
21
+ /** Maximum size of the old generation heap in megabytes. */
22
+ maxOldGenerationSizeMb?: number;
23
+ /** Maximum size of the young generation heap in megabytes. */
24
+ maxYoungGenerationSizeMb?: number;
25
+ /** Maximum V8 stack size in megabytes. */
26
+ stackSizeMb?: number;
27
+ }
28
+ /**
29
+ * Options for constructing an inline QuickJS executor.
30
+ */
31
+ interface QuickJsInlineExecutorOptions extends ExecutorRuntimeOptions {
32
+ /** Uses inline QuickJS execution inside the current process. */
33
+ host?: "inline";
34
+ /** Optional QuickJS module loader override for tests or custom builds. */
35
+ loadModule?: () => Promise<unknown> | unknown;
36
+ }
37
+ /**
38
+ * Options for constructing a worker-backed QuickJS executor.
39
+ */
40
+ interface QuickJsWorkerExecutorOptions extends ExecutorRuntimeOptions {
41
+ /** Uses a worker thread to host each QuickJS runtime. */
42
+ host: "worker";
43
+ /** Time to wait before forcefully tearing down a hung worker shell. */
44
+ cancelGraceMs?: number;
45
+ /** Whether to reuse worker shells or spawn a fresh one per execution. */
46
+ mode?: QuickJsHostedMode;
47
+ /** Pool sizing and idle-eviction settings for pooled worker shells. */
48
+ pool?: ExecutorPoolOptions;
49
+ /** Optional worker thread V8 limits used as a coarse safety backstop. */
50
+ workerResourceLimits?: WorkerResourceLimits;
51
+ }
52
+ /**
53
+ * Options for constructing a QuickJS executor.
54
+ */
55
+ type QuickJsExecutorOptions = QuickJsInlineExecutorOptions | QuickJsWorkerExecutorOptions;
56
+ //#endregion
57
+ //#region src/quickjsExecutor.d.ts
10
58
  /**
11
59
  * QuickJS-backed executor for inline or worker-backed JavaScript runs.
12
60
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/quickjsExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AAwCA,CAAA,CAAA;AAQuB,OAAA,CAAA,KAAA,CARV,eAAA,CAAA,UAAA,CAA2B,QAQjB,CAAA;EAqBJ,OAAA,CAAA,QAAA,CAAA,cAAA;EAQc,OAAA,CAAA,QAAA,CAAA,OAAA;EASlB,CAAA,CAAA;;;;EA9CyB,WAAA,CAAA,OAAA,CAAA,CAAA,CAQjB,sBARiB,CAAA;EAAQ,CAAA,CAAA;;;aA6B7B;;;;;2BAQc;;;;mCASlB,kCACF,mBACR,QAAQ"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/quickjsExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAQA,CAAA,CAAA;AAKY,IAAA,CALA,mBAAA,CAAA,CAAA,CAKiB,CAAA,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA,MAAA,CAAA;AAK7B,CAAA,CAAA;AAYA,CAAA,CAAA,CAAA,SAAA,CAAA,KAAA,CAAA,GAAA,CAAA,MAAA,CAAA,MAAA,CAAA,OAAA,CAAA,MAAA;AAWA,CAAA,CAAA;AAQS,IAAA,CApCG,iBAAA,CAAA,CAAA,CAoCH,CAAA,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA,SAAA,CAAA;;;;AARmE,SAAA,CAvB3D,oBAAA,CAuB2D;EAoBhE,CAAA,CAAA,CAAA,CAAA,OAAA,CAAA,IAAA,CAAA,EAAA,CAAA,GAAA,CAAA,GAAA,CAAA,UAAA,CAAA,IAAA,CAAA,EAAA,CAAA,SAAA,CAAA,CAAA,CAAA;;;;ECrBC,CAAA,CAAA,CAAA,CAAA,OAAA,CAAA,EAAA,CAAA,KAAA,CAAA,IAAA,CAAA,EAAA,CAAA,SAAA,CAAA,CAAA,CAAA;EAQU,WAAA,CAAA,CAAA,CAAA,MAAA;;;;;AAuCV,SAAA,CDzDI,4BAAA,CAAA,OAAA,CAAqC,sBCyDzC,CAAA;EAAR,CAAA,CAAA,CAAA,CAAA,IAAA,CAAA,MAAA,CAAA,OAAA,CAAA,SAAA,CAAA,MAAA,CAAA,GAAA,CAAA,OAAA,CAAA,OAAA,CAAA,CAAA,CAAA;EA/CmC,IAAA,CAAA,CAAA,CAAA,CAAA,MAAA,CAAA;EAAQ,CAAA,CAAA,CAAA,CAAA,QAAA,CAAA,OAAA,CAAA,MAAA,CAAA,MAAA,CAAA,QAAA,CAAA,GAAA,CAAA,KAAA,CAAA,EAAA,CAAA,MAAA,CAAA,MAAA,CAAA,CAAA,CAAA;qBDL3B;;;;;UAMJ,4BAAA,CAAA,OAAA,CAAqC;;;;;;SAQ7C;;SAGA;;yBAGgB;;;;;KAMb,sBAAA,CAAA,CAAA,CACR,+BACA;;;;AAvDJ,CAAA,CAAA,CAAA,OAAA,CAAA,MAAA,CAAA,QAAA,CAAA,GAAA,CAAA,MAAA,CAAA,EAAA,CAAA,MAAA,CAAA,MAAA,CAAA,UAAA,CAAA,IAAA;AAKA,CAAA,CAAA;AAKiB,OAAA,CAAA,KAAA,CCsBJ,eAAA,CAAA,UAAA,CAA2B,QDtBH,CAAA;EAYpB,OAAA,CAAA,QAAA,CAAA,cAA6B;EAW7B,OAAA,CAAA,QAAA,CAAA,OAAA;EAQR,CAAA,CAAA;;;;EARmE,WAAA,CAAA,OAAA,CAAA,CAAA,CCOrD,sBDPqD,CAAA;EAoBhE,CAAA,CAAA;;;aCOO;EA5BN,CAAA,CAAA;;;;EA6CE,OAAA,CAAA,KAAA,CAAA,CAAA,CAAA,MAAA,CAAA,CAAA,CATkB,OASlB,CAAA,IAAA,CAAA;EACF,CAAA,CAAA;;;EA9C2B,OAAA,CAAA,IAAA,CAAA,CAAA,MAAA,CAAA,CAAA,SAAA,CAAA,CA6CzB,oBA7CyB,CAAA,CAAA,CAAA,CAAA,OAAA,CAAA,CAAA,CA8C3B,gBA9C2B,CAAA,CAAA,CA+CnC,OA/CmC,CA+C3B,aA/C2B,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as runQuickJsSession } from "./runner-oZXbguX3.js";
1
+ import { t as runQuickJsSession } from "./runner-DJd4Bh8V.js";
2
2
  import { createTimeoutExecuteResult, createToolCallDispatcher, extractProviderManifests, resolveExecutorRuntimeOptions } from "@execbox/core/runtime";
3
3
  import { availableParallelism } from "node:os";
4
4
  import { Worker } from "node:worker_threads";
@@ -309,7 +309,7 @@ var QuickJsExecutor = class {
309
309
  */
310
310
  constructor(options = {}) {
311
311
  const unsupportedHost = getUnsupportedHost(options);
312
- if (unsupportedHost !== void 0) throw new Error(`QuickJsExecutor host "${unsupportedHost}" is no longer supported. Use host "worker" for local hosted execution, or @execbox/remote for process, container, or VM boundaries.`);
312
+ if (unsupportedHost !== void 0) throw new Error(`QuickJsExecutor host "${unsupportedHost}" is no longer supported. Use host "worker" for local hosted execution.`);
313
313
  if (isWorkerOptions(options)) {
314
314
  this.hostedExecutor = new WorkerHostedQuickJsExecutor(options);
315
315
  return;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions>","closeReason: TransportCloseReason | undefined","leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }>"],"sources":["../src/hosted/shared.ts","../src/hosted/workerHostedExecutor.ts","../src/quickjsExecutor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n runHostTransportSession,\n type HostTransport,\n} from \"@execbox/core/protocol\";\nimport type { ExecutorPoolOptions } from \"@execbox/core\";\nimport { resolveExecutorRuntimeOptions } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n ExecutorRuntimeOptions,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\n/**\n * Default grace period before a worker-hosted shell is forcefully terminated.\n */\nconst DEFAULT_CANCEL_GRACE_MS = 25;\n\n/**\n * Default pooling limits shared by worker-hosted QuickJS executors.\n */\nconst DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions> = {\n idleTimeoutMs: 30_000,\n maxSize: 1,\n minSize: 0,\n prewarm: false,\n};\n\n/**\n * Minimal code used to warm a worker shell without touching user providers.\n */\nconst DEFAULT_PREWARM_CODE = \"undefined\";\n\nexport { DEFAULT_CANCEL_GRACE_MS, DEFAULT_POOL_OPTIONS, DEFAULT_PREWARM_CODE };\n\n/**\n * Wraps a transport so warmup and pooled execution can borrow it without\n * taking ownership of its lifecycle.\n */\nexport function createBorrowedTransport(\n transport: HostTransport,\n): HostTransport {\n return {\n dispose() {},\n onClose: transport.onClose,\n onError: transport.onError,\n onMessage: transport.onMessage,\n send: transport.send,\n terminate: transport.terminate,\n };\n}\n\n/**\n * Resolves how many pooled shells should be prewarmed from the pool settings.\n */\nexport function getPrewarmCount(pool: ExecutorPoolOptions | undefined): number {\n if (!pool?.prewarm) {\n return 0;\n }\n\n if (typeof pool.prewarm === \"number\") {\n return Math.max(0, Math.min(pool.prewarm, pool.maxSize));\n }\n\n return Math.max(1, Math.min(pool.minSize ?? 1, pool.maxSize));\n}\n\n/**\n * Caps an explicit warmup request to the configured pool boundaries.\n */\nexport function getWarmupTarget(\n count: number | undefined,\n poolOptions: ExecutorPoolOptions,\n): number {\n return Math.max(\n 0,\n Math.min(count ?? poolOptions.minSize ?? 0, poolOptions.maxSize),\n );\n}\n\n/**\n * Returns whether a hosted execution result is safe to return to a pool.\n */\nexport function isReusableResult(result: ExecuteResult): boolean {\n return (\n result.ok || ![\"internal_error\", \"timeout\"].includes(result.error.code)\n );\n}\n\n/**\n * Normalizes a failed warmup result into an actionable host-side error.\n */\nexport function toWarmupError(label: string, result: ExecuteResult): Error {\n if (result.ok) {\n return new Error(`Failed to prewarm pooled ${label}`);\n }\n\n return new Error(\n `Failed to prewarm pooled ${label}: ${result.error.message}`,\n );\n}\n\n/**\n * Runs one transport-backed execution session with resolved runtime limits and\n * a fresh execution identifier.\n */\nexport async function runHostedTransportSession(options: {\n cancelGraceMs: number;\n code: string;\n executorOptions: ExecutorRuntimeOptions;\n onSettled?: (result: ExecuteResult) => Promise<void> | void;\n providers: ResolvedToolProvider[];\n requestOptions?: ExecutionOptions;\n transport: HostTransport;\n}): Promise<ExecuteResult> {\n return await runHostTransportSession({\n cancelGraceMs: options.cancelGraceMs,\n code: options.code,\n executionId: randomUUID(),\n onSettled: options.onSettled,\n providers: options.providers,\n runtimeOptions: resolveExecutorRuntimeOptions(\n options.executorOptions,\n options.requestOptions,\n ),\n signal: options.requestOptions?.signal,\n transport: options.transport,\n });\n}\n\n/**\n * Exercises a set of leased shells with a warmup run and releases each lease\n * according to the warmup result.\n */\nexport async function warmHostedPool<Shell>(options: {\n count: number;\n getTransport: (shell: Shell) => HostTransport;\n label: string;\n onRelease: (shell: Shell, reusable: boolean) => Promise<void>;\n runSession: (\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n ) => Promise<ExecuteResult>;\n shells: Shell[];\n}): Promise<void> {\n const results = await Promise.allSettled(\n options.shells.map(async (shell) => {\n let reusable = false;\n\n try {\n const result = await options.runSession(\n createBorrowedTransport(options.getTransport(shell)),\n DEFAULT_PREWARM_CODE,\n [],\n );\n reusable = result.ok;\n if (!result.ok) {\n throw toWarmupError(options.label, result);\n }\n } finally {\n await options.onRelease(shell, reusable);\n }\n }),\n );\n\n const rejected = results.find((result) => result.status === \"rejected\");\n if (rejected?.status === \"rejected\") {\n throw rejected.reason;\n }\n}\n","import { availableParallelism } from \"node:os\";\nimport { Worker } from \"node:worker_threads\";\n\nimport {\n createResourcePool,\n getNodeTransportExecArgv,\n type HostTransport,\n type ResourcePool,\n type RunnerMessage,\n type TransportCloseReason,\n} from \"@execbox/core/protocol\";\nimport { createTimeoutExecuteResult } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n Executor,\n ExecutorPoolOptions,\n ExecuteResult,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport type { QuickJsWorkerExecutorOptions } from \"../types.ts\";\nimport {\n DEFAULT_CANCEL_GRACE_MS,\n DEFAULT_POOL_OPTIONS,\n createBorrowedTransport,\n getPrewarmCount,\n getWarmupTarget,\n isReusableResult,\n runHostedTransportSession,\n warmHostedPool,\n} from \"./shared.ts\";\n\nconst DEFAULT_POOLED_WORKER_MAX_SIZE = 4;\n\ninterface WorkerShell {\n transport: HostTransport;\n worker: Worker;\n}\n\nfunction resolveWorkerEntryUrl(): URL {\n const extension = import.meta.url.endsWith(\".ts\") ? \".ts\" : \".js\";\n return new URL(`../workerEntry${extension}`, import.meta.url);\n}\n\nfunction createWorkerTransport(worker: Worker): HostTransport {\n let terminated = false;\n let closeReason: TransportCloseReason | undefined;\n const closeHandlers = new Set<(reason?: TransportCloseReason) => void>();\n const errorHandlers = new Set<(error: Error) => void>();\n const messageHandlers = new Set<(message: RunnerMessage) => void>();\n\n const terminateWorker = async () => {\n if (terminated) {\n return;\n }\n\n terminated = true;\n await worker.terminate().catch(() => {});\n };\n\n const notifyClose = (reason: TransportCloseReason) => {\n if (closeReason) {\n return;\n }\n\n closeReason = reason;\n for (const handler of closeHandlers) {\n handler(reason);\n }\n };\n\n const onExit = (code: number) => {\n notifyClose({\n code,\n message: `Worker exited unexpectedly with code ${code}`,\n });\n };\n const onError = (error: Error) => {\n for (const handler of errorHandlers) {\n handler(error);\n }\n };\n const onMessage = (message: unknown) => {\n for (const handler of messageHandlers) {\n handler(message as RunnerMessage);\n }\n };\n\n worker.on(\"exit\", onExit);\n worker.on(\"error\", onError);\n worker.on(\"message\", onMessage);\n\n return {\n dispose: async () => {\n worker.off(\"exit\", onExit);\n worker.off(\"error\", onError);\n worker.off(\"message\", onMessage);\n await terminateWorker();\n },\n onClose: (handler) => {\n closeHandlers.add(handler);\n if (closeReason) {\n queueMicrotask(() => {\n if (closeHandlers.has(handler)) {\n handler(closeReason);\n }\n });\n }\n return () => closeHandlers.delete(handler);\n },\n onError: (handler) => {\n errorHandlers.add(handler);\n return () => errorHandlers.delete(handler);\n },\n onMessage: (handler) => {\n messageHandlers.add(handler);\n return () => messageHandlers.delete(handler);\n },\n send: (message) => {\n worker.postMessage(message);\n },\n terminate: async () => {\n await terminateWorker();\n },\n };\n}\n\nfunction createWorkerShell(options: QuickJsWorkerExecutorOptions): WorkerShell {\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: options.workerResourceLimits,\n });\n\n return {\n transport: createWorkerTransport(worker),\n worker,\n };\n}\n\nfunction getDefaultPoolMaxSize(): number {\n try {\n return Math.max(\n 1,\n Math.min(availableParallelism(), DEFAULT_POOLED_WORKER_MAX_SIZE),\n );\n } catch {\n return 1;\n }\n}\n\nfunction resolvePoolOptions(\n options: QuickJsWorkerExecutorOptions,\n): ExecutorPoolOptions | undefined {\n if (options.mode === \"ephemeral\") {\n return undefined;\n }\n\n return {\n ...DEFAULT_POOL_OPTIONS,\n maxSize: getDefaultPoolMaxSize(),\n ...options.pool,\n };\n}\n\n/**\n * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.\n */\nexport class WorkerHostedQuickJsExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: QuickJsWorkerExecutorOptions;\n private readonly pool: ResourcePool<WorkerShell> | undefined;\n private readonly poolOptions: ExecutorPoolOptions | undefined;\n private readonly warmup: Promise<void> | undefined;\n\n /**\n * Creates a QuickJS executor that launches worker-thread shells on demand.\n */\n constructor(options: QuickJsWorkerExecutorOptions) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n const poolOptions = resolvePoolOptions(options);\n this.poolOptions = poolOptions;\n\n if (poolOptions) {\n this.pool = createResourcePool({\n create: async () => createWorkerShell(options),\n destroy: async (shell) => {\n await shell.transport.dispose();\n },\n idleTimeoutMs: poolOptions.idleTimeoutMs,\n maxSize: poolOptions.maxSize,\n minSize: poolOptions.minSize,\n });\n const prewarmCount = getPrewarmCount(poolOptions);\n if (prewarmCount > 0) {\n this.warmup = this.warmPool(prewarmCount);\n }\n }\n }\n\n /**\n * Disposes any pooled worker-thread shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.pool?.dispose();\n }\n\n /**\n * Prewarms pooled worker-thread shells up to the requested count.\n */\n async prewarm(count?: number): Promise<void> {\n if (!this.pool || !this.poolOptions) {\n return;\n }\n\n const target = getWarmupTarget(count, this.poolOptions);\n if (target <= 0) {\n return;\n }\n\n await this.warmPool(target);\n }\n\n private async runTransportSession(\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n onSettled?: (result: ExecuteResult) => Promise<void> | void,\n ): Promise<ExecuteResult> {\n return await runHostedTransportSession({\n cancelGraceMs: this.cancelGraceMs,\n code,\n executorOptions: this.options,\n onSettled,\n providers,\n requestOptions: options,\n transport,\n });\n }\n\n private async warmPool(count: number): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n await this.pool.prewarm(count);\n\n const leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }> = [];\n try {\n for (let index = 0; index < count; index += 1) {\n leases.push(await this.pool.acquire());\n }\n } catch (error) {\n await Promise.allSettled(\n leases.map(async (lease) => await lease.release(false)),\n );\n throw error;\n }\n\n await warmHostedPool({\n count,\n getTransport: (lease) => lease.value.transport,\n label: \"worker shell\",\n onRelease: async (lease, reusable) => await lease.release(reusable),\n runSession: async (transport, code, providers) =>\n await this.runTransportSession(transport, code, providers),\n shells: leases,\n });\n }\n\n /**\n * Executes guest code in a worker-thread-hosted QuickJS shell.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n await this.warmup;\n if (this.pool) {\n const lease = await this.pool.acquire();\n\n return await this.runTransportSession(\n createBorrowedTransport(lease.value.transport),\n code,\n providers,\n options,\n async (result) => {\n await lease.release(isReusableResult(result));\n },\n );\n }\n\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: this.options.workerResourceLimits,\n });\n\n return await this.runTransportSession(\n createWorkerTransport(worker),\n code,\n providers,\n options,\n );\n }\n}\n","import {\n createTimeoutExecuteResult,\n createToolCallDispatcher,\n extractProviderManifests,\n} from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n Executor,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport { WorkerHostedQuickJsExecutor } from \"./hosted/workerHostedExecutor.ts\";\nimport { runQuickJsSession } from \"./runner/index.ts\";\nimport type {\n QuickJsExecutorOptions,\n QuickJsInlineExecutorOptions,\n QuickJsWorkerExecutorOptions,\n} from \"./types\";\n\nfunction isWorkerOptions(\n options: QuickJsExecutorOptions,\n): options is QuickJsWorkerExecutorOptions {\n return options.host === \"worker\";\n}\n\nfunction getUnsupportedHost(\n options: QuickJsExecutorOptions,\n): string | undefined {\n const host = (options as { host?: unknown }).host;\n if (host === undefined || host === \"inline\" || host === \"worker\") {\n return undefined;\n }\n\n return String(host);\n}\n\n/**\n * QuickJS-backed executor for inline or worker-backed JavaScript runs.\n */\nexport class QuickJsExecutor implements Executor {\n private readonly hostedExecutor: Executor | undefined;\n private readonly options: QuickJsInlineExecutorOptions | undefined;\n\n /**\n * Creates a QuickJS executor with inline QuickJS by default, or a hosted\n * worker shell when `host` is explicitly set.\n */\n constructor(options: QuickJsExecutorOptions = {}) {\n const unsupportedHost = getUnsupportedHost(options);\n if (unsupportedHost !== undefined) {\n throw new Error(\n `QuickJsExecutor host \"${unsupportedHost}\" is no longer supported. ` +\n 'Use host \"worker\" for local hosted execution, or @execbox/remote ' +\n \"for process, container, or VM boundaries.\",\n );\n }\n\n if (isWorkerOptions(options)) {\n this.hostedExecutor = new WorkerHostedQuickJsExecutor(options);\n return;\n }\n\n this.options = options;\n }\n\n /**\n * Disposes any pooled hosted shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.hostedExecutor?.dispose?.();\n }\n\n /**\n * Prewarms pooled hosted shells when the executor is running in worker mode.\n * Inline mode treats this as a no-op.\n */\n async prewarm(count?: number): Promise<void> {\n await this.hostedExecutor?.prewarm?.(count);\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh QuickJS runtime.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (this.hostedExecutor) {\n return await this.hostedExecutor.execute(code, providers, options);\n }\n\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const abortController = new AbortController();\n const onToolCall = createToolCallDispatcher(\n providers,\n abortController.signal,\n );\n const onAbort = () => {\n abortController.abort();\n };\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n return await runQuickJsSession(\n {\n abortController,\n code,\n onToolCall,\n providers: extractProviderManifests(providers),\n },\n {\n ...this.options,\n ...options,\n },\n );\n } finally {\n options.signal?.removeEventListener(\"abort\", onAbort);\n abortController.abort();\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions>","closeReason: TransportCloseReason | undefined","leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }>"],"sources":["../src/hosted/shared.ts","../src/hosted/workerHostedExecutor.ts","../src/quickjsExecutor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n runHostTransportSession,\n type HostTransport,\n} from \"@execbox/core/protocol\";\nimport type { ExecutorPoolOptions } from \"@execbox/core\";\nimport { resolveExecutorRuntimeOptions } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n ExecutorRuntimeOptions,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\n/**\n * Default grace period before a worker-hosted shell is forcefully terminated.\n */\nconst DEFAULT_CANCEL_GRACE_MS = 25;\n\n/**\n * Default pooling limits shared by worker-hosted QuickJS executors.\n */\nconst DEFAULT_POOL_OPTIONS: Required<ExecutorPoolOptions> = {\n idleTimeoutMs: 30_000,\n maxSize: 1,\n minSize: 0,\n prewarm: false,\n};\n\n/**\n * Minimal code used to warm a worker shell without touching user providers.\n */\nconst DEFAULT_PREWARM_CODE = \"undefined\";\n\nexport { DEFAULT_CANCEL_GRACE_MS, DEFAULT_POOL_OPTIONS, DEFAULT_PREWARM_CODE };\n\n/**\n * Wraps a transport so warmup and pooled execution can borrow it without\n * taking ownership of its lifecycle.\n */\nexport function createBorrowedTransport(\n transport: HostTransport,\n): HostTransport {\n return {\n dispose() {},\n onClose: transport.onClose,\n onError: transport.onError,\n onMessage: transport.onMessage,\n send: transport.send,\n terminate: transport.terminate,\n };\n}\n\n/**\n * Resolves how many pooled shells should be prewarmed from the pool settings.\n */\nexport function getPrewarmCount(pool: ExecutorPoolOptions | undefined): number {\n if (!pool?.prewarm) {\n return 0;\n }\n\n if (typeof pool.prewarm === \"number\") {\n return Math.max(0, Math.min(pool.prewarm, pool.maxSize));\n }\n\n return Math.max(1, Math.min(pool.minSize ?? 1, pool.maxSize));\n}\n\n/**\n * Caps an explicit warmup request to the configured pool boundaries.\n */\nexport function getWarmupTarget(\n count: number | undefined,\n poolOptions: ExecutorPoolOptions,\n): number {\n return Math.max(\n 0,\n Math.min(count ?? poolOptions.minSize ?? 0, poolOptions.maxSize),\n );\n}\n\n/**\n * Returns whether a hosted execution result is safe to return to a pool.\n */\nexport function isReusableResult(result: ExecuteResult): boolean {\n return (\n result.ok || ![\"internal_error\", \"timeout\"].includes(result.error.code)\n );\n}\n\n/**\n * Normalizes a failed warmup result into an actionable host-side error.\n */\nexport function toWarmupError(label: string, result: ExecuteResult): Error {\n if (result.ok) {\n return new Error(`Failed to prewarm pooled ${label}`);\n }\n\n return new Error(\n `Failed to prewarm pooled ${label}: ${result.error.message}`,\n );\n}\n\n/**\n * Runs one transport-backed execution session with resolved runtime limits and\n * a fresh execution identifier.\n */\nexport async function runHostedTransportSession(options: {\n cancelGraceMs: number;\n code: string;\n executorOptions: ExecutorRuntimeOptions;\n onSettled?: (result: ExecuteResult) => Promise<void> | void;\n providers: ResolvedToolProvider[];\n requestOptions?: ExecutionOptions;\n transport: HostTransport;\n}): Promise<ExecuteResult> {\n return await runHostTransportSession({\n cancelGraceMs: options.cancelGraceMs,\n code: options.code,\n executionId: randomUUID(),\n onSettled: options.onSettled,\n providers: options.providers,\n runtimeOptions: resolveExecutorRuntimeOptions(\n options.executorOptions,\n options.requestOptions,\n ),\n signal: options.requestOptions?.signal,\n transport: options.transport,\n });\n}\n\n/**\n * Exercises a set of leased shells with a warmup run and releases each lease\n * according to the warmup result.\n */\nexport async function warmHostedPool<Shell>(options: {\n count: number;\n getTransport: (shell: Shell) => HostTransport;\n label: string;\n onRelease: (shell: Shell, reusable: boolean) => Promise<void>;\n runSession: (\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n ) => Promise<ExecuteResult>;\n shells: Shell[];\n}): Promise<void> {\n const results = await Promise.allSettled(\n options.shells.map(async (shell) => {\n let reusable = false;\n\n try {\n const result = await options.runSession(\n createBorrowedTransport(options.getTransport(shell)),\n DEFAULT_PREWARM_CODE,\n [],\n );\n reusable = result.ok;\n if (!result.ok) {\n throw toWarmupError(options.label, result);\n }\n } finally {\n await options.onRelease(shell, reusable);\n }\n }),\n );\n\n const rejected = results.find((result) => result.status === \"rejected\");\n if (rejected?.status === \"rejected\") {\n throw rejected.reason;\n }\n}\n","import { availableParallelism } from \"node:os\";\nimport { Worker } from \"node:worker_threads\";\n\nimport {\n createResourcePool,\n getNodeTransportExecArgv,\n type HostTransport,\n type ResourcePool,\n type RunnerMessage,\n type TransportCloseReason,\n} from \"@execbox/core/protocol\";\nimport { createTimeoutExecuteResult } from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n Executor,\n ExecutorPoolOptions,\n ExecuteResult,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport type { QuickJsWorkerExecutorOptions } from \"../types.ts\";\nimport {\n DEFAULT_CANCEL_GRACE_MS,\n DEFAULT_POOL_OPTIONS,\n createBorrowedTransport,\n getPrewarmCount,\n getWarmupTarget,\n isReusableResult,\n runHostedTransportSession,\n warmHostedPool,\n} from \"./shared.ts\";\n\nconst DEFAULT_POOLED_WORKER_MAX_SIZE = 4;\n\ninterface WorkerShell {\n transport: HostTransport;\n worker: Worker;\n}\n\nfunction resolveWorkerEntryUrl(): URL {\n const extension = import.meta.url.endsWith(\".ts\") ? \".ts\" : \".js\";\n return new URL(`../workerEntry${extension}`, import.meta.url);\n}\n\nfunction createWorkerTransport(worker: Worker): HostTransport {\n let terminated = false;\n let closeReason: TransportCloseReason | undefined;\n const closeHandlers = new Set<(reason?: TransportCloseReason) => void>();\n const errorHandlers = new Set<(error: Error) => void>();\n const messageHandlers = new Set<(message: RunnerMessage) => void>();\n\n const terminateWorker = async () => {\n if (terminated) {\n return;\n }\n\n terminated = true;\n await worker.terminate().catch(() => {});\n };\n\n const notifyClose = (reason: TransportCloseReason) => {\n if (closeReason) {\n return;\n }\n\n closeReason = reason;\n for (const handler of closeHandlers) {\n handler(reason);\n }\n };\n\n const onExit = (code: number) => {\n notifyClose({\n code,\n message: `Worker exited unexpectedly with code ${code}`,\n });\n };\n const onError = (error: Error) => {\n for (const handler of errorHandlers) {\n handler(error);\n }\n };\n const onMessage = (message: unknown) => {\n for (const handler of messageHandlers) {\n handler(message as RunnerMessage);\n }\n };\n\n worker.on(\"exit\", onExit);\n worker.on(\"error\", onError);\n worker.on(\"message\", onMessage);\n\n return {\n dispose: async () => {\n worker.off(\"exit\", onExit);\n worker.off(\"error\", onError);\n worker.off(\"message\", onMessage);\n await terminateWorker();\n },\n onClose: (handler) => {\n closeHandlers.add(handler);\n if (closeReason) {\n queueMicrotask(() => {\n if (closeHandlers.has(handler)) {\n handler(closeReason);\n }\n });\n }\n return () => closeHandlers.delete(handler);\n },\n onError: (handler) => {\n errorHandlers.add(handler);\n return () => errorHandlers.delete(handler);\n },\n onMessage: (handler) => {\n messageHandlers.add(handler);\n return () => messageHandlers.delete(handler);\n },\n send: (message) => {\n worker.postMessage(message);\n },\n terminate: async () => {\n await terminateWorker();\n },\n };\n}\n\nfunction createWorkerShell(options: QuickJsWorkerExecutorOptions): WorkerShell {\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: options.workerResourceLimits,\n });\n\n return {\n transport: createWorkerTransport(worker),\n worker,\n };\n}\n\nfunction getDefaultPoolMaxSize(): number {\n try {\n return Math.max(\n 1,\n Math.min(availableParallelism(), DEFAULT_POOLED_WORKER_MAX_SIZE),\n );\n } catch {\n return 1;\n }\n}\n\nfunction resolvePoolOptions(\n options: QuickJsWorkerExecutorOptions,\n): ExecutorPoolOptions | undefined {\n if (options.mode === \"ephemeral\") {\n return undefined;\n }\n\n return {\n ...DEFAULT_POOL_OPTIONS,\n maxSize: getDefaultPoolMaxSize(),\n ...options.pool,\n };\n}\n\n/**\n * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.\n */\nexport class WorkerHostedQuickJsExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: QuickJsWorkerExecutorOptions;\n private readonly pool: ResourcePool<WorkerShell> | undefined;\n private readonly poolOptions: ExecutorPoolOptions | undefined;\n private readonly warmup: Promise<void> | undefined;\n\n /**\n * Creates a QuickJS executor that launches worker-thread shells on demand.\n */\n constructor(options: QuickJsWorkerExecutorOptions) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n const poolOptions = resolvePoolOptions(options);\n this.poolOptions = poolOptions;\n\n if (poolOptions) {\n this.pool = createResourcePool({\n create: async () => createWorkerShell(options),\n destroy: async (shell) => {\n await shell.transport.dispose();\n },\n idleTimeoutMs: poolOptions.idleTimeoutMs,\n maxSize: poolOptions.maxSize,\n minSize: poolOptions.minSize,\n });\n const prewarmCount = getPrewarmCount(poolOptions);\n if (prewarmCount > 0) {\n this.warmup = this.warmPool(prewarmCount);\n }\n }\n }\n\n /**\n * Disposes any pooled worker-thread shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.pool?.dispose();\n }\n\n /**\n * Prewarms pooled worker-thread shells up to the requested count.\n */\n async prewarm(count?: number): Promise<void> {\n if (!this.pool || !this.poolOptions) {\n return;\n }\n\n const target = getWarmupTarget(count, this.poolOptions);\n if (target <= 0) {\n return;\n }\n\n await this.warmPool(target);\n }\n\n private async runTransportSession(\n transport: HostTransport,\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n onSettled?: (result: ExecuteResult) => Promise<void> | void,\n ): Promise<ExecuteResult> {\n return await runHostedTransportSession({\n cancelGraceMs: this.cancelGraceMs,\n code,\n executorOptions: this.options,\n onSettled,\n providers,\n requestOptions: options,\n transport,\n });\n }\n\n private async warmPool(count: number): Promise<void> {\n if (!this.pool) {\n return;\n }\n\n await this.pool.prewarm(count);\n\n const leases: Array<{\n release: (reusable: boolean) => Promise<void>;\n value: WorkerShell;\n }> = [];\n try {\n for (let index = 0; index < count; index += 1) {\n leases.push(await this.pool.acquire());\n }\n } catch (error) {\n await Promise.allSettled(\n leases.map(async (lease) => await lease.release(false)),\n );\n throw error;\n }\n\n await warmHostedPool({\n count,\n getTransport: (lease) => lease.value.transport,\n label: \"worker shell\",\n onRelease: async (lease, reusable) => await lease.release(reusable),\n runSession: async (transport, code, providers) =>\n await this.runTransportSession(transport, code, providers),\n shells: leases,\n });\n }\n\n /**\n * Executes guest code in a worker-thread-hosted QuickJS shell.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n await this.warmup;\n if (this.pool) {\n const lease = await this.pool.acquire();\n\n return await this.runTransportSession(\n createBorrowedTransport(lease.value.transport),\n code,\n providers,\n options,\n async (result) => {\n await lease.release(isReusableResult(result));\n },\n );\n }\n\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: this.options.workerResourceLimits,\n });\n\n return await this.runTransportSession(\n createWorkerTransport(worker),\n code,\n providers,\n options,\n );\n }\n}\n","import {\n createTimeoutExecuteResult,\n createToolCallDispatcher,\n extractProviderManifests,\n} from \"@execbox/core/runtime\";\nimport type {\n ExecutionOptions,\n ExecuteResult,\n Executor,\n ResolvedToolProvider,\n} from \"@execbox/core\";\n\nimport { WorkerHostedQuickJsExecutor } from \"./hosted/workerHostedExecutor.ts\";\nimport { runQuickJsSession } from \"./runner/index.ts\";\nimport type {\n QuickJsExecutorOptions,\n QuickJsInlineExecutorOptions,\n QuickJsWorkerExecutorOptions,\n} from \"./types\";\n\nfunction isWorkerOptions(\n options: QuickJsExecutorOptions,\n): options is QuickJsWorkerExecutorOptions {\n return options.host === \"worker\";\n}\n\nfunction getUnsupportedHost(\n options: QuickJsExecutorOptions,\n): string | undefined {\n const host = (options as { host?: unknown }).host;\n if (host === undefined || host === \"inline\" || host === \"worker\") {\n return undefined;\n }\n\n return String(host);\n}\n\n/**\n * QuickJS-backed executor for inline or worker-backed JavaScript runs.\n */\nexport class QuickJsExecutor implements Executor {\n private readonly hostedExecutor: Executor | undefined;\n private readonly options: QuickJsInlineExecutorOptions | undefined;\n\n /**\n * Creates a QuickJS executor with inline QuickJS by default, or a hosted\n * worker shell when `host` is explicitly set.\n */\n constructor(options: QuickJsExecutorOptions = {}) {\n const unsupportedHost = getUnsupportedHost(options);\n if (unsupportedHost !== undefined) {\n throw new Error(\n `QuickJsExecutor host \"${unsupportedHost}\" is no longer supported. ` +\n 'Use host \"worker\" for local hosted execution.',\n );\n }\n\n if (isWorkerOptions(options)) {\n this.hostedExecutor = new WorkerHostedQuickJsExecutor(options);\n return;\n }\n\n this.options = options;\n }\n\n /**\n * Disposes any pooled hosted shells owned by this executor.\n */\n async dispose(): Promise<void> {\n await this.hostedExecutor?.dispose?.();\n }\n\n /**\n * Prewarms pooled hosted shells when the executor is running in worker mode.\n * Inline mode treats this as a no-op.\n */\n async prewarm(count?: number): Promise<void> {\n await this.hostedExecutor?.prewarm?.(count);\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces in a fresh QuickJS runtime.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (this.hostedExecutor) {\n return await this.hostedExecutor.execute(code, providers, options);\n }\n\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const abortController = new AbortController();\n const onToolCall = createToolCallDispatcher(\n providers,\n abortController.signal,\n );\n const onAbort = () => {\n abortController.abort();\n };\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n return await runQuickJsSession(\n {\n abortController,\n code,\n onToolCall,\n providers: extractProviderManifests(providers),\n },\n {\n ...this.options,\n ...options,\n },\n );\n } finally {\n options.signal?.removeEventListener(\"abort\", onAbort);\n abortController.abort();\n }\n }\n}\n"],"mappings":"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"}
@@ -55,81 +55,10 @@ function toGuestHandle(context, value) {
55
55
  }
56
56
 
57
57
  //#endregion
58
- //#region src/runner/index.ts
59
- /**
60
- * @packageDocumentation
61
- * Public API for the `@execbox/quickjs/runner` entrypoint.
62
- */
63
- const loadDefaultModule = (0, quickjs_emscripten.memoizePromiseFactory)(() => (0, quickjs_emscripten.newQuickJSWASMModule)(quickjs_emscripten.RELEASE_SYNC));
58
+ //#region src/runner/guestEnvironment.ts
64
59
  /**
65
- * Converts unexpected executor failures into stable public result errors.
60
+ * Installs the bounded console capture surface into a QuickJS context.
66
61
  */
67
- function toExecuteError(error, deadline) {
68
- if ((0, __execbox_core_runtime.isExecuteFailure)(error)) return {
69
- code: error.code,
70
- message: error.message
71
- };
72
- const message = (0, __execbox_core_runtime.normalizeThrownMessage)(error);
73
- if (Date.now() > deadline || message.includes("interrupted")) return {
74
- code: "timeout",
75
- message: (0, __execbox_core_runtime.getExecutionTimeoutMessage)()
76
- };
77
- if (message.toLowerCase().includes("out of memory")) return {
78
- code: "memory_limit",
79
- message
80
- };
81
- return {
82
- code: "runtime_error",
83
- message
84
- };
85
- }
86
- function errorFromGuestHandle(context, handle, trustedHostErrorKey) {
87
- const codeHandle = context.getProp(handle, "code");
88
- const messageHandle = context.getProp(handle, "message");
89
- const trustedMarkerHandle = context.getProp(handle, trustedHostErrorKey);
90
- try {
91
- const code = context.typeof(codeHandle) === "string" ? context.getString(codeHandle) : void 0;
92
- const trustedHostError = context.typeof(trustedMarkerHandle) === "boolean";
93
- const message = context.typeof(messageHandle) === "string" ? context.getString(messageHandle) : (0, __execbox_core_runtime.normalizeThrownMessage)(context.dump(handle));
94
- if (trustedHostError && (0, __execbox_core_runtime.isKnownExecuteErrorCode)(code)) return {
95
- code,
96
- message
97
- };
98
- return {
99
- code: "runtime_error",
100
- message
101
- };
102
- } finally {
103
- codeHandle.dispose();
104
- messageHandle.dispose();
105
- trustedMarkerHandle.dispose();
106
- }
107
- }
108
- async function waitForPromiseSettlement(runtime, promise, deadline, trustedHostErrorKey) {
109
- let settled = false;
110
- let rejection;
111
- promise.then(() => {
112
- settled = true;
113
- }, (error) => {
114
- settled = true;
115
- rejection = error;
116
- });
117
- while (!settled) {
118
- if (Date.now() > deadline) throw new __execbox_core_runtime.ExecuteFailure("timeout", (0, __execbox_core_runtime.getExecutionTimeoutMessage)());
119
- const pendingJobsResult = runtime.executePendingJobs(-1);
120
- if ((0, quickjs_emscripten.isFail)(pendingJobsResult)) {
121
- const pendingError = pendingJobsResult.error;
122
- try {
123
- const executeError = errorFromGuestHandle(pendingError.context, pendingError, trustedHostErrorKey);
124
- throw new __execbox_core_runtime.ExecuteFailure(executeError.code, executeError.message);
125
- } finally {
126
- pendingError.dispose();
127
- }
128
- }
129
- await new Promise((resolve) => setTimeout(resolve, 0));
130
- }
131
- if (rejection !== void 0) throw rejection;
132
- }
133
62
  function injectConsole(context, logs) {
134
63
  const consoleHandle = context.newObject();
135
64
  try {
@@ -151,6 +80,9 @@ function injectConsole(context, logs) {
151
80
  consoleHandle.dispose();
152
81
  }
153
82
  }
83
+ /**
84
+ * Installs provider namespaces as guest-visible async tool proxies.
85
+ */
154
86
  function injectProviders(context, providers, signal, trustedHostErrorKey, onToolCall) {
155
87
  for (const provider of providers) {
156
88
  const providerHandle = context.newObject();
@@ -249,6 +181,92 @@ function createToolHandle(context, providerName, safeToolName, signal, trustedHo
249
181
  return deferred.handle;
250
182
  });
251
183
  }
184
+
185
+ //#endregion
186
+ //#region src/runner/sessionErrors.ts
187
+ /**
188
+ * Converts unexpected executor failures into stable public result errors.
189
+ */
190
+ function toExecuteError(error, deadline) {
191
+ if ((0, __execbox_core_runtime.isExecuteFailure)(error)) return {
192
+ code: error.code,
193
+ message: error.message
194
+ };
195
+ const message = (0, __execbox_core_runtime.normalizeThrownMessage)(error);
196
+ if (Date.now() > deadline || message.includes("interrupted")) return {
197
+ code: "timeout",
198
+ message: (0, __execbox_core_runtime.getExecutionTimeoutMessage)()
199
+ };
200
+ if (message.toLowerCase().includes("out of memory")) return {
201
+ code: "memory_limit",
202
+ message
203
+ };
204
+ return {
205
+ code: "runtime_error",
206
+ message
207
+ };
208
+ }
209
+ /**
210
+ * Converts a guest-side error handle into the public execbox error shape.
211
+ */
212
+ function errorFromGuestHandle(context, handle, trustedHostErrorKey) {
213
+ const codeHandle = context.getProp(handle, "code");
214
+ const messageHandle = context.getProp(handle, "message");
215
+ const trustedMarkerHandle = context.getProp(handle, trustedHostErrorKey);
216
+ try {
217
+ const code = context.typeof(codeHandle) === "string" ? context.getString(codeHandle) : void 0;
218
+ const trustedHostError = context.typeof(trustedMarkerHandle) === "boolean";
219
+ const message = context.typeof(messageHandle) === "string" ? context.getString(messageHandle) : (0, __execbox_core_runtime.normalizeThrownMessage)(context.dump(handle));
220
+ if (trustedHostError && (0, __execbox_core_runtime.isKnownExecuteErrorCode)(code)) return {
221
+ code,
222
+ message
223
+ };
224
+ return {
225
+ code: "runtime_error",
226
+ message
227
+ };
228
+ } finally {
229
+ codeHandle.dispose();
230
+ messageHandle.dispose();
231
+ trustedMarkerHandle.dispose();
232
+ }
233
+ }
234
+ /**
235
+ * Advances QuickJS pending jobs until the resolved promise settles or times out.
236
+ */
237
+ async function waitForPromiseSettlement(runtime, promise, deadline, trustedHostErrorKey) {
238
+ let settled = false;
239
+ let rejection;
240
+ promise.then(() => {
241
+ settled = true;
242
+ }, (error) => {
243
+ settled = true;
244
+ rejection = error;
245
+ });
246
+ while (!settled) {
247
+ if (Date.now() > deadline) throw new __execbox_core_runtime.ExecuteFailure("timeout", (0, __execbox_core_runtime.getExecutionTimeoutMessage)());
248
+ const pendingJobsResult = runtime.executePendingJobs(-1);
249
+ if ((0, quickjs_emscripten.isFail)(pendingJobsResult)) {
250
+ const pendingError = pendingJobsResult.error;
251
+ try {
252
+ const executeError = errorFromGuestHandle(pendingError.context, pendingError, trustedHostErrorKey);
253
+ throw new __execbox_core_runtime.ExecuteFailure(executeError.code, executeError.message);
254
+ } finally {
255
+ pendingError.dispose();
256
+ }
257
+ }
258
+ await new Promise((resolve) => setTimeout(resolve, 0));
259
+ }
260
+ if (rejection !== void 0) throw rejection;
261
+ }
262
+
263
+ //#endregion
264
+ //#region src/runner/index.ts
265
+ /**
266
+ * @packageDocumentation
267
+ * Internal reusable QuickJS session runner.
268
+ */
269
+ const loadDefaultModule = (0, quickjs_emscripten.memoizePromiseFactory)(() => (0, quickjs_emscripten.newQuickJSWASMModule)(quickjs_emscripten.RELEASE_SYNC));
252
270
  /**
253
271
  * Runs one QuickJS-backed execution session using a transport-neutral tool callback.
254
272
  */
@@ -345,4 +363,4 @@ Object.defineProperty(exports, 'runQuickJsSession', {
345
363
  return runQuickJsSession;
346
364
  }
347
365
  });
348
- //# sourceMappingURL=runner-DRLfwiqY.cjs.map
366
+ //# sourceMappingURL=runner-BeRzBTrn.cjs.map