poe-code 14.0.82 → 14.0.84

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 (50) hide show
  1. package/dist/index.js +1105 -223
  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-7LGBDF56.js → chunk-2EZQJQ2C.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-V6LQP64H.js → chunk-CYVI4ZUK.js} +978 -161
  7. package/packages/safe-js/dist/chunks/chunk-CYVI4ZUK.js.map +7 -0
  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.js +2 -2
  11. package/packages/safe-js/dist/interp/array-buffer.d.ts +12 -0
  12. package/packages/safe-js/dist/interp/array-buffer.js +33 -0
  13. package/packages/safe-js/dist/interp/float32-prototypes.d.ts +3 -0
  14. package/packages/safe-js/dist/interp/float32-prototypes.js +1 -0
  15. package/packages/safe-js/dist/interp/float32.d.ts +7 -1
  16. package/packages/safe-js/dist/interp/float32.js +50 -14
  17. package/packages/safe-js/dist/interp/globals/array-buffer.d.ts +3 -0
  18. package/packages/safe-js/dist/interp/globals/array-buffer.js +112 -0
  19. package/packages/safe-js/dist/interp/globals/float32array.d.ts +4 -3
  20. package/packages/safe-js/dist/interp/globals/float32array.js +463 -68
  21. package/packages/safe-js/dist/interp/globals/object-array.js +3 -3
  22. package/packages/safe-js/dist/interp/globals.d.ts +2 -0
  23. package/packages/safe-js/dist/interp/globals.js +6 -2
  24. package/packages/safe-js/dist/interp/host-bridge.d.ts +1 -0
  25. package/packages/safe-js/dist/interp/host-bridge.js +21 -0
  26. package/packages/safe-js/dist/interp/host-call.js +26 -2
  27. package/packages/safe-js/dist/interp/instanceof.js +1 -1
  28. package/packages/safe-js/dist/interp/interpreter.js +2 -4
  29. package/packages/safe-js/dist/interp/iteration.js +15 -6
  30. package/packages/safe-js/dist/interp/methods/array-iterator.js +1 -1
  31. package/packages/safe-js/dist/interp/object-model.js +22 -1
  32. package/packages/safe-js/dist/interp/values.d.ts +1 -1
  33. package/packages/safe-js/dist/interp/values.js +59 -9
  34. package/packages/safe-js/dist/lint/rules/known-globals.d.ts +1 -1
  35. package/packages/safe-js/dist/lint/rules/known-globals.js +1 -0
  36. package/packages/safe-js/dist/parse/parser.js +8 -3
  37. package/packages/safe-js/dist/parse/tokenizer.js +45 -3
  38. package/packages/safe-js/dist/snapshot/array-buffer.d.ts +13 -0
  39. package/packages/safe-js/dist/snapshot/array-buffer.js +40 -0
  40. package/packages/safe-js/dist/snapshot/dump-format.js +25 -9
  41. package/packages/safe-js/dist/snapshot/float32array.d.ts +11 -1
  42. package/packages/safe-js/dist/snapshot/float32array.js +42 -5
  43. package/packages/safe-js/dist/snapshot/replay-data.d.ts +5 -0
  44. package/packages/safe-js/dist/snapshot/replay-data.js +35 -10
  45. package/packages/safe-js/dist/snapshot/restore.js +30 -3
  46. package/packages/safe-js/dist/snapshot/serialize.d.ts +7 -3
  47. package/packages/safe-js/dist/snapshot/serialize.js +24 -14
  48. package/packages/safe-js/dist/snapshot/validation.js +21 -1
  49. package/packages/safe-js/dist/chunks/chunk-V6LQP64H.js.map +0 -7
  50. /package/packages/safe-js/dist/chunks/{chunk-7LGBDF56.js.map → chunk-2EZQJQ2C.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { createConsoleJsonGlobals } from "./globals/console-json.js";
2
2
  import { createCollectionGlobals } from "./globals/collections.js";
3
- import { createFloat32ArrayGlobal } from "./globals/float32array.js";
3
+ import { createFloat32ArrayGlobal, createFloat32ArrayPrototypes } from "./globals/float32array.js";
4
4
  import { createErrorGlobals, createErrorPrototypes } from "./globals/error.js";
5
5
  import { createMathGlobals } from "./globals/math.js";
6
6
  import { createRegexGlobals } from "./globals/regex.js";
@@ -13,24 +13,28 @@ import { createPromiseGlobals } from "./promise.js";
13
13
  import { createDateGlobal } from "./globals/date.js";
14
14
  import { createSymbolGlobal } from "./globals/symbol.js";
15
15
  import { createBigIntGlobal } from "./globals/bigint.js";
16
+ import { createArrayBufferGlobal } from "./globals/array-buffer.js";
16
17
  import { registerBuiltinIdentities } from "./intrinsics.js";
17
18
  export function createBuiltinBindings(options) {
18
19
  const bindings = {
19
20
  ...createConsoleJsonGlobals(options),
20
21
  ...createCollectionGlobals(options),
21
- Float32Array: createFloat32ArrayGlobal(options.budget),
22
+ Float32Array: createFloat32ArrayGlobal(options.budget, options.float32Prototypes !== false),
22
23
  Date: createDateGlobal(options),
23
24
  Symbol: createSymbolGlobal(options.budget),
24
25
  BigInt: createBigIntGlobal(options.budget),
25
26
  ...createErrorGlobals({ ...options, errorPrototypes: options.errorPrototypes !== false }),
26
27
  ...createMathGlobals({ random: options.random, budget: options.budget }),
27
28
  ...createObjectArrayGlobals(options),
29
+ ArrayBuffer: createArrayBufferGlobal(options.budget),
28
30
  ...createMiscGlobals(options),
29
31
  ...createUriGlobals(options.budget),
30
32
  ...createPromiseGlobals(options),
31
33
  ...createRegexGlobals(options)
32
34
  };
33
35
  createFunctionPrototype(options.budget, options.functionHasInstance);
36
+ if (options.float32Prototypes !== false)
37
+ createFloat32ArrayPrototypes(options.budget, bindings.Float32Array);
34
38
  if (options.errorPrototypes !== false)
35
39
  createErrorPrototypes(options.budget, bindings);
36
40
  createGeneratorPrototypes(options.budget);
@@ -42,5 +42,6 @@ export declare function copyHostValueToSandbox(value: unknown, stackFrames: read
42
42
  errorData?: boolean;
43
43
  }, state: {
44
44
  seen: WeakMap<object, SandboxValue>;
45
+ float32Buffers?: WeakMap<ArrayBuffer, ArrayBuffer>;
45
46
  }, path: string): SandboxValue;
46
47
  export {};
@@ -5,6 +5,7 @@ import { exportHostCapability, importHostCapability, isLiveCapability } from "./
5
5
  import { attachErrorSpan, replaceErrorStack } from "../error/shape.js";
6
6
  import { SandboxError } from "./budget.js";
7
7
  import { CompileScope } from "./regex/compile-guard.js";
8
+ import { arrayBufferDataProperties, arrayBufferLength, copyArrayBufferStorage, isSandboxArrayBuffer } from "./array-buffer.js";
8
9
  import { checkFloat32Allocation, copyFloat32Storage, float32DataProperties, float32Storage, isFloat32Array } from "./float32.js";
9
10
  import { createSubsetErrorValue } from "./exceptions.js";
10
11
  import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
@@ -705,6 +706,25 @@ export function copyHostValueToSandbox(value, stackFrames, options, state, path)
705
706
  state.seen.set(value, date);
706
707
  return date;
707
708
  }
709
+ if (isSandboxArrayBuffer(value)) {
710
+ const existing = state.seen.get(value);
711
+ if (existing !== undefined)
712
+ return existing;
713
+ const length = arrayBufferLength(value);
714
+ budget.allocateArrayLength(length);
715
+ budget.provisionDataUsage(length + 1)();
716
+ const copy = copyArrayBufferStorage(value, state);
717
+ state.seen.set(value, copy);
718
+ for (const [key, descriptor] of arrayBufferDataProperties(value)) {
719
+ if (typeof key === "symbol")
720
+ throw new TypeError("Host ArrayBuffer symbol properties require an explicit capability path.");
721
+ Object.defineProperty(copy, key, { ...descriptor,
722
+ value: copyHostValueToSandbox(descriptor.value, stackFrames, { ...options, capabilityPath: [...(options.capabilityPath ?? []), key] }, state, joinPath(path, key)) });
723
+ }
724
+ if (!Object.isExtensible(value))
725
+ Object.preventExtensions(copy);
726
+ return copy;
727
+ }
708
728
  if (isFloat32Array(value)) {
709
729
  const existing = state.seen.get(value);
710
730
  if (existing !== undefined)
@@ -712,6 +732,7 @@ export function copyHostValueToSandbox(value, stackFrames, options, state, path)
712
732
  checkFloat32Allocation(Math.ceil(float32Storage(value).byteLength / 4), budget);
713
733
  const copy = copyFloat32Storage(value, state);
714
734
  state.seen.set(value, copy);
735
+ copyHostValueToSandbox(float32Storage(value).buffer, stackFrames, { ...options, capabilityPath: [...(options.capabilityPath ?? []), "buffer"] }, state, `${path}.buffer`);
715
736
  for (const [key, descriptor] of float32DataProperties(value)) {
716
737
  Object.defineProperty(copy, key, {
717
738
  ...descriptor,
@@ -1,5 +1,6 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { float32DataProperties, float32Storage, isFloat32Array } from "./float32.js";
2
+ import { float32DataProperties, float32Storage, float32ViewLayouts, isFloat32Array } from "./float32.js";
3
+ import { arrayBufferDataProperties, arrayBufferLength, arrayBufferOptions, isSandboxArrayBuffer } from "./array-buffer.js";
3
4
  import { copyNativeDate, serializedDateTime } from "./date.js";
4
5
  import { cloneSandboxValue, createSandboxClosure, defineOwnDataProperty, isArrayIndexKey, measureSandboxData } from "./values.js";
5
6
  import { CompileScope } from "./regex/compile-guard.js";
@@ -585,8 +586,26 @@ function normalize(value, seen) {
585
586
  const date = copyNativeDate(value);
586
587
  if (date !== undefined)
587
588
  return Object.assign(Object.create(null), { $type: "date", time: serializedDateTime(date) });
589
+ if (isSandboxArrayBuffer(value)) {
590
+ arrayBufferLength(value);
591
+ const properties = Object.create(null);
592
+ const entries = [];
593
+ for (const [key, descriptor] of arrayBufferDataProperties(value)) {
594
+ if (typeof key === "symbol")
595
+ throw new TypeError("ArrayBuffer symbol properties require an explicit host-call identity.");
596
+ entries.push([key, descriptor]);
597
+ }
598
+ for (const [key, descriptor] of entries.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0))
599
+ defineOwnDataProperty(properties, key, normalize(descriptor.value, seen));
600
+ return Object.assign(Object.create(null), { $type: "arraybuffer",
601
+ bytes: normalize(Array.from(new Uint8Array(value)), seen), ...arrayBufferOptions(value), properties });
602
+ }
588
603
  if (isFloat32Array(value)) {
589
604
  const storage = float32Storage(value);
605
+ const resizable = arrayBufferOptions(storage.buffer) !== undefined;
606
+ const layout = resizable ? float32ViewLayouts.get(value) : undefined;
607
+ if (resizable && layout === undefined)
608
+ throw new TypeError("Resizable Float32Array host-call identity requires known view layout.");
590
609
  const properties = Object.create(null);
591
610
  for (const [key, descriptor] of float32DataProperties(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)) {
592
611
  defineOwnDataProperty(properties, key, normalize(descriptor.value, seen));
@@ -596,7 +615,12 @@ function normalize(value, seen) {
596
615
  bytes: normalize(Array.from(new Uint8Array(storage.buffer)), seen),
597
616
  byteOffset: storage.byteOffset,
598
617
  length: storage.length,
599
- properties
618
+ properties,
619
+ ...(resizable || Reflect.ownKeys(storage.buffer).length > 0
620
+ ? { buffer: normalize(storage.buffer, seen) } : {}),
621
+ ...(layout === undefined ? {} : { viewLayout: {
622
+ byteOffset: layout.byteOffset, length: layout.length ?? null
623
+ } })
600
624
  });
601
625
  }
602
626
  if (Array.isArray(value)) {
@@ -27,7 +27,7 @@ export async function ordinaryHasInstance(value, constructor, budget, context) {
27
27
  return evaluateInstanceof(value, constructor.boundTarget, budget, context);
28
28
  }
29
29
  // These existing built-ins do not yet have ordinary prototype graphs.
30
- if (isFloat32ArrayConstructor(constructor))
30
+ if (isFloat32ArrayConstructor(constructor) && !isGuestClosure(constructor))
31
31
  return isFloat32Array(value);
32
32
  if ((!isGuestClosure(constructor) || (value !== null && typeof value === "object" && !hasExplicitSandboxPrototype(value))) &&
33
33
  isSandboxErrorConstructorInstance(value, constructor))
@@ -2380,7 +2380,7 @@ async function evaluateMemberCallExpression(node, context) {
2380
2380
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
2381
2381
  }
2382
2382
  if (isFloat32Array(member.object)) {
2383
- return evaluateResolvedCallExpression(node, getFloat32Member(member.object, member.property, context.budget), context, member.object);
2383
+ return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
2384
2384
  }
2385
2385
  if (isSandboxSet(member.object)) {
2386
2386
  return evaluatePrimitiveMemberCall(node, "Set", member.property, getSetMember(member.object, member.property, createSetMethodOptions(context)), context);
@@ -2911,9 +2911,7 @@ export function setSandboxProperty(target, property, value, budget, checkInherit
2911
2911
  if (isSandboxMap(target) || isSandboxSet(target))
2912
2912
  target = getCollectionProperties(target);
2913
2913
  if (isFloat32Array(target)) {
2914
- if (typeof property === "symbol")
2915
- throw new TypeError("Typed array symbol properties are not yet supported.");
2916
- setFloat32Member(target, property, value);
2914
+ setFloat32Member(target, property, value, budget);
2917
2915
  return;
2918
2916
  }
2919
2917
  if (isSandboxRegex(target)) {
@@ -1,6 +1,7 @@
1
1
  import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxSet } from "./values.js";
2
2
  import { enterRunningState } from "./running-state.js";
3
3
  import { isFloat32Array } from "./float32.js";
4
+ import { float32Prototypes } from "./float32-prototypes.js";
4
5
  import { boxedValue, isSandboxBox } from "./boxed.js";
5
6
  import { getHostObjectIterator, isGuestHostObject } from "./host-capabilities.js";
6
7
  import { isSandboxCollectionIterator, nextCollectionIterator } from "./collection-iterator.js";
@@ -98,6 +99,9 @@ export async function acquireSandboxIterator(value, budget, context, asyncProtoc
98
99
  const iterator = await invokeBuiltinClosure(factory, [], budget, context, value);
99
100
  if ((typeof iterator !== "object" && typeof iterator !== "function") || iterator === null)
100
101
  throw new TypeError("Iterator must be an object.");
102
+ if (!asyncProtocol && isSandboxGenerator(iterator) && !iterator.async &&
103
+ !hasExplicitSandboxPrototype(iterator) && getSandboxPropertyDescriptor(iterator, "next", budget) === undefined)
104
+ return getSandboxIterator(iterator, budget, context);
101
105
  const next = await context.getProperty(iterator, "next");
102
106
  return guestIterator(iterator, next, asyncProtocol, budget, context, signal);
103
107
  }
@@ -137,7 +141,7 @@ export async function readIteratorResult(iterator, result, property) {
137
141
  export function getSandboxAsyncIterator(value, budget, context, signal) {
138
142
  if (isSandboxGenerator(value) && value.async) {
139
143
  return hasExplicitSandboxPrototype(value) ? context?.getProperty === undefined
140
- ? generatorProtocolAdapter(value, budget, context, true, signal) : undefined
144
+ ? guestProtocolAdapter(value, budget, context, true, signal) : undefined
141
145
  : { ...generatorObjectIterator(value, budget, context), asyncProtocol: true };
142
146
  }
143
147
  if (value !== null &&
@@ -293,6 +297,11 @@ export function getSandboxIterator(value, budget, context) {
293
297
  if (isGuestHostObject(value))
294
298
  return getHostObjectIterator(value);
295
299
  if (isFloat32Array(value)) {
300
+ if (hasExplicitSandboxPrototype(value) || (budget !== undefined && float32Prototypes.has(budget))) {
301
+ if (getSandboxPropertyDescriptor(value, Symbol.iterator, budget) === undefined)
302
+ return undefined;
303
+ return guestProtocolAdapter(value, budget ?? new Budget(), context, false);
304
+ }
296
305
  return syncIterator(Float32Array.prototype.values.call(value));
297
306
  }
298
307
  if (isSandboxGenerator(value)) {
@@ -300,7 +309,7 @@ export function getSandboxIterator(value, budget, context) {
300
309
  return undefined;
301
310
  if (hasExplicitSandboxPrototype(value))
302
311
  return context?.getProperty === undefined
303
- ? generatorProtocolAdapter(value, budget ?? new Budget(), context, false) : undefined;
312
+ ? guestProtocolAdapter(value, budget ?? new Budget(), context, false) : undefined;
304
313
  return generatorObjectIterator(value, budget, context);
305
314
  }
306
315
  if (typeof value === "string") {
@@ -386,9 +395,9 @@ function collectionIterator(collection, value) {
386
395
  return adapter;
387
396
  }
388
397
  const asyncGeneratorRequests = new WeakMap();
389
- function generatorProtocolAdapter(value, budget, context, asyncProtocol, signal) {
390
- // Direct host adapters still need guest property reads, receiver binding and
391
- // cached next methods, but retain their asynchronous generator result channel.
398
+ function guestProtocolAdapter(value, budget, context, asyncProtocol, signal) {
399
+ // Direct adapters still need guest property reads, receiver binding and
400
+ // cached next methods without exposing native iterator objects.
392
401
  const bridge = {
393
402
  ...context,
394
403
  stack: context?.stack ?? [],
@@ -403,7 +412,7 @@ function generatorProtocolAdapter(value, budget, context, asyncProtocol, signal)
403
412
  let pending;
404
413
  const initialize = () => pending ??= acquireSandboxIterator(value, budget, bridge, asyncProtocol, signal).then(iterator => {
405
414
  if (iterator === undefined)
406
- throw new TypeError("Generator does not provide an iterator protocol.");
415
+ throw new TypeError("Value does not provide an iterator protocol.");
407
416
  return resolved = iterator;
408
417
  });
409
418
  return {
@@ -18,7 +18,7 @@ export async function nextArrayIterator(value, budget, context) {
18
18
  ?? getSandboxPropertyDescriptor(source, key, budget) ?? { value: undefined }, source, context);
19
19
  try {
20
20
  budget.visitNode();
21
- const number = isFloat32Array(source) ? float32Storage(source).length
21
+ const number = isFloat32Array(source) ? float32Storage(source, true).length
22
22
  : await sandboxNumber(await read("length"), budget, context);
23
23
  const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
24
24
  if (index >= length) {
@@ -8,6 +8,9 @@ import { isSandboxDate } from "./date.js";
8
8
  import { retainedAccessorClosures } from "./accessors.js";
9
9
  import { getHostObjectMember, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
10
10
  import { errorPrototypes } from "./error-prototypes.js";
11
+ import { float32Properties, isFloat32Array, isFloat32Index } from "./float32.js";
12
+ import { float32Prototypes } from "./float32-prototypes.js";
13
+ import { arrayBufferPrototypes, isSandboxArrayBuffer } from "./array-buffer.js";
11
14
  import { sandboxErrorTypes } from "../error/shape.js";
12
15
  import { boxedValue, isSandboxBox } from "./boxed.js";
13
16
  import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, getPromiseProperties, isSandboxRegex, getRegexProperties, getCollectionProperties, isSandboxSet } from "./values.js";
@@ -276,12 +279,18 @@ export function releaseObjectPrototype(budget) {
276
279
  functionPrototypes.delete(budget);
277
280
  generatorPrototypes.delete(budget);
278
281
  errorPrototypes.delete(budget);
282
+ float32Prototypes.delete(budget);
283
+ arrayBufferPrototypes.delete(budget);
279
284
  initialRegexDescriptors.delete(budget);
280
285
  intrinsicPrototypes.delete(budget);
281
286
  }
282
287
  export function getSandboxPrototype(value, budget) {
283
288
  if (prototypes.has(value))
284
289
  return prototypes.get(value) ?? null;
290
+ if (isSandboxArrayBuffer(value))
291
+ return budget === undefined ? null : arrayBufferPrototypes.get(budget) ?? null;
292
+ if (isFloat32Array(value))
293
+ return budget === undefined ? null : float32Prototypes.get(budget) ?? null;
285
294
  // Host transport records are data-only. Resolve their default prototype in
286
295
  // the receiving realm without persisting executable intrinsic graphs.
287
296
  const errorType = sandboxErrorTypes.get(value);
@@ -328,6 +337,10 @@ export function getSandboxPropertyDescriptor(value, key, budget) {
328
337
  while (typeof current === "object" &&
329
338
  current !== null &&
330
339
  (Array.isArray(current) || isSandboxGenerator(current) || isSandboxDate(current) || isSandboxPromise(current) || isSandboxRegex(current) || isSandboxMap(current) || isSandboxSet(current) || isPrototypeRecord(current))) {
340
+ // An integer-indexed object stops numeric-key lookup even when it occurs
341
+ // inside another object's prototype chain and the index is invalid.
342
+ if (isFloat32Array(current) && typeof key !== "symbol" && isFloat32Index(String(key)))
343
+ return Object.getOwnPropertyDescriptor(current, key);
331
344
  const properties = isSandboxGenerator(current) ? getGeneratorProperties(current) : isSandboxPromise(current) ? getPromiseProperties(current) : isGuestClosure(current)
332
345
  ? key === "prototype" && current.construct !== undefined && current.boundTarget === undefined
333
346
  ? materializeFunctionProperties(current) : getGuestFunctionProperties(current)
@@ -350,6 +363,8 @@ export function getSandboxDataProperty(value, key, budget) {
350
363
  let current = value;
351
364
  let depth = 0;
352
365
  while (typeof current === "object" && current !== null) {
366
+ if (isFloat32Array(current) && typeof key !== "symbol" && isFloat32Index(String(key)))
367
+ return Object.getOwnPropertyDescriptor(current, key)?.value;
353
368
  if (isGuestHostObject(current))
354
369
  return typeof key === "symbol" ? undefined : getHostObjectMember(current, String(key));
355
370
  if (isSandboxRegex(current))
@@ -416,6 +431,10 @@ export function setSandboxPrototype(value, prototype, budget) {
416
431
  prototypes.set(value, prototype);
417
432
  }
418
433
  function isPrototypeRecord(value) {
434
+ if (isSandboxArrayBuffer(value))
435
+ return true;
436
+ if (isFloat32Array(value))
437
+ return true;
419
438
  if (isGuestClosure(value))
420
439
  return true;
421
440
  if (isGuestHostObject(value))
@@ -447,5 +466,7 @@ export function hasGuestObjectState(value) {
447
466
  if (isSandboxBox(value) || isSandboxDate(value))
448
467
  return false;
449
468
  return (descriptorObjects.has(value) &&
450
- Object.values(Object.getOwnPropertyDescriptors(value)).some((descriptor) => !descriptor.enumerable || !descriptor.configurable || !descriptor.writable));
469
+ (isFloat32Array(value)
470
+ ? float32Properties(value).map(([, descriptor]) => descriptor)
471
+ : Object.values(Object.getOwnPropertyDescriptors(value))).some((descriptor) => !descriptor.enumerable || !descriptor.configurable || !descriptor.writable));
451
472
  }
@@ -17,7 +17,7 @@ declare const sandboxRegexBrand: unique symbol;
17
17
  declare const sandboxRegexPattern: unique symbol;
18
18
  declare const sandboxRetainedValues: unique symbol;
19
19
  export type SandboxPrimitive = string | number | bigint | boolean | symbol | null | undefined;
20
- export type SandboxValue = SandboxPrimitive | Date | Float32Array | SandboxObject | SandboxArray | SandboxClosure | SandboxGenerator | SandboxCollectionIterator | SandboxRegExpIterator | SandboxMap | SandboxSet | SandboxPromise | SandboxRegex;
20
+ export type SandboxValue = SandboxPrimitive | Date | Float32Array | ArrayBuffer | SandboxObject | SandboxArray | SandboxClosure | SandboxGenerator | SandboxCollectionIterator | SandboxRegExpIterator | SandboxMap | SandboxSet | SandboxPromise | SandboxRegex;
21
21
  export type SandboxObject = {
22
22
  [key: string]: SandboxValue;
23
23
  [key: symbol]: SandboxValue;
@@ -1,4 +1,5 @@
1
1
  import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
2
+ import { arrayBufferDataProperties, arrayBufferLength, copyArrayBufferStorage, isSandboxArrayBuffer } from "./array-buffer.js";
2
3
  import { internalSymbols } from "./internal-symbols.js";
3
4
  import { getIntrinsicIdentity } from "./intrinsics.js";
4
5
  import { getGeneratorProperties } from "./generator-properties.js";
@@ -17,7 +18,7 @@ import { boxedDataProperties, boxedValue, createSandboxBox, isSandboxBox, native
17
18
  import { getHostObjectKeys, getHostObjectMember, hasHostObjectMember, measureHostObjectData, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
18
19
  import { types as nodeTypes } from "node:util";
19
20
  import { CompileScope, RegexCompileGuard, regexCompiledData } from "./regex/compile-guard.js";
20
- import { copyFloat32Storage, float32DataProperties, float32Storage, isFloat32Array } from "./float32.js";
21
+ import { copyFloat32Storage, float32DataProperties, float32Properties, float32Storage, isFloat32Array } from "./float32.js";
21
22
  import { SandboxError } from "./budget.js";
22
23
  import { observeSandboxPromise, trackSandboxPromise } from "./promise-tracker.js";
23
24
  import { promiseReplayContext } from "./promise-replay.js";
@@ -399,15 +400,22 @@ export function measureSandboxData(values, options = {}) {
399
400
  const prototype = getSandboxPrototype(value);
400
401
  if (prototype !== null)
401
402
  visit(prototype, depth + 1);
403
+ if (isSandboxArrayBuffer(value))
404
+ usage += arrayBufferLength(value);
402
405
  if (isFloat32Array(value)) {
403
406
  const storage = float32Storage(value);
404
- if (!seen.has(storage.buffer)) {
405
- seen.add(storage.buffer);
406
- usage += storage.byteLength;
407
- }
408
- for (const [key, descriptor] of float32DataProperties(value)) {
409
- usage += key.length + 1;
410
- visit(descriptor.value, depth + 1);
407
+ visit(storage.buffer, depth + 1);
408
+ for (const [key, descriptor] of float32Properties(value)) {
409
+ usage += 1;
410
+ if (typeof key === "string")
411
+ usage += key.length;
412
+ else
413
+ visit(key, depth + 1);
414
+ if ("value" in descriptor)
415
+ visit(descriptor.value, depth + 1);
416
+ else
417
+ for (const closure of retainedAccessorClosures(descriptor))
418
+ visit(closure, depth + 1);
411
419
  }
412
420
  return;
413
421
  }
@@ -579,7 +587,7 @@ export function measureSandboxData(values, options = {}) {
579
587
  if (descriptor !== undefined)
580
588
  descriptors.push([key, descriptor]);
581
589
  }
582
- const includeNonEnumerable = isSandboxDate(value) || sandboxErrorTypes.has(value) || hasManagedDescriptors(value);
590
+ const includeNonEnumerable = isSandboxDate(value) || isSandboxArrayBuffer(value) || sandboxErrorTypes.has(value) || hasManagedDescriptors(value);
583
591
  for (const [key, descriptor] of descriptors) {
584
592
  if (!descriptor.enumerable && !includeNonEnumerable)
585
593
  continue;
@@ -796,6 +804,20 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
796
804
  }
797
805
  return sandboxPromise;
798
806
  }
807
+ if (isSandboxArrayBuffer(value)) {
808
+ const existing = state.seen.get(value);
809
+ if (existing !== undefined)
810
+ return existing;
811
+ const copy = copyArrayBufferStorage(value, state);
812
+ state.seen.set(value, copy);
813
+ for (const [key, descriptor] of arrayBufferDataProperties(value)) {
814
+ Object.defineProperty(copy, key, { ...descriptor,
815
+ value: copyToSandbox(descriptor.value, state, joinPath(path, key), cloneSandboxCollections, depth + 1) });
816
+ }
817
+ if (!Object.isExtensible(value))
818
+ Object.preventExtensions(copy);
819
+ return copy;
820
+ }
799
821
  if (nodeTypes.isDate(value)) {
800
822
  const existing = state.seen.get(value);
801
823
  if (existing !== undefined)
@@ -819,6 +841,7 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
819
841
  return existing;
820
842
  const copy = copyFloat32Storage(value, state);
821
843
  state.seen.set(value, copy);
844
+ copyToSandbox(float32Storage(value).buffer, state, `${path}.buffer`, cloneSandboxCollections, depth + 1);
822
845
  for (const [key, descriptor] of float32DataProperties(value)) {
823
846
  Object.defineProperty(copy, key, {
824
847
  ...descriptor,
@@ -1013,6 +1036,7 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
1013
1036
  return existing;
1014
1037
  const copy = copyFloat32Storage(value, state);
1015
1038
  state.seen.set(value, copy);
1039
+ copyFromSandbox(float32Storage(value).buffer, state, `${path}.buffer`, options, depth + 1);
1016
1040
  for (const [key, descriptor] of float32DataProperties(value)) {
1017
1041
  Object.defineProperty(copy, key, {
1018
1042
  ...descriptor,
@@ -1023,6 +1047,20 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
1023
1047
  Object.preventExtensions(copy);
1024
1048
  return copy;
1025
1049
  }
1050
+ if (isSandboxArrayBuffer(value)) {
1051
+ const existing = state.seen.get(value);
1052
+ if (existing !== undefined)
1053
+ return existing;
1054
+ const copy = copyArrayBufferStorage(value, state);
1055
+ state.seen.set(value, copy);
1056
+ for (const [key, descriptor] of arrayBufferDataProperties(value)) {
1057
+ Object.defineProperty(copy, key, { ...descriptor,
1058
+ value: copyFromSandbox(descriptor.value, state, joinPath(path, key), options, depth + 1) });
1059
+ }
1060
+ if (!Object.isExtensible(value))
1061
+ Object.preventExtensions(copy);
1062
+ return copy;
1063
+ }
1026
1064
  if (isSandboxDate(value)) {
1027
1065
  const existing = state.seen.get(value);
1028
1066
  if (existing !== undefined)
@@ -1180,6 +1218,18 @@ function allocateSandboxValue(value, budget, seen) {
1180
1218
  budget.allocateString(value);
1181
1219
  return;
1182
1220
  }
1221
+ if (isSandboxArrayBuffer(value)) {
1222
+ if (seen.has(value))
1223
+ return;
1224
+ seen.add(value);
1225
+ budget.allocateArrayLength(arrayBufferLength(value));
1226
+ for (const [key, descriptor] of arrayBufferDataProperties(value)) {
1227
+ if (typeof key === "string")
1228
+ budget.allocateString(key);
1229
+ allocateSandboxValue(descriptor.value, budget, seen);
1230
+ }
1231
+ return;
1232
+ }
1183
1233
  if (isSandboxBox(value)) {
1184
1234
  if (seen.has(value))
1185
1235
  return;
@@ -1 +1 @@
1
- export declare const KNOWN_RUNTIME_GLOBALS: readonly ["AggregateError", "Array", "Boolean", "BigInt", "Date", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "Error", "EvalError", "Infinity", "isFinite", "isNaN", "JSON", "Map", "Float32Array", "Math", "NaN", "Number", "Object", "parseFloat", "parseInt", "Promise", "RangeError", "ReferenceError", "RegExp", "Set", "String", "Symbol", "structuredClone", "SyntaxError", "TypeError", "URIError", "console"];
1
+ export declare const KNOWN_RUNTIME_GLOBALS: readonly ["AggregateError", "Array", "ArrayBuffer", "Boolean", "BigInt", "Date", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "Error", "EvalError", "Infinity", "isFinite", "isNaN", "JSON", "Map", "Float32Array", "Math", "NaN", "Number", "Object", "parseFloat", "parseInt", "Promise", "RangeError", "ReferenceError", "RegExp", "Set", "String", "Symbol", "structuredClone", "SyntaxError", "TypeError", "URIError", "console"];
@@ -1,6 +1,7 @@
1
1
  export const KNOWN_RUNTIME_GLOBALS = [
2
2
  "AggregateError",
3
3
  "Array",
4
+ "ArrayBuffer",
4
5
  "Boolean",
5
6
  "BigInt",
6
7
  "Date",
@@ -2709,6 +2709,7 @@ class Parser {
2709
2709
  return undefined;
2710
2710
  }
2711
2711
  findTopLevelForIterationOperator(startIndex) {
2712
+ let operator;
2712
2713
  let depth = 0;
2713
2714
  let previousToken;
2714
2715
  for (let index = startIndex; index < this.tokens.length; index += 1) {
@@ -2719,7 +2720,7 @@ class Parser {
2719
2720
  }
2720
2721
  else if (token.value === ")" || token.value === "]" || token.value === "}") {
2721
2722
  if (depth === 0 && token.value === ")") {
2722
- return undefined;
2723
+ return operator;
2723
2724
  }
2724
2725
  depth -= 1;
2725
2726
  }
@@ -2730,9 +2731,12 @@ class Parser {
2730
2731
  if (depth === 0 &&
2731
2732
  token.type === "keyword" &&
2732
2733
  (token.value === "of" || token.value === "in") &&
2734
+ index !== startIndex &&
2735
+ !(token.value === "of" && index === startIndex + 1 &&
2736
+ ["const", "let", "var"].includes(previousToken?.value ?? "")) &&
2733
2737
  previousToken?.value !== "." &&
2734
2738
  previousToken?.value !== "?.") {
2735
- return token;
2739
+ operator ??= token;
2736
2740
  }
2737
2741
  previousToken = token;
2738
2742
  }
@@ -3752,7 +3756,8 @@ function isLiteralPropertyKey(token) {
3752
3756
  return token.type === "numeric" || token.type === "string";
3753
3757
  }
3754
3758
  function isIdentifierLikeToken(token) {
3755
- return token.type === "identifier" || (token.type === "keyword" && token.value === "async");
3759
+ return token.type === "identifier" ||
3760
+ (token.type === "keyword" && (token.value === "async" || token.value === "of"));
3756
3761
  }
3757
3762
  function isNewToken(token) {
3758
3763
  return token.value === "new";
@@ -358,7 +358,7 @@ class Lexer {
358
358
  }
359
359
  if (char === "/" &&
360
360
  this.peekChar(1) !== "=" &&
361
- shouldRejectRegexLiteral(tokens[tokens.length - 1], lastClosedControlParenthesis)) {
361
+ shouldRejectRegexLiteral(tokens[tokens.length - 1], lastClosedControlParenthesis, tokens)) {
362
362
  if (!this.options.allowRegexLiterals) {
363
363
  this.syntaxError("Regular expression literals are not supported", this.position());
364
364
  }
@@ -633,7 +633,7 @@ class Lexer {
633
633
  readSlashOrPunctuator(start) {
634
634
  if (this.currentChar() === "/" &&
635
635
  this.peekChar(1) !== "=" &&
636
- shouldRejectRegexLiteral(this.lastSignificantToken(), this.lastClosedControlParenthesis)) {
636
+ shouldRejectRegexLiteral(this.lastSignificantToken(), this.lastClosedControlParenthesis, this.tokens)) {
637
637
  if (!this.options.allowRegexLiterals) {
638
638
  this.syntaxError("Regular expression literals are not supported", start);
639
639
  }
@@ -919,7 +919,7 @@ function matchPunctuator(source, index) {
919
919
  return PUNCTUATORS.find((punctuator) => source.startsWith(punctuator, index) &&
920
920
  (punctuator !== "?." || !isDecimalDigit(source[index + 2] ?? "")));
921
921
  }
922
- function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis) {
922
+ function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis, tokens) {
923
923
  if (previousToken === undefined) {
924
924
  return true;
925
925
  }
@@ -930,6 +930,8 @@ function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis) {
930
930
  return false;
931
931
  }
932
932
  if (previousToken.type === "keyword") {
933
+ if (previousToken.value === "of")
934
+ return endsWithForOfSeparator(tokens);
933
935
  return !EXPRESSION_ENDING_KEYWORDS.has(previousToken.value);
934
936
  }
935
937
  if (previousToken.value === ")") {
@@ -937,6 +939,46 @@ function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis) {
937
939
  }
938
940
  return !isExpressionEndingPunctuator(previousToken.value);
939
941
  }
942
+ function endsWithForOfSeparator(tokens) {
943
+ let depth = 0;
944
+ let start = -1;
945
+ for (let index = tokens.length - 2; index >= 0; index--) {
946
+ const token = tokens[index];
947
+ if (token.type !== "punctuator")
948
+ continue;
949
+ if ([")", "]", "}"].includes(token.value))
950
+ depth++;
951
+ else if (["(", "[", "{"].includes(token.value)) {
952
+ if (depth > 0) {
953
+ depth--;
954
+ continue;
955
+ }
956
+ if (token.value === "(" && (tokens[index - 1]?.value === "for" ||
957
+ (tokens[index - 1]?.value === "await" && tokens[index - 2]?.value === "for")))
958
+ start = index + 1;
959
+ break;
960
+ }
961
+ else if (depth === 0 && token.value === ";")
962
+ break;
963
+ }
964
+ if (start < 0)
965
+ return false;
966
+ depth = 0;
967
+ for (let index = start; index < tokens.length; index++) {
968
+ const token = tokens[index];
969
+ if (token.type === "punctuator") {
970
+ if (["(", "[", "{"].includes(token.value))
971
+ depth++;
972
+ else if ([")", "]", "}"].includes(token.value))
973
+ depth--;
974
+ }
975
+ if (depth === 0 && token.type === "keyword" && token.value === "of" &&
976
+ index !== start && tokens[index - 1]?.value !== "." && tokens[index - 1]?.value !== "?." &&
977
+ !(index === start + 1 && ["const", "let", "var"].includes(tokens[start].value)))
978
+ return index === tokens.length - 1;
979
+ }
980
+ return false;
981
+ }
940
982
  function updateGroupingState(groupingStack, previousToken, punctuator) {
941
983
  if (punctuator === "(") {
942
984
  groupingStack.push({
@@ -0,0 +1,13 @@
1
+ import type { GuestObjectState } from "./guest-heap.js";
2
+ export type ArrayBufferData<TReference> = {
3
+ kind: "arraybuffer";
4
+ } & ({
5
+ bytes: number[];
6
+ maxByteLength?: number;
7
+ } | {
8
+ buffer: TReference;
9
+ });
10
+ export declare function captureArrayBufferState<T>(value: ArrayBuffer, encode: (value: unknown) => T): GuestObjectState<T>;
11
+ export declare function encodeArrayBufferStorage<T>(value: ArrayBuffer, id: number, buffers: WeakMap<ArrayBuffer, number>, reference: (id: number) => T): ArrayBufferData<T>;
12
+ export declare function validateArrayBufferStorage(value: Record<string, unknown>): void;
13
+ export declare function decodeArrayBufferStorage(value: Record<string, unknown>, resolve: (reference: unknown) => unknown): ArrayBuffer;