@ricsam/isolate 0.1.4 → 0.1.6

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 (80) hide show
  1. package/README.md +45 -2
  2. package/dist/cjs/internal/async-context/index.cjs +401 -0
  3. package/dist/cjs/internal/async-context/index.cjs.map +10 -0
  4. package/dist/cjs/internal/client/connection.cjs +175 -123
  5. package/dist/cjs/internal/client/connection.cjs.map +3 -3
  6. package/dist/cjs/internal/console/index.cjs +2 -2
  7. package/dist/cjs/internal/console/index.cjs.map +2 -2
  8. package/dist/cjs/internal/core/index.cjs +22 -6
  9. package/dist/cjs/internal/core/index.cjs.map +3 -3
  10. package/dist/cjs/internal/crypto/index.cjs +2 -2
  11. package/dist/cjs/internal/crypto/index.cjs.map +2 -2
  12. package/dist/cjs/internal/daemon/connection.cjs +77 -12
  13. package/dist/cjs/internal/daemon/connection.cjs.map +3 -3
  14. package/dist/cjs/internal/encoding/index.cjs.map +1 -1
  15. package/dist/cjs/internal/fetch/index.cjs +119 -18
  16. package/dist/cjs/internal/fetch/index.cjs.map +3 -3
  17. package/dist/cjs/internal/fetch/stream-state.cjs.map +1 -1
  18. package/dist/cjs/internal/fs/index.cjs +2 -2
  19. package/dist/cjs/internal/fs/index.cjs.map +2 -2
  20. package/dist/cjs/internal/module-loader/bundle.cjs +277 -1
  21. package/dist/cjs/internal/module-loader/bundle.cjs.map +3 -3
  22. package/dist/cjs/internal/path/index.cjs.map +1 -1
  23. package/dist/cjs/internal/playwright/index.cjs +2 -2
  24. package/dist/cjs/internal/playwright/index.cjs.map +2 -2
  25. package/dist/cjs/internal/runtime/index.cjs +78 -6
  26. package/dist/cjs/internal/runtime/index.cjs.map +3 -3
  27. package/dist/cjs/internal/test-environment/index.cjs +2 -2
  28. package/dist/cjs/internal/test-environment/index.cjs.map +2 -2
  29. package/dist/cjs/internal/timers/index.cjs +42 -7
  30. package/dist/cjs/internal/timers/index.cjs.map +3 -3
  31. package/dist/cjs/internal/typecheck/isolate-types.cjs +36 -1
  32. package/dist/cjs/internal/typecheck/isolate-types.cjs.map +3 -3
  33. package/dist/cjs/package.json +1 -1
  34. package/dist/mjs/internal/async-context/index.mjs +361 -0
  35. package/dist/mjs/internal/async-context/index.mjs.map +10 -0
  36. package/dist/mjs/internal/client/connection.mjs +176 -123
  37. package/dist/mjs/internal/client/connection.mjs.map +3 -3
  38. package/dist/mjs/internal/console/index.mjs +2 -2
  39. package/dist/mjs/internal/console/index.mjs.map +2 -2
  40. package/dist/mjs/internal/core/index.mjs +22 -6
  41. package/dist/mjs/internal/core/index.mjs.map +3 -3
  42. package/dist/mjs/internal/crypto/index.mjs +2 -2
  43. package/dist/mjs/internal/crypto/index.mjs.map +2 -2
  44. package/dist/mjs/internal/daemon/connection.mjs +77 -12
  45. package/dist/mjs/internal/daemon/connection.mjs.map +3 -3
  46. package/dist/mjs/internal/encoding/index.mjs.map +1 -1
  47. package/dist/mjs/internal/fetch/index.mjs +119 -18
  48. package/dist/mjs/internal/fetch/index.mjs.map +3 -3
  49. package/dist/mjs/internal/fetch/stream-state.mjs.map +1 -1
  50. package/dist/mjs/internal/fs/index.mjs +2 -2
  51. package/dist/mjs/internal/fs/index.mjs.map +2 -2
  52. package/dist/mjs/internal/module-loader/bundle.mjs +277 -1
  53. package/dist/mjs/internal/module-loader/bundle.mjs.map +3 -3
  54. package/dist/mjs/internal/path/index.mjs.map +1 -1
  55. package/dist/mjs/internal/playwright/index.mjs +2 -2
  56. package/dist/mjs/internal/playwright/index.mjs.map +2 -2
  57. package/dist/mjs/internal/runtime/index.mjs +78 -6
  58. package/dist/mjs/internal/runtime/index.mjs.map +3 -3
  59. package/dist/mjs/internal/test-environment/index.mjs +2 -2
  60. package/dist/mjs/internal/test-environment/index.mjs.map +2 -2
  61. package/dist/mjs/internal/timers/index.mjs +42 -7
  62. package/dist/mjs/internal/timers/index.mjs.map +3 -3
  63. package/dist/mjs/internal/typecheck/isolate-types.mjs +36 -1
  64. package/dist/mjs/internal/typecheck/isolate-types.mjs.map +3 -3
  65. package/dist/mjs/package.json +1 -1
  66. package/dist/types/internal/async-context/index.d.ts +5 -0
  67. package/dist/types/internal/console/index.d.ts +1 -1
  68. package/dist/types/internal/core/index.d.ts +2 -2
  69. package/dist/types/internal/crypto/index.d.ts +1 -1
  70. package/dist/types/internal/daemon/types.d.ts +1 -0
  71. package/dist/types/internal/encoding/index.d.ts +1 -1
  72. package/dist/types/internal/fetch/index.d.ts +1 -1
  73. package/dist/types/internal/fetch/stream-state.d.ts +1 -1
  74. package/dist/types/internal/fs/index.d.ts +1 -1
  75. package/dist/types/internal/path/index.d.ts +1 -1
  76. package/dist/types/internal/playwright/index.d.ts +1 -1
  77. package/dist/types/internal/test-environment/index.d.ts +1 -1
  78. package/dist/types/internal/timers/index.d.ts +1 -1
  79. package/dist/types/internal/typecheck/isolate-types.d.ts +2 -2
  80. package/package.json +8 -3
package/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # @ricsam/isolate
2
2
 
3
- `@ricsam/isolate` is a runtime-centric JavaScript sandbox built on [`isolated-vm`](https://github.com/nicknisi/isolated-vm). It gives you a single host API for running isolated code with web-style capabilities such as `fetch`, files, streams, server handlers, module loading, and Playwright-backed browser tests.
3
+ `@ricsam/isolate` is a runtime-centric JavaScript sandbox built on an async-context-enabled [`@ricsam/isolated-vm`](https://github.com/ricsam/isolated-vm) engine build. It gives you a single host API for running isolated code with web-style capabilities such as `fetch`, files, streams, server handlers, module loading, and Playwright-backed browser tests.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm add @ricsam/isolate isolated-vm
8
+ npm add @ricsam/isolate @ricsam/isolated-vm
9
9
  ```
10
10
 
11
+ The `@ricsam/isolated-vm` peer includes the `createContext({ asyncContext: true })` support required by this repo. Upstream `isolated-vm` will fail fast during runtime boot with a clear AsyncContext error.
12
+
11
13
  Install Playwright when you want browser runtimes:
12
14
 
13
15
  ```bash
@@ -41,6 +43,47 @@ Each runtime is configured through `bindings`, which describe how sandboxed code
41
43
 
42
44
  Every host callback receives a `HostCallContext` with an `AbortSignal`, runtime identity, resource identity, and request metadata.
43
45
 
46
+ ## Async Context
47
+
48
+ Runtimes created by `@ricsam/isolate` enable the TC39 proposal-style `AsyncContext` global inside the sandbox. This is an experimental surface for now, and the proposal API is used to implement the `node:async_hooks` shim exported to sandboxed code.
49
+
50
+ This shim is intended for async context propagation inside the sandbox. It is not a full reimplementation of Node's `async_hooks` lifecycle, resource graph, or profiling APIs.
51
+
52
+ What is currently supported:
53
+
54
+ - `AsyncContext.Variable`
55
+ - `AsyncContext.Snapshot`
56
+ - `node:async_hooks` `AsyncLocalStorage`
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`
63
+
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.
65
+
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
+ ```
86
+
44
87
  ## Quick Start
45
88
 
46
89
  ```ts
@@ -0,0 +1,401 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ function __accessProp(key) {
6
+ return this[key];
7
+ }
8
+ var __toCommonJS = (from) => {
9
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
10
+ if (entry)
11
+ return entry;
12
+ entry = __defProp({}, "__esModule", { value: true });
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (var key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(entry, key))
16
+ __defProp(entry, key, {
17
+ get: __accessProp.bind(from, key),
18
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
+ });
20
+ }
21
+ __moduleCache.set(from, entry);
22
+ return entry;
23
+ };
24
+ var __moduleCache;
25
+ var __returnValue = (v) => v;
26
+ function __exportSetter(name, newValue) {
27
+ this[name] = __returnValue.bind(null, newValue);
28
+ }
29
+ var __export = (target, all) => {
30
+ for (var name in all)
31
+ __defProp(target, name, {
32
+ get: all[name],
33
+ enumerable: true,
34
+ configurable: true,
35
+ set: __exportSetter.bind(all, name)
36
+ });
37
+ };
38
+
39
+ // src/internal/async-context/index.ts
40
+ var exports_async_context = {};
41
+ __export(exports_async_context, {
42
+ setupAsyncContext: () => setupAsyncContext
43
+ });
44
+ module.exports = __toCommonJS(exports_async_context);
45
+ var ASYNC_CONTEXT_BOOTSTRAP = `
46
+ (function() {
47
+ if (globalThis.__isolateAsyncContextInternals) {
48
+ return;
49
+ }
50
+
51
+ const AsyncContext = globalThis.AsyncContext;
52
+ const native = globalThis.__ivmAsyncContextInternal;
53
+ if (
54
+ !AsyncContext
55
+ || typeof AsyncContext.Variable !== "function"
56
+ || typeof AsyncContext.Snapshot !== "function"
57
+ || !native
58
+ || typeof native.getContinuationPreservedEmbedderData !== "function"
59
+ || typeof native.setContinuationPreservedEmbedderData !== "function"
60
+ || typeof native.setPromiseHooks !== "function"
61
+ ) {
62
+ throw new Error(
63
+ "The installed isolated-vm runtime does not expose async context support. " +
64
+ "Install the async-context-enabled isolate engine build."
65
+ );
66
+ }
67
+
68
+ class AsyncContextFrame extends Map {
69
+ constructor(store, value) {
70
+ super(AsyncContextFrame.current() ?? undefined);
71
+ if (arguments.length > 0) {
72
+ this.set(store, value);
73
+ }
74
+ }
75
+
76
+ static current() {
77
+ return native.getContinuationPreservedEmbedderData();
78
+ }
79
+
80
+ static set(frame) {
81
+ native.setContinuationPreservedEmbedderData(frame);
82
+ }
83
+
84
+ static exchange(frame) {
85
+ const prior = this.current();
86
+ this.set(frame);
87
+ return prior;
88
+ }
89
+
90
+ static disable(store) {
91
+ const frame = this.current();
92
+ frame?.delete(store);
93
+ }
94
+ }
95
+
96
+ Object.defineProperty(AsyncContextFrame, "enabled", {
97
+ configurable: true,
98
+ enumerable: false,
99
+ value: true,
100
+ });
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,
113
+ });
114
+
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 = {}) {
219
+ if (typeof callback !== "function") {
220
+ return callback;
221
+ }
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
+ }
354
+
355
+ Object.defineProperty(globalThis, "__isolateAsyncContextInternals", {
356
+ configurable: true,
357
+ enumerable: false,
358
+ writable: false,
359
+ value: {
360
+ AsyncContextFrame,
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,
376
+ wrapCallback,
377
+ releaseCallback,
378
+ enableHook,
379
+ disableHook,
380
+ },
381
+ });
382
+ })();
383
+ `;
384
+ async function setupAsyncContext(context) {
385
+ const supported = context.evalSync(`
386
+ typeof globalThis.AsyncContext === "object"
387
+ && typeof globalThis.AsyncContext?.Variable === "function"
388
+ && typeof globalThis.AsyncContext?.Snapshot === "function"
389
+ && typeof globalThis.__ivmAsyncContextInternal === "object"
390
+ && typeof globalThis.__ivmAsyncContextInternal?.getContinuationPreservedEmbedderData === "function"
391
+ && typeof globalThis.__ivmAsyncContextInternal?.setContinuationPreservedEmbedderData === "function"
392
+ && typeof globalThis.__ivmAsyncContextInternal?.setPromiseHooks === "function"
393
+ `);
394
+ if (!supported) {
395
+ throw new Error("The installed isolated-vm runtime does not support AsyncContext. " + "Use the async-context-enabled isolate engine build.");
396
+ }
397
+ context.evalSync(ASYNC_CONTEXT_BOOTSTRAP);
398
+ return { supported };
399
+ }
400
+
401
+ //# debugId=890EACA6895F598664756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/internal/async-context/index.ts"],
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 || 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
+ ],
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
+ "names": []
10
+ }