poe-code 13.0.3 → 13.0.5

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 (57) hide show
  1. package/dist/index.js +14421 -13628
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-js/dist/chunks/{chunk-73LWNNUG.js → chunk-BI5UBZ7A.js} +14508 -13744
  6. package/packages/safe-js/dist/chunks/chunk-BI5UBZ7A.js.map +7 -0
  7. package/packages/safe-js/dist/chunks/{chunk-QCJ7UAMC.js → chunk-FH5X7CUS.js} +2 -2
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.js +1 -1
  10. package/packages/safe-js/dist/index.d.ts +11 -3
  11. package/packages/safe-js/dist/index.js +14 -6
  12. package/packages/safe-js/dist/index.js.map +4 -4
  13. package/packages/safe-js/dist/interp/async.d.ts +2 -0
  14. package/packages/safe-js/dist/interp/async.js +31 -15
  15. package/packages/safe-js/dist/interp/budget.d.ts +29 -0
  16. package/packages/safe-js/dist/interp/budget.js +143 -0
  17. package/packages/safe-js/dist/interp/globals/console-json.d.ts +2 -1
  18. package/packages/safe-js/dist/interp/globals/console-json.js +24 -6
  19. package/packages/safe-js/dist/interp/globals/regex.d.ts +2 -1
  20. package/packages/safe-js/dist/interp/globals/regex.js +24 -3
  21. package/packages/safe-js/dist/interp/host-bridge.d.ts +2 -1
  22. package/packages/safe-js/dist/interp/host-bridge.js +98 -55
  23. package/packages/safe-js/dist/interp/host-call.d.ts +3 -2
  24. package/packages/safe-js/dist/interp/host-call.js +91 -52
  25. package/packages/safe-js/dist/interp/interpreter.d.ts +4 -1
  26. package/packages/safe-js/dist/interp/interpreter.js +115 -79
  27. package/packages/safe-js/dist/interp/methods/string.d.ts +2 -1
  28. package/packages/safe-js/dist/interp/methods/string.js +111 -100
  29. package/packages/safe-js/dist/interp/regex/compile-guard.d.ts +33 -0
  30. package/packages/safe-js/dist/interp/regex/compile-guard.js +179 -0
  31. package/packages/safe-js/dist/interp/regex/parse.d.ts +2 -1
  32. package/packages/safe-js/dist/interp/regex/parse.js +87 -16
  33. package/packages/safe-js/dist/interp/values.d.ts +7 -2
  34. package/packages/safe-js/dist/interp/values.js +95 -9
  35. package/packages/safe-js/dist/modules/registry.d.ts +2 -1
  36. package/packages/safe-js/dist/modules/registry.js +1 -0
  37. package/packages/safe-js/dist/parse/hash.d.ts +2 -1
  38. package/packages/safe-js/dist/parse/hash.js +7 -4
  39. package/packages/safe-js/dist/parse/parser.d.ts +5 -3
  40. package/packages/safe-js/dist/parse/parser.js +53 -27
  41. package/packages/safe-js/dist/parse/tokenizer.d.ts +2 -0
  42. package/packages/safe-js/dist/parse/tokenizer.js +48 -26
  43. package/packages/safe-js/dist/parse.d.ts +3 -1
  44. package/packages/safe-js/dist/parse.js +3 -1
  45. package/packages/safe-js/dist/restore.d.ts +2 -1
  46. package/packages/safe-js/dist/restore.js +3 -3
  47. package/packages/safe-js/dist/run.js +289 -263
  48. package/packages/safe-js/dist/snapshot/migration.d.ts +3 -2
  49. package/packages/safe-js/dist/snapshot/migration.js +12 -5
  50. package/packages/safe-js/dist/snapshot/replay-data.d.ts +2 -1
  51. package/packages/safe-js/dist/snapshot/replay-data.js +172 -162
  52. package/packages/safe-js/dist/snapshot/replay-inputs.d.ts +2 -1
  53. package/packages/safe-js/dist/snapshot/replay-inputs.js +18 -11
  54. package/packages/safe-js/dist/snapshot/restore.d.ts +2 -2
  55. package/packages/safe-js/dist/snapshot/restore.js +142 -113
  56. package/packages/safe-js/dist/chunks/chunk-73LWNNUG.js.map +0 -7
  57. /package/packages/safe-js/dist/chunks/{chunk-QCJ7UAMC.js.map → chunk-FH5X7CUS.js.map} +0 -0
@@ -1,11 +1,12 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
- import { hashSource } from "./parse/hash.js";
2
+ import { hashParsedAst, hashSource } from "./parse/hash.js";
3
3
  import { withRunResources } from "./interp/resources.js";
4
4
  import { createReplayableRandom } from "./random.js";
5
5
  import { attachErrorSpan, describeThrownValue, materializeWrappedErrorCause, replaceErrorStack } from "./error/shape.js";
6
- import { parseExecutableModule } from "./parse/parser.js";
6
+ import { findRegexLiteral, parseExecutableModule } from "./parse/parser.js";
7
7
  import { restore } from "./restore.js";
8
8
  import { Budget } from "./interp/budget.js";
9
+ import { CompileScope } from "./interp/regex/compile-guard.js";
9
10
  import { PromiseReplay, promiseReplayContext } from "./interp/promise-replay.js";
10
11
  import { wrapCancelableBindings } from "./interp/cancel.js";
11
12
  import { enterSnapshotRun } from "./interp/running-state.js";
@@ -22,7 +23,7 @@ import { createObjectArrayGlobals } from "./interp/globals/object-array.js";
22
23
  import { declareHostOperation, wrapCallerInjectedBindings } from "./interp/host-bridge.js";
23
24
  import { interpret, Scope } from "./interp/interpreter.js";
24
25
  import { consumeSettledHostCall, createPromiseGlobals } from "./interp/promise.js";
25
- import { deepCopyToSandbox, isSandboxClosure, isSandboxPromise, measureSandboxData } from "./interp/values.js";
26
+ import { deepCopyToSandbox, isSandboxClosure, isSandboxPromise, measureSandboxData, reconcileCompiledValues } from "./interp/values.js";
26
27
  import { resolveModuleImports } from "./modules/registry.js";
27
28
  import { activateOtelSink, getActiveOtelSpan, safeAddEvent } from "./observability/otel.js";
28
29
  import { attachDumpController, createDumpController } from "./snapshot/dump.js";
@@ -51,207 +52,175 @@ export function run(source, options = {}) {
51
52
  const promiseTracker = createSandboxPromiseRejectionTracker();
52
53
  let completedSnapshot;
53
54
  const execute = async () => {
54
- const promiseReplay = new PromiseReplay(options.snapshot?.promiseReplay);
55
- return promiseReplayContext.run(promiseReplay, async () => {
56
- const deactivateOtelSink = activateOtelSink(options.otelSink);
57
- let leaveSnapshotRun;
58
- let leaveHostReplay;
59
- let leaveInputReplay;
60
- let createFailureSnapshot;
61
- let cancellationSnapshot;
62
- let cancellationSnapshotError;
63
- let snapshotScheduler;
64
- const captureCancellationSnapshot = () => {
65
- try {
66
- cancellationSnapshot = createFailureSnapshot?.();
67
- }
68
- catch (reason) {
69
- cancellationSnapshotError = { reason };
70
- }
71
- };
72
- options.signal?.addEventListener("abort", captureCancellationSnapshot, { once: true });
73
- try {
74
- const restoredSnapshot = options.snapshot === undefined ? undefined : restore(options.snapshot, { source });
75
- const executionSemantics = restoredSnapshot?.executionSemantics === "jobs-v6" ? "jobs-v6" : EXECUTION_SEMANTICS;
76
- const convertInitialInput = (convert) => executionSemantics === "jobs-v6" ? convert() : promiseReplayContext.exit(convert);
77
- if (restoredSnapshot !== undefined) {
78
- leaveSnapshotRun = enterSnapshotRun(restoredSnapshot);
79
- }
80
- const budget = options.budget ?? new Budget({ maxCallDepth: DEFAULT_MAX_CALL_DEPTH });
81
- budget.reset();
82
- promiseReplay.attachBudget(budget);
83
- const filename = options.filename ?? "<input>";
84
- const module = parseExecutableModule(source, filename);
85
- promiseReplay.validateNodes(module);
86
- const sourceHash = hashSource(source);
87
- const hostCalls = new HostCallJournal(sourceHash, readHostCallSnapshot(restoredSnapshot), options.hostCallResumeProvider, restoredSnapshot?.replay, budget);
88
- leaveHostReplay = hostCalls.dispose.bind(hostCalls);
89
- promiseReplay.validateCallbacks(hostCalls.callbackPositions());
90
- const generator = options.random ??
91
- createReplayableRandom({ seed: options.randomSeed, snapshot: restoredSnapshot });
92
- const random = { seed: generator.seed, initialState: generator.snapshot(), generator };
93
- const interpreterSnapshot = restoredSnapshot?.replay === undefined && hasLoopIterationSnapshot(restoredSnapshot)
94
- ? {
95
- ...restoredSnapshot,
96
- resumeNodeId: restoredSnapshot.pendingAwaits?.[0]?.nodeId
55
+ const budget = options.budget ?? new Budget({ maxCallDepth: DEFAULT_MAX_CALL_DEPTH });
56
+ const operation = budget.acquireCompileOwner(true);
57
+ const compilation = new CompileScope(operation.owner);
58
+ try {
59
+ const promiseReplay = new PromiseReplay(options.snapshot?.promiseReplay);
60
+ return await promiseReplayContext.run(promiseReplay, async () => {
61
+ const deactivateOtelSink = activateOtelSink(options.otelSink);
62
+ let leaveSnapshotRun;
63
+ let leaveHostReplay;
64
+ let leaveInputReplay;
65
+ let createFailureSnapshot;
66
+ let cancellationSnapshot;
67
+ let cancellationSnapshotError;
68
+ let snapshotScheduler;
69
+ const captureCancellationSnapshot = () => {
70
+ try {
71
+ cancellationSnapshot = createFailureSnapshot?.();
72
+ }
73
+ catch (reason) {
74
+ cancellationSnapshotError = { reason };
97
75
  }
98
- : undefined;
99
- const callerBindings = convertInitialInput(() => options.bindings === undefined
100
- ? {}
101
- : wrapCallerInjectedBindings(options.bindings, {
102
- budget,
103
- hostCalls,
104
- moduleId: "<bindings>",
105
- signal: options.signal,
106
- lifecycle
107
- }));
108
- const builtinBindings = {
109
- ...createConsoleJsonGlobals({
110
- budget,
111
- hostCalls,
112
- sink: options.sink
113
- }),
114
- ...createCollectionGlobals({ budget }),
115
- Float32Array: createFloat32ArrayGlobal(budget),
116
- ...createErrorGlobals({
117
- budget
118
- }),
119
- ...createMathGlobals({
120
- random: random?.generator.next
121
- }),
122
- ...createObjectArrayGlobals({
123
- budget
124
- }),
125
- ...createMiscGlobals({
126
- budget
127
- }),
128
- ...createPromiseGlobals({
129
- budget
130
- }),
131
- ...createRegexGlobals()
132
76
  };
133
- const importMeta = convertInitialInput(() => deepCopyToSandbox(options.importMeta ?? {}));
134
- if (restoredSnapshot?.migration !== undefined) {
135
- if (Object.hasOwn(importMeta, "migration"))
136
- throw new TypeError("import.meta.migration is reserved for migrated checkpoint state.");
137
- Object.defineProperty(importMeta, "migration", {
138
- value: decodeReplayData(restoredSnapshot.migration.state),
139
- enumerable: true,
140
- configurable: true,
141
- writable: true
142
- });
143
- }
144
- const initialInputs = prepareReplayInputs({
145
- bindings: callerBindings,
146
- imports: convertInitialInput(() => resolveModuleImports(module, options.modules, {
147
- budget,
148
- hostCalls,
149
- signal: options.signal,
150
- allowMissing: restoredSnapshot?.initialInputs !== undefined
151
- })),
152
- entryPointArgs: convertInitialInput(() => options.entryPointArgs === undefined
77
+ options.signal?.addEventListener("abort", captureCancellationSnapshot, { once: true });
78
+ try {
79
+ const restoredSnapshot = options.snapshot === undefined
153
80
  ? undefined
154
- : deepCopyToSandbox([...options.entryPointArgs])),
155
- importMeta
156
- }, restoredSnapshot?.initialInputs, (promise, id) => {
157
- if (promise !== undefined)
158
- observeSandboxPromise(promise);
159
- const operation = declareHostOperation(() => {
160
- if (promise === undefined)
161
- throw new TypeError(`Missing initial promise '${id}'.`);
162
- return promise.promise;
163
- }, "read-side-effect");
164
- const binding = wrapCallerInjectedBindings({ [id]: operation }, {
165
- budget,
166
- hostCalls,
167
- moduleId: "<inputs>",
168
- signal: options.signal,
169
- lifecycle
170
- })[id];
171
- if (!isSandboxClosure(binding))
172
- throw new TypeError("Invalid initial promise operation.");
173
- return binding.call([]);
174
- }, hostCalls.rebindHostCapability.bind(hostCalls));
175
- hostCalls.validateHostCapabilities();
176
- budget.setRetainedDataUsage(initialInputs, measureSandboxData([
177
- ...Object.values(initialInputs.values.bindings),
178
- ...Object.values(initialInputs.values.imports),
179
- ...(initialInputs.values.entryPointArgs ?? []),
180
- initialInputs.values.importMeta
181
- ], { ignoreClosureCaptures: true }));
182
- leaveInputReplay = () => budget.setRetainedDataUsage(initialInputs, 0);
183
- const entryPointArgs = initialInputs.values.entryPointArgs;
184
- const cancelableCallerBindings = wrapCancelableBindings(initialInputs.values.bindings, options.signal);
185
- const scope = new Scope(builtinBindings, undefined, undefined, { chargeData: false }, interpreterSnapshot?.bindings);
186
- const callerScope = scope.child(cancelableCallerBindings);
187
- const executionScope = new Scope(initialInputs.values.imports, callerScope, initialInputs.values.importMeta, { functionBoundary: true });
188
- const activeSnapshotScheduler = createSnapshotScheduler({
189
- snapshotBackend: options.snapshotBackend,
190
- snapshotIntervalMs: options.snapshotIntervalMs,
191
- snapshotPath: options.snapshotPath
192
- });
193
- snapshotScheduler = activeSnapshotScheduler;
194
- createFailureSnapshot = () => createRunSnapshot({
195
- executionSemantics,
196
- migration: restoredSnapshot?.migration,
197
- bindings: executionScope.snapshot().bindings,
198
- clock: options.clock,
199
- hostCalls: hostCalls.snapshot(),
200
- replay: hostCalls.snapshotReplay(),
201
- initialInputs: initialInputs.snapshot,
202
- promiseReplay: promiseReplay.snapshot(),
203
- random,
204
- sourceHash
205
- });
206
- let snapshotIteration = 0;
207
- const topLevelResult = await interpret(createExecutableNode(module), {
208
- budget,
209
- captureReplayState: random.generator.snapshot,
210
- onYield: (yieldPoint) => {
211
- snapshotIteration += 1;
212
- safeAddEvent(yieldPoint.otelSpan ?? getActiveOtelSpan(), "snapshot.saved", {
213
- iteration: snapshotIteration
81
+ : restore(options.snapshot, { source }, operation.owner);
82
+ const executionSemantics = restoredSnapshot?.executionSemantics === "jobs-v6" ? "jobs-v6" : EXECUTION_SEMANTICS;
83
+ const convertInitialInput = (convert) => executionSemantics === "jobs-v6" ? convert() : promiseReplayContext.exit(convert);
84
+ if (restoredSnapshot !== undefined) {
85
+ leaveSnapshotRun = enterSnapshotRun(restoredSnapshot);
86
+ }
87
+ promiseReplay.attachBudget(budget);
88
+ const filename = options.filename ?? "<input>";
89
+ const module = parseExecutableModule(source, filename, operation.owner);
90
+ promiseReplay.validateNodes(module);
91
+ const sourceHash = findRegexLiteral(module) === undefined
92
+ ? hashSource(source, operation.owner)
93
+ : hashParsedAst(module);
94
+ const hostCalls = new HostCallJournal(sourceHash, readHostCallSnapshot(restoredSnapshot), options.hostCallResumeProvider, restoredSnapshot?.replay, budget, operation.owner);
95
+ leaveHostReplay = hostCalls.dispose.bind(hostCalls);
96
+ promiseReplay.validateCallbacks(hostCalls.callbackPositions());
97
+ const generator = options.random ??
98
+ createReplayableRandom({ seed: options.randomSeed, snapshot: restoredSnapshot });
99
+ const random = { seed: generator.seed, initialState: generator.snapshot(), generator };
100
+ const interpreterSnapshot = restoredSnapshot?.replay === undefined && hasLoopIterationSnapshot(restoredSnapshot)
101
+ ? {
102
+ ...restoredSnapshot,
103
+ resumeNodeId: restoredSnapshot.pendingAwaits?.[0]?.nodeId
104
+ }
105
+ : undefined;
106
+ const callerBindings = convertInitialInput(() => options.bindings === undefined
107
+ ? {}
108
+ : wrapCallerInjectedBindings(options.bindings, {
109
+ budget,
110
+ compileOwner: operation.owner,
111
+ hostCalls,
112
+ moduleId: "<bindings>",
113
+ signal: options.signal,
114
+ lifecycle
115
+ }));
116
+ const builtinBindings = {
117
+ ...createConsoleJsonGlobals({
118
+ compileOwner: operation.owner,
119
+ budget,
120
+ hostCalls,
121
+ sink: options.sink
122
+ }),
123
+ ...createCollectionGlobals({ budget }),
124
+ Float32Array: createFloat32ArrayGlobal(budget),
125
+ ...createErrorGlobals({
126
+ budget
127
+ }),
128
+ ...createMathGlobals({
129
+ random: random?.generator.next
130
+ }),
131
+ ...createObjectArrayGlobals({
132
+ budget
133
+ }),
134
+ ...createMiscGlobals({
135
+ budget
136
+ }),
137
+ ...createPromiseGlobals({
138
+ budget
139
+ }),
140
+ ...createRegexGlobals(operation.owner)
141
+ };
142
+ const importMeta = convertInitialInput(() => deepCopyToSandbox(options.importMeta ?? {}));
143
+ if (restoredSnapshot?.migration !== undefined) {
144
+ if (Object.hasOwn(importMeta, "migration"))
145
+ throw new TypeError("import.meta.migration is reserved for migrated checkpoint state.");
146
+ Object.defineProperty(importMeta, "migration", {
147
+ value: decodeReplayData(restoredSnapshot.migration.state, {}, compilation),
148
+ enumerable: true,
149
+ configurable: true,
150
+ writable: true
214
151
  });
215
- let snapshot;
216
- const createSnapshot = () => {
217
- if (snapshot !== undefined) {
218
- return snapshot;
219
- }
220
- const interpreterSnapshot = yieldPoint.snapshot();
221
- snapshot = createRunSnapshot({
222
- executionSemantics,
223
- migration: restoredSnapshot?.migration,
224
- bindings: interpreterSnapshot.bindings,
225
- clock: options.clock,
226
- hostCalls: hostCalls.snapshot(),
227
- loopIterations: interpreterSnapshot.loopIterations,
228
- pendingAwaits: [createPendingAwaitSnapshot(yieldPoint)],
229
- replay: hostCalls.snapshotReplay(),
230
- initialInputs: initialInputs.snapshot,
231
- promiseReplay: promiseReplay.snapshot(),
232
- random,
233
- randomResumeState: typeof yieldPoint.replayState === "number" ? yieldPoint.replayState : undefined,
234
- sourceHash
235
- });
236
- return snapshot;
237
- };
238
- activeSnapshotScheduler.onYield(createSnapshot);
239
- dumpController.onYield(createSnapshot);
240
- },
241
- scope: executionScope,
242
- signal: options.signal,
243
- snapshot: interpreterSnapshot,
244
- surfaceUnhandledThrows: true,
245
- useScopeDirectly: true
246
- });
247
- const result = entryPointArgs === undefined || !topLevelResult.ok
248
- ? topLevelResult
249
- : await callEntryPoint({
250
- args: entryPointArgs,
152
+ }
153
+ const initialInputs = prepareReplayInputs({
154
+ bindings: callerBindings,
155
+ imports: convertInitialInput(() => resolveModuleImports(module, options.modules, {
156
+ budget,
157
+ compileOwner: operation.owner,
158
+ hostCalls,
159
+ signal: options.signal,
160
+ allowMissing: restoredSnapshot?.initialInputs !== undefined
161
+ })),
162
+ entryPointArgs: convertInitialInput(() => options.entryPointArgs === undefined
163
+ ? undefined
164
+ : deepCopyToSandbox([...options.entryPointArgs])),
165
+ importMeta
166
+ }, restoredSnapshot?.initialInputs, (promise, id) => {
167
+ if (promise !== undefined)
168
+ observeSandboxPromise(promise);
169
+ const operation = declareHostOperation(() => {
170
+ if (promise === undefined)
171
+ throw new TypeError(`Missing initial promise '${id}'.`);
172
+ return promise.promise;
173
+ }, "read-side-effect");
174
+ const binding = wrapCallerInjectedBindings({ [id]: operation }, {
175
+ budget,
176
+ hostCalls,
177
+ moduleId: "<inputs>",
178
+ compileOwner: compilation.owner,
179
+ signal: options.signal,
180
+ lifecycle
181
+ })[id];
182
+ if (!isSandboxClosure(binding))
183
+ throw new TypeError("Invalid initial promise operation.");
184
+ return binding.call([]);
185
+ }, hostCalls.rebindHostCapability.bind(hostCalls), compilation);
186
+ hostCalls.validateHostCapabilities();
187
+ const inputTickets = new Set();
188
+ const inputSize = measureSandboxData([
189
+ ...Object.values(initialInputs.values.bindings),
190
+ ...Object.values(initialInputs.values.imports),
191
+ ...(initialInputs.values.entryPointArgs ?? []),
192
+ initialInputs.values.importMeta
193
+ ], { ignoreClosureCaptures: true, compileTickets: inputTickets });
194
+ budget.reconcileCompileData(inputSize, inputTickets, inputTickets, initialInputs);
195
+ leaveInputReplay = () => budget.setRetainedDataUsage(initialInputs, 0);
196
+ const entryPointArgs = initialInputs.values.entryPointArgs;
197
+ const cancelableCallerBindings = wrapCancelableBindings(initialInputs.values.bindings, options.signal);
198
+ const scope = new Scope(builtinBindings, undefined, undefined, { chargeData: false }, interpreterSnapshot?.bindings);
199
+ const callerScope = scope.child(cancelableCallerBindings);
200
+ const executionScope = new Scope(initialInputs.values.imports, callerScope, initialInputs.values.importMeta, { functionBoundary: true });
201
+ const activeSnapshotScheduler = createSnapshotScheduler({
202
+ snapshotBackend: options.snapshotBackend,
203
+ snapshotIntervalMs: options.snapshotIntervalMs,
204
+ snapshotPath: options.snapshotPath
205
+ });
206
+ snapshotScheduler = activeSnapshotScheduler;
207
+ createFailureSnapshot = () => createRunSnapshot({
208
+ executionSemantics,
209
+ migration: restoredSnapshot?.migration,
210
+ bindings: executionScope.snapshot().bindings,
211
+ clock: options.clock,
212
+ hostCalls: hostCalls.snapshot(),
213
+ replay: hostCalls.snapshotReplay(),
214
+ initialInputs: initialInputs.snapshot,
215
+ promiseReplay: promiseReplay.snapshot(),
216
+ random,
217
+ sourceHash
218
+ });
219
+ let snapshotIteration = 0;
220
+ const topLevelResult = await interpret(createExecutableNode(module), {
221
+ compilation,
251
222
  budget,
252
223
  captureReplayState: random.generator.snapshot,
253
- filename,
254
- module,
255
224
  onYield: (yieldPoint) => {
256
225
  snapshotIteration += 1;
257
226
  safeAddEvent(yieldPoint.otelSpan ?? getActiveOtelSpan(), "snapshot.saved", {
@@ -275,9 +244,7 @@ export function run(source, options = {}) {
275
244
  initialInputs: initialInputs.snapshot,
276
245
  promiseReplay: promiseReplay.snapshot(),
277
246
  random,
278
- randomResumeState: typeof yieldPoint.replayState === "number"
279
- ? yieldPoint.replayState
280
- : undefined,
247
+ randomResumeState: typeof yieldPoint.replayState === "number" ? yieldPoint.replayState : undefined,
281
248
  sourceHash
282
249
  });
283
250
  return snapshot;
@@ -287,75 +254,133 @@ export function run(source, options = {}) {
287
254
  },
288
255
  scope: executionScope,
289
256
  signal: options.signal,
290
- snapshot: interpreterSnapshot
257
+ snapshot: interpreterSnapshot,
258
+ surfaceUnhandledThrows: true,
259
+ useScopeDirectly: true
291
260
  });
292
- await throwIfReturnedPromiseRejected(result);
293
- await throwIfUnhandledPromiseRejected(promiseTracker);
294
- await activeSnapshotScheduler.finish();
295
- let replay;
296
- let replayError;
297
- try {
298
- replay = hostCalls.snapshotReplay();
299
- }
300
- catch (error) {
301
- if (!(error instanceof MissingReplayCapabilityError))
302
- throw error;
303
- replayError = error.message;
304
- }
305
- const snapshot = createRunSnapshot({
306
- executionSemantics,
307
- migration: restoredSnapshot?.migration,
308
- bindings: executionScope.snapshot().bindings,
309
- clock: options.clock,
310
- hostCalls: hostCalls.snapshot(),
311
- replay,
312
- initialInputs: initialInputs.snapshot,
313
- promiseReplay: promiseReplay.snapshot(),
314
- random,
315
- sourceHash
316
- });
317
- if (replayError !== undefined)
318
- snapshot.replayError = replayError;
319
- dumpController.finalize(snapshot);
320
- completedSnapshot = snapshot;
321
- return {
322
- ...result,
323
- snapshot
324
- };
325
- }
326
- catch (error) {
327
- promiseReplay.fail(error);
328
- materializeWrappedErrorCause(error);
329
- if (createFailureSnapshot !== undefined && snapshotScheduler !== undefined) {
261
+ const result = entryPointArgs === undefined || !topLevelResult.ok
262
+ ? topLevelResult
263
+ : await callEntryPoint({
264
+ args: entryPointArgs,
265
+ budget,
266
+ compilation,
267
+ captureReplayState: random.generator.snapshot,
268
+ filename,
269
+ module,
270
+ onYield: (yieldPoint) => {
271
+ snapshotIteration += 1;
272
+ safeAddEvent(yieldPoint.otelSpan ?? getActiveOtelSpan(), "snapshot.saved", {
273
+ iteration: snapshotIteration
274
+ });
275
+ let snapshot;
276
+ const createSnapshot = () => {
277
+ if (snapshot !== undefined) {
278
+ return snapshot;
279
+ }
280
+ const interpreterSnapshot = yieldPoint.snapshot();
281
+ snapshot = createRunSnapshot({
282
+ executionSemantics,
283
+ migration: restoredSnapshot?.migration,
284
+ bindings: interpreterSnapshot.bindings,
285
+ clock: options.clock,
286
+ hostCalls: hostCalls.snapshot(),
287
+ loopIterations: interpreterSnapshot.loopIterations,
288
+ pendingAwaits: [createPendingAwaitSnapshot(yieldPoint)],
289
+ replay: hostCalls.snapshotReplay(),
290
+ initialInputs: initialInputs.snapshot,
291
+ promiseReplay: promiseReplay.snapshot(),
292
+ random,
293
+ randomResumeState: typeof yieldPoint.replayState === "number"
294
+ ? yieldPoint.replayState
295
+ : undefined,
296
+ sourceHash
297
+ });
298
+ return snapshot;
299
+ };
300
+ activeSnapshotScheduler.onYield(createSnapshot);
301
+ dumpController.onYield(createSnapshot);
302
+ },
303
+ scope: executionScope,
304
+ signal: options.signal,
305
+ snapshot: interpreterSnapshot
306
+ });
307
+ await throwIfReturnedPromiseRejected(result);
308
+ await throwIfUnhandledPromiseRejected(promiseTracker);
309
+ await activeSnapshotScheduler.finish();
310
+ let replay;
311
+ let replayError;
330
312
  try {
331
- if (cancellationSnapshotError !== undefined)
332
- throw cancellationSnapshotError.reason;
333
- const snapshot = cancellationSnapshot ?? createFailureSnapshot();
334
- dumpController.finalize(snapshot);
335
- await snapshotScheduler.write(snapshot);
313
+ replay = hostCalls.snapshotReplay();
336
314
  }
337
- catch (snapshotError) {
338
- if (snapshotError instanceof UnsnapshotableValueError) {
339
- console.warn(`Skipping failure snapshot: ${snapshotError.message}`);
315
+ catch (error) {
316
+ if (!(error instanceof MissingReplayCapabilityError))
317
+ throw error;
318
+ replayError = error.message;
319
+ }
320
+ const snapshot = createRunSnapshot({
321
+ executionSemantics,
322
+ migration: restoredSnapshot?.migration,
323
+ bindings: executionScope.snapshot().bindings,
324
+ clock: options.clock,
325
+ hostCalls: hostCalls.snapshot(),
326
+ replay,
327
+ initialInputs: initialInputs.snapshot,
328
+ promiseReplay: promiseReplay.snapshot(),
329
+ random,
330
+ sourceHash
331
+ });
332
+ if (replayError !== undefined)
333
+ snapshot.replayError = replayError;
334
+ dumpController.finalize(snapshot);
335
+ completedSnapshot = snapshot;
336
+ reconcileCompiledValues(budget, [
337
+ ...Object.values(result.snapshot.bindings),
338
+ ...(result.ok && "returnValue" in result ? [result.returnValue] : []),
339
+ ...budget.retainedValues()
340
+ ], compilation);
341
+ return {
342
+ ...result,
343
+ snapshot
344
+ };
345
+ }
346
+ catch (error) {
347
+ promiseReplay.fail(error);
348
+ materializeWrappedErrorCause(error);
349
+ if (createFailureSnapshot !== undefined && snapshotScheduler !== undefined) {
350
+ try {
351
+ if (cancellationSnapshotError !== undefined)
352
+ throw cancellationSnapshotError.reason;
353
+ const snapshot = cancellationSnapshot ?? createFailureSnapshot();
354
+ dumpController.finalize(snapshot);
355
+ await snapshotScheduler.write(snapshot);
340
356
  }
341
- else {
342
- console.warn("Failed to write failure snapshot.", snapshotError);
357
+ catch (snapshotError) {
358
+ if (snapshotError instanceof UnsnapshotableValueError) {
359
+ console.warn(`Skipping failure snapshot: ${snapshotError.message}`);
360
+ }
361
+ else {
362
+ console.warn("Failed to write failure snapshot.", snapshotError);
363
+ }
343
364
  }
344
365
  }
366
+ dumpController.fail(error);
367
+ throw error;
345
368
  }
346
- dumpController.fail(error);
347
- throw error;
348
- }
349
- finally {
350
- lifecycle.hostCallbackContext.disable();
351
- options.signal?.removeEventListener("abort", captureCancellationSnapshot);
352
- leaveInputReplay?.();
353
- leaveHostReplay?.();
354
- promiseReplay.dispose();
355
- leaveSnapshotRun?.();
356
- deactivateOtelSink();
357
- }
358
- });
369
+ finally {
370
+ lifecycle.hostCallbackContext.disable();
371
+ options.signal?.removeEventListener("abort", captureCancellationSnapshot);
372
+ leaveInputReplay?.();
373
+ leaveHostReplay?.();
374
+ promiseReplay.dispose();
375
+ leaveSnapshotRun?.();
376
+ deactivateOtelSink();
377
+ }
378
+ });
379
+ }
380
+ finally {
381
+ compilation.dispose();
382
+ operation.release();
383
+ }
359
384
  };
360
385
  const result = withRunResources(options.signal, () => withSandboxPromiseRejectionTracker(promiseTracker, execute)).catch(async (error) => {
361
386
  if (completedSnapshot !== undefined) {
@@ -409,6 +434,7 @@ async function callEntryPoint(input) {
409
434
  ...argumentBindings
410
435
  });
411
436
  return interpret(createEntryPointAwait(input.args.length, input.module.span), {
437
+ compilation: input.compilation,
412
438
  signal: input.signal,
413
439
  budget: input.budget,
414
440
  captureReplayState: input.captureReplayState,
@@ -1,5 +1,6 @@
1
1
  import { type HostCallReplay } from "../interp/host-call.js";
2
2
  import { type ReplayData } from "./replay-data.js";
3
+ import type { CompileOwner } from "../interp/budget.js";
3
4
  export type SnapshotMigrationResolution = {
4
5
  callId: string;
5
6
  disposition: "not-performed";
@@ -29,6 +30,6 @@ export type SnapshotMigration = {
29
30
  }>;
30
31
  };
31
32
  export declare function validateMigrationSemantics(value: unknown): asserts value is string;
32
- export declare function validateMigrationJournal(sourceHash: string, replay: unknown, hostCalls?: unknown): HostCallReplay;
33
+ export declare function validateMigrationJournal(sourceHash: string, replay: unknown, hostCalls?: unknown, owner?: CompileOwner): HostCallReplay;
33
34
  export declare function validateMigrationReconciliation(value: unknown, checkpointDigest: string, calls: HostCallReplay["calls"]): asserts value is SnapshotMigrationReconciliation;
34
- export declare function validateSnapshotMigration(value: unknown, sourceHash: string): SnapshotMigration | undefined;
35
+ export declare function validateSnapshotMigration(value: unknown, sourceHash: string, owner?: CompileOwner): SnapshotMigration | undefined;