poe-code 14.0.83 → 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 (42) hide show
  1. package/dist/index.js +588 -93
  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-37V6Q4K3.js → chunk-2EZQJQ2C.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-PT7PBLVT.js → chunk-CYVI4ZUK.js} +536 -85
  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.d.ts +6 -1
  14. package/packages/safe-js/dist/interp/float32.js +38 -10
  15. package/packages/safe-js/dist/interp/globals/array-buffer.d.ts +3 -0
  16. package/packages/safe-js/dist/interp/globals/array-buffer.js +112 -0
  17. package/packages/safe-js/dist/interp/globals/float32array.d.ts +1 -1
  18. package/packages/safe-js/dist/interp/globals/float32array.js +104 -15
  19. package/packages/safe-js/dist/interp/globals.d.ts +1 -0
  20. package/packages/safe-js/dist/interp/globals.js +2 -0
  21. package/packages/safe-js/dist/interp/host-bridge.d.ts +1 -0
  22. package/packages/safe-js/dist/interp/host-bridge.js +21 -0
  23. package/packages/safe-js/dist/interp/host-call.js +26 -2
  24. package/packages/safe-js/dist/interp/methods/array-iterator.js +1 -1
  25. package/packages/safe-js/dist/interp/object-model.js +6 -0
  26. package/packages/safe-js/dist/interp/values.d.ts +1 -1
  27. package/packages/safe-js/dist/interp/values.js +47 -5
  28. package/packages/safe-js/dist/lint/rules/known-globals.d.ts +1 -1
  29. package/packages/safe-js/dist/lint/rules/known-globals.js +1 -0
  30. package/packages/safe-js/dist/snapshot/array-buffer.d.ts +13 -0
  31. package/packages/safe-js/dist/snapshot/array-buffer.js +40 -0
  32. package/packages/safe-js/dist/snapshot/dump-format.js +25 -9
  33. package/packages/safe-js/dist/snapshot/float32array.d.ts +8 -1
  34. package/packages/safe-js/dist/snapshot/float32array.js +23 -5
  35. package/packages/safe-js/dist/snapshot/replay-data.d.ts +5 -0
  36. package/packages/safe-js/dist/snapshot/replay-data.js +35 -10
  37. package/packages/safe-js/dist/snapshot/restore.js +13 -1
  38. package/packages/safe-js/dist/snapshot/serialize.d.ts +5 -2
  39. package/packages/safe-js/dist/snapshot/serialize.js +20 -11
  40. package/packages/safe-js/dist/snapshot/validation.js +11 -1
  41. package/packages/safe-js/dist/chunks/chunk-PT7PBLVT.js.map +0 -7
  42. /package/packages/safe-js/dist/chunks/{chunk-37V6Q4K3.js.map → chunk-2EZQJQ2C.js.map} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  resolveFsConfig,
23
23
  splitFrontmatter,
24
24
  withBrokenPipeGuard
25
- } from "./chunks/chunk-37V6Q4K3.js";
25
+ } from "./chunks/chunk-2EZQJQ2C.js";
26
26
  import {
27
27
  Budget,
28
28
  SandboxError,
@@ -34,7 +34,7 @@ import {
34
34
  replaceErrorStack,
35
35
  restore,
36
36
  run
37
- } from "./chunks/chunk-PT7PBLVT.js";
37
+ } from "./chunks/chunk-CYVI4ZUK.js";
38
38
  import "./chunks/chunk-M2DLCGEF.js";
39
39
  import "./chunks/chunk-Q7USUEL7.js";
40
40
  import "./chunks/chunk-4YIDX44G.js";
@@ -5,7 +5,7 @@ import {
5
5
  defineExtension,
6
6
  lint,
7
7
  run
8
- } from "./chunks/chunk-PT7PBLVT.js";
8
+ } from "./chunks/chunk-CYVI4ZUK.js";
9
9
  import "./chunks/chunk-4YIDX44G.js";
10
10
  export {
11
11
  Budget,
@@ -26,7 +26,7 @@ import {
26
26
  runWithSpawnUsageAccumulator,
27
27
  splitFrontmatter,
28
28
  supportsSpawnMode
29
- } from "./chunks/chunk-37V6Q4K3.js";
29
+ } from "./chunks/chunk-2EZQJQ2C.js";
30
30
  import {
31
31
  Budget,
32
32
  FileSnapshotBackend,
@@ -50,7 +50,7 @@ import {
50
50
  registerPendingHostCallPolicy,
51
51
  restore,
52
52
  run
53
- } from "./chunks/chunk-PT7PBLVT.js";
53
+ } from "./chunks/chunk-CYVI4ZUK.js";
54
54
  import "./chunks/chunk-M2DLCGEF.js";
55
55
  import "./chunks/chunk-Q7USUEL7.js";
56
56
  import "./chunks/chunk-4YIDX44G.js";
@@ -0,0 +1,12 @@
1
+ import type { Budget } from "./budget.js";
2
+ import type { SandboxObject } from "./values.js";
3
+ export declare const arrayBufferPrototypes: WeakMap<Budget, SandboxObject>;
4
+ export declare function isSandboxArrayBuffer(value: unknown): value is ArrayBuffer;
5
+ export declare function arrayBufferLength(value: ArrayBuffer): number;
6
+ export declare function arrayBufferOptions(value: ArrayBuffer): {
7
+ maxByteLength: number;
8
+ } | undefined;
9
+ export declare function copyArrayBufferStorage(value: ArrayBuffer, state: {
10
+ float32Buffers?: WeakMap<ArrayBuffer, ArrayBuffer>;
11
+ }): ArrayBuffer;
12
+ export declare function arrayBufferDataProperties(value: ArrayBuffer): Array<[string | symbol, PropertyDescriptor]>;
@@ -0,0 +1,33 @@
1
+ import { types } from "node:util";
2
+ const readLength = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get;
3
+ const readResizable = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "resizable")?.get;
4
+ const readMaxLength = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "maxByteLength")?.get;
5
+ export const arrayBufferPrototypes = new WeakMap();
6
+ export function isSandboxArrayBuffer(value) {
7
+ return types.isArrayBuffer(value) && Object.getPrototypeOf(value) === ArrayBuffer.prototype;
8
+ }
9
+ export function arrayBufferLength(value) {
10
+ return Reflect.apply(readLength, value, []);
11
+ }
12
+ export function arrayBufferOptions(value) {
13
+ return readResizable !== undefined && Reflect.apply(readResizable, value, [])
14
+ ? { maxByteLength: Reflect.apply(readMaxLength, value, []) } : undefined;
15
+ }
16
+ export function copyArrayBufferStorage(value, state) {
17
+ state.float32Buffers ??= new WeakMap();
18
+ let copy = state.float32Buffers.get(value);
19
+ if (copy === undefined) {
20
+ copy = Reflect.construct(ArrayBuffer, [arrayBufferLength(value), arrayBufferOptions(value)]);
21
+ new Uint8Array(copy).set(new Uint8Array(value));
22
+ state.float32Buffers.set(value, copy);
23
+ }
24
+ return copy;
25
+ }
26
+ export function arrayBufferDataProperties(value) {
27
+ return Reflect.ownKeys(value).map(key => {
28
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
29
+ if (!("value" in descriptor))
30
+ throw new TypeError("ArrayBuffer accessors cannot be copied as data.");
31
+ return [key, descriptor];
32
+ });
33
+ }
@@ -1,6 +1,11 @@
1
1
  import type { Budget } from "./budget.js";
2
+ export declare const float32ViewLayouts: WeakMap<Float32Array<ArrayBufferLike>, {
3
+ byteOffset: number;
4
+ length?: number;
5
+ }>;
6
+ export declare function restoreFloat32View(buffer: ArrayBuffer, byteOffset: number, length?: number, budget?: Budget): Float32Array;
2
7
  export declare function isFloat32Array(value: unknown): value is Float32Array;
3
- export declare function float32Storage(value: Float32Array): {
8
+ export declare function float32Storage(value: Float32Array, requireInBounds?: boolean): {
4
9
  buffer: ArrayBuffer;
5
10
  byteOffset: number;
6
11
  length: number;
@@ -1,20 +1,48 @@
1
+ import { arrayBufferLength, arrayBufferOptions, copyArrayBufferStorage } from "./array-buffer.js";
1
2
  const typedArrayPrototype = Object.getPrototypeOf(Float32Array.prototype);
2
3
  const readLength = Object.getOwnPropertyDescriptor(typedArrayPrototype, "length").get;
3
4
  const readOffset = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteOffset").get;
4
5
  const readBuffer = Object.getOwnPropertyDescriptor(typedArrayPrototype, "buffer").get;
5
6
  const readTag = Object.getOwnPropertyDescriptor(typedArrayPrototype, Symbol.toStringTag).get;
7
+ const createValuesIterator = Object.getOwnPropertyDescriptor(typedArrayPrototype, "values").value;
6
8
  const bufferLength = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get;
7
9
  const bufferResizable = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "resizable")?.get;
10
+ export const float32ViewLayouts = new WeakMap();
11
+ const resizeBuffer = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "resize").value;
12
+ export function restoreFloat32View(buffer, byteOffset, length, budget) {
13
+ const originalLength = arrayBufferLength(buffer);
14
+ const required = byteOffset + (length ?? 0) * 4;
15
+ const options = arrayBufferOptions(buffer);
16
+ const grow = required > originalLength;
17
+ if (grow) {
18
+ if (options === undefined || required > options.maxByteLength)
19
+ throw new RangeError("Float32Array layout exceeds backing capacity.");
20
+ budget?.allocateArrayLength(Math.ceil(required / 4));
21
+ budget?.provisionDataUsage(required - originalLength)();
22
+ Reflect.apply(resizeBuffer, buffer, [required]);
23
+ }
24
+ try {
25
+ const view = new Float32Array(buffer, byteOffset, length);
26
+ if (options !== undefined)
27
+ float32ViewLayouts.set(view, { byteOffset, ...(length === undefined ? {} : { length }) });
28
+ return view;
29
+ }
30
+ finally {
31
+ if (grow)
32
+ Reflect.apply(resizeBuffer, buffer, [originalLength]);
33
+ }
34
+ }
8
35
  export function isFloat32Array(value) {
9
36
  return (ArrayBuffer.isView(value) &&
10
37
  Object.getPrototypeOf(value) === Float32Array.prototype &&
11
38
  Reflect.apply(readTag, value, []) === "Float32Array");
12
39
  }
13
- export function float32Storage(value) {
40
+ export function float32Storage(value, requireInBounds = false) {
41
+ if (requireInBounds)
42
+ Reflect.apply(createValuesIterator, value, []);
14
43
  const buffer = Reflect.apply(readBuffer, value, []);
15
- if (Object.getPrototypeOf(buffer) !== ArrayBuffer.prototype ||
16
- (bufferResizable !== undefined && Reflect.apply(bufferResizable, buffer, []))) {
17
- throw new TypeError("Float32Array requires a fixed, non-shared ArrayBuffer.");
44
+ if (Object.getPrototypeOf(buffer) !== ArrayBuffer.prototype) {
45
+ throw new TypeError("Float32Array requires a non-shared ArrayBuffer.");
18
46
  }
19
47
  return {
20
48
  buffer,
@@ -63,12 +91,12 @@ export function checkFloat32Allocation(length, budget) {
63
91
  }
64
92
  export function copyFloat32Storage(value, state) {
65
93
  const storage = float32Storage(value);
66
- state.float32Buffers ??= new WeakMap();
67
- let buffer = state.float32Buffers.get(storage.buffer);
68
- if (buffer === undefined) {
69
- buffer = new ArrayBuffer(storage.byteLength);
70
- new Uint8Array(buffer).set(new Uint8Array(storage.buffer));
71
- state.float32Buffers.set(storage.buffer, buffer);
94
+ const buffer = copyArrayBufferStorage(storage.buffer, state);
95
+ if (bufferResizable !== undefined && Reflect.apply(bufferResizable, storage.buffer, [])) {
96
+ const layout = float32ViewLayouts.get(value);
97
+ if (layout === undefined)
98
+ throw new TypeError("Resizable Float32Array copies require known view layout.");
99
+ return restoreFloat32View(buffer, layout.byteOffset, layout.length);
72
100
  }
73
101
  return new Float32Array(buffer, storage.byteOffset, storage.length);
74
102
  }
@@ -0,0 +1,3 @@
1
+ import type { Budget } from "../budget.js";
2
+ import { type SandboxClosure } from "../values.js";
3
+ export declare function createArrayBufferGlobal(budget: Budget): SandboxClosure;
@@ -0,0 +1,112 @@
1
+ import { arrayBufferLength, arrayBufferOptions, arrayBufferPrototypes, isSandboxArrayBuffer } from "../array-buffer.js";
2
+ import { accessorAdapter, readPropertyDescriptor } from "../accessors.js";
3
+ import { createSandboxClosure } from "../values.js";
4
+ import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, materializeFunctionProperties, registerIntrinsicFunction, registerIntrinsicObject, setSandboxPrototype } from "../object-model.js";
5
+ import { invokeBuiltinClosure } from "../builtin-call.js";
6
+ import { registerBuiltinIdentities } from "../intrinsics.js";
7
+ import { sandboxNumber } from "../string-coercion.js";
8
+ import { retainValues } from "../resources.js";
9
+ const resizeBuffer = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "resize").value;
10
+ export function createArrayBufferGlobal(budget) {
11
+ const prototype = Object.create(null);
12
+ const constructor = createSandboxClosure({
13
+ guest: true, sandbox: true, name: "ArrayBuffer", length: 1,
14
+ call: () => { throw new TypeError("ArrayBuffer requires new."); },
15
+ construct: async (args, context) => {
16
+ let selected;
17
+ let current;
18
+ const bridge = {
19
+ ...context, stack: context?.stack ?? [], thisValue: undefined,
20
+ getProperty: context?.getProperty ?? ((value, key) => {
21
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
22
+ return descriptor === undefined ? getSandboxDataProperty(value, key, budget)
23
+ : readPropertyDescriptor(descriptor, value, bridge);
24
+ }),
25
+ invokeClosure: context?.invokeClosure ?? ((callee, values, receiver, construct) => invokeBuiltinClosure(callee, values, budget, context, receiver, construct))
26
+ };
27
+ const release = retainValues(budget, () => [selected, current, ...args]);
28
+ try {
29
+ const number = await sandboxNumber(args[0], budget, bridge);
30
+ const length = Number.isNaN(number) ? 0 : Math.trunc(number);
31
+ if (length < 0 || !Number.isSafeInteger(length))
32
+ throw new RangeError("Invalid ArrayBuffer length.");
33
+ let maxByteLength;
34
+ if (args[1] !== null && typeof args[1] === "object") {
35
+ current = await bridge.getProperty(args[1], "maxByteLength");
36
+ if (current !== undefined) {
37
+ const maximum = await sandboxNumber(current, budget, bridge);
38
+ maxByteLength = Number.isNaN(maximum) ? 0 : Math.trunc(maximum);
39
+ if (!Number.isSafeInteger(maxByteLength) || maxByteLength < length)
40
+ throw new RangeError("Invalid ArrayBuffer maximum length.");
41
+ }
42
+ }
43
+ const target = context?.newTarget ?? constructor;
44
+ selected = await bridge.getProperty(target, "prototype");
45
+ budget.allocateArrayLength(maxByteLength ?? length);
46
+ budget.provisionDataUsage(length + 1)();
47
+ const result = Reflect.construct(ArrayBuffer, [length, maxByteLength === undefined ? undefined : { maxByteLength }]);
48
+ setSandboxPrototype(result, selected !== null && typeof selected === "object" ? selected : prototype, budget);
49
+ return result;
50
+ }
51
+ finally {
52
+ release();
53
+ }
54
+ }
55
+ });
56
+ Object.defineProperty(materializeFunctionProperties(constructor), "prototype", { value: prototype, writable: false });
57
+ Object.defineProperty(materializeFunctionProperties(constructor), "isView", {
58
+ writable: true, configurable: true,
59
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "isView", length: 1,
60
+ call: args => ArrayBuffer.isView(args[0]) })
61
+ });
62
+ Object.defineProperties(prototype, {
63
+ constructor: { value: constructor, writable: true, configurable: true },
64
+ [Symbol.toStringTag]: { value: "ArrayBuffer", configurable: true }
65
+ });
66
+ const getters = [];
67
+ Object.defineProperty(prototype, "resize", { writable: true, configurable: true,
68
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "resize", length: 1,
69
+ call: async (args, context) => {
70
+ const receiver = context?.thisValue;
71
+ if (!isSandboxArrayBuffer(receiver) || arrayBufferOptions(receiver) === undefined)
72
+ throw new TypeError("ArrayBuffer resize requires a resizable buffer receiver.");
73
+ const release = retainValues(budget, () => [receiver, ...args]);
74
+ try {
75
+ const number = await sandboxNumber(args[0], budget, context);
76
+ const length = Number.isNaN(number) ? 0 : Math.trunc(number);
77
+ if (!Number.isSafeInteger(length) || length < 0 || length > arrayBufferOptions(receiver).maxByteLength)
78
+ throw new RangeError("Invalid ArrayBuffer resize length.");
79
+ budget.allocateArrayLength(length);
80
+ budget.provisionDataUsage(Math.max(length - arrayBufferLength(receiver), 0))();
81
+ Reflect.apply(resizeBuffer, receiver, [length]);
82
+ return undefined;
83
+ }
84
+ finally {
85
+ release();
86
+ }
87
+ }
88
+ })
89
+ });
90
+ for (const key of ["byteLength", "maxByteLength", "resizable"]) {
91
+ const getter = createSandboxClosure({ guest: true, sandbox: true, name: `get ${key}`, length: 0,
92
+ call: (_args, context) => {
93
+ if (!isSandboxArrayBuffer(context?.thisValue))
94
+ throw new TypeError(`ArrayBuffer ${key} requires a buffer receiver.`);
95
+ if (key === "byteLength")
96
+ return arrayBufferLength(context.thisValue);
97
+ const options = arrayBufferOptions(context.thisValue);
98
+ return key === "resizable" ? options !== undefined : options?.maxByteLength ?? arrayBufferLength(context.thisValue);
99
+ }
100
+ });
101
+ Object.defineProperty(prototype, key, { get: accessorAdapter(getter, "get"), configurable: true });
102
+ getters.push(getter);
103
+ }
104
+ setSandboxPrototype(prototype, getSandboxPrototype(Object.create(null), budget));
105
+ arrayBufferPrototypes.set(budget, prototype);
106
+ registerBuiltinIdentities(budget, { ArrayBuffer: constructor });
107
+ registerIntrinsicFunction(budget, constructor);
108
+ for (const getter of getters)
109
+ registerIntrinsicFunction(budget, getter);
110
+ registerIntrinsicObject(budget, prototype);
111
+ return constructor;
112
+ }
@@ -3,5 +3,5 @@ import { type SandboxClosure, type SandboxValue } from "../values.js";
3
3
  export declare function createFloat32ArrayGlobal(budget: Budget, nativePrototype?: boolean): SandboxClosure;
4
4
  export declare function createFloat32ArrayPrototypes(budget: Budget, constructor: SandboxClosure): void;
5
5
  export declare function isFloat32ArrayConstructor(value: unknown): boolean;
6
- export declare function getFloat32Member(value: Float32Array, property: string | number, budget: Budget): SandboxValue;
6
+ export declare function getFloat32Member(value: Float32Array, property: string | number, budget: Budget, defaultConstructor?: SandboxClosure): SandboxValue;
7
7
  export declare function setFloat32Member(value: Float32Array, property: PropertyKey, entry: SandboxValue, budget?: Budget): void;
@@ -1,4 +1,4 @@
1
- import { checkFloat32Allocation, float32Number, float32Storage, isFloat32Array, isFloat32Index } from "../float32.js";
1
+ import { checkFloat32Allocation, float32Number, float32Storage, float32ViewLayouts, isFloat32Array, isFloat32Index } from "../float32.js";
2
2
  import { createSandboxClosure, isSandboxClosure, measureSandboxData } from "../values.js";
3
3
  import { accessorAdapter, readPropertyDescriptor } from "../accessors.js";
4
4
  import { float32Prototypes } from "../float32-prototypes.js";
@@ -10,6 +10,7 @@ import { sandboxNumber, sandboxString } from "../string-coercion.js";
10
10
  import { acquireSandboxIterator, readIteratorResult } from "../iteration.js";
11
11
  import { createDataCheckpoint } from "../data-checkpoint.js";
12
12
  import { createSandboxBox } from "../boxed.js";
13
+ import { arrayBufferLength, arrayBufferOptions, isSandboxArrayBuffer } from "../array-buffer.js";
13
14
  const constructors = new WeakSet();
14
15
  export function createFloat32ArrayGlobal(budget, nativePrototype = false) {
15
16
  const constructor = createSandboxClosure({
@@ -32,6 +33,32 @@ export function createFloat32ArrayGlobal(budget, nativePrototype = false) {
32
33
  const prototype = candidate !== null && typeof candidate === "object" ? candidate : float32Prototypes.get(budget);
33
34
  const release = retainValues(budget, () => [prototype, ...args]);
34
35
  try {
36
+ if (isSandboxArrayBuffer(args[0])) {
37
+ const buffer = args[0];
38
+ const number = await sandboxNumber(args[1], budget, context);
39
+ const offset = Number.isNaN(number) ? 0 : Math.trunc(number);
40
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset % 4 !== 0)
41
+ throw new RangeError("Invalid Float32Array buffer offset.");
42
+ const bytes = arrayBufferLength(buffer);
43
+ let length;
44
+ if (args[2] === undefined) {
45
+ if ((arrayBufferOptions(buffer) === undefined && bytes % 4 !== 0) || offset > bytes)
46
+ throw new RangeError("Invalid Float32Array buffer length.");
47
+ length = Math.floor((bytes - offset) / 4);
48
+ }
49
+ else {
50
+ const size = await sandboxNumber(args[2], budget, context);
51
+ length = Number.isNaN(size) ? 0 : Math.trunc(size);
52
+ if (!Number.isSafeInteger(length) || length < 0 || offset + length * 4 > arrayBufferLength(buffer))
53
+ throw new RangeError("Invalid Float32Array view length.");
54
+ }
55
+ budget.allocateArrayLength(length);
56
+ const result = new Float32Array(buffer, offset, args[2] === undefined ? undefined : length);
57
+ if (arrayBufferOptions(buffer) !== undefined)
58
+ float32ViewLayouts.set(result, { byteOffset: offset, ...(args[2] === undefined ? {} : { length }) });
59
+ setSandboxPrototype(result, prototype, budget);
60
+ return result;
61
+ }
35
62
  const result = args[0] !== null && typeof args[0] === "object" && !isFloat32Array(args[0])
36
63
  ? await allocateFloat32Input(args[0], budget, context)
37
64
  : allocateFloat32Array(args[0], budget);
@@ -242,7 +269,13 @@ export function createFloat32ArrayPrototypes(budget, constructor) {
242
269
  setSandboxPrototype(prototype, shared);
243
270
  setSandboxPrototype(shared, getSandboxPrototype(Object.create(null), budget));
244
271
  const getters = [];
245
- for (const key of ["length", "byteLength", "byteOffset"]) {
272
+ const species = createSandboxClosure({ guest: true, sandbox: true, name: "get [Symbol.species]", length: 0,
273
+ call: (_args, context) => context?.thisValue });
274
+ getters.push(species);
275
+ Object.defineProperty(materializeFunctionProperties(typedArray), Symbol.species, {
276
+ get: accessorAdapter(species, "get"), configurable: true
277
+ });
278
+ for (const key of ["length", "byteLength", "byteOffset", "buffer"]) {
246
279
  const getter = createSandboxClosure({ guest: true, sandbox: true, name: `get ${key}`, length: 0,
247
280
  call: (_args, context) => {
248
281
  if (!isFloat32Array(context?.thisValue))
@@ -255,7 +288,7 @@ export function createFloat32ArrayPrototypes(budget, constructor) {
255
288
  Object.defineProperty(shared, key, { get: accessorAdapter(getter, "get"), configurable: true });
256
289
  }
257
290
  for (const key of ["set", "slice", "subarray"])
258
- Object.defineProperty(shared, key, { value: getFloat32Member(new Float32Array(0), key, budget), writable: true, configurable: true });
291
+ Object.defineProperty(shared, key, { value: getFloat32Member(new Float32Array(0), key, budget, constructor), writable: true, configurable: true });
259
292
  const arrayPrototype = resolveIntrinsicIdentity(budget, '["Array","prototype"]');
260
293
  Object.defineProperty(shared, "toString", { value: getSandboxDataProperty(arrayPrototype, "toString", budget), writable: true, configurable: true });
261
294
  Object.defineProperty(shared, "join", { writable: true, configurable: true,
@@ -264,7 +297,7 @@ export function createFloat32ArrayPrototypes(budget, constructor) {
264
297
  if (!isFloat32Array(context?.thisValue))
265
298
  throw new TypeError("TypedArray join requires a typed array receiver.");
266
299
  const receiver = context.thisValue;
267
- const length = float32Storage(receiver).length;
300
+ const length = float32Storage(receiver, true).length;
268
301
  let separator = ",";
269
302
  let text = "";
270
303
  const release = retainValues(budget, () => [receiver, separator, text, ...args]);
@@ -273,7 +306,8 @@ export function createFloat32ArrayPrototypes(budget, constructor) {
273
306
  separator = await sandboxString(args[0], budget, context);
274
307
  for (let index = 0; index < length; index++) {
275
308
  budget.visitNode();
276
- text = budget.allocateString(text + (index === 0 ? "" : separator) + String(receiver[index]));
309
+ const value = receiver[index];
310
+ text = budget.allocateString(text + (index === 0 ? "" : separator) + (value === undefined ? "" : String(value)));
277
311
  }
278
312
  return text;
279
313
  }
@@ -293,6 +327,7 @@ export function createFloat32ArrayPrototypes(budget, constructor) {
293
327
  call: (args, context) => {
294
328
  if (!isFloat32Array(context?.thisValue))
295
329
  throw new TypeError(`TypedArray ${key} requires a typed array receiver.`);
330
+ float32Storage(context.thisValue, true);
296
331
  return invokeBuiltinClosure(method, args, budget, context, context.thisValue);
297
332
  }
298
333
  });
@@ -312,7 +347,7 @@ export function createFloat32ArrayPrototypes(budget, constructor) {
312
347
  export function isFloat32ArrayConstructor(value) {
313
348
  return typeof value === "object" && value !== null && constructors.has(value);
314
349
  }
315
- export function getFloat32Member(value, property, budget) {
350
+ export function getFloat32Member(value, property, budget, defaultConstructor) {
316
351
  const key = String(property);
317
352
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
318
353
  if (descriptor !== undefined) {
@@ -342,7 +377,7 @@ export function getFloat32Member(value, property, budget) {
342
377
  const receiver = context?.thisValue;
343
378
  if (!isFloat32Array(receiver))
344
379
  throw new TypeError(`Float32Array#${key} requires a Float32Array receiver.`);
345
- const storage = float32Storage(receiver);
380
+ const storage = float32Storage(receiver, key === "slice");
346
381
  const bridge = {
347
382
  ...context, stack: context?.stack ?? [], thisValue: receiver,
348
383
  getProperty: context?.getProperty ?? ((value, property) => {
@@ -363,18 +398,19 @@ export function getFloat32Member(value, property, budget) {
363
398
  const offset = Number.isNaN(number) ? 0 : Math.trunc(number);
364
399
  if (offset < 0)
365
400
  throw new RangeError("Float32Array#set offset is out of bounds.");
401
+ const targetStorage = float32Storage(receiver, true);
366
402
  if (source === null || source === undefined)
367
403
  throw new TypeError("Float32Array#set requires a non-null source.");
368
404
  let length;
369
405
  if (isFloat32Array(source))
370
- length = float32Storage(source).length;
406
+ length = float32Storage(source, true).length;
371
407
  else {
372
408
  sourceObject = typeof source === "object" ? source : createSandboxBox(source);
373
409
  current = await bridge.getProperty(sourceObject, "length");
374
410
  const size = await sandboxNumber(current, budget, bridge);
375
411
  length = Number.isNaN(size) || size <= 0 ? 0 : Math.min(Math.trunc(size), Number.MAX_SAFE_INTEGER);
376
412
  }
377
- if (offset + length > storage.length)
413
+ if (offset + length > targetStorage.length)
378
414
  throw new RangeError("Float32Array#set source is out of bounds.");
379
415
  if (isFloat32Array(source))
380
416
  Float32Array.prototype.set.call(receiver, source, offset);
@@ -392,17 +428,70 @@ export function getFloat32Member(value, property, budget) {
392
428
  })();
393
429
  }
394
430
  return (async () => {
395
- const release = retainValues(budget, () => [receiver, ...args]);
431
+ let candidate;
432
+ let result;
433
+ const release = retainValues(budget, () => [receiver, candidate, result, ...args]);
396
434
  try {
397
435
  const start = relativeIndex(await sandboxNumber(args[0], budget, bridge), storage.length);
398
436
  const end = args[1] === undefined ? storage.length
399
437
  : relativeIndex(await sandboxNumber(args[1], budget, bridge), storage.length);
400
438
  const length = Math.max(end - start, 0);
401
- if (key === "subarray")
402
- return new Float32Array(storage.buffer, storage.byteOffset + start * 4, length);
403
- checkFloat32Allocation(length, budget);
404
- const result = new Float32Array(length);
405
- new Uint8Array(result.buffer).set(new Uint8Array(storage.buffer, storage.byteOffset + start * 4, length * 4));
439
+ const layout = float32ViewLayouts.get(receiver);
440
+ const offset = (layout?.byteOffset ?? storage.byteOffset) + start * 4;
441
+ const tracking = layout !== undefined && layout.length === undefined && args[1] === undefined;
442
+ if (defaultConstructor !== undefined) {
443
+ candidate = await bridge.getProperty(receiver, "constructor");
444
+ if (candidate !== undefined) {
445
+ if (candidate === null || typeof candidate !== "object")
446
+ throw new TypeError("TypedArray constructor must be an object.");
447
+ candidate = await bridge.getProperty(candidate, Symbol.species);
448
+ if (candidate !== undefined && candidate !== null &&
449
+ (!isSandboxClosure(candidate) || candidate.construct === undefined))
450
+ throw new TypeError("TypedArray species must be a constructor.");
451
+ }
452
+ }
453
+ if (candidate !== undefined && candidate !== null && candidate !== defaultConstructor) {
454
+ const values = key === "slice" ? [length]
455
+ : [storage.buffer, offset, tracking ? undefined : length];
456
+ result = await invokeBuiltinClosure(candidate, values, budget, bridge, undefined, true);
457
+ if (!isFloat32Array(result))
458
+ throw new TypeError("TypedArray species must return typed storage.");
459
+ const target = float32Storage(result, key === "slice");
460
+ if (key === "slice" && target.length < length)
461
+ throw new TypeError("TypedArray species returned insufficient storage.");
462
+ }
463
+ if (key === "subarray") {
464
+ if (result === undefined) {
465
+ result = new Float32Array(storage.buffer, offset, tracking ? undefined : length);
466
+ if (arrayBufferOptions(storage.buffer) !== undefined)
467
+ float32ViewLayouts.set(result, { byteOffset: offset, ...(tracking ? {} : { length }) });
468
+ }
469
+ return result;
470
+ }
471
+ if (result === undefined) {
472
+ checkFloat32Allocation(length, budget);
473
+ result = new Float32Array(length);
474
+ }
475
+ if (!isFloat32Array(result))
476
+ throw new TypeError("TypedArray species must return typed storage.");
477
+ if (length > 0) {
478
+ const current = float32Storage(receiver, true);
479
+ const target = float32Storage(result, true);
480
+ const count = Math.min(length, Math.max(current.length - start, 0));
481
+ if (count > 0) {
482
+ const sourceBytes = new Uint8Array(current.buffer, current.byteOffset + start * 4, count * 4);
483
+ const targetBytes = new Uint8Array(target.buffer, target.byteOffset, count * 4);
484
+ if (current.buffer === target.buffer && targetBytes.byteOffset > sourceBytes.byteOffset &&
485
+ targetBytes.byteOffset < sourceBytes.byteOffset + sourceBytes.length) {
486
+ for (let index = 0; index < sourceBytes.length; index++) {
487
+ budget.visitNode();
488
+ targetBytes[index] = sourceBytes[index];
489
+ }
490
+ }
491
+ else
492
+ targetBytes.set(sourceBytes);
493
+ }
494
+ }
406
495
  return result;
407
496
  }
408
497
  finally {
@@ -18,6 +18,7 @@ export declare function createBuiltinBindings(options: Parameters<typeof createC
18
18
  parseFloat: import("./values.js").SandboxClosure;
19
19
  isNaN: import("./values.js").SandboxClosure;
20
20
  isFinite: import("./values.js").SandboxClosure;
21
+ ArrayBuffer: import("./values.js").SandboxClosure;
21
22
  Object: import("./values.js").SandboxClosure;
22
23
  Array: import("./values.js").SandboxClosure;
23
24
  String: import("./values.js").SandboxClosure;
@@ -13,6 +13,7 @@ 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 = {
@@ -25,6 +26,7 @@ export function createBuiltinBindings(options) {
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),
@@ -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,