@ricsam/isolate 0.1.5 → 0.1.7

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 (37) hide show
  1. package/README.md +26 -6
  2. package/dist/cjs/internal/async-context/index.cjs +269 -8
  3. package/dist/cjs/internal/async-context/index.cjs.map +3 -3
  4. package/dist/cjs/internal/core/index.cjs +12 -4
  5. package/dist/cjs/internal/core/index.cjs.map +3 -3
  6. package/dist/cjs/internal/fetch/index.cjs +52 -13
  7. package/dist/cjs/internal/fetch/index.cjs.map +3 -3
  8. package/dist/cjs/internal/module-loader/bundle.cjs +111 -35
  9. package/dist/cjs/internal/module-loader/bundle.cjs.map +3 -3
  10. package/dist/cjs/internal/runtime/index.cjs +2 -2
  11. package/dist/cjs/internal/runtime/index.cjs.map +2 -2
  12. package/dist/cjs/internal/server/index.cjs +150 -19
  13. package/dist/cjs/internal/server/index.cjs.map +3 -3
  14. package/dist/cjs/internal/timers/index.cjs +39 -9
  15. package/dist/cjs/internal/timers/index.cjs.map +3 -3
  16. package/dist/cjs/package.json +1 -1
  17. package/dist/cjs/server/app-server.cjs +12 -10
  18. package/dist/cjs/server/app-server.cjs.map +3 -3
  19. package/dist/mjs/internal/async-context/index.mjs +269 -8
  20. package/dist/mjs/internal/async-context/index.mjs.map +3 -3
  21. package/dist/mjs/internal/core/index.mjs +12 -4
  22. package/dist/mjs/internal/core/index.mjs.map +3 -3
  23. package/dist/mjs/internal/fetch/index.mjs +52 -13
  24. package/dist/mjs/internal/fetch/index.mjs.map +3 -3
  25. package/dist/mjs/internal/module-loader/bundle.mjs +111 -35
  26. package/dist/mjs/internal/module-loader/bundle.mjs.map +3 -3
  27. package/dist/mjs/internal/runtime/index.mjs +2 -2
  28. package/dist/mjs/internal/runtime/index.mjs.map +2 -2
  29. package/dist/mjs/internal/server/index.mjs +150 -19
  30. package/dist/mjs/internal/server/index.mjs.map +3 -3
  31. package/dist/mjs/internal/timers/index.mjs +39 -9
  32. package/dist/mjs/internal/timers/index.mjs.map +3 -3
  33. package/dist/mjs/package.json +1 -1
  34. package/dist/mjs/server/app-server.mjs +12 -10
  35. package/dist/mjs/server/app-server.mjs.map +3 -3
  36. package/dist/types/internal/server/index.d.ts +7 -2
  37. package/package.json +2 -2
package/README.md CHANGED
@@ -55,14 +55,34 @@ What is currently supported:
55
55
  - `AsyncContext.Snapshot`
56
56
  - `node:async_hooks` `AsyncLocalStorage`
57
57
  - `node:async_hooks` `AsyncResource`
58
+ - `node:async_hooks` `createHook()`
59
+ - `node:async_hooks` `executionAsyncId()`
60
+ - `node:async_hooks` `triggerAsyncId()`
61
+ - `node:async_hooks` `executionAsyncResource()`
62
+ - `node:async_hooks` `asyncWrapProviders`
58
63
 
59
- What is intentionally not implemented in `node:async_hooks` yet:
64
+ Hook callbacks observe sandbox-managed resources such as promises, timers, host callback bridges, and user-created `AsyncResource`s. This is still not a claim of full Node internals parity outside the sandbox runtime.
60
65
 
61
- - `createHook()`
62
- - `executionAsyncId()`
63
- - `triggerAsyncId()`
64
- - `executionAsyncResource()`
65
- - `asyncWrapProviders`
66
+ ```ts
67
+ import {
68
+ createHook,
69
+ executionAsyncResource,
70
+ } from "node:async_hooks";
71
+
72
+ const hook = createHook({
73
+ init(asyncId, type, triggerAsyncId, resource) {
74
+ resource.requestTag = type + ":" + asyncId;
75
+ },
76
+ before() {
77
+ console.log(executionAsyncResource().requestTag ?? null);
78
+ },
79
+ }).enable();
80
+
81
+ setTimeout(() => {
82
+ console.log(executionAsyncResource().requestTag);
83
+ hook.disable();
84
+ }, 0);
85
+ ```
66
86
 
67
87
  ## Quick Start
68
88
 
@@ -57,6 +57,7 @@ var ASYNC_CONTEXT_BOOTSTRAP = `
57
57
  || !native
58
58
  || typeof native.getContinuationPreservedEmbedderData !== "function"
59
59
  || typeof native.setContinuationPreservedEmbedderData !== "function"
60
+ || typeof native.setPromiseHooks !== "function"
60
61
  ) {
61
62
  throw new Error(
62
63
  "The installed isolated-vm runtime does not expose async context support. " +
@@ -97,17 +98,259 @@ var ASYNC_CONTEXT_BOOTSTRAP = `
97
98
  enumerable: false,
98
99
  value: true,
99
100
  });
100
- const currentAsyncResource = new AsyncContext.Variable({
101
- name: "isolate.asyncResource",
102
- defaultValue: undefined,
101
+
102
+ const topLevelResource = {};
103
+ const topLevelExecutionState = {
104
+ asyncId: 1,
105
+ triggerAsyncId: 0,
106
+ type: "ROOT",
107
+ resource: topLevelResource,
108
+ destroyed: false,
109
+ };
110
+ const currentExecutionState = new AsyncContext.Variable({
111
+ name: "isolate.executionState",
112
+ defaultValue: topLevelExecutionState,
103
113
  });
104
114
 
105
- const wrapCallback = (callback) => {
115
+ const promiseStateByPromise = new WeakMap();
116
+ const activeHooks = new Map();
117
+ const promiseFrameStack = [];
118
+ const kWrappedState = Symbol("isolate.asyncResourceState");
119
+ const kWrappedDestroy = Symbol("isolate.destroyAsyncResource");
120
+ let nextAsyncId = 2;
121
+ let hookDispatchDepth = 0;
122
+ let promiseHooksEnabled = false;
123
+
124
+ function getCurrentExecutionState() {
125
+ return currentExecutionState.get();
126
+ }
127
+
128
+ function normalizeType(type, fallback) {
129
+ if (typeof type === "string" && type.length > 0) {
130
+ return type;
131
+ }
132
+ return fallback;
133
+ }
134
+
135
+ function normalizeTriggerAsyncId(triggerAsyncId) {
136
+ return Number.isSafeInteger(triggerAsyncId) && triggerAsyncId >= 0
137
+ ? triggerAsyncId
138
+ : undefined;
139
+ }
140
+
141
+ function dispatchHook(name, args) {
142
+ if (hookDispatchDepth > 0 || activeHooks.size === 0) {
143
+ return;
144
+ }
145
+
146
+ hookDispatchDepth++;
147
+ try {
148
+ for (const [hook, callbacks] of Array.from(activeHooks.entries())) {
149
+ const callback = callbacks[name];
150
+ if (typeof callback === "function") {
151
+ Reflect.apply(callback, hook, args);
152
+ }
153
+ }
154
+ } finally {
155
+ hookDispatchDepth--;
156
+ }
157
+ }
158
+
159
+ function createResource(type, resource, options = {}) {
160
+ const normalizedOptions =
161
+ options && typeof options === "object" ? options : {};
162
+ const state = {
163
+ asyncId: nextAsyncId++,
164
+ triggerAsyncId:
165
+ normalizeTriggerAsyncId(normalizedOptions.triggerAsyncId)
166
+ ?? getCurrentExecutionState().asyncId,
167
+ type: normalizeType(type, "isolate.resource"),
168
+ resource:
169
+ resource !== undefined && resource !== null ? resource : {},
170
+ destroyed: false,
171
+ };
172
+
173
+ if (normalizedOptions.emitInit !== false) {
174
+ dispatchHook("init", [
175
+ state.asyncId,
176
+ state.type,
177
+ state.triggerAsyncId,
178
+ state.resource,
179
+ ]);
180
+ }
181
+
182
+ return state;
183
+ }
184
+
185
+ function enterResource(resourceState) {
186
+ return AsyncContextFrame.exchange(
187
+ new AsyncContextFrame(currentExecutionState, resourceState),
188
+ );
189
+ }
190
+
191
+ function destroyResource(resourceState) {
192
+ if (!resourceState || resourceState.destroyed) {
193
+ return false;
194
+ }
195
+ resourceState.destroyed = true;
196
+ dispatchHook("destroy", [resourceState.asyncId]);
197
+ return true;
198
+ }
199
+
200
+ function runWithResource(resourceState, fn, thisArg, args) {
201
+ const priorFrame = enterResource(resourceState);
202
+ let didRunBeforeHook = false;
203
+ try {
204
+ dispatchHook("before", [resourceState.asyncId]);
205
+ didRunBeforeHook = true;
206
+ return Reflect.apply(fn, thisArg, args);
207
+ } finally {
208
+ try {
209
+ if (didRunBeforeHook) {
210
+ dispatchHook("after", [resourceState.asyncId]);
211
+ }
212
+ } finally {
213
+ AsyncContextFrame.set(priorFrame);
214
+ }
215
+ }
216
+ }
217
+
218
+ function wrapCallback(callback, options = {}) {
106
219
  if (typeof callback !== "function") {
107
220
  return callback;
108
221
  }
109
- return AsyncContext.Snapshot.wrap(callback);
110
- };
222
+
223
+ const normalizedOptions =
224
+ options && typeof options === "object" ? options : {};
225
+ const snapshot = new AsyncContext.Snapshot();
226
+ const resourceState = createResource(
227
+ normalizedOptions.type,
228
+ normalizedOptions.resource,
229
+ normalizedOptions,
230
+ );
231
+
232
+ function wrapped(...args) {
233
+ const thisArg = normalizedOptions.thisArg === undefined
234
+ ? this
235
+ : normalizedOptions.thisArg;
236
+ return snapshot.run(
237
+ () => runWithResource(resourceState, callback, thisArg, args),
238
+ );
239
+ }
240
+
241
+ try {
242
+ Object.defineProperty(wrapped, "name", {
243
+ configurable: true,
244
+ value: callback.name ? "wrapped " + callback.name : "wrapped",
245
+ });
246
+ } catch {}
247
+
248
+ Object.defineProperty(wrapped, kWrappedState, {
249
+ configurable: false,
250
+ enumerable: false,
251
+ value: resourceState,
252
+ writable: false,
253
+ });
254
+ Object.defineProperty(wrapped, kWrappedDestroy, {
255
+ configurable: false,
256
+ enumerable: false,
257
+ value: () => destroyResource(resourceState),
258
+ writable: false,
259
+ });
260
+
261
+ return wrapped;
262
+ }
263
+
264
+ function releaseCallback(callback) {
265
+ if (typeof callback !== "function") {
266
+ return false;
267
+ }
268
+ const destroy = callback[kWrappedDestroy];
269
+ if (typeof destroy === "function") {
270
+ return destroy();
271
+ }
272
+ return false;
273
+ }
274
+
275
+ function onPromiseInit(promise, parentPromise) {
276
+ const parentState = (
277
+ parentPromise && typeof parentPromise === "object"
278
+ ? promiseStateByPromise.get(parentPromise)
279
+ : undefined
280
+ );
281
+ const promiseState = createResource("PROMISE", promise, {
282
+ triggerAsyncId: parentState?.asyncId ?? getCurrentExecutionState().asyncId,
283
+ });
284
+ promiseStateByPromise.set(promise, promiseState);
285
+ }
286
+
287
+ function onPromiseBefore(promise) {
288
+ const promiseState = promiseStateByPromise.get(promise);
289
+ if (!promiseState) {
290
+ return;
291
+ }
292
+ const priorFrame = enterResource(promiseState);
293
+ promiseFrameStack.push(priorFrame);
294
+ try {
295
+ dispatchHook("before", [promiseState.asyncId]);
296
+ } catch (error) {
297
+ promiseFrameStack.pop();
298
+ AsyncContextFrame.set(priorFrame);
299
+ throw error;
300
+ }
301
+ }
302
+
303
+ function onPromiseAfter(promise) {
304
+ const promiseState = promiseStateByPromise.get(promise);
305
+ if (!promiseState) {
306
+ return;
307
+ }
308
+ const priorFrame = promiseFrameStack.pop();
309
+ try {
310
+ dispatchHook("after", [promiseState.asyncId]);
311
+ } finally {
312
+ AsyncContextFrame.set(priorFrame);
313
+ }
314
+ }
315
+
316
+ function onPromiseResolve(promise) {
317
+ const promiseState = promiseStateByPromise.get(promise);
318
+ if (!promiseState) {
319
+ return;
320
+ }
321
+ dispatchHook("promiseResolve", [promiseState.asyncId]);
322
+ }
323
+
324
+ function refreshPromiseHooks() {
325
+ if (activeHooks.size > 0) {
326
+ if (!promiseHooksEnabled) {
327
+ native.setPromiseHooks(
328
+ onPromiseInit,
329
+ onPromiseBefore,
330
+ onPromiseAfter,
331
+ onPromiseResolve,
332
+ );
333
+ promiseHooksEnabled = true;
334
+ }
335
+ return;
336
+ }
337
+
338
+ if (promiseHooksEnabled) {
339
+ native.setPromiseHooks(undefined, undefined, undefined, undefined);
340
+ promiseFrameStack.length = 0;
341
+ promiseHooksEnabled = false;
342
+ }
343
+ }
344
+
345
+ function enableHook(hook, callbacks) {
346
+ activeHooks.set(hook, callbacks);
347
+ refreshPromiseHooks();
348
+ }
349
+
350
+ function disableHook(hook) {
351
+ activeHooks.delete(hook);
352
+ refreshPromiseHooks();
353
+ }
111
354
 
112
355
  Object.defineProperty(globalThis, "__isolateAsyncContextInternals", {
113
356
  configurable: true,
@@ -115,8 +358,25 @@ var ASYNC_CONTEXT_BOOTSTRAP = `
115
358
  writable: false,
116
359
  value: {
117
360
  AsyncContextFrame,
118
- currentAsyncResource,
361
+ topLevelExecutionState,
362
+ currentExecutionState,
363
+ getCurrentExecutionState,
364
+ executionAsyncId() {
365
+ return getCurrentExecutionState().asyncId;
366
+ },
367
+ triggerAsyncId() {
368
+ return getCurrentExecutionState().triggerAsyncId;
369
+ },
370
+ executionAsyncResource() {
371
+ return getCurrentExecutionState().resource;
372
+ },
373
+ createResource,
374
+ runWithResource,
375
+ destroyResource,
119
376
  wrapCallback,
377
+ releaseCallback,
378
+ enableHook,
379
+ disableHook,
120
380
  },
121
381
  });
122
382
  })();
@@ -129,6 +389,7 @@ async function setupAsyncContext(context) {
129
389
  && typeof globalThis.__ivmAsyncContextInternal === "object"
130
390
  && typeof globalThis.__ivmAsyncContextInternal?.getContinuationPreservedEmbedderData === "function"
131
391
  && typeof globalThis.__ivmAsyncContextInternal?.setContinuationPreservedEmbedderData === "function"
392
+ && typeof globalThis.__ivmAsyncContextInternal?.setPromiseHooks === "function"
132
393
  `);
133
394
  if (!supported) {
134
395
  throw new Error("The installed isolated-vm runtime does not support AsyncContext. " + "Use the async-context-enabled isolate engine build.");
@@ -137,4 +398,4 @@ async function setupAsyncContext(context) {
137
398
  return { supported };
138
399
  }
139
400
 
140
- //# debugId=68BD605C0C0582DB64756E2164756E21
401
+ //# debugId=890EACA6895F598664756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/internal/async-context/index.ts"],
4
4
  "sourcesContent": [
5
- "import type ivm from \"@ricsam/isolated-vm\";\n\nconst ASYNC_CONTEXT_BOOTSTRAP = `\n(function() {\n if (globalThis.__isolateAsyncContextInternals) {\n return;\n }\n\n const AsyncContext = globalThis.AsyncContext;\n const native = globalThis.__ivmAsyncContextInternal;\n if (\n !AsyncContext\n || typeof AsyncContext.Variable !== \"function\"\n || typeof AsyncContext.Snapshot !== \"function\"\n || !native\n || typeof native.getContinuationPreservedEmbedderData !== \"function\"\n || typeof native.setContinuationPreservedEmbedderData !== \"function\"\n ) {\n throw new Error(\n \"The installed isolated-vm runtime does not expose async context support. \" +\n \"Install the async-context-enabled isolate engine build.\"\n );\n }\n\n class AsyncContextFrame extends Map {\n constructor(store, value) {\n super(AsyncContextFrame.current() ?? undefined);\n if (arguments.length > 0) {\n this.set(store, value);\n }\n }\n\n static current() {\n return native.getContinuationPreservedEmbedderData();\n }\n\n static set(frame) {\n native.setContinuationPreservedEmbedderData(frame);\n }\n\n static exchange(frame) {\n const prior = this.current();\n this.set(frame);\n return prior;\n }\n\n static disable(store) {\n const frame = this.current();\n frame?.delete(store);\n }\n }\n\n Object.defineProperty(AsyncContextFrame, \"enabled\", {\n configurable: true,\n enumerable: false,\n value: true,\n });\n const currentAsyncResource = new AsyncContext.Variable({\n name: \"isolate.asyncResource\",\n defaultValue: undefined,\n });\n\n const wrapCallback = (callback) => {\n if (typeof callback !== \"function\") {\n return callback;\n }\n return AsyncContext.Snapshot.wrap(callback);\n };\n\n Object.defineProperty(globalThis, \"__isolateAsyncContextInternals\", {\n configurable: true,\n enumerable: false,\n writable: false,\n value: {\n AsyncContextFrame,\n currentAsyncResource,\n wrapCallback,\n },\n });\n})();\n`;\n\nexport interface AsyncContextHandle {\n supported: boolean;\n}\n\nexport async function setupAsyncContext(context: ivm.Context): Promise<AsyncContextHandle> {\n const supported = context.evalSync(`\n typeof globalThis.AsyncContext === \"object\"\n && typeof globalThis.AsyncContext?.Variable === \"function\"\n && typeof globalThis.AsyncContext?.Snapshot === \"function\"\n && typeof globalThis.__ivmAsyncContextInternal === \"object\"\n && typeof globalThis.__ivmAsyncContextInternal?.getContinuationPreservedEmbedderData === \"function\"\n && typeof globalThis.__ivmAsyncContextInternal?.setContinuationPreservedEmbedderData === \"function\"\n `) as boolean;\n\n if (!supported) {\n throw new Error(\n \"The installed isolated-vm runtime does not support AsyncContext. \" +\n \"Use the async-context-enabled isolate engine build.\"\n );\n }\n\n context.evalSync(ASYNC_CONTEXT_BOOTSTRAP);\n return { supported };\n}\n"
5
+ "import type ivm from \"@ricsam/isolated-vm\";\n\nconst ASYNC_CONTEXT_BOOTSTRAP = `\n(function() {\n if (globalThis.__isolateAsyncContextInternals) {\n return;\n }\n\n const AsyncContext = globalThis.AsyncContext;\n const native = globalThis.__ivmAsyncContextInternal;\n if (\n !AsyncContext\n || typeof AsyncContext.Variable !== \"function\"\n || typeof AsyncContext.Snapshot !== \"function\"\n || !native\n || typeof native.getContinuationPreservedEmbedderData !== \"function\"\n || typeof native.setContinuationPreservedEmbedderData !== \"function\"\n || typeof native.setPromiseHooks !== \"function\"\n ) {\n throw new Error(\n \"The installed isolated-vm runtime does not expose async context support. \" +\n \"Install the async-context-enabled isolate engine build.\"\n );\n }\n\n class AsyncContextFrame extends Map {\n constructor(store, value) {\n super(AsyncContextFrame.current() ?? undefined);\n if (arguments.length > 0) {\n this.set(store, value);\n }\n }\n\n static current() {\n return native.getContinuationPreservedEmbedderData();\n }\n\n static set(frame) {\n native.setContinuationPreservedEmbedderData(frame);\n }\n\n static exchange(frame) {\n const prior = this.current();\n this.set(frame);\n return prior;\n }\n\n static disable(store) {\n const frame = this.current();\n frame?.delete(store);\n }\n }\n\n Object.defineProperty(AsyncContextFrame, \"enabled\", {\n configurable: true,\n enumerable: false,\n value: true,\n });\n\n const topLevelResource = {};\n const topLevelExecutionState = {\n asyncId: 1,\n triggerAsyncId: 0,\n type: \"ROOT\",\n resource: topLevelResource,\n destroyed: false,\n };\n const currentExecutionState = new AsyncContext.Variable({\n name: \"isolate.executionState\",\n defaultValue: topLevelExecutionState,\n });\n\n const promiseStateByPromise = new WeakMap();\n const activeHooks = new Map();\n const promiseFrameStack = [];\n const kWrappedState = Symbol(\"isolate.asyncResourceState\");\n const kWrappedDestroy = Symbol(\"isolate.destroyAsyncResource\");\n let nextAsyncId = 2;\n let hookDispatchDepth = 0;\n let promiseHooksEnabled = false;\n\n function getCurrentExecutionState() {\n return currentExecutionState.get();\n }\n\n function normalizeType(type, fallback) {\n if (typeof type === \"string\" && type.length > 0) {\n return type;\n }\n return fallback;\n }\n\n function normalizeTriggerAsyncId(triggerAsyncId) {\n return Number.isSafeInteger(triggerAsyncId) && triggerAsyncId >= 0\n ? triggerAsyncId\n : undefined;\n }\n\n function dispatchHook(name, args) {\n if (hookDispatchDepth > 0 || activeHooks.size === 0) {\n return;\n }\n\n hookDispatchDepth++;\n try {\n for (const [hook, callbacks] of Array.from(activeHooks.entries())) {\n const callback = callbacks[name];\n if (typeof callback === \"function\") {\n Reflect.apply(callback, hook, args);\n }\n }\n } finally {\n hookDispatchDepth--;\n }\n }\n\n function createResource(type, resource, options = {}) {\n const normalizedOptions =\n options && typeof options === \"object\" ? options : {};\n const state = {\n asyncId: nextAsyncId++,\n triggerAsyncId:\n normalizeTriggerAsyncId(normalizedOptions.triggerAsyncId)\n ?? getCurrentExecutionState().asyncId,\n type: normalizeType(type, \"isolate.resource\"),\n resource:\n resource !== undefined && resource !== null ? resource : {},\n destroyed: false,\n };\n\n if (normalizedOptions.emitInit !== false) {\n dispatchHook(\"init\", [\n state.asyncId,\n state.type,\n state.triggerAsyncId,\n state.resource,\n ]);\n }\n\n return state;\n }\n\n function enterResource(resourceState) {\n return AsyncContextFrame.exchange(\n new AsyncContextFrame(currentExecutionState, resourceState),\n );\n }\n\n function destroyResource(resourceState) {\n if (!resourceState || resourceState.destroyed) {\n return false;\n }\n resourceState.destroyed = true;\n dispatchHook(\"destroy\", [resourceState.asyncId]);\n return true;\n }\n\n function runWithResource(resourceState, fn, thisArg, args) {\n const priorFrame = enterResource(resourceState);\n let didRunBeforeHook = false;\n try {\n dispatchHook(\"before\", [resourceState.asyncId]);\n didRunBeforeHook = true;\n return Reflect.apply(fn, thisArg, args);\n } finally {\n try {\n if (didRunBeforeHook) {\n dispatchHook(\"after\", [resourceState.asyncId]);\n }\n } finally {\n AsyncContextFrame.set(priorFrame);\n }\n }\n }\n\n function wrapCallback(callback, options = {}) {\n if (typeof callback !== \"function\") {\n return callback;\n }\n\n const normalizedOptions =\n options && typeof options === \"object\" ? options : {};\n const snapshot = new AsyncContext.Snapshot();\n const resourceState = createResource(\n normalizedOptions.type,\n normalizedOptions.resource,\n normalizedOptions,\n );\n\n function wrapped(...args) {\n const thisArg = normalizedOptions.thisArg === undefined\n ? this\n : normalizedOptions.thisArg;\n return snapshot.run(\n () => runWithResource(resourceState, callback, thisArg, args),\n );\n }\n\n try {\n Object.defineProperty(wrapped, \"name\", {\n configurable: true,\n value: callback.name ? \"wrapped \" + callback.name : \"wrapped\",\n });\n } catch {}\n\n Object.defineProperty(wrapped, kWrappedState, {\n configurable: false,\n enumerable: false,\n value: resourceState,\n writable: false,\n });\n Object.defineProperty(wrapped, kWrappedDestroy, {\n configurable: false,\n enumerable: false,\n value: () => destroyResource(resourceState),\n writable: false,\n });\n\n return wrapped;\n }\n\n function releaseCallback(callback) {\n if (typeof callback !== \"function\") {\n return false;\n }\n const destroy = callback[kWrappedDestroy];\n if (typeof destroy === \"function\") {\n return destroy();\n }\n return false;\n }\n\n function onPromiseInit(promise, parentPromise) {\n const parentState = (\n parentPromise && typeof parentPromise === \"object\"\n ? promiseStateByPromise.get(parentPromise)\n : undefined\n );\n const promiseState = createResource(\"PROMISE\", promise, {\n triggerAsyncId: parentState?.asyncId ?? getCurrentExecutionState().asyncId,\n });\n promiseStateByPromise.set(promise, promiseState);\n }\n\n function onPromiseBefore(promise) {\n const promiseState = promiseStateByPromise.get(promise);\n if (!promiseState) {\n return;\n }\n const priorFrame = enterResource(promiseState);\n promiseFrameStack.push(priorFrame);\n try {\n dispatchHook(\"before\", [promiseState.asyncId]);\n } catch (error) {\n promiseFrameStack.pop();\n AsyncContextFrame.set(priorFrame);\n throw error;\n }\n }\n\n function onPromiseAfter(promise) {\n const promiseState = promiseStateByPromise.get(promise);\n if (!promiseState) {\n return;\n }\n const priorFrame = promiseFrameStack.pop();\n try {\n dispatchHook(\"after\", [promiseState.asyncId]);\n } finally {\n AsyncContextFrame.set(priorFrame);\n }\n }\n\n function onPromiseResolve(promise) {\n const promiseState = promiseStateByPromise.get(promise);\n if (!promiseState) {\n return;\n }\n dispatchHook(\"promiseResolve\", [promiseState.asyncId]);\n }\n\n function refreshPromiseHooks() {\n if (activeHooks.size > 0) {\n if (!promiseHooksEnabled) {\n native.setPromiseHooks(\n onPromiseInit,\n onPromiseBefore,\n onPromiseAfter,\n onPromiseResolve,\n );\n promiseHooksEnabled = true;\n }\n return;\n }\n\n if (promiseHooksEnabled) {\n native.setPromiseHooks(undefined, undefined, undefined, undefined);\n promiseFrameStack.length = 0;\n promiseHooksEnabled = false;\n }\n }\n\n function enableHook(hook, callbacks) {\n activeHooks.set(hook, callbacks);\n refreshPromiseHooks();\n }\n\n function disableHook(hook) {\n activeHooks.delete(hook);\n refreshPromiseHooks();\n }\n\n Object.defineProperty(globalThis, \"__isolateAsyncContextInternals\", {\n configurable: true,\n enumerable: false,\n writable: false,\n value: {\n AsyncContextFrame,\n topLevelExecutionState,\n currentExecutionState,\n getCurrentExecutionState,\n executionAsyncId() {\n return getCurrentExecutionState().asyncId;\n },\n triggerAsyncId() {\n return getCurrentExecutionState().triggerAsyncId;\n },\n executionAsyncResource() {\n return getCurrentExecutionState().resource;\n },\n createResource,\n runWithResource,\n destroyResource,\n wrapCallback,\n releaseCallback,\n enableHook,\n disableHook,\n },\n });\n})();\n`;\n\nexport interface AsyncContextHandle {\n supported: boolean;\n}\n\nexport async function setupAsyncContext(context: ivm.Context): Promise<AsyncContextHandle> {\n const supported = context.evalSync(`\n typeof globalThis.AsyncContext === \"object\"\n && typeof globalThis.AsyncContext?.Variable === \"function\"\n && typeof globalThis.AsyncContext?.Snapshot === \"function\"\n && typeof globalThis.__ivmAsyncContextInternal === \"object\"\n && typeof globalThis.__ivmAsyncContextInternal?.getContinuationPreservedEmbedderData === \"function\"\n && typeof globalThis.__ivmAsyncContextInternal?.setContinuationPreservedEmbedderData === \"function\"\n && typeof globalThis.__ivmAsyncContextInternal?.setPromiseHooks === \"function\"\n `) as boolean;\n\n if (!supported) {\n throw new Error(\n \"The installed isolated-vm runtime does not support AsyncContext. \" +\n \"Use the async-context-enabled isolate engine build.\"\n );\n }\n\n context.evalSync(ASYNC_CONTEXT_BOOTSTRAP);\n return { supported };\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoFhC,eAAsB,iBAAiB,CAAC,SAAmD;AAAA,EACzF,MAAM,YAAY,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAOlC;AAAA,EAED,IAAI,CAAC,WAAW;AAAA,IACd,MAAM,IAAI,MACR,sEACA,qDACF;AAAA,EACF;AAAA,EAEA,QAAQ,SAAS,uBAAuB;AAAA,EACxC,OAAO,EAAE,UAAU;AAAA;",
8
- "debugId": "68BD605C0C0582DB64756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwVhC,eAAsB,iBAAiB,CAAC,SAAmD;AAAA,EACzF,MAAM,YAAY,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQlC;AAAA,EAED,IAAI,CAAC,WAAW;AAAA,IACd,MAAM,IAAI,MACR,sEACA,qDACF;AAAA,EACF;AAAA,EAEA,QAAQ,SAAS,uBAAuB;AAAA,EACxC,OAAO,EAAE,UAAU;AAAA;",
8
+ "debugId": "890EACA6895F598664756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1753,10 +1753,15 @@ async function injectAbortController(context) {
1753
1753
  // Use WeakMap for private state (similar to Blob pattern)
1754
1754
  const _abortSignalState = new WeakMap();
1755
1755
  const __wrapAsyncContextCallback = (callback) => (
1756
- typeof callback === 'function' && globalThis.AsyncContext?.Snapshot?.wrap
1757
- ? globalThis.AsyncContext.Snapshot.wrap(callback)
1756
+ typeof callback === 'function' && globalThis.__isolateAsyncContextInternals?.wrapCallback
1757
+ ? globalThis.__isolateAsyncContextInternals.wrapCallback(callback, { type: 'isolate.abort' })
1758
1758
  : callback
1759
1759
  );
1760
+ const __releaseAsyncContextCallback = (callback) => (
1761
+ typeof callback === 'function' && globalThis.__isolateAsyncContextInternals?.releaseCallback
1762
+ ? globalThis.__isolateAsyncContextInternals.releaseCallback(callback)
1763
+ : false
1764
+ );
1760
1765
 
1761
1766
  class AbortSignal {
1762
1767
  constructor() {
@@ -1817,7 +1822,10 @@ async function injectAbortController(context) {
1817
1822
  const idx = state.listeners.findIndex((entry) => (
1818
1823
  entry.original === listener || entry.wrapped === listener
1819
1824
  ));
1820
- if (idx !== -1) state.listeners.splice(idx, 1);
1825
+ if (idx !== -1) {
1826
+ __releaseAsyncContextCallback(state.listeners[idx].wrapped);
1827
+ state.listeners.splice(idx, 1);
1828
+ }
1821
1829
  }
1822
1830
  }
1823
1831
 
@@ -2750,4 +2758,4 @@ async function injectStreams(context, _stateMap) {
2750
2758
  context.evalSync(streamsCode);
2751
2759
  }
2752
2760
 
2753
- //# debugId=3ADD8E1C76B8563A64756E2164756E21
2761
+ //# debugId=42B699410F9B400664756E2164756E21