poe-code 14.0.81 → 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 (44) hide show
  1. package/dist/index.js +933 -353
  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-2LNBLFJ3.js → chunk-37V6Q4K3.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-ZSYBRZU6.js → chunk-PT7PBLVT.js} +764 -224
  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/error-prototypes.d.ts +3 -0
  12. package/packages/safe-js/dist/interp/error-prototypes.js +1 -0
  13. package/packages/safe-js/dist/interp/exceptions.d.ts +1 -0
  14. package/packages/safe-js/dist/interp/exceptions.js +39 -15
  15. package/packages/safe-js/dist/interp/float32-prototypes.d.ts +3 -0
  16. package/packages/safe-js/dist/interp/float32-prototypes.js +1 -0
  17. package/packages/safe-js/dist/interp/float32.d.ts +1 -0
  18. package/packages/safe-js/dist/interp/float32.js +12 -4
  19. package/packages/safe-js/dist/interp/globals/error.d.ts +2 -0
  20. package/packages/safe-js/dist/interp/globals/error.js +104 -4
  21. package/packages/safe-js/dist/interp/globals/float32array.d.ts +3 -2
  22. package/packages/safe-js/dist/interp/globals/float32array.js +371 -65
  23. package/packages/safe-js/dist/interp/globals/object-array.js +3 -3
  24. package/packages/safe-js/dist/interp/globals.d.ts +2 -0
  25. package/packages/safe-js/dist/interp/globals.js +8 -4
  26. package/packages/safe-js/dist/interp/host-bridge.js +4 -2
  27. package/packages/safe-js/dist/interp/instanceof.js +4 -3
  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/object-model.js +27 -1
  31. package/packages/safe-js/dist/interp/values.js +59 -6
  32. package/packages/safe-js/dist/parse/parser.js +8 -3
  33. package/packages/safe-js/dist/parse/tokenizer.js +45 -3
  34. package/packages/safe-js/dist/snapshot/float32array.d.ts +3 -0
  35. package/packages/safe-js/dist/snapshot/float32array.js +20 -1
  36. package/packages/safe-js/dist/snapshot/guest-heap-validation.js +4 -1
  37. package/packages/safe-js/dist/snapshot/guest-heap.d.ts +2 -0
  38. package/packages/safe-js/dist/snapshot/guest-heap.js +6 -2
  39. package/packages/safe-js/dist/snapshot/restore.js +33 -3
  40. package/packages/safe-js/dist/snapshot/serialize.d.ts +2 -1
  41. package/packages/safe-js/dist/snapshot/serialize.js +10 -9
  42. package/packages/safe-js/dist/snapshot/validation.js +11 -1
  43. package/packages/safe-js/dist/chunks/chunk-ZSYBRZU6.js.map +0 -7
  44. /package/packages/safe-js/dist/chunks/{chunk-2LNBLFJ3.js.map → chunk-37V6Q4K3.js.map} +0 -0
@@ -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)
@@ -4,6 +4,8 @@ export declare function createBuiltinBindings(options: Parameters<typeof createC
4
4
  random?: () => number;
5
5
  clock?: RunClock;
6
6
  functionHasInstance?: boolean;
7
+ errorPrototypes?: boolean;
8
+ float32Prototypes?: boolean;
7
9
  }): {
8
10
  RegExp: import("./values.js").SandboxClosure;
9
11
  Promise: import("./values.js").SandboxClosure;
@@ -1,7 +1,7 @@
1
1
  import { createConsoleJsonGlobals } from "./globals/console-json.js";
2
2
  import { createCollectionGlobals } from "./globals/collections.js";
3
- import { createFloat32ArrayGlobal } from "./globals/float32array.js";
4
- import { createErrorGlobals } from "./globals/error.js";
3
+ import { createFloat32ArrayGlobal, createFloat32ArrayPrototypes } from "./globals/float32array.js";
4
+ import { createErrorGlobals, createErrorPrototypes } from "./globals/error.js";
5
5
  import { createMathGlobals } from "./globals/math.js";
6
6
  import { createRegexGlobals } from "./globals/regex.js";
7
7
  import { createMiscGlobals } from "./globals/misc.js";
@@ -18,11 +18,11 @@ 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),
25
- ...createErrorGlobals(options),
25
+ ...createErrorGlobals({ ...options, errorPrototypes: options.errorPrototypes !== false }),
26
26
  ...createMathGlobals({ random: options.random, budget: options.budget }),
27
27
  ...createObjectArrayGlobals(options),
28
28
  ...createMiscGlobals(options),
@@ -31,6 +31,10 @@ 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);
36
+ if (options.errorPrototypes !== false)
37
+ createErrorPrototypes(options.budget, bindings);
34
38
  createGeneratorPrototypes(options.budget);
35
39
  registerBuiltinIdentities(options.budget, bindings);
36
40
  return bindings;
@@ -408,10 +408,12 @@ function createHostErrorValue(reason, stackFrames, budget, span, state = { seen:
408
408
  const error = reason instanceof Error
409
409
  ? createSubsetErrorValue(reason.name, reason.message, stackFrames, budget, {
410
410
  cause: reason,
411
- chargeBudget
411
+ chargeBudget,
412
+ transport: true
412
413
  })
413
414
  : createSubsetErrorValue("Error", describeThrownReason(reason), stackFrames, budget, {
414
- chargeBudget: false
415
+ chargeBudget: false,
416
+ transport: true
415
417
  });
416
418
  if (reason instanceof Error) {
417
419
  state.seen.set(reason, error);
@@ -4,7 +4,7 @@ import { invokeBuiltinClosure } from "./builtin-call.js";
4
4
  import { isFloat32Array } from "./float32.js";
5
5
  import { isFloat32ArrayConstructor } from "./globals/float32array.js";
6
6
  import { isSandboxErrorConstructorInstance } from "./globals/error.js";
7
- import { getSandboxPropertyDescriptor, getSandboxPrototype, isGuestClosure } from "./object-model.js";
7
+ import { getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure } from "./object-model.js";
8
8
  import { isSandboxClosure } from "./values.js";
9
9
  export async function evaluateInstanceof(value, constructor, budget, context) {
10
10
  if (constructor === null || typeof constructor !== "object")
@@ -27,9 +27,10 @@ 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
- if (isSandboxErrorConstructorInstance(value, constructor))
32
+ if ((!isGuestClosure(constructor) || (value !== null && typeof value === "object" && !hasExplicitSandboxPrototype(value))) &&
33
+ isSandboxErrorConstructorInstance(value, constructor))
33
34
  return true;
34
35
  if (!isGuestClosure(constructor) || typeof value !== "object" || value === null)
35
36
  return false;
@@ -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)) {