@ricsam/quickjs-core 0.2.15 → 0.2.17

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.
package/README.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # @ricsam/quickjs-core
2
2
 
3
- Core utilities and Web Streams API.
3
+ Core utilities and Web Streams API for QuickJS runtime bindings.
4
+
5
+ > **Note**: This is a low-level package. For most use cases, use [`@ricsam/quickjs-runtime`](../runtime) with `createRuntime()` instead.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ bun add @ricsam/quickjs-core
11
+ ```
12
+
13
+ ## Setup
4
14
 
5
15
  ```typescript
6
16
  import { setupCore } from "@ricsam/quickjs-core";
@@ -8,12 +18,13 @@ import { setupCore } from "@ricsam/quickjs-core";
8
18
  const handle = setupCore(context);
9
19
  ```
10
20
 
11
- **Injected Globals:**
21
+ ## Injected Globals
22
+
12
23
  - `ReadableStream`, `WritableStream`, `TransformStream`
13
24
  - `ReadableStreamDefaultReader`, `WritableStreamDefaultWriter`
14
25
  - `Blob`, `File`
15
26
 
16
- **Usage in QuickJS:**
27
+ ## Usage in QuickJS
17
28
 
18
29
  ```javascript
19
30
  // Streams
@@ -35,4 +46,100 @@ const text = await blob.text(); // "hello world"
35
46
  // File
36
47
  const file = new File(["content"], "file.txt", { type: "text/plain" });
37
48
  console.log(file.name); // "file.txt"
38
- ```
49
+ ```
50
+
51
+ ## Core Utilities
52
+
53
+ ```typescript
54
+ import {
55
+ // Marshalling
56
+ marshal, // JS value -> QuickJS handle
57
+ unmarshal, // QuickJS handle -> JS value
58
+
59
+ // Handle utilities
60
+ isHandle, // Check if value is a QuickJS handle
61
+ getHandleType, // Get handle type as string
62
+
63
+ // Scope management
64
+ withScope, // Automatic handle cleanup
65
+ withScopeAsync, // Async version
66
+
67
+ // Class/function builders
68
+ defineClass,
69
+ defineFunction,
70
+ defineAsyncFunction,
71
+ defineAsyncIteratorFunction, // For async generators
72
+ cleanupAsyncIterators, // Cleanup on context disposal
73
+
74
+ // State management
75
+ createStateMap,
76
+ getState,
77
+ setState,
78
+ } from "@ricsam/quickjs-core";
79
+ ```
80
+
81
+ ### Marshalling Example
82
+
83
+ ```typescript
84
+ // Marshal JS values to QuickJS
85
+ const handle = marshal(context, {
86
+ name: "test",
87
+ values: [1, 2, 3],
88
+ callback: (x) => x * 2,
89
+ });
90
+
91
+ // Unmarshal QuickJS values to JS
92
+ const value = unmarshal(context, handle);
93
+ ```
94
+
95
+ ### Custom Class Definition
96
+
97
+ ```typescript
98
+ const PointClass = defineClass(context, stateMap, {
99
+ name: "Point",
100
+ construct: ([x, y]) => ({ x: Number(x), y: Number(y) }),
101
+ properties: {
102
+ x: {
103
+ get() { return this.x; },
104
+ set(v) { this.x = Number(v); },
105
+ },
106
+ y: {
107
+ get() { return this.y; },
108
+ set(v) { this.y = Number(v); },
109
+ },
110
+ },
111
+ methods: {
112
+ distance() {
113
+ return Math.sqrt(this.x ** 2 + this.y ** 2);
114
+ },
115
+ },
116
+ });
117
+
118
+ context.setProp(context.global, "Point", PointClass);
119
+ ```
120
+
121
+ ### Async Iterator Function
122
+
123
+ Define functions that return async iterables (for streaming data):
124
+
125
+ ```typescript
126
+ import { defineAsyncIteratorFunction, cleanupAsyncIterators } from "@ricsam/quickjs-core";
127
+
128
+ const streamFn = defineAsyncIteratorFunction(context, "streamNumbers", async function* (count) {
129
+ for (let i = 0; i < Number(count); i++) {
130
+ await new Promise(r => setTimeout(r, 100));
131
+ yield i;
132
+ }
133
+ });
134
+
135
+ context.setProp(context.global, "streamNumbers", streamFn);
136
+ streamFn.dispose();
137
+
138
+ // In QuickJS:
139
+ // for await (const n of streamNumbers(5)) {
140
+ // console.log(n); // 0, 1, 2, 3, 4
141
+ // }
142
+
143
+ // Clean up before context disposal
144
+ cleanupAsyncIterators(context);
145
+ ```
@@ -124,11 +124,17 @@ function defineClass(context, stateMap, definition) {
124
124
  if (result2 instanceof Promise) {
125
125
  const deferred = context.newPromise();
126
126
  result2.then((resolved) => {
127
+ if (!context.alive) {
128
+ return;
129
+ }
127
130
  const resolvedHandle = import_marshal.marshal(context, resolved);
128
131
  deferred.resolve(resolvedHandle);
129
132
  resolvedHandle.dispose();
130
133
  context.runtime.executePendingJobs();
131
134
  }).catch((error) => {
135
+ if (!context.alive) {
136
+ return;
137
+ }
132
138
  const errorHandle = import_marshal.marshal(context, error instanceof Error ? { name: error.name, message: error.message } : { message: String(error) });
133
139
  deferred.reject(errorHandle);
134
140
  errorHandle.dispose();
@@ -282,4 +288,4 @@ function clearAllInstanceState() {
282
288
  }
283
289
  })
284
290
 
285
- //# debugId=7DABC9B5D523AE4664756E2164756E21
291
+ //# debugId=9607AA37A2AFD77364756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/class-builder.ts"],
4
4
  "sourcesContent": [
5
- "import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { ClassDefinition, StateMap } from \"./types.cjs\";\nimport { unmarshal } from \"./unmarshal.cjs\";\nimport { marshal } from \"./marshal.cjs\";\nimport {\n nextInstanceId,\n registerInstance,\n getInstanceStateById as getStateById,\n setInstanceStateById,\n cleanupInstanceState as cleanupState,\n clearAllInstanceState as clearAllState,\n} from \"./instance-state.cjs\";\n\n// ============================================\n// Error Type Preservation\n// ============================================\n\n/**\n * Supported error types for typed error creation.\n */\nconst ERROR_TYPES = [\"TypeError\", \"RangeError\", \"SyntaxError\", \"ReferenceError\", \"URIError\", \"EvalError\"] as const;\n\n/**\n * Create a typed error in the QuickJS context.\n * Gets the error constructor fresh each time to avoid handle lifecycle issues.\n */\nfunction createTypedError(\n context: QuickJSContext,\n error: Error\n): QuickJSHandle {\n if ((ERROR_TYPES as readonly string[]).includes(error.name)) {\n const ctor = context.getProp(context.global, error.name);\n if (context.typeof(ctor) === \"function\") {\n const messageHandle = context.newString(error.message);\n const result = context.callFunction(ctor, context.undefined, messageHandle);\n messageHandle.dispose();\n ctor.dispose();\n\n if (!result.error) {\n return result.value;\n }\n result.error.dispose();\n } else {\n ctor.dispose();\n }\n }\n\n // Fallback to generic Error\n return context.newError(error.message);\n}\n\n/**\n * Create a new StateMap for tracking object internal states\n */\nexport function createStateMap(): StateMap {\n return new WeakMap();\n}\n\n/**\n * Get the internal state associated with a QuickJS object handle\n */\nexport function getState<T extends object>(\n stateMap: StateMap,\n handle: QuickJSHandle\n): T | undefined {\n return stateMap.get(handle) as T | undefined;\n}\n\n/**\n * Set the internal state associated with a QuickJS object handle\n */\nexport function setState<T extends object>(\n stateMap: StateMap,\n handle: QuickJSHandle,\n state: T\n): void {\n stateMap.set(handle, state);\n}\n\n// Instance state is now managed by instance-state.ts\n\n/**\n * Define a class in the QuickJS context\n *\n * Uses evalCode to create a proper JavaScript class that can be called with 'new'.\n * Host-side callbacks are registered and invoked by the JavaScript class.\n *\n * @returns Handle to the class constructor (caller must manage disposal)\n *\n * @example\n * const Point = defineClass(context, stateMap, {\n * name: \"Point\",\n * construct: ([x, y]) => ({ x: Number(x), y: Number(y) }),\n * methods: {\n * distance(this: { x: number; y: number }) {\n * return Math.sqrt(this.x ** 2 + this.y ** 2);\n * }\n * },\n * properties: {\n * x: {\n * get(this: { x: number }) { return this.x; },\n * set(this: { x: number }, v: unknown) { this.x = Number(v); }\n * }\n * }\n * });\n * context.setProp(context.global, \"Point\", Point);\n */\nexport function defineClass<TState extends object>(\n context: QuickJSContext,\n stateMap: StateMap,\n definition: ClassDefinition<TState>\n): QuickJSHandle {\n const className = definition.name;\n\n // Create the __hostCall__ function if it doesn't exist\n const existingHostCall = context.getProp(context.global, \"__hostCall__\");\n const hasHostCall = context.typeof(existingHostCall) === \"function\";\n existingHostCall.dispose();\n\n if (!hasHostCall) {\n const hostCallFn = context.newFunction(\"__hostCall__\", (classNameHandle, actionHandle, instanceIdHandle, ...argHandles) => {\n const classNameStr = context.getString(classNameHandle);\n const action = context.getString(actionHandle);\n const instanceId = context.getNumber(instanceIdHandle);\n const args = argHandles.map((h) => unmarshal(context, h));\n\n const callbacks = classCallbackRegistry.get(classNameStr);\n if (!callbacks) {\n throw context.newError(`No callbacks registered for class ${classNameStr}`);\n }\n\n const state = getStateById<TState>(instanceId);\n\n try {\n let result: unknown;\n\n if (action === \"__construct__\") {\n // Constructor call\n if (callbacks.construct) {\n const newState = callbacks.construct(args);\n // Register instance with className for cross-class access\n registerInstance(instanceId, classNameStr, newState);\n result = undefined;\n }\n } else if (action.startsWith(\"get:\")) {\n // Getter call\n const propName = action.slice(4);\n const getter = callbacks.properties?.[propName]?.get;\n if (getter && state) {\n result = getter.call(state);\n }\n } else if (action.startsWith(\"set:\")) {\n // Setter call\n const propName = action.slice(4);\n const setter = callbacks.properties?.[propName]?.set;\n if (setter && state) {\n setter.call(state, args[0]);\n }\n result = undefined;\n } else if (action.startsWith(\"static:\")) {\n // Static method call\n const methodName = action.slice(7);\n const staticMethod = callbacks.staticMethods?.[methodName];\n if (staticMethod) {\n result = staticMethod(...args);\n }\n } else {\n // Instance method call\n const method = callbacks.methods?.[action];\n if (method && state) {\n result = method.call(state, ...args);\n }\n }\n\n // Handle promises\n if (result instanceof Promise) {\n const deferred = context.newPromise();\n result\n .then((resolved) => {\n const resolvedHandle = marshal(context, resolved);\n deferred.resolve(resolvedHandle);\n resolvedHandle.dispose();\n context.runtime.executePendingJobs();\n })\n .catch((error) => {\n const errorHandle = marshal(\n context,\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) }\n );\n deferred.reject(errorHandle);\n errorHandle.dispose();\n context.runtime.executePendingJobs();\n });\n return deferred.handle;\n }\n\n return marshal(context, result);\n } catch (error) {\n // Preserve error type (TypeError, RangeError, etc.) when re-throwing\n if (error instanceof Error) {\n throw createTypedError(context, error);\n }\n throw context.newError(String(error));\n }\n });\n context.setProp(context.global, \"__hostCall__\", hostCallFn);\n hostCallFn.dispose();\n }\n\n // Create __nextInstanceId__ function if it doesn't exist\n const existingNextId = context.getProp(context.global, \"__nextInstanceId__\");\n const hasNextId = context.typeof(existingNextId) === \"function\";\n existingNextId.dispose();\n\n if (!hasNextId) {\n const nextIdFn = context.newFunction(\"__nextInstanceId__\", () => {\n return context.newNumber(nextInstanceId());\n });\n context.setProp(context.global, \"__nextInstanceId__\", nextIdFn);\n nextIdFn.dispose();\n }\n\n // Register callbacks for this class\n const callbacks: ClassCallbacks<TState> = {\n construct: definition.construct,\n methods: definition.methods,\n properties: definition.properties,\n staticMethods: definition.staticMethods,\n };\n classCallbackRegistry.set(className, callbacks as unknown as ClassCallbacks<object>);\n\n // Build the JavaScript class code\n const hasParent = definition.extends !== undefined;\n\n // If extending a class, temporarily set it as a global so the IIFE can access it\n if (hasParent) {\n context.setProp(context.global, \"__tempParentClass__\", definition.extends!);\n }\n\n let classCode = hasParent\n ? `(function() {\n const __className__ = ${JSON.stringify(className)};\n const __ParentClass__ = __tempParentClass__;\n\n class ${className} extends __ParentClass__ {\n constructor(...args) {\n super();\n // __instanceId__ is already set by parent class, just call our construct\n __hostCall__(__className__, \"__construct__\", this.__instanceId__, ...args);\n }`\n : `(function() {\n const __className__ = ${JSON.stringify(className)};\n\n class ${className} {\n constructor(...args) {\n Object.defineProperty(this, '__instanceId__', {\n value: __nextInstanceId__(),\n enumerable: false,\n writable: false,\n configurable: false\n });\n __hostCall__(__className__, \"__construct__\", this.__instanceId__, ...args);\n }`;\n\n // Add methods\n if (definition.methods) {\n for (const methodName of Object.keys(definition.methods)) {\n classCode += `\n ${methodName}(...args) {\n return __hostCall__(__className__, ${JSON.stringify(methodName)}, this.__instanceId__, ...args);\n }\n`;\n }\n }\n\n // Add properties (getters/setters)\n if (definition.properties) {\n for (const [propName, descriptor] of Object.entries(definition.properties)) {\n if (descriptor.get) {\n classCode += `\n get ${propName}() {\n return __hostCall__(__className__, \"get:${propName}\", this.__instanceId__);\n }\n`;\n }\n if (descriptor.set) {\n classCode += `\n set ${propName}(value) {\n __hostCall__(__className__, \"set:${propName}\", this.__instanceId__, value);\n }\n`;\n }\n }\n }\n\n // Close the class definition\n classCode += ` }\n`;\n\n // Add static methods\n if (definition.staticMethods) {\n for (const methodName of Object.keys(definition.staticMethods)) {\n classCode += `\n ${className}.${methodName} = function(...args) {\n return __hostCall__(__className__, \"static:${methodName}\", 0, ...args);\n };\n`;\n }\n }\n\n // Add static properties\n if (definition.staticProperties) {\n for (const [propName, value] of Object.entries(definition.staticProperties)) {\n classCode += `\n ${className}.${propName} = ${JSON.stringify(value)};\n`;\n }\n }\n\n classCode += `\n return ${className};\n})()`;\n\n // Evaluate the class definition\n const result = context.evalCode(classCode);\n\n // Clean up temporary parent class global if we set one\n if (hasParent) {\n context.setProp(context.global, \"__tempParentClass__\", context.undefined);\n }\n\n if (result.error) {\n const error = context.dump(result.error);\n result.error.dispose();\n throw new Error(`Failed to define class ${className}: ${JSON.stringify(error)}`);\n }\n\n // Store reference to instance state in stateMap for backwards compatibility\n // When an instance handle is accessed, we can look up its state via __instanceId__\n const classHandle = result.value;\n\n return classHandle;\n}\n\n// Registry for class callbacks\ninterface ClassCallbacks<TState extends object> {\n construct?: (args: unknown[]) => TState;\n methods?: Record<string, (this: TState, ...args: unknown[]) => unknown>;\n properties?: Record<string, { get?: (this: TState) => unknown; set?: (this: TState, value: unknown) => void }>;\n staticMethods?: Record<string, (...args: unknown[]) => unknown>;\n}\n\nconst classCallbackRegistry = new Map<string, ClassCallbacks<object>>();\n\n/**\n * Get internal state for a QuickJS instance by extracting its __instanceId__\n */\nexport function getInstanceState<T>(\n context: QuickJSContext,\n instanceHandle: QuickJSHandle\n): T | undefined {\n const idHandle = context.getProp(instanceHandle, \"__instanceId__\");\n if (context.typeof(idHandle) !== \"number\") {\n idHandle.dispose();\n return undefined;\n }\n const id = context.getNumber(idHandle);\n idHandle.dispose();\n return getStateById<T>(id);\n}\n\n/**\n * Set internal state for a QuickJS instance by extracting its __instanceId__\n */\nexport function setInstanceState<T>(\n context: QuickJSContext,\n instanceHandle: QuickJSHandle,\n state: T\n): void {\n const idHandle = context.getProp(instanceHandle, \"__instanceId__\");\n if (context.typeof(idHandle) !== \"number\") {\n idHandle.dispose();\n throw new Error(\"Cannot set state: instance has no __instanceId__\");\n }\n const id = context.getNumber(idHandle);\n idHandle.dispose();\n setInstanceStateById(id, state);\n}\n\n/**\n * Get internal state by instance ID directly\n * Useful when you have the instanceId from an unmarshaled object\n */\nexport function getInstanceStateById<T>(instanceId: number): T | undefined {\n return getStateById<T>(instanceId);\n}\n\n/**\n * Clean up instance state when an instance is no longer needed\n */\nexport function cleanupInstanceState(instanceId: number): void {\n cleanupState(instanceId);\n}\n\n/**\n * Clear all instance state (useful for context disposal or testing cleanup)\n */\nexport function clearAllInstanceState(): void {\n clearAllState();\n}\n"
5
+ "import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport type { ClassDefinition, StateMap } from \"./types.cjs\";\nimport { unmarshal } from \"./unmarshal.cjs\";\nimport { marshal } from \"./marshal.cjs\";\nimport {\n nextInstanceId,\n registerInstance,\n getInstanceStateById as getStateById,\n setInstanceStateById,\n cleanupInstanceState as cleanupState,\n clearAllInstanceState as clearAllState,\n} from \"./instance-state.cjs\";\n\n// ============================================\n// Error Type Preservation\n// ============================================\n\n/**\n * Supported error types for typed error creation.\n */\nconst ERROR_TYPES = [\"TypeError\", \"RangeError\", \"SyntaxError\", \"ReferenceError\", \"URIError\", \"EvalError\"] as const;\n\n/**\n * Create a typed error in the QuickJS context.\n * Gets the error constructor fresh each time to avoid handle lifecycle issues.\n */\nfunction createTypedError(\n context: QuickJSContext,\n error: Error\n): QuickJSHandle {\n if ((ERROR_TYPES as readonly string[]).includes(error.name)) {\n const ctor = context.getProp(context.global, error.name);\n if (context.typeof(ctor) === \"function\") {\n const messageHandle = context.newString(error.message);\n const result = context.callFunction(ctor, context.undefined, messageHandle);\n messageHandle.dispose();\n ctor.dispose();\n\n if (!result.error) {\n return result.value;\n }\n result.error.dispose();\n } else {\n ctor.dispose();\n }\n }\n\n // Fallback to generic Error\n return context.newError(error.message);\n}\n\n/**\n * Create a new StateMap for tracking object internal states\n */\nexport function createStateMap(): StateMap {\n return new WeakMap();\n}\n\n/**\n * Get the internal state associated with a QuickJS object handle\n */\nexport function getState<T extends object>(\n stateMap: StateMap,\n handle: QuickJSHandle\n): T | undefined {\n return stateMap.get(handle) as T | undefined;\n}\n\n/**\n * Set the internal state associated with a QuickJS object handle\n */\nexport function setState<T extends object>(\n stateMap: StateMap,\n handle: QuickJSHandle,\n state: T\n): void {\n stateMap.set(handle, state);\n}\n\n// Instance state is now managed by instance-state.ts\n\n/**\n * Define a class in the QuickJS context\n *\n * Uses evalCode to create a proper JavaScript class that can be called with 'new'.\n * Host-side callbacks are registered and invoked by the JavaScript class.\n *\n * @returns Handle to the class constructor (caller must manage disposal)\n *\n * @example\n * const Point = defineClass(context, stateMap, {\n * name: \"Point\",\n * construct: ([x, y]) => ({ x: Number(x), y: Number(y) }),\n * methods: {\n * distance(this: { x: number; y: number }) {\n * return Math.sqrt(this.x ** 2 + this.y ** 2);\n * }\n * },\n * properties: {\n * x: {\n * get(this: { x: number }) { return this.x; },\n * set(this: { x: number }, v: unknown) { this.x = Number(v); }\n * }\n * }\n * });\n * context.setProp(context.global, \"Point\", Point);\n */\nexport function defineClass<TState extends object>(\n context: QuickJSContext,\n stateMap: StateMap,\n definition: ClassDefinition<TState>\n): QuickJSHandle {\n const className = definition.name;\n\n // Create the __hostCall__ function if it doesn't exist\n const existingHostCall = context.getProp(context.global, \"__hostCall__\");\n const hasHostCall = context.typeof(existingHostCall) === \"function\";\n existingHostCall.dispose();\n\n if (!hasHostCall) {\n const hostCallFn = context.newFunction(\"__hostCall__\", (classNameHandle, actionHandle, instanceIdHandle, ...argHandles) => {\n const classNameStr = context.getString(classNameHandle);\n const action = context.getString(actionHandle);\n const instanceId = context.getNumber(instanceIdHandle);\n const args = argHandles.map((h) => unmarshal(context, h));\n\n const callbacks = classCallbackRegistry.get(classNameStr);\n if (!callbacks) {\n throw context.newError(`No callbacks registered for class ${classNameStr}`);\n }\n\n const state = getStateById<TState>(instanceId);\n\n try {\n let result: unknown;\n\n if (action === \"__construct__\") {\n // Constructor call\n if (callbacks.construct) {\n const newState = callbacks.construct(args);\n // Register instance with className for cross-class access\n registerInstance(instanceId, classNameStr, newState);\n result = undefined;\n }\n } else if (action.startsWith(\"get:\")) {\n // Getter call\n const propName = action.slice(4);\n const getter = callbacks.properties?.[propName]?.get;\n if (getter && state) {\n result = getter.call(state);\n }\n } else if (action.startsWith(\"set:\")) {\n // Setter call\n const propName = action.slice(4);\n const setter = callbacks.properties?.[propName]?.set;\n if (setter && state) {\n setter.call(state, args[0]);\n }\n result = undefined;\n } else if (action.startsWith(\"static:\")) {\n // Static method call\n const methodName = action.slice(7);\n const staticMethod = callbacks.staticMethods?.[methodName];\n if (staticMethod) {\n result = staticMethod(...args);\n }\n } else {\n // Instance method call\n const method = callbacks.methods?.[action];\n if (method && state) {\n result = method.call(state, ...args);\n }\n }\n\n // Handle promises\n if (result instanceof Promise) {\n const deferred = context.newPromise();\n result\n .then((resolved) => {\n // Guard: Check if context is still alive\n if (!context.alive) {\n return;\n }\n const resolvedHandle = marshal(context, resolved);\n deferred.resolve(resolvedHandle);\n resolvedHandle.dispose();\n context.runtime.executePendingJobs();\n })\n .catch((error) => {\n // Guard: Check if context is still alive\n if (!context.alive) {\n return;\n }\n const errorHandle = marshal(\n context,\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) }\n );\n deferred.reject(errorHandle);\n errorHandle.dispose();\n context.runtime.executePendingJobs();\n });\n return deferred.handle;\n }\n\n return marshal(context, result);\n } catch (error) {\n // Preserve error type (TypeError, RangeError, etc.) when re-throwing\n if (error instanceof Error) {\n throw createTypedError(context, error);\n }\n throw context.newError(String(error));\n }\n });\n context.setProp(context.global, \"__hostCall__\", hostCallFn);\n hostCallFn.dispose();\n }\n\n // Create __nextInstanceId__ function if it doesn't exist\n const existingNextId = context.getProp(context.global, \"__nextInstanceId__\");\n const hasNextId = context.typeof(existingNextId) === \"function\";\n existingNextId.dispose();\n\n if (!hasNextId) {\n const nextIdFn = context.newFunction(\"__nextInstanceId__\", () => {\n return context.newNumber(nextInstanceId());\n });\n context.setProp(context.global, \"__nextInstanceId__\", nextIdFn);\n nextIdFn.dispose();\n }\n\n // Register callbacks for this class\n const callbacks: ClassCallbacks<TState> = {\n construct: definition.construct,\n methods: definition.methods,\n properties: definition.properties,\n staticMethods: definition.staticMethods,\n };\n classCallbackRegistry.set(className, callbacks as unknown as ClassCallbacks<object>);\n\n // Build the JavaScript class code\n const hasParent = definition.extends !== undefined;\n\n // If extending a class, temporarily set it as a global so the IIFE can access it\n if (hasParent) {\n context.setProp(context.global, \"__tempParentClass__\", definition.extends!);\n }\n\n let classCode = hasParent\n ? `(function() {\n const __className__ = ${JSON.stringify(className)};\n const __ParentClass__ = __tempParentClass__;\n\n class ${className} extends __ParentClass__ {\n constructor(...args) {\n super();\n // __instanceId__ is already set by parent class, just call our construct\n __hostCall__(__className__, \"__construct__\", this.__instanceId__, ...args);\n }`\n : `(function() {\n const __className__ = ${JSON.stringify(className)};\n\n class ${className} {\n constructor(...args) {\n Object.defineProperty(this, '__instanceId__', {\n value: __nextInstanceId__(),\n enumerable: false,\n writable: false,\n configurable: false\n });\n __hostCall__(__className__, \"__construct__\", this.__instanceId__, ...args);\n }`;\n\n // Add methods\n if (definition.methods) {\n for (const methodName of Object.keys(definition.methods)) {\n classCode += `\n ${methodName}(...args) {\n return __hostCall__(__className__, ${JSON.stringify(methodName)}, this.__instanceId__, ...args);\n }\n`;\n }\n }\n\n // Add properties (getters/setters)\n if (definition.properties) {\n for (const [propName, descriptor] of Object.entries(definition.properties)) {\n if (descriptor.get) {\n classCode += `\n get ${propName}() {\n return __hostCall__(__className__, \"get:${propName}\", this.__instanceId__);\n }\n`;\n }\n if (descriptor.set) {\n classCode += `\n set ${propName}(value) {\n __hostCall__(__className__, \"set:${propName}\", this.__instanceId__, value);\n }\n`;\n }\n }\n }\n\n // Close the class definition\n classCode += ` }\n`;\n\n // Add static methods\n if (definition.staticMethods) {\n for (const methodName of Object.keys(definition.staticMethods)) {\n classCode += `\n ${className}.${methodName} = function(...args) {\n return __hostCall__(__className__, \"static:${methodName}\", 0, ...args);\n };\n`;\n }\n }\n\n // Add static properties\n if (definition.staticProperties) {\n for (const [propName, value] of Object.entries(definition.staticProperties)) {\n classCode += `\n ${className}.${propName} = ${JSON.stringify(value)};\n`;\n }\n }\n\n classCode += `\n return ${className};\n})()`;\n\n // Evaluate the class definition\n const result = context.evalCode(classCode);\n\n // Clean up temporary parent class global if we set one\n if (hasParent) {\n context.setProp(context.global, \"__tempParentClass__\", context.undefined);\n }\n\n if (result.error) {\n const error = context.dump(result.error);\n result.error.dispose();\n throw new Error(`Failed to define class ${className}: ${JSON.stringify(error)}`);\n }\n\n // Store reference to instance state in stateMap for backwards compatibility\n // When an instance handle is accessed, we can look up its state via __instanceId__\n const classHandle = result.value;\n\n return classHandle;\n}\n\n// Registry for class callbacks\ninterface ClassCallbacks<TState extends object> {\n construct?: (args: unknown[]) => TState;\n methods?: Record<string, (this: TState, ...args: unknown[]) => unknown>;\n properties?: Record<string, { get?: (this: TState) => unknown; set?: (this: TState, value: unknown) => void }>;\n staticMethods?: Record<string, (...args: unknown[]) => unknown>;\n}\n\nconst classCallbackRegistry = new Map<string, ClassCallbacks<object>>();\n\n/**\n * Get internal state for a QuickJS instance by extracting its __instanceId__\n */\nexport function getInstanceState<T>(\n context: QuickJSContext,\n instanceHandle: QuickJSHandle\n): T | undefined {\n const idHandle = context.getProp(instanceHandle, \"__instanceId__\");\n if (context.typeof(idHandle) !== \"number\") {\n idHandle.dispose();\n return undefined;\n }\n const id = context.getNumber(idHandle);\n idHandle.dispose();\n return getStateById<T>(id);\n}\n\n/**\n * Set internal state for a QuickJS instance by extracting its __instanceId__\n */\nexport function setInstanceState<T>(\n context: QuickJSContext,\n instanceHandle: QuickJSHandle,\n state: T\n): void {\n const idHandle = context.getProp(instanceHandle, \"__instanceId__\");\n if (context.typeof(idHandle) !== \"number\") {\n idHandle.dispose();\n throw new Error(\"Cannot set state: instance has no __instanceId__\");\n }\n const id = context.getNumber(idHandle);\n idHandle.dispose();\n setInstanceStateById(id, state);\n}\n\n/**\n * Get internal state by instance ID directly\n * Useful when you have the instanceId from an unmarshaled object\n */\nexport function getInstanceStateById<T>(instanceId: number): T | undefined {\n return getStateById<T>(instanceId);\n}\n\n/**\n * Clean up instance state when an instance is no longer needed\n */\nexport function cleanupInstanceState(instanceId: number): void {\n cleanupState(instanceId);\n}\n\n/**\n * Clear all instance state (useful for context disposal or testing cleanup)\n */\nexport function clearAllInstanceState(): void {\n clearAllState();\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "7DABC9B5D523AE4664756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "9607AA37A2AFD77364756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -31,11 +31,160 @@ var __export = (target, all) => {
31
31
  var exports_function_builder = {};
32
32
  __export(exports_function_builder, {
33
33
  defineFunction: () => defineFunction,
34
- defineAsyncFunction: () => defineAsyncFunction
34
+ defineAsyncIteratorFunction: () => defineAsyncIteratorFunction,
35
+ defineAsyncFunction: () => defineAsyncFunction,
36
+ cleanupAsyncIterators: () => cleanupAsyncIterators
35
37
  });
36
38
  module.exports = __toCommonJS(exports_function_builder);
37
39
  var import_unmarshal = require("./unmarshal.cjs");
38
40
  var import_marshal = require("./marshal.cjs");
41
+ var generatorRegistries = new WeakMap;
42
+ var generatorCounters = new WeakMap;
43
+ var setupContexts = new WeakSet;
44
+ function getGeneratorRegistry(context) {
45
+ let registry = generatorRegistries.get(context);
46
+ if (!registry) {
47
+ registry = new Map;
48
+ generatorRegistries.set(context, registry);
49
+ }
50
+ return registry;
51
+ }
52
+ function nextGeneratorId(context) {
53
+ let counter = generatorCounters.get(context);
54
+ if (!counter) {
55
+ counter = { value: 0 };
56
+ generatorCounters.set(context, counter);
57
+ }
58
+ return ++counter.value;
59
+ }
60
+ function registerGenerator(context, generator) {
61
+ const id = nextGeneratorId(context);
62
+ const registry = getGeneratorRegistry(context);
63
+ registry.set(id, generator);
64
+ return id;
65
+ }
66
+ function setupAsyncIteratorInfrastructure(context) {
67
+ if (setupContexts.has(context)) {
68
+ return;
69
+ }
70
+ setupContexts.add(context);
71
+ const nextFn = context.newFunction("__asyncIteratorNext__", (idHandle) => {
72
+ const id = context.getNumber(idHandle);
73
+ const registry = getGeneratorRegistry(context);
74
+ const generator = registry.get(id);
75
+ if (!generator) {
76
+ const deferred2 = context.newPromise();
77
+ const errorHandle = context.newError(`Generator ${id} not found`);
78
+ deferred2.reject(errorHandle);
79
+ errorHandle.dispose();
80
+ context.runtime.executePendingJobs();
81
+ return deferred2.handle;
82
+ }
83
+ const deferred = context.newPromise();
84
+ generator.next().then((result) => {
85
+ if (!context.alive)
86
+ return;
87
+ const resultHandle = import_marshal.marshal(context, {
88
+ value: result.value,
89
+ done: result.done
90
+ });
91
+ deferred.resolve(resultHandle);
92
+ resultHandle.dispose();
93
+ if (result.done) {
94
+ registry.delete(id);
95
+ }
96
+ context.runtime.executePendingJobs();
97
+ }).catch((error) => {
98
+ if (!context.alive)
99
+ return;
100
+ const errorHandle = context.newError(error instanceof Error ? error.message : String(error));
101
+ deferred.reject(errorHandle);
102
+ errorHandle.dispose();
103
+ registry.delete(id);
104
+ context.runtime.executePendingJobs();
105
+ });
106
+ return deferred.handle;
107
+ });
108
+ context.setProp(context.global, "__asyncIteratorNext__", nextFn);
109
+ nextFn.dispose();
110
+ const returnFn = context.newFunction("__asyncIteratorReturn__", (idHandle, valueHandle) => {
111
+ const id = context.getNumber(idHandle);
112
+ const value = import_unmarshal.unmarshal(context, valueHandle);
113
+ const registry = getGeneratorRegistry(context);
114
+ const generator = registry.get(id);
115
+ const deferred = context.newPromise();
116
+ if (!generator) {
117
+ const resultHandle = import_marshal.marshal(context, { value, done: true });
118
+ deferred.resolve(resultHandle);
119
+ resultHandle.dispose();
120
+ context.runtime.executePendingJobs();
121
+ return deferred.handle;
122
+ }
123
+ generator.return(value).then((result) => {
124
+ if (!context.alive)
125
+ return;
126
+ const resultHandle = import_marshal.marshal(context, {
127
+ value: result.value,
128
+ done: result.done
129
+ });
130
+ deferred.resolve(resultHandle);
131
+ resultHandle.dispose();
132
+ registry.delete(id);
133
+ context.runtime.executePendingJobs();
134
+ }).catch((error) => {
135
+ if (!context.alive)
136
+ return;
137
+ const errorHandle = context.newError(error instanceof Error ? error.message : String(error));
138
+ deferred.reject(errorHandle);
139
+ errorHandle.dispose();
140
+ registry.delete(id);
141
+ context.runtime.executePendingJobs();
142
+ });
143
+ return deferred.handle;
144
+ });
145
+ context.setProp(context.global, "__asyncIteratorReturn__", returnFn);
146
+ returnFn.dispose();
147
+ const throwFn = context.newFunction("__asyncIteratorThrow__", (idHandle, errorHandle) => {
148
+ const id = context.getNumber(idHandle);
149
+ const errorValue = import_unmarshal.unmarshal(context, errorHandle);
150
+ const registry = getGeneratorRegistry(context);
151
+ const generator = registry.get(id);
152
+ const deferred = context.newPromise();
153
+ if (!generator) {
154
+ const errHandle = context.newError(errorValue instanceof Error ? errorValue.message : String(errorValue));
155
+ deferred.reject(errHandle);
156
+ errHandle.dispose();
157
+ context.runtime.executePendingJobs();
158
+ return deferred.handle;
159
+ }
160
+ const error = errorValue instanceof Error ? errorValue : new Error(String(errorValue));
161
+ generator.throw(error).then((result) => {
162
+ if (!context.alive)
163
+ return;
164
+ const resultHandle = import_marshal.marshal(context, {
165
+ value: result.value,
166
+ done: result.done
167
+ });
168
+ deferred.resolve(resultHandle);
169
+ resultHandle.dispose();
170
+ if (result.done) {
171
+ registry.delete(id);
172
+ }
173
+ context.runtime.executePendingJobs();
174
+ }).catch((err) => {
175
+ if (!context.alive)
176
+ return;
177
+ const errHandle = context.newError(err instanceof Error ? err.message : String(err));
178
+ deferred.reject(errHandle);
179
+ errHandle.dispose();
180
+ registry.delete(id);
181
+ context.runtime.executePendingJobs();
182
+ });
183
+ return deferred.handle;
184
+ });
185
+ context.setProp(context.global, "__asyncIteratorThrow__", throwFn);
186
+ throwFn.dispose();
187
+ }
39
188
  function defineFunction(context, name, fn) {
40
189
  return context.newFunction(name, (...argHandles) => {
41
190
  const args = argHandles.map((h) => import_unmarshal.unmarshal(context, h));
@@ -52,11 +201,17 @@ function defineAsyncFunction(context, name, fn) {
52
201
  const args = argHandles.map((h) => import_unmarshal.unmarshal(context, h));
53
202
  const deferred = context.newPromise();
54
203
  fn(...args).then((result) => {
204
+ if (!context.alive) {
205
+ return;
206
+ }
55
207
  const resultHandle = import_marshal.marshal(context, result);
56
208
  deferred.resolve(resultHandle);
57
209
  resultHandle.dispose();
58
210
  context.runtime.executePendingJobs();
59
211
  }).catch((error) => {
212
+ if (!context.alive) {
213
+ return;
214
+ }
60
215
  const errorHandle = import_marshal.marshal(context, error instanceof Error ? { name: error.name, message: error.message } : { message: String(error) });
61
216
  deferred.reject(errorHandle);
62
217
  errorHandle.dispose();
@@ -65,6 +220,39 @@ function defineAsyncFunction(context, name, fn) {
65
220
  return deferred.handle;
66
221
  });
67
222
  }
223
+ function defineAsyncIteratorFunction(context, name, fn) {
224
+ setupAsyncIteratorInfrastructure(context);
225
+ return context.newFunction(name, (...argHandles) => {
226
+ const args = argHandles.map((h) => import_unmarshal.unmarshal(context, h));
227
+ try {
228
+ const generator = fn(...args);
229
+ const generatorId = registerGenerator(context, generator);
230
+ const result = context.evalCode(`({
231
+ [Symbol.asyncIterator]() {
232
+ return {
233
+ next: () => __asyncIteratorNext__(${generatorId}),
234
+ return: (v) => __asyncIteratorReturn__(${generatorId}, v),
235
+ throw: (e) => __asyncIteratorThrow__(${generatorId}, e)
236
+ };
237
+ }
238
+ })`);
239
+ if (result.error) {
240
+ const err = context.dump(result.error);
241
+ result.error.dispose();
242
+ const registry = getGeneratorRegistry(context);
243
+ registry.delete(generatorId);
244
+ throw context.newError(String(err));
245
+ }
246
+ return result.value;
247
+ } catch (error) {
248
+ throw context.newError(error instanceof Error ? error.message : String(error));
249
+ }
250
+ });
251
+ }
252
+ function cleanupAsyncIterators(context) {
253
+ generatorRegistries.delete(context);
254
+ generatorCounters.delete(context);
255
+ }
68
256
  })
69
257
 
70
- //# debugId=561C450345A3A77C64756E2164756E21
258
+ //# debugId=679B9EDB41D36FF564756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/function-builder.ts"],
4
4
  "sourcesContent": [
5
- "import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport { unmarshal } from \"./unmarshal.cjs\";\nimport { marshal } from \"./marshal.cjs\";\n\n/**\n * Define a global function in the QuickJS context\n *\n * @returns Handle to the function (caller must manage disposal)\n *\n * @example\n * const logFn = defineFunction(context, \"log\", (...args) => {\n * console.log(\"[QuickJS]\", ...args);\n * });\n * context.setProp(context.global, \"log\", logFn);\n */\nexport function defineFunction(\n context: QuickJSContext,\n name: string,\n fn: (...args: unknown[]) => unknown\n): QuickJSHandle {\n return context.newFunction(name, (...argHandles) => {\n // Unmarshal arguments\n const args = argHandles.map((h) => unmarshal(context, h));\n\n try {\n // Call host function\n const result = fn(...args);\n\n // Marshal result\n return marshal(context, result);\n } catch (error) {\n // Throw error in QuickJS\n throw context.newError(\n error instanceof Error ? error.message : String(error)\n );\n }\n });\n}\n\n/**\n * Define an async function that returns a promise to QuickJS\n *\n * @example\n * const fetchFn = defineAsyncFunction(context, \"fetch\", async (url) => {\n * const response = await fetch(String(url));\n * return response.text();\n * });\n */\nexport function defineAsyncFunction(\n context: QuickJSContext,\n name: string,\n fn: (...args: unknown[]) => Promise<unknown>\n): QuickJSHandle {\n return context.newFunction(name, (...argHandles) => {\n // Unmarshal arguments\n const args = argHandles.map((h) => unmarshal(context, h));\n\n // Create a promise in QuickJS\n const deferred = context.newPromise();\n\n // Call the async function\n fn(...args)\n .then((result) => {\n const resultHandle = marshal(context, result);\n deferred.resolve(resultHandle);\n resultHandle.dispose();\n context.runtime.executePendingJobs();\n })\n .catch((error) => {\n const errorHandle = marshal(\n context,\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) }\n );\n deferred.reject(errorHandle);\n errorHandle.dispose();\n context.runtime.executePendingJobs();\n });\n\n return deferred.handle;\n });\n}\n"
5
+ "import type { QuickJSContext, QuickJSHandle } from \"quickjs-emscripten\";\nimport { unmarshal } from \"./unmarshal.cjs\";\nimport { marshal } from \"./marshal.cjs\";\n\n/**\n * Registry for async generators, scoped per-context.\n * Uses WeakMap to automatically clean up when context is GC'd.\n */\nconst generatorRegistries = new WeakMap<\n QuickJSContext,\n Map<number, AsyncGenerator<unknown, unknown, unknown>>\n>();\n\n/**\n * Counter for generating unique generator IDs per context.\n */\nconst generatorCounters = new WeakMap<QuickJSContext, { value: number }>();\n\n/**\n * Track which contexts have had async iterator infrastructure set up.\n */\nconst setupContexts = new WeakSet<QuickJSContext>();\n\n/**\n * Get or create the generator registry for a context.\n */\nfunction getGeneratorRegistry(\n context: QuickJSContext\n): Map<number, AsyncGenerator<unknown, unknown, unknown>> {\n let registry = generatorRegistries.get(context);\n if (!registry) {\n registry = new Map();\n generatorRegistries.set(context, registry);\n }\n return registry;\n}\n\n/**\n * Get next generator ID for a context.\n */\nfunction nextGeneratorId(context: QuickJSContext): number {\n let counter = generatorCounters.get(context);\n if (!counter) {\n counter = { value: 0 };\n generatorCounters.set(context, counter);\n }\n return ++counter.value;\n}\n\n/**\n * Register a generator and return its ID.\n */\nfunction registerGenerator(\n context: QuickJSContext,\n generator: AsyncGenerator<unknown, unknown, unknown>\n): number {\n const id = nextGeneratorId(context);\n const registry = getGeneratorRegistry(context);\n registry.set(id, generator);\n return id;\n}\n\n/**\n * Setup async iterator infrastructure helpers in the context.\n * These are global functions that proxy to host-side generators.\n */\nfunction setupAsyncIteratorInfrastructure(context: QuickJSContext): void {\n if (setupContexts.has(context)) {\n return;\n }\n setupContexts.add(context);\n\n // __asyncIteratorNext__(id) - calls generator.next()\n const nextFn = context.newFunction(\n \"__asyncIteratorNext__\",\n (idHandle: QuickJSHandle) => {\n const id = context.getNumber(idHandle);\n const registry = getGeneratorRegistry(context);\n const generator = registry.get(id);\n\n if (!generator) {\n // Generator not found - already cleaned up or invalid ID\n const deferred = context.newPromise();\n const errorHandle = context.newError(`Generator ${id} not found`);\n deferred.reject(errorHandle);\n errorHandle.dispose();\n context.runtime.executePendingJobs();\n return deferred.handle;\n }\n\n const deferred = context.newPromise();\n\n generator\n .next()\n .then((result) => {\n if (!context.alive) return;\n\n const resultHandle = marshal(context, {\n value: result.value,\n done: result.done,\n });\n deferred.resolve(resultHandle);\n resultHandle.dispose();\n\n // Clean up if done\n if (result.done) {\n registry.delete(id);\n }\n\n context.runtime.executePendingJobs();\n })\n .catch((error) => {\n if (!context.alive) return;\n\n // Create a proper Error object for rejection\n const errorHandle = context.newError(\n error instanceof Error ? error.message : String(error)\n );\n deferred.reject(errorHandle);\n errorHandle.dispose();\n\n // Clean up on error\n registry.delete(id);\n\n context.runtime.executePendingJobs();\n });\n\n return deferred.handle;\n }\n );\n context.setProp(context.global, \"__asyncIteratorNext__\", nextFn);\n nextFn.dispose();\n\n // __asyncIteratorReturn__(id, value) - calls generator.return(value)\n const returnFn = context.newFunction(\n \"__asyncIteratorReturn__\",\n (idHandle: QuickJSHandle, valueHandle: QuickJSHandle) => {\n const id = context.getNumber(idHandle);\n const value = unmarshal(context, valueHandle);\n const registry = getGeneratorRegistry(context);\n const generator = registry.get(id);\n\n const deferred = context.newPromise();\n\n if (!generator) {\n // Generator not found - return a completed result\n const resultHandle = marshal(context, { value, done: true });\n deferred.resolve(resultHandle);\n resultHandle.dispose();\n context.runtime.executePendingJobs();\n return deferred.handle;\n }\n\n generator\n .return(value)\n .then((result) => {\n if (!context.alive) return;\n\n const resultHandle = marshal(context, {\n value: result.value,\n done: result.done,\n });\n deferred.resolve(resultHandle);\n resultHandle.dispose();\n\n // Always clean up after return\n registry.delete(id);\n\n context.runtime.executePendingJobs();\n })\n .catch((error) => {\n if (!context.alive) return;\n\n const errorHandle = context.newError(\n error instanceof Error ? error.message : String(error)\n );\n deferred.reject(errorHandle);\n errorHandle.dispose();\n\n registry.delete(id);\n\n context.runtime.executePendingJobs();\n });\n\n return deferred.handle;\n }\n );\n context.setProp(context.global, \"__asyncIteratorReturn__\", returnFn);\n returnFn.dispose();\n\n // __asyncIteratorThrow__(id, error) - calls generator.throw(error)\n const throwFn = context.newFunction(\n \"__asyncIteratorThrow__\",\n (idHandle: QuickJSHandle, errorHandle: QuickJSHandle) => {\n const id = context.getNumber(idHandle);\n const errorValue = unmarshal(context, errorHandle);\n const registry = getGeneratorRegistry(context);\n const generator = registry.get(id);\n\n const deferred = context.newPromise();\n\n if (!generator) {\n // Generator not found - reject with a proper error\n const errHandle = context.newError(\n errorValue instanceof Error ? errorValue.message : String(errorValue)\n );\n deferred.reject(errHandle);\n errHandle.dispose();\n context.runtime.executePendingJobs();\n return deferred.handle;\n }\n\n // Convert to Error if needed\n const error =\n errorValue instanceof Error\n ? errorValue\n : new Error(String(errorValue));\n\n generator\n .throw(error)\n .then((result) => {\n if (!context.alive) return;\n\n const resultHandle = marshal(context, {\n value: result.value,\n done: result.done,\n });\n deferred.resolve(resultHandle);\n resultHandle.dispose();\n\n if (result.done) {\n registry.delete(id);\n }\n\n context.runtime.executePendingJobs();\n })\n .catch((err) => {\n if (!context.alive) return;\n\n const errHandle = context.newError(\n err instanceof Error ? err.message : String(err)\n );\n deferred.reject(errHandle);\n errHandle.dispose();\n\n registry.delete(id);\n\n context.runtime.executePendingJobs();\n });\n\n return deferred.handle;\n }\n );\n context.setProp(context.global, \"__asyncIteratorThrow__\", throwFn);\n throwFn.dispose();\n}\n\n/**\n * Define a global function in the QuickJS context\n *\n * @returns Handle to the function (caller must manage disposal)\n *\n * @example\n * const logFn = defineFunction(context, \"log\", (...args) => {\n * console.log(\"[QuickJS]\", ...args);\n * });\n * context.setProp(context.global, \"log\", logFn);\n */\nexport function defineFunction(\n context: QuickJSContext,\n name: string,\n fn: (...args: unknown[]) => unknown\n): QuickJSHandle {\n return context.newFunction(name, (...argHandles) => {\n // Unmarshal arguments\n const args = argHandles.map((h) => unmarshal(context, h));\n\n try {\n // Call host function\n const result = fn(...args);\n\n // Marshal result\n return marshal(context, result);\n } catch (error) {\n // Throw error in QuickJS\n throw context.newError(\n error instanceof Error ? error.message : String(error)\n );\n }\n });\n}\n\n/**\n * Define an async function that returns a promise to QuickJS\n *\n * @example\n * const fetchFn = defineAsyncFunction(context, \"fetch\", async (url) => {\n * const response = await fetch(String(url));\n * return response.text();\n * });\n */\nexport function defineAsyncFunction(\n context: QuickJSContext,\n name: string,\n fn: (...args: unknown[]) => Promise<unknown>\n): QuickJSHandle {\n return context.newFunction(name, (...argHandles) => {\n // Unmarshal arguments\n const args = argHandles.map((h) => unmarshal(context, h));\n\n // Create a promise in QuickJS\n const deferred = context.newPromise();\n\n // Call the async function\n fn(...args)\n .then((result) => {\n // Guard: Check if context is still alive\n if (!context.alive) {\n return;\n }\n const resultHandle = marshal(context, result);\n deferred.resolve(resultHandle);\n resultHandle.dispose();\n context.runtime.executePendingJobs();\n })\n .catch((error) => {\n // Guard: Check if context is still alive\n if (!context.alive) {\n return;\n }\n const errorHandle = marshal(\n context,\n error instanceof Error\n ? { name: error.name, message: error.message }\n : { message: String(error) }\n );\n deferred.reject(errorHandle);\n errorHandle.dispose();\n context.runtime.executePendingJobs();\n });\n\n return deferred.handle;\n });\n}\n\n/**\n * Define an async iterator function that returns an async iterable to QuickJS.\n * The host function should be an async generator.\n *\n * @example\n * const streamFn = defineAsyncIteratorFunction(context, \"stream\", async function* (n) {\n * for (let i = 0; i < n; i++) {\n * yield i;\n * }\n * return \"done\";\n * });\n *\n * // In QuickJS:\n * // for await (const value of stream(3)) { console.log(value); }\n * // Outputs: 0, 1, 2\n */\nexport function defineAsyncIteratorFunction(\n context: QuickJSContext,\n name: string,\n fn: (...args: unknown[]) => AsyncGenerator<unknown, unknown, unknown>\n): QuickJSHandle {\n // Ensure infrastructure is set up\n setupAsyncIteratorInfrastructure(context);\n\n return context.newFunction(name, (...argHandles) => {\n // Unmarshal arguments\n const args = argHandles.map((h) => unmarshal(context, h));\n\n try {\n // Call host function to get generator instance\n const generator = fn(...args);\n\n // Register generator and get ID\n const generatorId = registerGenerator(context, generator);\n\n // Create proxy object that implements async iterator protocol\n // This object when iterated will call our infrastructure helpers\n const result = context.evalCode(`({\n [Symbol.asyncIterator]() {\n return {\n next: () => __asyncIteratorNext__(${generatorId}),\n return: (v) => __asyncIteratorReturn__(${generatorId}, v),\n throw: (e) => __asyncIteratorThrow__(${generatorId}, e)\n };\n }\n })`);\n\n if (result.error) {\n const err = context.dump(result.error);\n result.error.dispose();\n // Clean up the registered generator since we failed\n const registry = getGeneratorRegistry(context);\n registry.delete(generatorId);\n throw context.newError(String(err));\n }\n\n return result.value;\n } catch (error) {\n // Throw error in QuickJS\n throw context.newError(\n error instanceof Error ? error.message : String(error)\n );\n }\n });\n}\n\n/**\n * Clean up all async iterator state for a context.\n * Should be called before context disposal.\n */\nexport function cleanupAsyncIterators(context: QuickJSContext): void {\n generatorRegistries.delete(context);\n generatorCounters.delete(context);\n // Note: setupContexts uses WeakSet, so no need to explicitly delete\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAC0B,IAA1B;AACwB,IAAxB;AAaO,SAAS,cAAc,CAC5B,SACA,MACA,IACe;AAAA,EACf,OAAO,QAAQ,YAAY,MAAM,IAAI,eAAe;AAAA,IAElD,MAAM,OAAO,WAAW,IAAI,CAAC,MAAM,2BAAU,SAAS,CAAC,CAAC;AAAA,IAExD,IAAI;AAAA,MAEF,MAAM,SAAS,GAAG,GAAG,IAAI;AAAA,MAGzB,OAAO,uBAAQ,SAAS,MAAM;AAAA,MAC9B,OAAO,OAAO;AAAA,MAEd,MAAM,QAAQ,SACZ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA;AAAA,GAEH;AAAA;AAYI,SAAS,mBAAmB,CACjC,SACA,MACA,IACe;AAAA,EACf,OAAO,QAAQ,YAAY,MAAM,IAAI,eAAe;AAAA,IAElD,MAAM,OAAO,WAAW,IAAI,CAAC,MAAM,2BAAU,SAAS,CAAC,CAAC;AAAA,IAGxD,MAAM,WAAW,QAAQ,WAAW;AAAA,IAGpC,GAAG,GAAG,IAAI,EACP,KAAK,CAAC,WAAW;AAAA,MAChB,MAAM,eAAe,uBAAQ,SAAS,MAAM;AAAA,MAC5C,SAAS,QAAQ,YAAY;AAAA,MAC7B,aAAa,QAAQ;AAAA,MACrB,QAAQ,QAAQ,mBAAmB;AAAA,KACpC,EACA,MAAM,CAAC,UAAU;AAAA,MAChB,MAAM,cAAc,uBAClB,SACA,iBAAiB,QACb,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,IAC3C,EAAE,SAAS,OAAO,KAAK,EAAE,CAC/B;AAAA,MACA,SAAS,OAAO,WAAW;AAAA,MAC3B,YAAY,QAAQ;AAAA,MACpB,QAAQ,QAAQ,mBAAmB;AAAA,KACpC;AAAA,IAEH,OAAO,SAAS;AAAA,GACjB;AAAA;",
8
- "debugId": "561C450345A3A77C64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "679B9EDB41D36FF564756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -58,6 +58,7 @@ __export(exports_src, {
58
58
  getClassInstanceState: () => import_class_helpers.getClassInstanceState,
59
59
  defineFunction: () => import_function_builder.defineFunction,
60
60
  defineClass: () => import_class_builder2.defineClass,
61
+ defineAsyncIteratorFunction: () => import_function_builder.defineAsyncIteratorFunction,
61
62
  defineAsyncFunction: () => import_function_builder.defineAsyncFunction,
62
63
  createWritableStream: () => import_writable_stream2.createWritableStream,
63
64
  createURLSearchParamsClass: () => import_url_search_params2.createURLSearchParamsClass,
@@ -79,6 +80,7 @@ __export(exports_src, {
79
80
  cleanupUnmarshaledHandles: () => import_unmarshal.cleanupUnmarshaledHandles,
80
81
  cleanupInstanceStateById: () => import_instance_state.cleanupInstanceState,
81
82
  cleanupInstanceState: () => import_class_builder2.cleanupInstanceState,
83
+ cleanupAsyncIterators: () => import_function_builder.cleanupAsyncIterators,
82
84
  classCoercer: () => import_coerce.classCoercer,
83
85
  addURLSearchParamsLinkage: () => import_url2.addURLSearchParamsLinkage,
84
86
  addURLSearchParamsGetter: () => import_url2.addURLSearchParamsGetter,
@@ -285,4 +287,4 @@ function setupCore(context, options) {
285
287
  }
286
288
  })
287
289
 
288
- //# debugId=AAC8B5BEA5BE896D64756E2164756E21
290
+ //# debugId=2704213322BFE26C64756E2164756E21