poe-code 14.0.5 → 14.0.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 (54) hide show
  1. package/dist/index.js +1604 -255
  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-B7H4ZL65.js → chunk-BWVASPJX.js} +2099 -783
  6. package/packages/safe-js/dist/chunks/chunk-BWVASPJX.js.map +7 -0
  7. package/packages/safe-js/dist/chunks/{chunk-7B7BKWVF.js → chunk-ETKM3KPA.js} +2 -2
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.d.ts +3 -0
  10. package/packages/safe-js/dist/core.js +5 -1
  11. package/packages/safe-js/dist/extensions.d.ts +44 -0
  12. package/packages/safe-js/dist/extensions.js +83 -0
  13. package/packages/safe-js/dist/index.d.ts +4 -1
  14. package/packages/safe-js/dist/index.js +6 -2
  15. package/packages/safe-js/dist/index.js.map +2 -2
  16. package/packages/safe-js/dist/interp/async.d.ts +1 -0
  17. package/packages/safe-js/dist/interp/date.d.ts +19 -0
  18. package/packages/safe-js/dist/interp/date.js +129 -0
  19. package/packages/safe-js/dist/interp/globals/console-json.js +5 -1
  20. package/packages/safe-js/dist/interp/globals/date.d.ts +10 -0
  21. package/packages/safe-js/dist/interp/globals/date.js +95 -0
  22. package/packages/safe-js/dist/interp/globals/object-array.d.ts +2 -1
  23. package/packages/safe-js/dist/interp/globals/object-array.js +15 -1
  24. package/packages/safe-js/dist/interp/globals.d.ts +34 -0
  25. package/packages/safe-js/dist/interp/globals.js +24 -0
  26. package/packages/safe-js/dist/interp/host-bridge.d.ts +18 -1
  27. package/packages/safe-js/dist/interp/host-bridge.js +39 -5
  28. package/packages/safe-js/dist/interp/host-call.js +4 -0
  29. package/packages/safe-js/dist/interp/host-capabilities.d.ts +50 -0
  30. package/packages/safe-js/dist/interp/host-capabilities.js +151 -0
  31. package/packages/safe-js/dist/interp/interpreter.d.ts +4 -0
  32. package/packages/safe-js/dist/interp/interpreter.js +41 -6
  33. package/packages/safe-js/dist/interp/object-model.js +7 -0
  34. package/packages/safe-js/dist/interp/string-coercion.js +3 -0
  35. package/packages/safe-js/dist/interp/values.d.ts +2 -1
  36. package/packages/safe-js/dist/interp/values.js +36 -0
  37. package/packages/safe-js/dist/lint/rules/known-globals.d.ts +1 -1
  38. package/packages/safe-js/dist/lint/rules/known-globals.js +1 -0
  39. package/packages/safe-js/dist/modules/registry.d.ts +3 -1
  40. package/packages/safe-js/dist/modules/registry.js +2 -1
  41. package/packages/safe-js/dist/parse/parser.js +4 -2
  42. package/packages/safe-js/dist/realm.d.ts +46 -0
  43. package/packages/safe-js/dist/realm.js +779 -0
  44. package/packages/safe-js/dist/run.d.ts +7 -1
  45. package/packages/safe-js/dist/run.js +6 -35
  46. package/packages/safe-js/dist/snapshot/dump-format.js +8 -3
  47. package/packages/safe-js/dist/snapshot/replay-data.d.ts +4 -1
  48. package/packages/safe-js/dist/snapshot/replay-data.js +11 -0
  49. package/packages/safe-js/dist/snapshot/restore.js +6 -0
  50. package/packages/safe-js/dist/snapshot/serialize.d.ts +5 -2
  51. package/packages/safe-js/dist/snapshot/serialize.js +8 -2
  52. package/packages/safe-js/dist/snapshot/validation.js +18 -1
  53. package/packages/safe-js/dist/chunks/chunk-B7H4ZL65.js.map +0 -7
  54. /package/packages/safe-js/dist/chunks/{chunk-7B7BKWVF.js.map → chunk-ETKM3KPA.js.map} +0 -0
@@ -1,10 +1,11 @@
1
+ import { type RealmOptions } from "./realm.js";
1
2
  import { type ErrorSourceSpan } from "./error/shape.js";
2
3
  import { type SourceSpan } from "./parse/parser.js";
3
4
  import { type SafeJSSnapshot } from "./restore.js";
4
5
  import { Budget } from "./interp/budget.js";
5
6
  import { type PromiseReplaySnapshot } from "./interp/promise-replay.js";
6
7
  import { type HostCallRecord, type HostCallReplay, type HostCallResumeProvider } from "./interp/host-call.js";
7
- import { type ConsoleSink } from "./interp/globals/console-json.js";
8
+ import type { ConsoleSink } from "./interp/globals/console-json.js";
8
9
  import { type CallerInjectedBinding } from "./interp/host-bridge.js";
9
10
  import { type InterpreterResult, type LoopIterationSnapshot } from "./interp/interpreter.js";
10
11
  import { type ModuleRegistry } from "./modules/registry.js";
@@ -12,6 +13,9 @@ import { type OtelSink } from "./observability/otel.js";
12
13
  import type { SnapshotBackend } from "./snapshot/backend.js";
13
14
  import { type ReplayData } from "./snapshot/replay-data.js";
14
15
  export type RunOptions = {
16
+ extensions?: RealmOptions["extensions"];
17
+ grants?: RealmOptions["grants"];
18
+ limits?: RealmOptions["limits"];
15
19
  bindings?: Record<string, CallerInjectedBinding>;
16
20
  budget?: Budget;
17
21
  clock?: RunClock;
@@ -59,6 +63,8 @@ export type RunClockSnapshot = {
59
63
  next: number;
60
64
  };
61
65
  export type RunClock = {
66
+ now?: () => number;
67
+ restore?: (snapshot: RunClockSnapshot) => void;
62
68
  snapshot: () => RunClockSnapshot | undefined;
63
69
  };
64
70
  export type RunRandom = {
@@ -1,4 +1,5 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { runWithExtensions } from "./realm.js";
2
3
  import { hashParsedAst, hashSource } from "./parse/hash.js";
3
4
  import { withRunResources } from "./interp/resources.js";
4
5
  import { createReplayableRandom } from "./random.js";
@@ -12,17 +13,10 @@ import { wrapCancelableBindings } from "./interp/cancel.js";
12
13
  import { enterSnapshotRun } from "./interp/running-state.js";
13
14
  import { createSandboxPromiseRejectionTracker, observeSandboxPromise, withSandboxPromiseRejectionTracker } from "./interp/promise-tracker.js";
14
15
  import { HostCallJournal } from "./interp/host-call.js";
15
- import { createConsoleJsonGlobals } from "./interp/globals/console-json.js";
16
- import { createCollectionGlobals } from "./interp/globals/collections.js";
17
- import { createFloat32ArrayGlobal } from "./interp/globals/float32array.js";
18
- import { createErrorGlobals } from "./interp/globals/error.js";
19
- import { createMathGlobals } from "./interp/globals/math.js";
20
- import { createRegexGlobals } from "./interp/globals/regex.js";
21
- import { createMiscGlobals } from "./interp/globals/misc.js";
22
- import { createObjectArrayGlobals } from "./interp/globals/object-array.js";
16
+ import { createBuiltinBindings } from "./interp/globals.js";
23
17
  import { declareHostOperation, wrapCallerInjectedBindings } from "./interp/host-bridge.js";
24
18
  import { interpret, Scope } from "./interp/interpreter.js";
25
- import { consumeSettledHostCall, createPromiseGlobals } from "./interp/promise.js";
19
+ import { consumeSettledHostCall } from "./interp/promise.js";
26
20
  import { deepCopyToSandbox, isSandboxClosure, isSandboxPromise, measureSandboxData, reconcileCompiledValues } from "./interp/values.js";
27
21
  import { resolveModuleImports } from "./modules/registry.js";
28
22
  import { activateOtelSink, getActiveOtelSpan, safeAddEvent } from "./observability/otel.js";
@@ -44,6 +38,8 @@ export class UnhandledRejectionError extends Error {
44
38
  }
45
39
  const DEFAULT_MAX_CALL_DEPTH = 1_000;
46
40
  export function run(source, options = {}) {
41
+ if (options.extensions !== undefined)
42
+ return runWithExtensions(source, options);
47
43
  const lifecycle = {
48
44
  hostCallbackDepth: 0,
49
45
  hostCallbackContext: new AsyncLocalStorage()
@@ -113,32 +109,7 @@ export function run(source, options = {}) {
113
109
  signal: options.signal,
114
110
  lifecycle
115
111
  }));
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
- };
112
+ const builtinBindings = createBuiltinBindings({ compileOwner: operation.owner, budget, hostCalls, sink: options.sink, random: random?.generator.next, clock: options.clock });
142
113
  const importMeta = convertInitialInput(() => deepCopyToSandbox(options.importMeta ?? {}));
143
114
  if (restoredSnapshot?.migration !== undefined) {
144
115
  if (Object.hasOwn(importMeta, "migration"))
@@ -8,6 +8,7 @@ import { serializeArguments } from "./arguments.js";
8
8
  import { requiresArrayEntries, serializeArray } from "./arrays.js";
9
9
  import { float32DataProperties, isFloat32Array } from "../interp/float32.js";
10
10
  import { encodeFloat32Storage } from "./float32array.js";
11
+ import { isSandboxDate, serializedDateTime } from "../interp/date.js";
11
12
  const SKIP_VALUE = Symbol("SafeJS.skip-dump-value");
12
13
  export function serializeSafeJSSnapshot(snapshot) {
13
14
  const replayError = Object.getOwnPropertyDescriptor(snapshot, "replayError");
@@ -72,7 +73,7 @@ function serializeDumpValue(value, path, state) {
72
73
  if (hasGuestObjectState(value)) {
73
74
  throw new TypeError("Guest function properties and prototype links cannot be serialized.");
74
75
  }
75
- if (isFloat32Array(value))
76
+ if (isSandboxDate(value) || isFloat32Array(value))
76
77
  return serializeHeapReference(value, path, state);
77
78
  if (Array.isArray(value)) {
78
79
  const reference = serializeHeapReference(value, path, state);
@@ -97,7 +98,10 @@ function serializeHeapReference(value, path, state) {
97
98
  }
98
99
  if (!state.serializedHeapIds.has(id)) {
99
100
  state.serializedHeapIds.add(id);
100
- if (isFloat32Array(value)) {
101
+ if (isSandboxDate(value)) {
102
+ state.heap[String(id)] = { kind: "date", time: serializedDateTime(value) };
103
+ }
104
+ else if (isFloat32Array(value)) {
101
105
  const storage = encodeFloat32Storage(value, id, state.float32Buffers, (id) => ({
102
106
  kind: "ref",
103
107
  id
@@ -159,6 +163,7 @@ function indexHeapContainers(snapshot) {
159
163
  for (const [value, stat] of stats.entries()) {
160
164
  if (stat.count > 1 ||
161
165
  stat.cyclic ||
166
+ isSandboxDate(value) ||
162
167
  isFloat32Array(value) ||
163
168
  (Array.isArray(value) && requiresArrayEntries(value)) ||
164
169
  isSandboxArguments(value) ||
@@ -173,7 +178,7 @@ function collectContainerStats(value, stats, ancestors) {
173
178
  if (value === null || typeof value !== "object") {
174
179
  return;
175
180
  }
176
- if (!Array.isArray(value) && !isPlainObject(value) && !isFloat32Array(value)) {
181
+ if (!Array.isArray(value) && !isPlainObject(value) && !isFloat32Array(value) && !isSandboxDate(value)) {
177
182
  return;
178
183
  }
179
184
  let stat = stats.get(value);
@@ -24,7 +24,10 @@ type Properties = Record<string, {
24
24
  enumerable: boolean;
25
25
  writable: boolean;
26
26
  }>;
27
- type DataNode = (Float32Data<Atom> & {
27
+ type DataNode = {
28
+ kind: "date";
29
+ time: number | null;
30
+ } | (Float32Data<Atom> & {
28
31
  properties: Properties;
29
32
  extensible: boolean;
30
33
  }) | {
@@ -3,6 +3,7 @@ import { hasGuestObjectState } from "../interp/object-model.js";
3
3
  import { CompileScope } from "../interp/regex/compile-guard.js";
4
4
  import { float32DataProperties, isFloat32Array } from "../interp/float32.js";
5
5
  import { decodeFloat32Storage, encodeFloat32Storage } from "./float32array.js";
6
+ import { isSandboxDate, restoreDateTime, serializedDateTime } from "../interp/date.js";
6
7
  import { sandboxErrorNames, sandboxErrorTypes } from "../error/shape.js";
7
8
  import { createSandboxArguments, createSandboxClosure, createSandboxMap, createSandboxRegex, createSandboxSet, isSandboxArguments, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "../interp/values.js";
8
9
  import { serializeArguments } from "./arguments.js";
@@ -63,6 +64,9 @@ export function encodeReplayData(value, options = {}) {
63
64
  properties: child(entry.properties, "properties")
64
65
  };
65
66
  }
67
+ else if (isSandboxDate(entry)) {
68
+ nodes[id] = { kind: "date", time: serializedDateTime(entry) };
69
+ }
66
70
  else if (isFloat32Array(entry)) {
67
71
  const storage = encodeFloat32Storage(entry, id, float32Buffers, (id) => ({
68
72
  tag: "ref",
@@ -231,6 +235,13 @@ export function decodeReplayData(input, options = {}, parent) {
231
235
  options.onCapabilityRestored?.(capability, copy);
232
236
  return copy;
233
237
  }
238
+ if (kind === "date") {
239
+ if (Object.keys(node).length !== 2)
240
+ throw new TypeError("Invalid serialized Date fields.");
241
+ const result = restoreDateTime(own(node, "time"));
242
+ restored.set(id, result);
243
+ return result;
244
+ }
234
245
  if (kind === "float32array") {
235
246
  if (typeof node.extensible !== "boolean")
236
247
  throw new TypeError("Invalid Float32Array extensibility.");
@@ -1,6 +1,7 @@
1
1
  import { Budget, SandboxError } from "../interp/budget.js";
2
2
  import { CompileScope } from "../interp/regex/compile-guard.js";
3
3
  import { decodeFloat32Storage } from "./float32array.js";
4
+ import { restoreDateTime } from "../interp/date.js";
4
5
  import { sandboxErrorTypes } from "../error/shape.js";
5
6
  import { SnapshotMismatchError } from "../restore.js";
6
7
  import { Scope, setSandboxProperty } from "../interp/interpreter.js";
@@ -339,6 +340,11 @@ function restoreHeapValue(id, state) {
339
340
  if (serialized === undefined) {
340
341
  throw new Error(`Snapshot references unknown heap value ${id}.`);
341
342
  }
343
+ if (serialized.kind === "date") {
344
+ const value = restoreDateTime(serialized.time);
345
+ state.heapValueById.set(id, value);
346
+ return value;
347
+ }
342
348
  if (serialized.kind === "float32array") {
343
349
  const value = decodeFloat32Storage(serialized, (reference) => deserializeValue(reference, state));
344
350
  state.heapValueById.set(id, value);
@@ -40,7 +40,10 @@ export type SerializedReferenceValue = {
40
40
  kind: "ref";
41
41
  id: number;
42
42
  };
43
- export type SerializedHeapValue = (Float32Data<SerializedReferenceValue> & {
43
+ export type SerializedHeapValue = {
44
+ kind: "date";
45
+ time: number | null;
46
+ } | (Float32Data<SerializedReferenceValue> & {
44
47
  entries: Record<string, SerializedSnapshotValue>;
45
48
  }) | SerializedArguments<SerializedSnapshotValue> | SerializedArray<SerializedSnapshotValue> | {
46
49
  kind: "object";
@@ -72,7 +75,7 @@ export type RuntimePromiseValue = {
72
75
  id: SnapshotId;
73
76
  promise?: Promise<unknown>;
74
77
  };
75
- export type RuntimeSnapshotValue = Float32Array | boolean | null | number | string | undefined | RuntimeClosureValue | SandboxGenerator | RuntimePromiseValue | SandboxMap | SandboxRegex | SandboxSet | RuntimeSnapshotValue[] | {
78
+ export type RuntimeSnapshotValue = Date | Float32Array | boolean | null | number | string | undefined | RuntimeClosureValue | SandboxGenerator | RuntimePromiseValue | SandboxMap | SandboxRegex | SandboxSet | RuntimeSnapshotValue[] | {
76
79
  [key: string]: RuntimeSnapshotValue;
77
80
  };
78
81
  export type RuntimeScopeFrame = {
@@ -6,6 +6,7 @@ import { serializeArguments } from "./arguments.js";
6
6
  import { requiresArrayEntries, serializeArray } from "./arrays.js";
7
7
  import { float32DataProperties, isFloat32Array } from "../interp/float32.js";
8
8
  import { encodeFloat32Storage } from "./float32array.js";
9
+ import { isSandboxDate, serializedDateTime } from "../interp/date.js";
9
10
  import { isSandboxArguments, isSandboxGenerator, isSandboxMap, isSandboxRegex, isSandboxSet } from "../interp/values.js";
10
11
  export class UnsnapshotableValueError extends Error {
11
12
  path;
@@ -161,7 +162,7 @@ function serializeValue(value, path, state) {
161
162
  if (isSandboxRegex(value)) {
162
163
  return { kind: "regex", source: value.source, flags: value.flags, lastIndex: value.lastIndex };
163
164
  }
164
- if (isSandboxMap(value) || isSandboxSet(value) || isFloat32Array(value)) {
165
+ if (isSandboxDate(value) || isSandboxMap(value) || isSandboxSet(value) || isFloat32Array(value)) {
165
166
  const reference = serializeHeapReference(value, path, state);
166
167
  if (reference === undefined) {
167
168
  throw new TypeError(`Cannot serialize collection without a heap reference at ${path}.`);
@@ -190,7 +191,10 @@ function serializeHeapReference(value, path, state) {
190
191
  }
191
192
  if (!state.serializedHeapIds.has(id)) {
192
193
  state.serializedHeapIds.add(id);
193
- if (isFloat32Array(value)) {
194
+ if (isSandboxDate(value)) {
195
+ state.heap[String(id)] = { kind: "date", time: serializedDateTime(value) };
196
+ }
197
+ else if (isFloat32Array(value)) {
194
198
  const storage = encodeFloat32Storage(value, id, state.float32Buffers, (id) => ({
195
199
  kind: "ref",
196
200
  id
@@ -297,6 +301,7 @@ function indexHeapContainers(input) {
297
301
  for (const [value, stat] of stats.entries()) {
298
302
  if (stat.count > 1 ||
299
303
  stat.cyclic ||
304
+ isSandboxDate(value) ||
300
305
  isFloat32Array(value) ||
301
306
  (Array.isArray(value) && requiresArrayEntries(value)) ||
302
307
  sandboxErrorTypes.has(value) ||
@@ -319,6 +324,7 @@ function collectContainerStats(value, stats, ancestors) {
319
324
  }
320
325
  if (!Array.isArray(value) &&
321
326
  !isPlainObject(value) &&
327
+ !isSandboxDate(value) &&
322
328
  !isFloat32Array(value) &&
323
329
  !isSandboxMap(value) &&
324
330
  !isSandboxSet(value)) {
@@ -3,6 +3,7 @@ import { types } from "node:util";
3
3
  import { DUMP_FORMAT_VERSION } from "./dump-format.js";
4
4
  import { MAX_DATA_DEPTH } from "../graph-depth.js";
5
5
  import { validateFloat32Storage } from "./float32array.js";
6
+ import { restoreDateTime } from "../interp/date.js";
6
7
  import { hasGuestObjectState } from "../interp/object-model.js";
7
8
  const DEFAULT_MAX_DEPTH = MAX_DATA_DEPTH;
8
9
  const DEFAULT_MAX_ENTRIES = 100_000;
@@ -80,6 +81,10 @@ function validateDumpHeap(root, state) {
80
81
  addUnique(heapIds, id, path);
81
82
  const entry = requireRecord(value, path);
82
83
  validateErrorType(entry, path);
84
+ if (entry.kind === "date") {
85
+ validateDateRecord(entry, path);
86
+ continue;
87
+ }
83
88
  if (entry.kind === "float32array") {
84
89
  validateFloat32Storage(entry);
85
90
  requireRecord(entry.entries, `${path}.entries`);
@@ -402,7 +407,7 @@ function validateGeneratorShape(record, path, state) {
402
407
  function validateHeapValue(value, path, state) {
403
408
  const record = requireRecord(value, path);
404
409
  validateErrorType(record, path);
405
- if (!["arguments", "array", "object", "map", "set", "float32array"].includes(String(record.kind)))
410
+ if (!["arguments", "array", "object", "map", "set", "float32array", "date"].includes(String(record.kind)))
406
411
  fail("unknownTag", `${path}.kind`, "unknown heap tag");
407
412
  validateValue(record, path, 1, state);
408
413
  if (record.kind === "arguments")
@@ -411,6 +416,8 @@ function validateHeapValue(value, path, state) {
411
416
  validateArrayHeap(record, path, state);
412
417
  if (record.kind === "object")
413
418
  requireRecord(record.entries, `${path}.entries`);
419
+ if (record.kind === "date")
420
+ validateDateRecord(record, path);
414
421
  if (record.kind === "float32array") {
415
422
  validateFloat32Storage(record);
416
423
  requireRecord(record.entries, `${path}.entries`);
@@ -425,6 +432,16 @@ function validateHeapValue(value, path, state) {
425
432
  if (record.kind === "set")
426
433
  requireArray(record.values, `${path}.values`, state);
427
434
  }
435
+ function validateDateRecord(record, path) {
436
+ if (Object.keys(record).length !== 2)
437
+ fail("invalidValue", path, "invalid Date fields");
438
+ try {
439
+ restoreDateTime(record.time);
440
+ }
441
+ catch {
442
+ fail("invalidValue", `${path}.time`, "invalid Date epoch");
443
+ }
444
+ }
428
445
  function validateArrayHeap(record, path, state) {
429
446
  if (Object.hasOwn(record, "items")) {
430
447
  requireArray(record.items, `${path}.items`, state);