poe-code 14.0.6 → 14.0.8

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 +944 -143
  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-2M6MNQBY.js → chunk-MO3YD4ID.js} +888 -133
  6. package/packages/safe-js/dist/chunks/chunk-MO3YD4ID.js.map +7 -0
  7. package/packages/safe-js/dist/chunks/{chunk-QSSQJNKE.js → chunk-RXLDJ6LQ.js} +2 -2
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.d.ts +1 -1
  10. package/packages/safe-js/dist/core.js +1 -1
  11. package/packages/safe-js/dist/extensions.d.ts +2 -0
  12. package/packages/safe-js/dist/index.d.ts +1 -1
  13. package/packages/safe-js/dist/index.js +2 -2
  14. package/packages/safe-js/dist/index.js.map +1 -1
  15. package/packages/safe-js/dist/interp/async.js +1 -0
  16. package/packages/safe-js/dist/interp/date.d.ts +19 -0
  17. package/packages/safe-js/dist/interp/date.js +129 -0
  18. package/packages/safe-js/dist/interp/globals/console-json.js +5 -1
  19. package/packages/safe-js/dist/interp/globals/date.d.ts +10 -0
  20. package/packages/safe-js/dist/interp/globals/date.js +95 -0
  21. package/packages/safe-js/dist/interp/globals/object-array.d.ts +4 -3
  22. package/packages/safe-js/dist/interp/globals/object-array.js +42 -5
  23. package/packages/safe-js/dist/interp/globals/object.d.ts +4 -0
  24. package/packages/safe-js/dist/interp/globals/object.js +153 -0
  25. package/packages/safe-js/dist/interp/globals.d.ts +4 -1
  26. package/packages/safe-js/dist/interp/globals.js +2 -0
  27. package/packages/safe-js/dist/interp/host-bridge.d.ts +4 -0
  28. package/packages/safe-js/dist/interp/host-bridge.js +21 -2
  29. package/packages/safe-js/dist/interp/host-call.js +4 -0
  30. package/packages/safe-js/dist/interp/host-capabilities.d.ts +28 -1
  31. package/packages/safe-js/dist/interp/host-capabilities.js +220 -5
  32. package/packages/safe-js/dist/interp/interpreter.js +46 -11
  33. package/packages/safe-js/dist/interp/iteration.js +3 -0
  34. package/packages/safe-js/dist/interp/object-model.d.ts +3 -1
  35. package/packages/safe-js/dist/interp/object-model.js +39 -9
  36. package/packages/safe-js/dist/interp/string-coercion.js +3 -0
  37. package/packages/safe-js/dist/interp/values.d.ts +3 -1
  38. package/packages/safe-js/dist/interp/values.js +34 -6
  39. package/packages/safe-js/dist/lint/rules/known-globals.d.ts +1 -1
  40. package/packages/safe-js/dist/lint/rules/known-globals.js +1 -0
  41. package/packages/safe-js/dist/parse/parser.js +4 -2
  42. package/packages/safe-js/dist/realm.d.ts +4 -1
  43. package/packages/safe-js/dist/realm.js +89 -10
  44. package/packages/safe-js/dist/run.d.ts +2 -0
  45. package/packages/safe-js/dist/run.js +3 -1
  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-2M6MNQBY.js.map +0 -7
  54. /package/packages/safe-js/dist/chunks/{chunk-QSSQJNKE.js.map → chunk-RXLDJ6LQ.js.map} +0 -0
@@ -1,5 +1,6 @@
1
1
  import { promiseReplayContext } from "./promise-replay.js";
2
- import { getHostObjectKeys, getHostObjectMember, isGuestHostObject, setHostObjectMember } from "./host-capabilities.js";
2
+ import { getHostObjectKeys, getHostObjectMember, hasHostObjectMember, isGuestHostObject, setHostObjectMember } from "./host-capabilities.js";
3
+ import { sandboxString } from "./string-coercion.js";
3
4
  import { assertPromiseExecutionAllowed } from "./promise-tracker.js";
4
5
  import { SandboxJobQueue, runAsyncPrefix, suspendJob } from "./jobs.js";
5
6
  import { withCancellationSignal } from "./cancel.js";
@@ -11,7 +12,7 @@ import { CompileScope, RegexCompileGuard } from "./regex/compile-guard.js";
11
12
  import { coerceThrownValue, createCapturedException, evaluateThrowStatement as evaluateThrowStatementResult, evaluateTryStatement as evaluateTryStatementResult, isCapturedException, surfaceThrownValue } from "./exceptions.js";
12
13
  import { callArrayMethod, getArrayMember, isArrayMethodName } from "./methods/array.js";
13
14
  import { getFunctionMember } from "./methods/function.js";
14
- import { getGuestFunctionProperty, getSandboxPrototype, isGuestClosure, materializeFunctionProperties } from "./object-model.js";
15
+ import { getGuestFunctionProperty, getSandboxPrototype, isGuestClosure, materializeFunctionProperties, setSandboxPrototype } from "./object-model.js";
15
16
  import { assertSandboxDataDepth } from "../graph-depth.js";
16
17
  import { callMapMethod, getMapMember, isMapMethodName } from "./methods/map.js";
17
18
  import { callNumberMethod, getNumberMember, isNumberMethodName } from "./methods/number.js";
@@ -27,6 +28,8 @@ import { isSandboxErrorConstructorInstance } from "./globals/error.js";
27
28
  import { isSandboxMapConstructor, isSandboxSetConstructor } from "./globals/collections.js";
28
29
  import { getFloat32Member, isFloat32ArrayConstructor, setFloat32Member } from "./globals/float32array.js";
29
30
  import { isFloat32Array } from "./float32.js";
31
+ import { dateString, dateTime, isSandboxDate } from "./date.js";
32
+ import { getDateMember, getDatePrototype, isDateConstructor } from "./globals/date.js";
30
33
  import { createSandboxRegex, allocateProducedSandboxValue, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, reconcileCompiledValues } from "./values.js";
31
34
  import { Scope } from "./scope.js";
32
35
  import { hoistVarDeclarations } from "./var-hoist.js";
@@ -323,6 +326,9 @@ async function evaluateObjectExpression(node, context) {
323
326
  return value;
324
327
  }
325
328
  if (isObjectPrototypeSetterProperty(property, key.value)) {
329
+ if (value.value === null || typeof value.value === "object") {
330
+ setSandboxPrototype(object, value.value, context.budget);
331
+ }
326
332
  continue;
327
333
  }
328
334
  defineSandboxProperty(object, String(key.value), value.value);
@@ -431,7 +437,13 @@ async function evaluateBinaryExpression(node, context) {
431
437
  if (right.kind !== "normal") {
432
438
  return right;
433
439
  }
434
- const value = applyBinaryOperator(node, left.value, right.value, context);
440
+ const value = node.operator === "in" && isGuestHostObject(right.value)
441
+ ? hasHostObjectMember(right.value, await sandboxString(left.value, context.budget, {
442
+ stack: context.callStack,
443
+ thisValue: undefined,
444
+ invokeClosure: (closure, args, thisValue) => invokeSandboxClosure(closure, args, context, context.callStack, undefined, thisValue)
445
+ }))
446
+ : applyBinaryOperator(node, left.value, right.value, context);
435
447
  return {
436
448
  kind: "normal",
437
449
  hasValue: true,
@@ -1128,7 +1140,7 @@ function forInKeys(object, budget) {
1128
1140
  const keys = [];
1129
1141
  const seen = new Set();
1130
1142
  let depth = 0;
1131
- for (let current = object; current !== null; current = getSandboxPrototype(current)) {
1143
+ for (let current = object; current !== null; current = getSandboxPrototype(current, budget)) {
1132
1144
  if (depth > 0)
1133
1145
  budget.visitNode();
1134
1146
  assertSandboxDataDepth(depth++);
@@ -1147,9 +1159,9 @@ function forInKeys(object, budget) {
1147
1159
  }
1148
1160
  function hasForInProperty(object, key, budget) {
1149
1161
  if (isGuestHostObject(object))
1150
- return getHostObjectKeys(object).includes(key);
1162
+ return hasHostObjectMember(object, key, true);
1151
1163
  let depth = 0;
1152
- for (let current = object; current !== null; current = getSandboxPrototype(current)) {
1164
+ for (let current = object; current !== null; current = getSandboxPrototype(current, budget)) {
1153
1165
  if (depth > 0)
1154
1166
  budget.visitNode();
1155
1167
  assertSandboxDataDepth(depth++);
@@ -1648,6 +1660,8 @@ function getPropertyValue(target, property, context) {
1648
1660
  return undefined;
1649
1661
  if (isFloat32Array(target))
1650
1662
  return getFloat32Member(target, property, context.budget);
1663
+ if (isSandboxDate(target))
1664
+ return getDateMember(property, context.budget, context.compilation?.owner);
1651
1665
  if (isSandboxMap(target))
1652
1666
  return getMapMember(target, property, createMapMethodOptions(context));
1653
1667
  if (isSandboxSet(target))
@@ -1864,6 +1878,9 @@ async function evaluateMemberCallExpression(node, context) {
1864
1878
  if (isSandboxMap(member.object)) {
1865
1879
  return evaluatePrimitiveMemberCall(node, "Map", member.property, getMapMember(member.object, member.property, createMapMethodOptions(context)), context);
1866
1880
  }
1881
+ if (isSandboxDate(member.object)) {
1882
+ return evaluateResolvedCallExpression(node, getDateMember(member.property, context.budget, context.compilation?.owner), context, member.object);
1883
+ }
1867
1884
  if (isFloat32Array(member.object)) {
1868
1885
  return evaluateResolvedCallExpression(node, getFloat32Member(member.object, member.property, context.budget), context, member.object);
1869
1886
  }
@@ -2076,6 +2093,8 @@ function applyBinaryOperator(node, left, right, context) {
2076
2093
  }
2077
2094
  if (isFloat32ArrayConstructor(right))
2078
2095
  return isFloat32Array(left);
2096
+ if (isDateConstructor(right))
2097
+ return isSandboxDate(left) && getDatePrototype(left, context.budget, context.compilation?.owner) !== null;
2079
2098
  if (isSandboxSetConstructor(right) && isSandboxSet(left)) {
2080
2099
  return true;
2081
2100
  }
@@ -2090,7 +2109,7 @@ function applyBinaryOperator(node, left, right, context) {
2090
2109
  throw new TypeError("Function has a non-object prototype in instanceof check.");
2091
2110
  }
2092
2111
  let depth = 0;
2093
- for (let current = getSandboxPrototype(left); current !== null; current = getSandboxPrototype(current)) {
2112
+ for (let current = getSandboxPrototype(left, context.budget); current !== null; current = getSandboxPrototype(current, context.budget)) {
2094
2113
  context.budget.visitNode();
2095
2114
  assertSandboxDataDepth(depth++);
2096
2115
  if (current === prototype)
@@ -2141,8 +2160,8 @@ function applyAdditionOperator(left, right, context) {
2141
2160
  return toNumber(leftPrimitive) + toNumber(rightPrimitive);
2142
2161
  }
2143
2162
  function compareRelational(left, right, operator) {
2144
- const leftPrimitive = toPrimitive(left);
2145
- const rightPrimitive = toPrimitive(right);
2163
+ const leftPrimitive = isSandboxDate(left) ? dateTime(left) : toPrimitive(left);
2164
+ const rightPrimitive = isSandboxDate(right) ? dateTime(right) : toPrimitive(right);
2146
2165
  if (typeof leftPrimitive === "string" && typeof rightPrimitive === "string") {
2147
2166
  switch (operator) {
2148
2167
  case "<":
@@ -2225,6 +2244,8 @@ function toPrimitive(value) {
2225
2244
  return toString(value);
2226
2245
  }
2227
2246
  async function toNumericPrimitive(value, context) {
2247
+ if (isSandboxDate(value))
2248
+ return dateTime(value);
2228
2249
  if (isPrimitiveCoercionType(getCoercionType(value))) {
2229
2250
  return value;
2230
2251
  }
@@ -2247,6 +2268,8 @@ async function toNumericPrimitive(value, context) {
2247
2268
  return toString(value);
2248
2269
  }
2249
2270
  function toNumber(value) {
2271
+ if (isSandboxDate(value))
2272
+ return dateTime(value);
2250
2273
  if (typeof value === "number") {
2251
2274
  return value;
2252
2275
  }
@@ -2265,6 +2288,8 @@ function toNumber(value) {
2265
2288
  return toNumber(toPrimitive(value));
2266
2289
  }
2267
2290
  function toString(value) {
2291
+ if (isSandboxDate(value))
2292
+ return dateString(value);
2268
2293
  if (Array.isArray(value)) {
2269
2294
  return value
2270
2295
  .map((entry) => (entry === null || entry === undefined ? "" : toString(entry)))
@@ -2308,7 +2333,7 @@ function getMemberValue(target, property, context) {
2308
2333
  }
2309
2334
  if (Object.hasOwn(current, String(property)))
2310
2335
  return current[String(property)];
2311
- current = getSandboxPrototype(current);
2336
+ current = getSandboxPrototype(current, context.budget);
2312
2337
  if (current !== null) {
2313
2338
  context.budget.visitNode();
2314
2339
  assertSandboxDataDepth(++depth);
@@ -2323,6 +2348,8 @@ function getArrayMemberValue(target, property, context) {
2323
2348
  return getArrayMember(target, property, createArrayMethodOptions(context));
2324
2349
  }
2325
2350
  export function setSandboxProperty(target, property, value, budget) {
2351
+ if (isSandboxDate(target))
2352
+ throw new TypeError("Date own properties are not supported.");
2326
2353
  if (isGuestHostObject(target)) {
2327
2354
  setHostObjectMember(target, String(property), value);
2328
2355
  return;
@@ -2359,7 +2386,7 @@ export function setSandboxProperty(target, property, value, budget) {
2359
2386
  else {
2360
2387
  if (typeof prototypeOwner === "object" && prototypeOwner !== null) {
2361
2388
  let depth = 0;
2362
- for (let prototype = getSandboxPrototype(prototypeOwner); prototype !== null; prototype = getSandboxPrototype(prototype)) {
2389
+ for (let prototype = getSandboxPrototype(prototypeOwner, budget); prototype !== null; prototype = getSandboxPrototype(prototype, budget)) {
2363
2390
  budget.visitNode();
2364
2391
  assertSandboxDataDepth(depth++);
2365
2392
  const properties = isSandboxClosure(prototype) ? prototype.properties : prototype;
@@ -2553,6 +2580,14 @@ async function evaluateObjectSpread(node, context) {
2553
2580
  value: []
2554
2581
  };
2555
2582
  }
2583
+ if (isGuestHostObject(value.value)) {
2584
+ const entries = [];
2585
+ for (const key of getHostObjectKeys(value.value)) {
2586
+ if (hasHostObjectMember(value.value, key, true))
2587
+ entries.push([key, getHostObjectMember(value.value, key)]);
2588
+ }
2589
+ return { ok: true, value: entries };
2590
+ }
2556
2591
  if ((isSandboxClosure(value.value) && !isGuestClosure(value.value)) || isSandboxPromise(value.value)) {
2557
2592
  throw new TypeError(`Cannot spread ${describeObjectSpreadValue(value.value)} into object literal.`);
2558
2593
  }
@@ -1,7 +1,10 @@
1
1
  import { isSandboxGenerator, isSandboxMap, isSandboxSet } from "./values.js";
2
2
  import { enterRunningState } from "./running-state.js";
3
3
  import { isFloat32Array } from "./float32.js";
4
+ import { getHostObjectIterator, isGuestHostObject } from "./host-capabilities.js";
4
5
  export function getSandboxIterator(value) {
6
+ if (isGuestHostObject(value))
7
+ return getHostObjectIterator(value);
5
8
  if (isFloat32Array(value)) {
6
9
  return syncIterator(Float32Array.prototype.values.call(value));
7
10
  }
@@ -5,7 +5,9 @@ export declare function isGuestClosure(value: unknown): value is SandboxClosure;
5
5
  export declare function getGuestFunctionProperties(closure: SandboxClosure): SandboxObject | undefined;
6
6
  export declare function materializeFunctionProperties(closure: SandboxClosure): SandboxObject;
7
7
  export declare function getGuestFunctionProperty(closure: SandboxClosure, key: string): SandboxValue;
8
- export declare function getSandboxPrototype(value: object): object | null;
8
+ export declare function installObjectPrototype(budget: Budget, prototype: SandboxObject, constructor: SandboxClosure): void;
9
+ export declare function releaseObjectPrototype(budget: Budget): void;
10
+ export declare function getSandboxPrototype(value: object, budget?: Budget): object | null;
9
11
  export declare function getSandboxDataProperty(value: SandboxValue, key: string | number, budget?: Budget): SandboxValue;
10
12
  export declare function setSandboxPrototype(value: object, prototype: object | null, budget?: Budget): void;
11
13
  export declare function markDescriptorObject(value: object): void;
@@ -4,6 +4,8 @@ import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, i
4
4
  const guestClosures = new WeakSet();
5
5
  const functionProperties = new WeakMap();
6
6
  const prototypes = new WeakMap();
7
+ const intrinsicPrototypes = new WeakMap();
8
+ const intrinsicConstructors = new WeakMap();
7
9
  const descriptorObjects = new WeakSet();
8
10
  export function registerGuestClosure(closure) {
9
11
  guestClosures.add(closure);
@@ -56,8 +58,33 @@ export function getGuestFunctionProperty(closure, key) {
56
58
  ? undefined
57
59
  : Object.getOwnPropertyDescriptor(properties, key)?.value;
58
60
  }
59
- export function getSandboxPrototype(value) {
60
- return prototypes.get(value) ?? null;
61
+ export function installObjectPrototype(budget, prototype, constructor) {
62
+ prototypes.set(prototype, null);
63
+ intrinsicPrototypes.set(budget, prototype);
64
+ const records = [prototype, materializeFunctionProperties(constructor)].map(value => ({
65
+ value, descriptors: new Map(Object.entries(Object.getOwnPropertyDescriptors(value)))
66
+ }));
67
+ const unchanged = (before, after) => before !== undefined && after !== undefined && before.value === after.value &&
68
+ before.writable === after.writable && before.configurable === after.configurable && before.enumerable === after.enumerable;
69
+ intrinsicConstructors.set(constructor, () => records.every(({ value, descriptors }) => {
70
+ const current = Object.getOwnPropertyDescriptors(value);
71
+ return Object.keys(current).length === descriptors.size &&
72
+ Object.keys(current).every(key => unchanged(descriptors.get(key), current[key]));
73
+ }));
74
+ budget.setRetainedValues(prototype, () => records.flatMap(({ value, descriptors }) => Object.entries(Object.getOwnPropertyDescriptors(value)).flatMap(([key, descriptor]) => unchanged(descriptors.get(key), descriptor) ? [] : [key, descriptor.value])));
75
+ }
76
+ export function releaseObjectPrototype(budget) {
77
+ const prototype = intrinsicPrototypes.get(budget);
78
+ if (prototype !== undefined)
79
+ budget.setRetainedValues(prototype, undefined);
80
+ intrinsicPrototypes.delete(budget);
81
+ }
82
+ export function getSandboxPrototype(value, budget) {
83
+ if (prototypes.has(value))
84
+ return prototypes.get(value) ?? null;
85
+ return budget !== undefined && isPrototypeRecord(value)
86
+ ? intrinsicPrototypes.get(budget) ?? null
87
+ : null;
61
88
  }
62
89
  export function getSandboxDataProperty(value, key, budget) {
63
90
  let current = value;
@@ -81,7 +108,7 @@ export function getSandboxDataProperty(value, key, budget) {
81
108
  return undefined;
82
109
  if (Object.hasOwn(current, String(key)))
83
110
  return current[String(key)];
84
- current = getSandboxPrototype(current);
111
+ current = getSandboxPrototype(current, budget);
85
112
  if (current !== null) {
86
113
  budget?.visitNode();
87
114
  assertSandboxDataDepth(++depth);
@@ -90,25 +117,25 @@ export function getSandboxDataProperty(value, key, budget) {
90
117
  return undefined;
91
118
  }
92
119
  export function setSandboxPrototype(value, prototype, budget) {
120
+ if (budget !== undefined && intrinsicPrototypes.get(budget) === value && prototype !== null) {
121
+ throw new TypeError("Object.prototype has an immutable null prototype.");
122
+ }
93
123
  if (!isPrototypeRecord(value) || (prototype !== null && !isPrototypeRecord(prototype))) {
94
124
  throw new TypeError("Prototype links require ordinary sandbox objects; callable and exotic prototype chains are not supported.");
95
125
  }
96
- if (getSandboxPrototype(value) === prototype)
126
+ if (prototypes.has(value) && getSandboxPrototype(value, budget) === prototype)
97
127
  return;
98
128
  if (!Object.isExtensible(isGuestClosure(value) ? materializeFunctionProperties(value) : value)) {
99
129
  throw new TypeError("Cannot change the prototype of a non-extensible object.");
100
130
  }
101
131
  let depth = 0;
102
- for (let current = prototype; current !== null; current = getSandboxPrototype(current)) {
132
+ for (let current = prototype; current !== null; current = getSandboxPrototype(current, budget)) {
103
133
  budget?.visitNode();
104
134
  assertSandboxDataDepth(depth++);
105
135
  if (current === value)
106
136
  throw new TypeError("Cyclic prototype value.");
107
137
  }
108
- if (prototype === null)
109
- prototypes.delete(value);
110
- else
111
- prototypes.set(value, prototype);
138
+ prototypes.set(value, prototype);
112
139
  }
113
140
  function isPrototypeRecord(value) {
114
141
  if (isGuestHostObject(value))
@@ -130,6 +157,9 @@ export function hasManagedDescriptors(value) {
130
157
  return descriptorObjects.has(value);
131
158
  }
132
159
  export function hasGuestObjectState(value) {
160
+ const intrinsicUnchanged = intrinsicConstructors.get(value);
161
+ if (intrinsicUnchanged !== undefined)
162
+ return !intrinsicUnchanged();
133
163
  if (isLiveCapability(value))
134
164
  return true;
135
165
  if (functionProperties.has(value) || prototypes.has(value))
@@ -1,4 +1,5 @@
1
1
  import { sandboxErrorTypes } from "../error/shape.js";
2
+ import { dateString, isSandboxDate } from "./date.js";
2
3
  import { float32Storage, isFloat32Array } from "./float32.js";
3
4
  import { isSandboxClosure, isSandboxPromise } from "./values.js";
4
5
  export function sandboxString(value, budget, context, joining = new Set()) {
@@ -41,6 +42,8 @@ async function stringifyObject(value, budget, context, joining) {
41
42
  }
42
43
  }
43
44
  async function defaultToString(value, budget, context, joining) {
45
+ if (isSandboxDate(value))
46
+ return budget.allocateString(dateString(value));
44
47
  if (Array.isArray(value) || isFloat32Array(value)) {
45
48
  if (Object.hasOwn(value, "join")) {
46
49
  const join = ownDataValue(value, "join");
@@ -12,7 +12,7 @@ declare const sandboxRegexPattern: unique symbol;
12
12
  declare const sandboxSetBrand: unique symbol;
13
13
  declare const sandboxRetainedValues: unique symbol;
14
14
  export type SandboxPrimitive = string | number | boolean | null | undefined;
15
- export type SandboxValue = SandboxPrimitive | Float32Array | SandboxObject | SandboxArray | SandboxClosure | SandboxGenerator | SandboxMap | SandboxSet | SandboxPromise | SandboxRegex;
15
+ export type SandboxValue = SandboxPrimitive | Date | Float32Array | SandboxObject | SandboxArray | SandboxClosure | SandboxGenerator | SandboxMap | SandboxSet | SandboxPromise | SandboxRegex;
16
16
  export type SandboxObject = {
17
17
  [key: string]: SandboxValue;
18
18
  };
@@ -55,6 +55,7 @@ export type SandboxCallContext = {
55
55
  };
56
56
  export type SandboxClosure = {
57
57
  readonly async?: true;
58
+ readonly generator?: true;
58
59
  readonly sandbox?: true;
59
60
  readonly boundTarget?: SandboxClosure;
60
61
  readonly cancellationSignal?: AbortSignal;
@@ -92,6 +93,7 @@ type CopyFromSandboxOptions = {
92
93
  export declare function createSandboxClosure(input: {
93
94
  guest?: boolean;
94
95
  async?: boolean;
96
+ generator?: boolean;
95
97
  sandbox?: boolean;
96
98
  boundTarget?: SandboxClosure;
97
99
  cancellationSignal?: AbortSignal;
@@ -1,5 +1,6 @@
1
1
  import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
2
- import { getHostObjectKeys, getHostObjectMember, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
2
+ import { copyNativeDate, exportDate, isSandboxDate } from "./date.js";
3
+ import { getHostObjectKeys, getHostObjectMember, hasHostObjectMember, measureHostObjectData, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
3
4
  import { types as nodeTypes } from "node:util";
4
5
  import { CompileScope, RegexCompileGuard, regexCompiledData } from "./regex/compile-guard.js";
5
6
  import { copyFloat32Storage, float32DataProperties, float32Storage, isFloat32Array } from "./float32.js";
@@ -40,6 +41,8 @@ export function createSandboxClosure(input) {
40
41
  if (input.sandbox === true) {
41
42
  Object.defineProperty(closure, "sandbox", { value: true });
42
43
  }
44
+ if (input.generator === true)
45
+ Object.defineProperty(closure, "generator", { value: true });
43
46
  if (input.length !== undefined) {
44
47
  Object.defineProperty(closure, "length", { value: input.length });
45
48
  }
@@ -71,8 +74,14 @@ export function createSandboxClosure(input) {
71
74
  return Object.freeze(closure);
72
75
  }
73
76
  export function ownEnumerableSandboxEntries(value) {
74
- if (isGuestHostObject(value))
75
- return getHostObjectKeys(value).map(key => [key, getHostObjectMember(value, key)]);
77
+ if (isGuestHostObject(value)) {
78
+ const entries = [];
79
+ for (const key of getHostObjectKeys(value)) {
80
+ if (hasHostObjectMember(value, key, true))
81
+ entries.push([key, getHostObjectMember(value, key)]);
82
+ }
83
+ return entries;
84
+ }
76
85
  if (value === null || value === undefined)
77
86
  throw new TypeError("Cannot convert undefined or null to object.");
78
87
  if (isGuestClosure(value))
@@ -225,9 +234,12 @@ export function measureSandboxData(values, options = {}) {
225
234
  assertSandboxDataDepth(depth);
226
235
  seen.add(value);
227
236
  usage += 1;
237
+ if (isSandboxDate(value)) {
238
+ usage += 8;
239
+ return;
240
+ }
228
241
  if (isGuestHostObject(value)) {
229
- for (const key of getHostObjectKeys(value))
230
- usage += key.length + 1;
242
+ usage += measureHostObjectData(value);
231
243
  return;
232
244
  }
233
245
  const prototype = getSandboxPrototype(value);
@@ -341,7 +353,7 @@ export function reconcileCompiledValues(budget, values, compilation, parent, esc
341
353
  while (parent?.closed)
342
354
  parent = parent.parent;
343
355
  const included = new Set();
344
- const usage = measureSandboxData(values, { compileTickets: included });
356
+ const usage = measureSandboxData([...values, ...budget.retainedValues()], { compileTickets: included });
345
357
  const kept = new Set();
346
358
  if (parent !== undefined)
347
359
  measureSandboxData(escaping, { compileTickets: kept });
@@ -435,6 +447,14 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
435
447
  }
436
448
  return sandboxPromise;
437
449
  }
450
+ if (nodeTypes.isDate(value)) {
451
+ const existing = state.seen.get(value);
452
+ if (existing !== undefined)
453
+ return existing;
454
+ const copy = copyNativeDate(value);
455
+ state.seen.set(value, copy);
456
+ return copy;
457
+ }
438
458
  if (isFloat32Array(value)) {
439
459
  const existing = state.seen.get(value);
440
460
  if (existing !== undefined)
@@ -567,6 +587,14 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
567
587
  Object.preventExtensions(copy);
568
588
  return copy;
569
589
  }
590
+ if (isSandboxDate(value)) {
591
+ const existing = state.seen.get(value);
592
+ if (existing !== undefined)
593
+ return existing;
594
+ const copy = exportDate(value);
595
+ state.seen.set(value, copy);
596
+ return copy;
597
+ }
570
598
  if (isSandboxClosure(value)) {
571
599
  if (options.wrapClosure === undefined) {
572
600
  throw new TypeError("Sandbox closures cannot cross into host values without an explicit wrapper.");
@@ -1 +1 @@
1
- export declare const KNOWN_RUNTIME_GLOBALS: readonly ["AggregateError", "Array", "Boolean", "Error", "Infinity", "isFinite", "isNaN", "JSON", "Map", "Float32Array", "Math", "NaN", "Number", "Object", "parseFloat", "parseInt", "Promise", "RangeError", "ReferenceError", "RegExp", "Set", "String", "structuredClone", "SyntaxError", "TypeError", "console"];
1
+ export declare const KNOWN_RUNTIME_GLOBALS: readonly ["AggregateError", "Array", "Boolean", "Date", "Error", "Infinity", "isFinite", "isNaN", "JSON", "Map", "Float32Array", "Math", "NaN", "Number", "Object", "parseFloat", "parseInt", "Promise", "RangeError", "ReferenceError", "RegExp", "Set", "String", "structuredClone", "SyntaxError", "TypeError", "console"];
@@ -2,6 +2,7 @@ export const KNOWN_RUNTIME_GLOBALS = [
2
2
  "AggregateError",
3
3
  "Array",
4
4
  "Boolean",
5
+ "Date",
5
6
  "Error",
6
7
  "Infinity",
7
8
  "isFinite",
@@ -1832,8 +1832,10 @@ class Parser {
1832
1832
  }
1833
1833
  break;
1834
1834
  }
1835
- this.expectPunctuator("(");
1836
- const args = this.parseArguments();
1835
+ const optional = this.consumePunctuator("?.");
1836
+ if (optional !== undefined)
1837
+ throw new DisallowedSyntaxError("new optional chain", optional.start);
1838
+ const args = this.consumePunctuator("(") === undefined ? [] : this.parseArguments();
1837
1839
  const end = this.previousToken();
1838
1840
  return {
1839
1841
  node: {
@@ -4,15 +4,17 @@ import { type CallerInjectedBinding } from "./interp/host-bridge.js";
4
4
  import { type CallbackOptions, type SafeJSExtension } from "./extensions.js";
5
5
  import { type ModuleRegistry } from "./modules/registry.js";
6
6
  import type { ConsoleSink } from "./interp/globals/console-json.js";
7
- import type { RunOptions, RunResult } from "./run.js";
7
+ import type { RunClock, RunOptions, RunResult } from "./run.js";
8
8
  export type RealmLimits = {
9
9
  extensions?: number;
10
10
  hostObjects?: number;
11
11
  callbacks?: number;
12
+ guestReferences?: number;
12
13
  cleanups?: number;
13
14
  nestedEvaluations?: number;
14
15
  };
15
16
  export type RealmOptions = {
17
+ clock?: RunClock;
16
18
  bindings?: Record<string, CallerInjectedBinding>;
17
19
  modules?: ModuleRegistry;
18
20
  extensions?: readonly SafeJSExtension[];
@@ -37,6 +39,7 @@ export type SafeJSRealm = {
37
39
  }): Promise<RealmResult>;
38
40
  invokeCallback(callback: unknown, options?: CallbackOptions): Promise<unknown>;
39
41
  releaseCallback(callback: unknown): void;
42
+ releaseGuestReference(reference: unknown): void;
40
43
  close(): Promise<void>;
41
44
  };
42
45
  export declare function createRealm(options?: RealmOptions): SafeJSRealm;