poe-code 14.0.82 → 14.0.83

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 (34) hide show
  1. package/dist/index.js +543 -156
  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-37V6Q4K3.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-V6LQP64H.js → chunk-PT7PBLVT.js} +457 -91
  7. package/packages/safe-js/dist/chunks/chunk-PT7PBLVT.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/float32-prototypes.d.ts +3 -0
  12. package/packages/safe-js/dist/interp/float32-prototypes.js +1 -0
  13. package/packages/safe-js/dist/interp/float32.d.ts +1 -0
  14. package/packages/safe-js/dist/interp/float32.js +12 -4
  15. package/packages/safe-js/dist/interp/globals/float32array.d.ts +3 -2
  16. package/packages/safe-js/dist/interp/globals/float32array.js +371 -65
  17. package/packages/safe-js/dist/interp/globals/object-array.js +3 -3
  18. package/packages/safe-js/dist/interp/globals.d.ts +1 -0
  19. package/packages/safe-js/dist/interp/globals.js +4 -2
  20. package/packages/safe-js/dist/interp/instanceof.js +1 -1
  21. package/packages/safe-js/dist/interp/interpreter.js +2 -4
  22. package/packages/safe-js/dist/interp/iteration.js +15 -6
  23. package/packages/safe-js/dist/interp/object-model.js +16 -1
  24. package/packages/safe-js/dist/interp/values.js +12 -4
  25. package/packages/safe-js/dist/parse/parser.js +8 -3
  26. package/packages/safe-js/dist/parse/tokenizer.js +45 -3
  27. package/packages/safe-js/dist/snapshot/float32array.d.ts +3 -0
  28. package/packages/safe-js/dist/snapshot/float32array.js +20 -1
  29. package/packages/safe-js/dist/snapshot/restore.js +17 -2
  30. package/packages/safe-js/dist/snapshot/serialize.d.ts +2 -1
  31. package/packages/safe-js/dist/snapshot/serialize.js +10 -9
  32. package/packages/safe-js/dist/snapshot/validation.js +10 -0
  33. package/packages/safe-js/dist/chunks/chunk-V6LQP64H.js.map +0 -7
  34. /package/packages/safe-js/dist/chunks/{chunk-7LGBDF56.js.map → chunk-37V6Q4K3.js.map} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  resolveFsConfig,
23
23
  splitFrontmatter,
24
24
  withBrokenPipeGuard
25
- } from "./chunks/chunk-7LGBDF56.js";
25
+ } from "./chunks/chunk-37V6Q4K3.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-V6LQP64H.js";
37
+ } from "./chunks/chunk-PT7PBLVT.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-V6LQP64H.js";
8
+ } from "./chunks/chunk-PT7PBLVT.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-7LGBDF56.js";
29
+ } from "./chunks/chunk-37V6Q4K3.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-V6LQP64H.js";
53
+ } from "./chunks/chunk-PT7PBLVT.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,3 @@
1
+ import type { Budget } from "./budget.js";
2
+ import type { SandboxObject } from "./values.js";
3
+ export declare const float32Prototypes: WeakMap<Budget, SandboxObject>;
@@ -0,0 +1 @@
1
+ export const float32Prototypes = new WeakMap();
@@ -6,6 +6,7 @@ export declare function float32Storage(value: Float32Array): {
6
6
  length: number;
7
7
  byteLength: number;
8
8
  };
9
+ export declare function float32Properties(value: Float32Array): Array<[PropertyKey, PropertyDescriptor]>;
9
10
  export declare function float32DataProperties(value: Float32Array): Array<[string, PropertyDescriptor]>;
10
11
  export declare function isFloat32Index(key: string): boolean;
11
12
  export declare function float32Number(value: unknown): number;
@@ -23,14 +23,22 @@ export function float32Storage(value) {
23
23
  byteLength: Reflect.apply(bufferLength, buffer, [])
24
24
  };
25
25
  }
26
+ export function float32Properties(value) {
27
+ const properties = [];
28
+ for (const key of Reflect.ownKeys(value)) {
29
+ if (typeof key === "string" && isFloat32Index(key))
30
+ continue;
31
+ properties.push([key, Object.getOwnPropertyDescriptor(value, key)]);
32
+ }
33
+ return properties;
34
+ }
26
35
  export function float32DataProperties(value) {
27
36
  if (Object.getOwnPropertySymbols(value).length > 0)
28
37
  throw new TypeError("Float32Array symbol properties are not supported.");
29
38
  const properties = [];
30
- for (const key of Object.getOwnPropertyNames(value)) {
31
- if (isFloat32Index(key))
32
- continue;
33
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
39
+ for (const [key, descriptor] of float32Properties(value)) {
40
+ if (typeof key !== "string")
41
+ throw new TypeError("Float32Array symbol properties are not supported.");
34
42
  if (!("value" in descriptor))
35
43
  throw new TypeError(`Float32Array accessor property '${key}' is not supported.`);
36
44
  properties.push([key, descriptor]);
@@ -1,6 +1,7 @@
1
1
  import type { Budget } from "../budget.js";
2
2
  import { type SandboxClosure, type SandboxValue } from "../values.js";
3
- export declare function createFloat32ArrayGlobal(budget: Budget): SandboxClosure;
3
+ export declare function createFloat32ArrayGlobal(budget: Budget, nativePrototype?: boolean): SandboxClosure;
4
+ export declare function createFloat32ArrayPrototypes(budget: Budget, constructor: SandboxClosure): void;
4
5
  export declare function isFloat32ArrayConstructor(value: unknown): boolean;
5
6
  export declare function getFloat32Member(value: Float32Array, property: string | number, budget: Budget): SandboxValue;
6
- export declare function setFloat32Member(value: Float32Array, property: string | number, entry: SandboxValue): void;
7
+ export declare function setFloat32Member(value: Float32Array, property: PropertyKey, entry: SandboxValue, budget?: Budget): void;
@@ -1,8 +1,19 @@
1
1
  import { checkFloat32Allocation, float32Number, float32Storage, isFloat32Array, isFloat32Index } from "../float32.js";
2
- import { createSandboxClosure } from "../values.js";
2
+ import { createSandboxClosure, isSandboxClosure, measureSandboxData } from "../values.js";
3
+ import { accessorAdapter, readPropertyDescriptor } from "../accessors.js";
4
+ import { float32Prototypes } from "../float32-prototypes.js";
5
+ import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, materializeFunctionProperties, registerIntrinsicFunction, registerIntrinsicObject, setSandboxPrototype } from "../object-model.js";
6
+ import { registerBuiltinIdentities, resolveIntrinsicIdentity } from "../intrinsics.js";
7
+ import { invokeBuiltinClosure } from "../builtin-call.js";
8
+ import { retainValues } from "../resources.js";
9
+ import { sandboxNumber, sandboxString } from "../string-coercion.js";
10
+ import { acquireSandboxIterator, readIteratorResult } from "../iteration.js";
11
+ import { createDataCheckpoint } from "../data-checkpoint.js";
12
+ import { createSandboxBox } from "../boxed.js";
3
13
  const constructors = new WeakSet();
4
- export function createFloat32ArrayGlobal(budget) {
14
+ export function createFloat32ArrayGlobal(budget, nativePrototype = false) {
5
15
  const constructor = createSandboxClosure({
16
+ guest: nativePrototype,
6
17
  sandbox: true,
7
18
  name: "Float32Array",
8
19
  length: 3,
@@ -10,33 +21,294 @@ export function createFloat32ArrayGlobal(budget) {
10
21
  call: () => {
11
22
  throw new TypeError("Constructor Float32Array requires 'new'.");
12
23
  },
13
- construct: ([source]) => {
14
- if (Array.isArray(source) || isFloat32Array(source)) {
15
- const length = isFloat32Array(source) ? float32Storage(source).length : source.length;
16
- checkFloat32Allocation(length, budget);
17
- if (isFloat32Array(source))
18
- return new Float32Array(source);
19
- const result = new Float32Array(length);
20
- for (let index = 0; index < length; index += 1) {
21
- budget.visitNode();
22
- const descriptor = Object.getOwnPropertyDescriptor(source, index);
23
- if (descriptor !== undefined && !("value" in descriptor))
24
- throw new TypeError("Float32Array input accessors are not supported.");
25
- result[index] = float32Number(descriptor?.value);
24
+ construct: (args, context) => {
25
+ if (!nativePrototype)
26
+ return allocateFloat32Array(args[0], budget);
27
+ return (async () => {
28
+ const newTarget = context?.newTarget ?? constructor;
29
+ const candidate = context?.getProperty === undefined
30
+ ? getSandboxDataProperty(newTarget, "prototype", budget)
31
+ : await context.getProperty(newTarget, "prototype");
32
+ const prototype = candidate !== null && typeof candidate === "object" ? candidate : float32Prototypes.get(budget);
33
+ const release = retainValues(budget, () => [prototype, ...args]);
34
+ try {
35
+ const result = args[0] !== null && typeof args[0] === "object" && !isFloat32Array(args[0])
36
+ ? await allocateFloat32Input(args[0], budget, context)
37
+ : allocateFloat32Array(args[0], budget);
38
+ setSandboxPrototype(result, prototype, budget);
39
+ return result;
26
40
  }
27
- return result;
28
- }
29
- const number = float32Number(source);
30
- const length = Number.isNaN(number) ? 0 : Math.trunc(number);
31
- if (length < 0 || !Number.isSafeInteger(length))
32
- throw new RangeError("Invalid typed array length.");
33
- checkFloat32Allocation(length, budget);
34
- return new Float32Array(length);
41
+ finally {
42
+ release();
43
+ }
44
+ })();
35
45
  }
36
46
  });
37
47
  constructors.add(constructor);
38
48
  return constructor;
39
49
  }
50
+ async function allocateFloat32Input(source, budget, context) {
51
+ const callerContext = context;
52
+ const bridge = {
53
+ ...callerContext, stack: callerContext?.stack ?? [], thisValue: undefined,
54
+ getProperty: callerContext?.getProperty ?? ((value, key) => {
55
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
56
+ return descriptor === undefined ? getSandboxDataProperty(value, key, budget)
57
+ : readPropertyDescriptor(descriptor, value, bridge);
58
+ }),
59
+ invokeClosure: callerContext?.invokeClosure ?? ((callee, values, receiver, construct) => invokeBuiltinClosure(callee, values, budget, callerContext, receiver, construct))
60
+ };
61
+ const values = [];
62
+ let iterator;
63
+ let current;
64
+ let result;
65
+ const release = retainValues(budget, () => [source, values, iterator?.retainedValue, current, result]);
66
+ const checkData = createDataCheckpoint(budget, bridge);
67
+ try {
68
+ iterator = await acquireSandboxIterator(source, budget, bridge);
69
+ let length;
70
+ if (iterator !== undefined) {
71
+ while (true) {
72
+ budget.visitNode();
73
+ const next = await iterator.next();
74
+ if (typeof next !== "object" || next === null)
75
+ throw new TypeError("Iterator result must be an object.");
76
+ if ((await readIteratorResult(iterator, next, "done")).value)
77
+ break;
78
+ current = (await readIteratorResult(iterator, next, "value")).value;
79
+ budget.allocateArrayLength(values.length + 1);
80
+ values.push(current);
81
+ checkData(values, 1 + (budget.limits.dataSize === undefined ? 0 : measureSandboxData([current])));
82
+ }
83
+ length = values.length;
84
+ }
85
+ else {
86
+ current = await bridge.getProperty(source, "length");
87
+ const number = await sandboxNumber(current, budget, bridge);
88
+ length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
89
+ }
90
+ checkFloat32Allocation(length, budget);
91
+ result = new Float32Array(length);
92
+ checkData(result, 0, true);
93
+ for (let index = 0; index < length; index++) {
94
+ budget.visitNode();
95
+ current = iterator === undefined ? await bridge.getProperty(source, String(index)) : values[index];
96
+ result[index] = await sandboxNumber(current, budget, bridge);
97
+ }
98
+ return result;
99
+ }
100
+ finally {
101
+ release();
102
+ }
103
+ }
104
+ function allocateFloat32Array(source, budget) {
105
+ if (Array.isArray(source) || isFloat32Array(source)) {
106
+ const length = isFloat32Array(source) ? float32Storage(source).length : source.length;
107
+ checkFloat32Allocation(length, budget);
108
+ if (isFloat32Array(source))
109
+ return new Float32Array(source);
110
+ const result = new Float32Array(length);
111
+ for (let index = 0; index < length; index += 1) {
112
+ budget.visitNode();
113
+ const descriptor = Object.getOwnPropertyDescriptor(source, index);
114
+ if (descriptor !== undefined && !("value" in descriptor))
115
+ throw new TypeError("Float32Array input accessors are not supported.");
116
+ result[index] = float32Number(descriptor?.value);
117
+ }
118
+ return result;
119
+ }
120
+ const number = float32Number(source);
121
+ const length = Number.isNaN(number) ? 0 : Math.trunc(number);
122
+ if (length < 0 || !Number.isSafeInteger(length))
123
+ throw new RangeError("Invalid typed array length.");
124
+ checkFloat32Allocation(length, budget);
125
+ return new Float32Array(length);
126
+ }
127
+ export function createFloat32ArrayPrototypes(budget, constructor) {
128
+ const prototype = Object.create(null);
129
+ const shared = Object.create(null);
130
+ const abstractCall = () => { throw new TypeError("Abstract TypedArray constructor cannot be called."); };
131
+ const typedArray = createSandboxClosure({ guest: true, sandbox: true, name: "TypedArray", length: 0,
132
+ call: abstractCall, construct: abstractCall });
133
+ Object.defineProperty(materializeFunctionProperties(typedArray), "prototype", { value: shared, writable: false });
134
+ Object.defineProperty(materializeFunctionProperties(typedArray), "from", {
135
+ writable: true, configurable: true,
136
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "from", length: 1,
137
+ call: async (args, context) => {
138
+ const target = context?.thisValue;
139
+ const [source, mapper, receiver] = args;
140
+ if (!isSandboxClosure(target) || target.construct === undefined)
141
+ throw new TypeError("TypedArray.from requires a constructor receiver.");
142
+ if (mapper !== undefined && !isSandboxClosure(mapper))
143
+ throw new TypeError("TypedArray.from mapper must be callable.");
144
+ if (source === null || source === undefined)
145
+ throw new TypeError("TypedArray.from requires a non-null source.");
146
+ const callerContext = context;
147
+ context = {
148
+ ...callerContext,
149
+ stack: callerContext?.stack ?? [],
150
+ thisValue: target,
151
+ getProperty: callerContext?.getProperty ?? ((value, key) => {
152
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
153
+ return descriptor === undefined ? getSandboxDataProperty(value, key, budget)
154
+ : readPropertyDescriptor(descriptor, value, context);
155
+ }),
156
+ invokeClosure: callerContext?.invokeClosure ?? ((callee, values, thisValue, construct) => invokeBuiltinClosure(callee, values, budget, callerContext, thisValue, construct))
157
+ };
158
+ let result;
159
+ let current;
160
+ let iterator;
161
+ const values = [];
162
+ const release = retainValues(budget, () => [target, result, current, iterator?.retainedValue, values, ...args]);
163
+ const checkData = createDataCheckpoint(budget, context);
164
+ const read = (key) => context?.getProperty === undefined
165
+ ? getSandboxDataProperty(source, key, budget) : context.getProperty(source, key);
166
+ try {
167
+ iterator = await acquireSandboxIterator(source, budget, context);
168
+ let length;
169
+ if (iterator !== undefined) {
170
+ while (true) {
171
+ budget.visitNode();
172
+ const next = await iterator.next();
173
+ if (typeof next !== "object" || next === null)
174
+ throw new TypeError("Iterator result must be an object.");
175
+ if ((await readIteratorResult(iterator, next, "done")).value)
176
+ break;
177
+ current = (await readIteratorResult(iterator, next, "value")).value;
178
+ budget.allocateArrayLength(values.length + 1);
179
+ values.push(current);
180
+ checkData(values, 1 + (budget.limits.dataSize === undefined ? 0 : measureSandboxData([current])));
181
+ }
182
+ length = values.length;
183
+ }
184
+ else {
185
+ const number = await sandboxNumber(await read("length"), budget, context);
186
+ length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
187
+ }
188
+ result = await invokeBuiltinClosure(target, [length], budget, context, undefined, true);
189
+ if (!isFloat32Array(result) || float32Storage(result).length < length)
190
+ throw new TypeError("TypedArray.from constructor must return sufficient typed storage.");
191
+ checkData(result, 0, true);
192
+ for (let index = 0; index < length; index++) {
193
+ budget.visitNode();
194
+ current = iterator === undefined ? await read(String(index)) : values[index];
195
+ if (mapper !== undefined)
196
+ current = await invokeBuiltinClosure(mapper, [current, index], budget, context, receiver);
197
+ result[index] = await sandboxNumber(current, budget, context);
198
+ }
199
+ return result;
200
+ }
201
+ finally {
202
+ release();
203
+ }
204
+ }
205
+ })
206
+ });
207
+ Object.defineProperty(materializeFunctionProperties(typedArray), "of", {
208
+ writable: true, configurable: true,
209
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "of", length: 0,
210
+ call: async (args, context) => {
211
+ const target = context?.thisValue;
212
+ if (!isSandboxClosure(target) || target.construct === undefined)
213
+ throw new TypeError("TypedArray.of requires a constructor receiver.");
214
+ let result;
215
+ const release = retainValues(budget, () => [target, result, ...args]);
216
+ try {
217
+ result = await invokeBuiltinClosure(target, [args.length], budget, context, undefined, true);
218
+ if (!isFloat32Array(result) || float32Storage(result).length < args.length)
219
+ throw new TypeError("TypedArray.of constructor must return sufficient typed storage.");
220
+ for (let index = 0; index < args.length; index++) {
221
+ budget.visitNode();
222
+ result[index] = await sandboxNumber(args[index], budget, context);
223
+ }
224
+ return result;
225
+ }
226
+ finally {
227
+ release();
228
+ }
229
+ }
230
+ })
231
+ });
232
+ Object.defineProperties(materializeFunctionProperties(constructor), {
233
+ prototype: { value: prototype, writable: false },
234
+ BYTES_PER_ELEMENT: { value: 4, writable: false, enumerable: false, configurable: false }
235
+ });
236
+ Object.defineProperties(prototype, {
237
+ constructor: { value: constructor, writable: true, configurable: true },
238
+ BYTES_PER_ELEMENT: { value: 4 }
239
+ });
240
+ Object.defineProperty(shared, "constructor", { value: typedArray, writable: true, configurable: true });
241
+ setSandboxPrototype(constructor, typedArray);
242
+ setSandboxPrototype(prototype, shared);
243
+ setSandboxPrototype(shared, getSandboxPrototype(Object.create(null), budget));
244
+ const getters = [];
245
+ for (const key of ["length", "byteLength", "byteOffset"]) {
246
+ const getter = createSandboxClosure({ guest: true, sandbox: true, name: `get ${key}`, length: 0,
247
+ call: (_args, context) => {
248
+ if (!isFloat32Array(context?.thisValue))
249
+ throw new TypeError(`TypedArray ${key} requires a typed array receiver.`);
250
+ const storage = float32Storage(context.thisValue);
251
+ return key === "byteLength" ? storage.length * 4 : storage[key];
252
+ }
253
+ });
254
+ getters.push(getter);
255
+ Object.defineProperty(shared, key, { get: accessorAdapter(getter, "get"), configurable: true });
256
+ }
257
+ for (const key of ["set", "slice", "subarray"])
258
+ Object.defineProperty(shared, key, { value: getFloat32Member(new Float32Array(0), key, budget), writable: true, configurable: true });
259
+ const arrayPrototype = resolveIntrinsicIdentity(budget, '["Array","prototype"]');
260
+ Object.defineProperty(shared, "toString", { value: getSandboxDataProperty(arrayPrototype, "toString", budget), writable: true, configurable: true });
261
+ Object.defineProperty(shared, "join", { writable: true, configurable: true,
262
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "join", length: 1,
263
+ call: async (args, context) => {
264
+ if (!isFloat32Array(context?.thisValue))
265
+ throw new TypeError("TypedArray join requires a typed array receiver.");
266
+ const receiver = context.thisValue;
267
+ const length = float32Storage(receiver).length;
268
+ let separator = ",";
269
+ let text = "";
270
+ const release = retainValues(budget, () => [receiver, separator, text, ...args]);
271
+ try {
272
+ if (args[0] !== undefined)
273
+ separator = await sandboxString(args[0], budget, context);
274
+ for (let index = 0; index < length; index++) {
275
+ budget.visitNode();
276
+ text = budget.allocateString(text + (index === 0 ? "" : separator) + String(receiver[index]));
277
+ }
278
+ return text;
279
+ }
280
+ finally {
281
+ release();
282
+ }
283
+ }
284
+ })
285
+ });
286
+ const tagGetter = createSandboxClosure({ guest: true, sandbox: true, name: "get [Symbol.toStringTag]", length: 0,
287
+ call: (_args, context) => isFloat32Array(context?.thisValue) ? "Float32Array" : undefined });
288
+ getters.push(tagGetter);
289
+ Object.defineProperty(shared, Symbol.toStringTag, { get: accessorAdapter(tagGetter, "get"), configurable: true });
290
+ for (const key of ["values", "keys", "entries"]) {
291
+ const method = getSandboxDataProperty(arrayPrototype, key, budget);
292
+ const closure = createSandboxClosure({ guest: true, sandbox: true, name: key, length: 0,
293
+ call: (args, context) => {
294
+ if (!isFloat32Array(context?.thisValue))
295
+ throw new TypeError(`TypedArray ${key} requires a typed array receiver.`);
296
+ return invokeBuiltinClosure(method, args, budget, context, context.thisValue);
297
+ }
298
+ });
299
+ Object.defineProperty(shared, key, { value: closure, writable: true, configurable: true });
300
+ if (key === "values")
301
+ Object.defineProperty(shared, Symbol.iterator, { value: closure, writable: true, configurable: true });
302
+ }
303
+ float32Prototypes.set(budget, prototype);
304
+ registerBuiltinIdentities(budget, { Float32Array: constructor, "%TypedArray%": typedArray });
305
+ registerIntrinsicFunction(budget, constructor);
306
+ registerIntrinsicFunction(budget, typedArray);
307
+ registerIntrinsicObject(budget, prototype);
308
+ registerIntrinsicObject(budget, shared);
309
+ for (const getter of getters)
310
+ registerIntrinsicFunction(budget, getter);
311
+ }
40
312
  export function isFloat32ArrayConstructor(value) {
41
313
  return typeof value === "object" && value !== null && constructors.has(value);
42
314
  }
@@ -48,6 +320,8 @@ export function getFloat32Member(value, property, budget) {
48
320
  throw new TypeError("Float32Array accessors are not supported.");
49
321
  return descriptor.value;
50
322
  }
323
+ if (float32Prototypes.has(budget))
324
+ return undefined;
51
325
  const storage = float32Storage(value);
52
326
  if (key === "length")
53
327
  return storage.length;
@@ -60,6 +334,7 @@ export function getFloat32Member(value, property, budget) {
60
334
  if (!["set", "slice", "subarray"].includes(key))
61
335
  return undefined;
62
336
  return createSandboxClosure({
337
+ guest: true,
63
338
  sandbox: true,
64
339
  name: key,
65
340
  length: key === "set" ? 1 : 2,
@@ -68,63 +343,94 @@ export function getFloat32Member(value, property, budget) {
68
343
  if (!isFloat32Array(receiver))
69
344
  throw new TypeError(`Float32Array#${key} requires a Float32Array receiver.`);
70
345
  const storage = float32Storage(receiver);
346
+ const bridge = {
347
+ ...context, stack: context?.stack ?? [], thisValue: receiver,
348
+ getProperty: context?.getProperty ?? ((value, property) => {
349
+ const descriptor = getSandboxPropertyDescriptor(value, property, budget);
350
+ return descriptor === undefined ? getSandboxDataProperty(value, property, budget)
351
+ : readPropertyDescriptor(descriptor, value, bridge);
352
+ }),
353
+ invokeClosure: context?.invokeClosure ?? ((callee, values, thisValue, construct) => invokeBuiltinClosure(callee, values, budget, context, thisValue, construct))
354
+ };
71
355
  if (key === "set") {
72
- const [source, offsetValue = 0] = args;
73
- if (!Array.isArray(source) && !isFloat32Array(source))
74
- throw new TypeError("Float32Array#set requires an array or Float32Array.");
75
- const number = float32Number(offsetValue);
76
- const offset = Number.isNaN(number) ? 0 : Math.trunc(number);
77
- const length = isFloat32Array(source) ? float32Storage(source).length : source.length;
78
- if (offset < 0 || !Number.isSafeInteger(offset) || offset + length > storage.length)
79
- throw new RangeError("Float32Array#set source is out of bounds.");
80
- if (isFloat32Array(source)) {
81
- Float32Array.prototype.set.call(receiver, source, offset);
82
- return undefined;
356
+ return (async () => {
357
+ const [source, offsetValue = 0] = args;
358
+ let current;
359
+ let sourceObject;
360
+ const release = retainValues(budget, () => [receiver, sourceObject, current, ...args]);
361
+ try {
362
+ const number = await sandboxNumber(offsetValue, budget, bridge);
363
+ const offset = Number.isNaN(number) ? 0 : Math.trunc(number);
364
+ if (offset < 0)
365
+ throw new RangeError("Float32Array#set offset is out of bounds.");
366
+ if (source === null || source === undefined)
367
+ throw new TypeError("Float32Array#set requires a non-null source.");
368
+ let length;
369
+ if (isFloat32Array(source))
370
+ length = float32Storage(source).length;
371
+ else {
372
+ sourceObject = typeof source === "object" ? source : createSandboxBox(source);
373
+ current = await bridge.getProperty(sourceObject, "length");
374
+ const size = await sandboxNumber(current, budget, bridge);
375
+ length = Number.isNaN(size) || size <= 0 ? 0 : Math.min(Math.trunc(size), Number.MAX_SAFE_INTEGER);
376
+ }
377
+ if (offset + length > storage.length)
378
+ throw new RangeError("Float32Array#set source is out of bounds.");
379
+ if (isFloat32Array(source))
380
+ Float32Array.prototype.set.call(receiver, source, offset);
381
+ else
382
+ for (let index = 0; index < length; index++) {
383
+ budget.visitNode();
384
+ current = await bridge.getProperty(sourceObject, String(index));
385
+ receiver[offset + index] = await sandboxNumber(current, budget, bridge);
386
+ }
387
+ return undefined;
388
+ }
389
+ finally {
390
+ release();
391
+ }
392
+ })();
393
+ }
394
+ return (async () => {
395
+ const release = retainValues(budget, () => [receiver, ...args]);
396
+ try {
397
+ const start = relativeIndex(await sandboxNumber(args[0], budget, bridge), storage.length);
398
+ const end = args[1] === undefined ? storage.length
399
+ : relativeIndex(await sandboxNumber(args[1], budget, bridge), storage.length);
400
+ 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));
406
+ return result;
83
407
  }
84
- checkFloat32Allocation(length, budget);
85
- const copied = new Float32Array(length);
86
- for (let index = 0; index < length; index += 1) {
87
- budget.visitNode();
88
- const entry = Object.getOwnPropertyDescriptor(source, index);
89
- if (entry !== undefined && !("value" in entry))
90
- throw new TypeError("Float32Array input accessors are not supported.");
91
- copied[index] = float32Number(entry?.value);
408
+ finally {
409
+ release();
92
410
  }
93
- Float32Array.prototype.set.call(receiver, copied, offset);
94
- return undefined;
95
- }
96
- const start = relativeIndex(args[0], storage.length, 0);
97
- const end = relativeIndex(args[1], storage.length, storage.length);
98
- const length = Math.max(end - start, 0);
99
- if (key === "subarray")
100
- return new Float32Array(storage.buffer, storage.byteOffset + start * 4, length);
101
- checkFloat32Allocation(length, budget);
102
- const result = new Float32Array(length);
103
- new Uint8Array(result.buffer).set(new Uint8Array(storage.buffer, storage.byteOffset + start * 4, length * 4));
104
- return result;
411
+ })();
105
412
  }
106
413
  });
107
414
  }
108
- export function setFloat32Member(value, property, entry) {
109
- const key = String(property);
110
- if (isFloat32Index(key)) {
415
+ export function setFloat32Member(value, property, entry, budget) {
416
+ const key = typeof property === "symbol" ? property : String(property);
417
+ if (typeof key !== "symbol" && isFloat32Index(key)) {
111
418
  Reflect.set(value, key, float32Number(entry));
112
419
  return;
113
420
  }
114
421
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
115
- if (descriptor === undefined &&
422
+ const inherited = descriptor ?? (budget === undefined ? undefined : getSandboxPropertyDescriptor(value, key, budget));
423
+ if (descriptor === undefined && typeof key === "string" &&
424
+ (budget === undefined || !float32Prototypes.has(budget)) &&
116
425
  ["length", "byteLength", "byteOffset", "buffer", "BYTES_PER_ELEMENT"].includes(key))
117
- throw new TypeError(`Cannot assign to read only property '${key}'.`);
118
- if (descriptor !== undefined && (!("value" in descriptor) || !descriptor.writable))
119
- throw new TypeError(`Cannot assign to read only property '${key}'.`);
426
+ throw new TypeError(`Cannot assign to read only property '${String(key)}'.`);
427
+ if (inherited !== undefined && (!("value" in inherited) || !inherited.writable))
428
+ throw new TypeError(`Cannot assign to read only property '${String(key)}'.`);
120
429
  Object.defineProperty(value, key, descriptor === undefined
121
430
  ? { value: entry, configurable: true, enumerable: true, writable: true }
122
431
  : { value: entry });
123
432
  }
124
- function relativeIndex(value, length, fallback) {
125
- if (value === undefined)
126
- return fallback;
127
- const numeric = float32Number(value);
433
+ function relativeIndex(numeric, length) {
128
434
  const integer = Number.isNaN(numeric) ? 0 : Math.trunc(numeric);
129
435
  return integer < 0 ? Math.max(length + integer, 0) : Math.min(integer, length);
130
436
  }
@@ -12,7 +12,7 @@ import { isSandboxDate } from "../date.js";
12
12
  import { createSandboxBox } from "../boxed.js";
13
13
  import { createObjectGlobal, hasOwnSandboxProperty } from "./object.js";
14
14
  import { isGuestHostObject } from "../host-capabilities.js";
15
- import { isFloat32Array } from "../float32.js";
15
+ import { float32Number, isFloat32Array, isFloat32Index } from "../float32.js";
16
16
  import { deleteSandboxProperty, setSandboxProperty } from "../interpreter.js";
17
17
  import { acquireSandboxIterator, closeIterator, getSandboxIterator, readIteratorResult } from "../iteration.js";
18
18
  import { sandboxNumber, sandboxString } from "../string-coercion.js";
@@ -681,8 +681,8 @@ async function definePropertiesFromObject(target, descriptors, budget, context)
681
681
  }
682
682
  export function defineDataProperty(target, key, descriptor, budget) {
683
683
  budget.visitNode();
684
- if (isFloat32Array(target))
685
- throw new TypeError("Typed array property descriptors are not supported.");
684
+ if (isFloat32Array(target) && typeof key !== "symbol" && isFloat32Index(String(key)) && "value" in descriptor)
685
+ descriptor = { ...descriptor, value: float32Number(descriptor.value) };
686
686
  const properties = objectProperties(target, true);
687
687
  if (Array.isArray(properties)) {
688
688
  if (key === "length" && "value" in descriptor)
@@ -5,6 +5,7 @@ export declare function createBuiltinBindings(options: Parameters<typeof createC
5
5
  clock?: RunClock;
6
6
  functionHasInstance?: boolean;
7
7
  errorPrototypes?: boolean;
8
+ float32Prototypes?: boolean;
8
9
  }): {
9
10
  RegExp: import("./values.js").SandboxClosure;
10
11
  Promise: import("./values.js").SandboxClosure;
@@ -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";
@@ -18,7 +18,7 @@ export function createBuiltinBindings(options) {
18
18
  const bindings = {
19
19
  ...createConsoleJsonGlobals(options),
20
20
  ...createCollectionGlobals(options),
21
- Float32Array: createFloat32ArrayGlobal(options.budget),
21
+ Float32Array: createFloat32ArrayGlobal(options.budget, options.float32Prototypes !== false),
22
22
  Date: createDateGlobal(options),
23
23
  Symbol: createSymbolGlobal(options.budget),
24
24
  BigInt: createBigIntGlobal(options.budget),
@@ -31,6 +31,8 @@ export function createBuiltinBindings(options) {
31
31
  ...createRegexGlobals(options)
32
32
  };
33
33
  createFunctionPrototype(options.budget, options.functionHasInstance);
34
+ if (options.float32Prototypes !== false)
35
+ createFloat32ArrayPrototypes(options.budget, bindings.Float32Array);
34
36
  if (options.errorPrototypes !== false)
35
37
  createErrorPrototypes(options.budget, bindings);
36
38
  createGeneratorPrototypes(options.budget);