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.
- package/dist/index.js +933 -353
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-js/dist/chunks/{chunk-2LNBLFJ3.js → chunk-37V6Q4K3.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-ZSYBRZU6.js → chunk-PT7PBLVT.js} +764 -224
- package/packages/safe-js/dist/chunks/chunk-PT7PBLVT.js.map +7 -0
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.js +1 -1
- package/packages/safe-js/dist/index.js +2 -2
- package/packages/safe-js/dist/interp/error-prototypes.d.ts +3 -0
- package/packages/safe-js/dist/interp/error-prototypes.js +1 -0
- package/packages/safe-js/dist/interp/exceptions.d.ts +1 -0
- package/packages/safe-js/dist/interp/exceptions.js +39 -15
- package/packages/safe-js/dist/interp/float32-prototypes.d.ts +3 -0
- package/packages/safe-js/dist/interp/float32-prototypes.js +1 -0
- package/packages/safe-js/dist/interp/float32.d.ts +1 -0
- package/packages/safe-js/dist/interp/float32.js +12 -4
- package/packages/safe-js/dist/interp/globals/error.d.ts +2 -0
- package/packages/safe-js/dist/interp/globals/error.js +104 -4
- package/packages/safe-js/dist/interp/globals/float32array.d.ts +3 -2
- package/packages/safe-js/dist/interp/globals/float32array.js +371 -65
- package/packages/safe-js/dist/interp/globals/object-array.js +3 -3
- package/packages/safe-js/dist/interp/globals.d.ts +2 -0
- package/packages/safe-js/dist/interp/globals.js +8 -4
- package/packages/safe-js/dist/interp/host-bridge.js +4 -2
- package/packages/safe-js/dist/interp/instanceof.js +4 -3
- package/packages/safe-js/dist/interp/interpreter.js +2 -4
- package/packages/safe-js/dist/interp/iteration.js +15 -6
- package/packages/safe-js/dist/interp/object-model.js +27 -1
- package/packages/safe-js/dist/interp/values.js +59 -6
- package/packages/safe-js/dist/parse/parser.js +8 -3
- package/packages/safe-js/dist/parse/tokenizer.js +45 -3
- package/packages/safe-js/dist/snapshot/float32array.d.ts +3 -0
- package/packages/safe-js/dist/snapshot/float32array.js +20 -1
- package/packages/safe-js/dist/snapshot/guest-heap-validation.js +4 -1
- package/packages/safe-js/dist/snapshot/guest-heap.d.ts +2 -0
- package/packages/safe-js/dist/snapshot/guest-heap.js +6 -2
- package/packages/safe-js/dist/snapshot/restore.js +33 -3
- package/packages/safe-js/dist/snapshot/serialize.d.ts +2 -1
- package/packages/safe-js/dist/snapshot/serialize.js +10 -9
- package/packages/safe-js/dist/snapshot/validation.js +11 -1
- package/packages/safe-js/dist/chunks/chunk-ZSYBRZU6.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-2LNBLFJ3.js.map → chunk-37V6Q4K3.js.map} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxSet } from "./values.js";
|
|
2
2
|
import { enterRunningState } from "./running-state.js";
|
|
3
3
|
import { isFloat32Array } from "./float32.js";
|
|
4
|
+
import { float32Prototypes } from "./float32-prototypes.js";
|
|
4
5
|
import { boxedValue, isSandboxBox } from "./boxed.js";
|
|
5
6
|
import { getHostObjectIterator, isGuestHostObject } from "./host-capabilities.js";
|
|
6
7
|
import { isSandboxCollectionIterator, nextCollectionIterator } from "./collection-iterator.js";
|
|
@@ -98,6 +99,9 @@ export async function acquireSandboxIterator(value, budget, context, asyncProtoc
|
|
|
98
99
|
const iterator = await invokeBuiltinClosure(factory, [], budget, context, value);
|
|
99
100
|
if ((typeof iterator !== "object" && typeof iterator !== "function") || iterator === null)
|
|
100
101
|
throw new TypeError("Iterator must be an object.");
|
|
102
|
+
if (!asyncProtocol && isSandboxGenerator(iterator) && !iterator.async &&
|
|
103
|
+
!hasExplicitSandboxPrototype(iterator) && getSandboxPropertyDescriptor(iterator, "next", budget) === undefined)
|
|
104
|
+
return getSandboxIterator(iterator, budget, context);
|
|
101
105
|
const next = await context.getProperty(iterator, "next");
|
|
102
106
|
return guestIterator(iterator, next, asyncProtocol, budget, context, signal);
|
|
103
107
|
}
|
|
@@ -137,7 +141,7 @@ export async function readIteratorResult(iterator, result, property) {
|
|
|
137
141
|
export function getSandboxAsyncIterator(value, budget, context, signal) {
|
|
138
142
|
if (isSandboxGenerator(value) && value.async) {
|
|
139
143
|
return hasExplicitSandboxPrototype(value) ? context?.getProperty === undefined
|
|
140
|
-
?
|
|
144
|
+
? guestProtocolAdapter(value, budget, context, true, signal) : undefined
|
|
141
145
|
: { ...generatorObjectIterator(value, budget, context), asyncProtocol: true };
|
|
142
146
|
}
|
|
143
147
|
if (value !== null &&
|
|
@@ -293,6 +297,11 @@ export function getSandboxIterator(value, budget, context) {
|
|
|
293
297
|
if (isGuestHostObject(value))
|
|
294
298
|
return getHostObjectIterator(value);
|
|
295
299
|
if (isFloat32Array(value)) {
|
|
300
|
+
if (hasExplicitSandboxPrototype(value) || (budget !== undefined && float32Prototypes.has(budget))) {
|
|
301
|
+
if (getSandboxPropertyDescriptor(value, Symbol.iterator, budget) === undefined)
|
|
302
|
+
return undefined;
|
|
303
|
+
return guestProtocolAdapter(value, budget ?? new Budget(), context, false);
|
|
304
|
+
}
|
|
296
305
|
return syncIterator(Float32Array.prototype.values.call(value));
|
|
297
306
|
}
|
|
298
307
|
if (isSandboxGenerator(value)) {
|
|
@@ -300,7 +309,7 @@ export function getSandboxIterator(value, budget, context) {
|
|
|
300
309
|
return undefined;
|
|
301
310
|
if (hasExplicitSandboxPrototype(value))
|
|
302
311
|
return context?.getProperty === undefined
|
|
303
|
-
?
|
|
312
|
+
? guestProtocolAdapter(value, budget ?? new Budget(), context, false) : undefined;
|
|
304
313
|
return generatorObjectIterator(value, budget, context);
|
|
305
314
|
}
|
|
306
315
|
if (typeof value === "string") {
|
|
@@ -386,9 +395,9 @@ function collectionIterator(collection, value) {
|
|
|
386
395
|
return adapter;
|
|
387
396
|
}
|
|
388
397
|
const asyncGeneratorRequests = new WeakMap();
|
|
389
|
-
function
|
|
390
|
-
// Direct
|
|
391
|
-
// cached next methods
|
|
398
|
+
function guestProtocolAdapter(value, budget, context, asyncProtocol, signal) {
|
|
399
|
+
// Direct adapters still need guest property reads, receiver binding and
|
|
400
|
+
// cached next methods without exposing native iterator objects.
|
|
392
401
|
const bridge = {
|
|
393
402
|
...context,
|
|
394
403
|
stack: context?.stack ?? [],
|
|
@@ -403,7 +412,7 @@ function generatorProtocolAdapter(value, budget, context, asyncProtocol, signal)
|
|
|
403
412
|
let pending;
|
|
404
413
|
const initialize = () => pending ??= acquireSandboxIterator(value, budget, bridge, asyncProtocol, signal).then(iterator => {
|
|
405
414
|
if (iterator === undefined)
|
|
406
|
-
throw new TypeError("
|
|
415
|
+
throw new TypeError("Value does not provide an iterator protocol.");
|
|
407
416
|
return resolved = iterator;
|
|
408
417
|
});
|
|
409
418
|
return {
|
|
@@ -7,6 +7,10 @@ import { releaseTemplateObjects } from "./template-objects.js";
|
|
|
7
7
|
import { isSandboxDate } from "./date.js";
|
|
8
8
|
import { retainedAccessorClosures } from "./accessors.js";
|
|
9
9
|
import { getHostObjectMember, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
|
|
10
|
+
import { errorPrototypes } from "./error-prototypes.js";
|
|
11
|
+
import { float32Properties, isFloat32Array, isFloat32Index } from "./float32.js";
|
|
12
|
+
import { float32Prototypes } from "./float32-prototypes.js";
|
|
13
|
+
import { sandboxErrorTypes } from "../error/shape.js";
|
|
10
14
|
import { boxedValue, isSandboxBox } from "./boxed.js";
|
|
11
15
|
import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, getPromiseProperties, isSandboxRegex, getRegexProperties, getCollectionProperties, isSandboxSet } from "./values.js";
|
|
12
16
|
const guestClosures = new WeakSet();
|
|
@@ -273,12 +277,24 @@ export function releaseObjectPrototype(budget) {
|
|
|
273
277
|
arrayPrototypes.delete(budget);
|
|
274
278
|
functionPrototypes.delete(budget);
|
|
275
279
|
generatorPrototypes.delete(budget);
|
|
280
|
+
errorPrototypes.delete(budget);
|
|
281
|
+
float32Prototypes.delete(budget);
|
|
276
282
|
initialRegexDescriptors.delete(budget);
|
|
277
283
|
intrinsicPrototypes.delete(budget);
|
|
278
284
|
}
|
|
279
285
|
export function getSandboxPrototype(value, budget) {
|
|
280
286
|
if (prototypes.has(value))
|
|
281
287
|
return prototypes.get(value) ?? null;
|
|
288
|
+
if (isFloat32Array(value))
|
|
289
|
+
return budget === undefined ? null : float32Prototypes.get(budget) ?? null;
|
|
290
|
+
// Host transport records are data-only. Resolve their default prototype in
|
|
291
|
+
// the receiving realm without persisting executable intrinsic graphs.
|
|
292
|
+
const errorType = sandboxErrorTypes.get(value);
|
|
293
|
+
if (budget !== undefined && errorType !== undefined) {
|
|
294
|
+
const prototype = errorPrototypes.get(budget)?.get(errorType);
|
|
295
|
+
if (prototype !== undefined)
|
|
296
|
+
return prototype;
|
|
297
|
+
}
|
|
282
298
|
if (budget !== undefined && isGuestClosure(value) && runResources.getStore()?.functionSourceText !== false)
|
|
283
299
|
return functionPrototypes.get(budget) ?? null;
|
|
284
300
|
if (budget !== undefined && Array.isArray(value))
|
|
@@ -317,6 +333,10 @@ export function getSandboxPropertyDescriptor(value, key, budget) {
|
|
|
317
333
|
while (typeof current === "object" &&
|
|
318
334
|
current !== null &&
|
|
319
335
|
(Array.isArray(current) || isSandboxGenerator(current) || isSandboxDate(current) || isSandboxPromise(current) || isSandboxRegex(current) || isSandboxMap(current) || isSandboxSet(current) || isPrototypeRecord(current))) {
|
|
336
|
+
// An integer-indexed object stops numeric-key lookup even when it occurs
|
|
337
|
+
// inside another object's prototype chain and the index is invalid.
|
|
338
|
+
if (isFloat32Array(current) && typeof key !== "symbol" && isFloat32Index(String(key)))
|
|
339
|
+
return Object.getOwnPropertyDescriptor(current, key);
|
|
320
340
|
const properties = isSandboxGenerator(current) ? getGeneratorProperties(current) : isSandboxPromise(current) ? getPromiseProperties(current) : isGuestClosure(current)
|
|
321
341
|
? key === "prototype" && current.construct !== undefined && current.boundTarget === undefined
|
|
322
342
|
? materializeFunctionProperties(current) : getGuestFunctionProperties(current)
|
|
@@ -339,6 +359,8 @@ export function getSandboxDataProperty(value, key, budget) {
|
|
|
339
359
|
let current = value;
|
|
340
360
|
let depth = 0;
|
|
341
361
|
while (typeof current === "object" && current !== null) {
|
|
362
|
+
if (isFloat32Array(current) && typeof key !== "symbol" && isFloat32Index(String(key)))
|
|
363
|
+
return Object.getOwnPropertyDescriptor(current, key)?.value;
|
|
342
364
|
if (isGuestHostObject(current))
|
|
343
365
|
return typeof key === "symbol" ? undefined : getHostObjectMember(current, String(key));
|
|
344
366
|
if (isSandboxRegex(current))
|
|
@@ -405,6 +427,8 @@ export function setSandboxPrototype(value, prototype, budget) {
|
|
|
405
427
|
prototypes.set(value, prototype);
|
|
406
428
|
}
|
|
407
429
|
function isPrototypeRecord(value) {
|
|
430
|
+
if (isFloat32Array(value))
|
|
431
|
+
return true;
|
|
408
432
|
if (isGuestClosure(value))
|
|
409
433
|
return true;
|
|
410
434
|
if (isGuestHostObject(value))
|
|
@@ -436,5 +460,7 @@ export function hasGuestObjectState(value) {
|
|
|
436
460
|
if (isSandboxBox(value) || isSandboxDate(value))
|
|
437
461
|
return false;
|
|
438
462
|
return (descriptorObjects.has(value) &&
|
|
439
|
-
|
|
463
|
+
(isFloat32Array(value)
|
|
464
|
+
? float32Properties(value).map(([, descriptor]) => descriptor)
|
|
465
|
+
: Object.values(Object.getOwnPropertyDescriptors(value))).some((descriptor) => !descriptor.enumerable || !descriptor.configurable || !descriptor.writable));
|
|
440
466
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
|
|
2
2
|
import { internalSymbols } from "./internal-symbols.js";
|
|
3
|
+
import { getIntrinsicIdentity } from "./intrinsics.js";
|
|
3
4
|
import { getGeneratorProperties } from "./generator-properties.js";
|
|
4
5
|
import { getRegexProperties, regexGuestProperties } from "./regexp-properties.js";
|
|
5
6
|
import { getCollectionProperties, collectionGuestProperties, copyCollectionProperties } from "./collection-properties.js";
|
|
@@ -16,7 +17,7 @@ import { boxedDataProperties, boxedValue, createSandboxBox, isSandboxBox, native
|
|
|
16
17
|
import { getHostObjectKeys, getHostObjectMember, hasHostObjectMember, measureHostObjectData, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
|
|
17
18
|
import { types as nodeTypes } from "node:util";
|
|
18
19
|
import { CompileScope, RegexCompileGuard, regexCompiledData } from "./regex/compile-guard.js";
|
|
19
|
-
import { copyFloat32Storage, float32DataProperties, float32Storage, isFloat32Array } from "./float32.js";
|
|
20
|
+
import { copyFloat32Storage, float32DataProperties, float32Properties, float32Storage, isFloat32Array } from "./float32.js";
|
|
20
21
|
import { SandboxError } from "./budget.js";
|
|
21
22
|
import { observeSandboxPromise, trackSandboxPromise } from "./promise-tracker.js";
|
|
22
23
|
import { promiseReplayContext } from "./promise-replay.js";
|
|
@@ -24,7 +25,7 @@ import { invokeCancelableClosure, readPromiseCancellation, registerPromiseCancel
|
|
|
24
25
|
import { parseRegex } from "./regex/parse.js";
|
|
25
26
|
import { assertSandboxDataDepth } from "../graph-depth.js";
|
|
26
27
|
import { sandboxErrorTypes } from "../error/shape.js";
|
|
27
|
-
import { getGuestFunctionProperties, getSandboxPrototype, hasGuestObjectState, hasManagedDescriptors, hasNullObjectPrototype, isGuestClosure, isIntrinsicFunction, registerGuestClosure, setSandboxPrototype } from "./object-model.js";
|
|
28
|
+
import { getGuestFunctionProperties, getSandboxPrototype, hasExplicitSandboxPrototype, hasGuestObjectState, hasManagedDescriptors, hasNullObjectPrototype, isGuestClosure, isIntrinsicFunction, registerGuestClosure, setSandboxPrototype } from "./object-model.js";
|
|
28
29
|
import { copySandboxArgumentProperties, createSandboxArguments, getSandboxArgumentEntries, isSandboxArguments } from "./arguments.js";
|
|
29
30
|
export { createSandboxArguments, isSandboxArguments } from "./arguments.js";
|
|
30
31
|
export { isSandboxMap, isSandboxSet } from "./collection-brands.js";
|
|
@@ -404,9 +405,17 @@ export function measureSandboxData(values, options = {}) {
|
|
|
404
405
|
seen.add(storage.buffer);
|
|
405
406
|
usage += storage.byteLength;
|
|
406
407
|
}
|
|
407
|
-
for (const [key, descriptor] of
|
|
408
|
-
usage +=
|
|
409
|
-
|
|
408
|
+
for (const [key, descriptor] of float32Properties(value)) {
|
|
409
|
+
usage += 1;
|
|
410
|
+
if (typeof key === "string")
|
|
411
|
+
usage += key.length;
|
|
412
|
+
else
|
|
413
|
+
visit(key, depth + 1);
|
|
414
|
+
if ("value" in descriptor)
|
|
415
|
+
visit(descriptor.value, depth + 1);
|
|
416
|
+
else
|
|
417
|
+
for (const closure of retainedAccessorClosures(descriptor))
|
|
418
|
+
visit(closure, depth + 1);
|
|
410
419
|
}
|
|
411
420
|
return;
|
|
412
421
|
}
|
|
@@ -578,7 +587,7 @@ export function measureSandboxData(values, options = {}) {
|
|
|
578
587
|
if (descriptor !== undefined)
|
|
579
588
|
descriptors.push([key, descriptor]);
|
|
580
589
|
}
|
|
581
|
-
const includeNonEnumerable = isSandboxDate(value) || hasManagedDescriptors(value);
|
|
590
|
+
const includeNonEnumerable = isSandboxDate(value) || sandboxErrorTypes.has(value) || hasManagedDescriptors(value);
|
|
582
591
|
for (const [key, descriptor] of descriptors) {
|
|
583
592
|
if (!descriptor.enumerable && !includeNonEnumerable)
|
|
584
593
|
continue;
|
|
@@ -908,6 +917,50 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
|
|
|
908
917
|
}
|
|
909
918
|
if (nodeTypes.isProxy(value))
|
|
910
919
|
throw new TypeError("Unsupported proxy sandbox value.");
|
|
920
|
+
if (sandboxErrorTypes.has(value) && hasExplicitSandboxPrototype(value)) {
|
|
921
|
+
const prototype = getSandboxPrototype(value);
|
|
922
|
+
let nativePrototype = null;
|
|
923
|
+
if (prototype !== null) {
|
|
924
|
+
const identity = getIntrinsicIdentity(prototype);
|
|
925
|
+
const nativePrototypes = {
|
|
926
|
+
Error: Error.prototype, TypeError: TypeError.prototype, RangeError: RangeError.prototype,
|
|
927
|
+
ReferenceError: ReferenceError.prototype, SyntaxError: SyntaxError.prototype,
|
|
928
|
+
URIError: URIError.prototype, EvalError: EvalError.prototype, AggregateError: AggregateError.prototype
|
|
929
|
+
};
|
|
930
|
+
const path = identity === undefined ? [] : JSON.parse(identity);
|
|
931
|
+
if (path.length !== 2 || typeof path[0] !== "string" || path[1] !== "prototype" || !Object.hasOwn(nativePrototypes, path[0]))
|
|
932
|
+
throw new TypeError("Custom Error prototype links cannot be copied as data.");
|
|
933
|
+
nativePrototype = nativePrototypes[path[0]];
|
|
934
|
+
let current = prototype;
|
|
935
|
+
let prototypeDepth = 0;
|
|
936
|
+
while (current !== null) {
|
|
937
|
+
assertSandboxDataDepth(++prototypeDepth);
|
|
938
|
+
const objectPrototype = getIntrinsicIdentity(current) === '["Object","prototype"]';
|
|
939
|
+
const owner = objectPrototype ? Object.getOwnPropertyDescriptor(current, "constructor")?.value : current;
|
|
940
|
+
if (owner === null || typeof owner !== "object" ||
|
|
941
|
+
(objectPrototype && getIntrinsicIdentity(owner) !== '["Object"]') || hasGuestObjectState(owner))
|
|
942
|
+
throw new TypeError("Modified Error prototype links cannot be copied as data.");
|
|
943
|
+
current = getSandboxPrototype(current);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
const existing = state.seen.get(value);
|
|
947
|
+
if (existing !== undefined)
|
|
948
|
+
return existing;
|
|
949
|
+
const descriptors = Reflect.ownKeys(value).filter(key => typeof key !== "symbol" || !internalSymbols.has(key))
|
|
950
|
+
.map(key => [key, Object.getOwnPropertyDescriptor(value, key)]);
|
|
951
|
+
if (descriptors.some(([, descriptor]) => !("value" in descriptor)))
|
|
952
|
+
throw new TypeError("Error accessor properties cannot be copied as data.");
|
|
953
|
+
const copy = new Error();
|
|
954
|
+
delete copy.stack;
|
|
955
|
+
Object.setPrototypeOf(copy, nativePrototype);
|
|
956
|
+
state.seen.set(value, copy);
|
|
957
|
+
for (const [key, descriptor] of descriptors)
|
|
958
|
+
Object.defineProperty(copy, key, { ...descriptor,
|
|
959
|
+
value: copyFromSandbox(descriptor.value, state, joinPath(path, key), options, depth + 1) });
|
|
960
|
+
if (!Object.isExtensible(value))
|
|
961
|
+
Object.preventExtensions(copy);
|
|
962
|
+
return copy;
|
|
963
|
+
}
|
|
911
964
|
if (!isSandboxClosure(value) && hasGuestObjectState(value)) {
|
|
912
965
|
throw new TypeError("Guest prototype links and custom descriptors cannot be copied as data.");
|
|
913
966
|
}
|
|
@@ -2709,6 +2709,7 @@ class Parser {
|
|
|
2709
2709
|
return undefined;
|
|
2710
2710
|
}
|
|
2711
2711
|
findTopLevelForIterationOperator(startIndex) {
|
|
2712
|
+
let operator;
|
|
2712
2713
|
let depth = 0;
|
|
2713
2714
|
let previousToken;
|
|
2714
2715
|
for (let index = startIndex; index < this.tokens.length; index += 1) {
|
|
@@ -2719,7 +2720,7 @@ class Parser {
|
|
|
2719
2720
|
}
|
|
2720
2721
|
else if (token.value === ")" || token.value === "]" || token.value === "}") {
|
|
2721
2722
|
if (depth === 0 && token.value === ")") {
|
|
2722
|
-
return
|
|
2723
|
+
return operator;
|
|
2723
2724
|
}
|
|
2724
2725
|
depth -= 1;
|
|
2725
2726
|
}
|
|
@@ -2730,9 +2731,12 @@ class Parser {
|
|
|
2730
2731
|
if (depth === 0 &&
|
|
2731
2732
|
token.type === "keyword" &&
|
|
2732
2733
|
(token.value === "of" || token.value === "in") &&
|
|
2734
|
+
index !== startIndex &&
|
|
2735
|
+
!(token.value === "of" && index === startIndex + 1 &&
|
|
2736
|
+
["const", "let", "var"].includes(previousToken?.value ?? "")) &&
|
|
2733
2737
|
previousToken?.value !== "." &&
|
|
2734
2738
|
previousToken?.value !== "?.") {
|
|
2735
|
-
|
|
2739
|
+
operator ??= token;
|
|
2736
2740
|
}
|
|
2737
2741
|
previousToken = token;
|
|
2738
2742
|
}
|
|
@@ -3752,7 +3756,8 @@ function isLiteralPropertyKey(token) {
|
|
|
3752
3756
|
return token.type === "numeric" || token.type === "string";
|
|
3753
3757
|
}
|
|
3754
3758
|
function isIdentifierLikeToken(token) {
|
|
3755
|
-
return token.type === "identifier" ||
|
|
3759
|
+
return token.type === "identifier" ||
|
|
3760
|
+
(token.type === "keyword" && (token.value === "async" || token.value === "of"));
|
|
3756
3761
|
}
|
|
3757
3762
|
function isNewToken(token) {
|
|
3758
3763
|
return token.value === "new";
|
|
@@ -358,7 +358,7 @@ class Lexer {
|
|
|
358
358
|
}
|
|
359
359
|
if (char === "/" &&
|
|
360
360
|
this.peekChar(1) !== "=" &&
|
|
361
|
-
shouldRejectRegexLiteral(tokens[tokens.length - 1], lastClosedControlParenthesis)) {
|
|
361
|
+
shouldRejectRegexLiteral(tokens[tokens.length - 1], lastClosedControlParenthesis, tokens)) {
|
|
362
362
|
if (!this.options.allowRegexLiterals) {
|
|
363
363
|
this.syntaxError("Regular expression literals are not supported", this.position());
|
|
364
364
|
}
|
|
@@ -633,7 +633,7 @@ class Lexer {
|
|
|
633
633
|
readSlashOrPunctuator(start) {
|
|
634
634
|
if (this.currentChar() === "/" &&
|
|
635
635
|
this.peekChar(1) !== "=" &&
|
|
636
|
-
shouldRejectRegexLiteral(this.lastSignificantToken(), this.lastClosedControlParenthesis)) {
|
|
636
|
+
shouldRejectRegexLiteral(this.lastSignificantToken(), this.lastClosedControlParenthesis, this.tokens)) {
|
|
637
637
|
if (!this.options.allowRegexLiterals) {
|
|
638
638
|
this.syntaxError("Regular expression literals are not supported", start);
|
|
639
639
|
}
|
|
@@ -919,7 +919,7 @@ function matchPunctuator(source, index) {
|
|
|
919
919
|
return PUNCTUATORS.find((punctuator) => source.startsWith(punctuator, index) &&
|
|
920
920
|
(punctuator !== "?." || !isDecimalDigit(source[index + 2] ?? "")));
|
|
921
921
|
}
|
|
922
|
-
function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis) {
|
|
922
|
+
function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis, tokens) {
|
|
923
923
|
if (previousToken === undefined) {
|
|
924
924
|
return true;
|
|
925
925
|
}
|
|
@@ -930,6 +930,8 @@ function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis) {
|
|
|
930
930
|
return false;
|
|
931
931
|
}
|
|
932
932
|
if (previousToken.type === "keyword") {
|
|
933
|
+
if (previousToken.value === "of")
|
|
934
|
+
return endsWithForOfSeparator(tokens);
|
|
933
935
|
return !EXPRESSION_ENDING_KEYWORDS.has(previousToken.value);
|
|
934
936
|
}
|
|
935
937
|
if (previousToken.value === ")") {
|
|
@@ -937,6 +939,46 @@ function shouldRejectRegexLiteral(previousToken, lastClosedControlParenthesis) {
|
|
|
937
939
|
}
|
|
938
940
|
return !isExpressionEndingPunctuator(previousToken.value);
|
|
939
941
|
}
|
|
942
|
+
function endsWithForOfSeparator(tokens) {
|
|
943
|
+
let depth = 0;
|
|
944
|
+
let start = -1;
|
|
945
|
+
for (let index = tokens.length - 2; index >= 0; index--) {
|
|
946
|
+
const token = tokens[index];
|
|
947
|
+
if (token.type !== "punctuator")
|
|
948
|
+
continue;
|
|
949
|
+
if ([")", "]", "}"].includes(token.value))
|
|
950
|
+
depth++;
|
|
951
|
+
else if (["(", "[", "{"].includes(token.value)) {
|
|
952
|
+
if (depth > 0) {
|
|
953
|
+
depth--;
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
if (token.value === "(" && (tokens[index - 1]?.value === "for" ||
|
|
957
|
+
(tokens[index - 1]?.value === "await" && tokens[index - 2]?.value === "for")))
|
|
958
|
+
start = index + 1;
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
else if (depth === 0 && token.value === ";")
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
if (start < 0)
|
|
965
|
+
return false;
|
|
966
|
+
depth = 0;
|
|
967
|
+
for (let index = start; index < tokens.length; index++) {
|
|
968
|
+
const token = tokens[index];
|
|
969
|
+
if (token.type === "punctuator") {
|
|
970
|
+
if (["(", "[", "{"].includes(token.value))
|
|
971
|
+
depth++;
|
|
972
|
+
else if ([")", "]", "}"].includes(token.value))
|
|
973
|
+
depth--;
|
|
974
|
+
}
|
|
975
|
+
if (depth === 0 && token.type === "keyword" && token.value === "of" &&
|
|
976
|
+
index !== start && tokens[index - 1]?.value !== "." && tokens[index - 1]?.value !== "?." &&
|
|
977
|
+
!(index === start + 1 && ["const", "let", "var"].includes(tokens[start].value)))
|
|
978
|
+
return index === tokens.length - 1;
|
|
979
|
+
}
|
|
980
|
+
return false;
|
|
981
|
+
}
|
|
940
982
|
function updateGroupingState(groupingStack, previousToken, punctuator) {
|
|
941
983
|
if (punctuator === "(") {
|
|
942
984
|
groupingStack.push({
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { GuestObjectState } from "./guest-heap.js";
|
|
2
|
+
export declare function captureFloat32State<T>(value: Float32Array, encode: (value: unknown) => T): GuestObjectState<T>;
|
|
3
|
+
export declare function restoreFloat32Properties<T>(value: Float32Array, state: GuestObjectState<T>, decode: (value: T) => unknown): void;
|
|
1
4
|
export type Float32Data<TReference> = {
|
|
2
5
|
kind: "float32array";
|
|
3
6
|
byteOffset: number;
|
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
import { float32Storage, isFloat32Array } from "../interp/float32.js";
|
|
1
|
+
import { float32Properties, float32Storage, isFloat32Array, isFloat32Index } from "../interp/float32.js";
|
|
2
|
+
import { getSandboxPrototype, hasExplicitSandboxPrototype } from "../interp/object-model.js";
|
|
3
|
+
import { restorePropertyDescriptors, serializePropertyDescriptors } from "./property-descriptors.js";
|
|
4
|
+
export function captureFloat32State(value, encode) {
|
|
5
|
+
const metadata = Object.defineProperties(Object.create(null), Object.fromEntries(float32Properties(value)));
|
|
6
|
+
if (!Object.isExtensible(value))
|
|
7
|
+
Object.preventExtensions(metadata);
|
|
8
|
+
return { properties: serializePropertyDescriptors(metadata, encode),
|
|
9
|
+
...(hasExplicitSandboxPrototype(value) ? { prototype: encode(getSandboxPrototype(value)) } : {}) };
|
|
10
|
+
}
|
|
11
|
+
export function restoreFloat32Properties(value, state, decode) {
|
|
12
|
+
const metadata = Object.create(null);
|
|
13
|
+
restorePropertyDescriptors(metadata, state.properties, decode);
|
|
14
|
+
const descriptors = Object.getOwnPropertyDescriptors(metadata);
|
|
15
|
+
if (Object.keys(descriptors).some(isFloat32Index))
|
|
16
|
+
throw new TypeError("Float32Array metadata cannot replace numeric storage.");
|
|
17
|
+
Object.defineProperties(value, descriptors);
|
|
18
|
+
if (!Object.isExtensible(metadata))
|
|
19
|
+
Object.preventExtensions(value);
|
|
20
|
+
}
|
|
2
21
|
export function encodeFloat32Storage(value, id, buffers, reference) {
|
|
3
22
|
const storage = float32Storage(value);
|
|
4
23
|
const existing = buffers.get(storage.buffer);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Budget } from "../interp/budget.js";
|
|
2
|
+
import { sandboxErrorNames } from "../error/shape.js";
|
|
2
3
|
import { createRawJson } from "../interp/raw-json.js";
|
|
3
4
|
import { createBuiltinBindings } from "../interp/globals.js";
|
|
4
5
|
import { getIntrinsicIdentity, listIntrinsicIdentities, resolveIntrinsicIdentity } from "../interp/intrinsics.js";
|
|
@@ -146,7 +147,9 @@ export function validateGuestHeapNode(raw, heap, maxArrayLength = 0xffffffff) {
|
|
|
146
147
|
state(node.state);
|
|
147
148
|
}
|
|
148
149
|
else if (node.kind === "guest-object" || node.kind === "guest-array") {
|
|
149
|
-
fields(node, ["kind", "state"], node.kind === "guest-array" ? ["templateNodeId", "templateOwner"] : []);
|
|
150
|
+
fields(node, ["kind", "state"], node.kind === "guest-array" ? ["templateNodeId", "templateOwner"] : ["errorType"]);
|
|
151
|
+
if (Object.hasOwn(node, "errorType") && !sandboxErrorNames.includes(node.errorType))
|
|
152
|
+
throw new TypeError("Invalid guest error type.");
|
|
150
153
|
if (Object.hasOwn(node, "templateOwner"))
|
|
151
154
|
reference(node.templateOwner, ["guest-array"]);
|
|
152
155
|
if (Object.hasOwn(node, "templateNodeId") && integer(node.templateNodeId) < 1)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SandboxErrorName } from "../error/shape.js";
|
|
1
2
|
import { type ScopeFrame } from "../interp/scope.js";
|
|
2
3
|
import { type PropertyDescriptorData } from "./property-descriptors.js";
|
|
3
4
|
import type { CompletionResult } from "../interp/exceptions.js";
|
|
@@ -73,6 +74,7 @@ export type GuestHeapNode<T> = {
|
|
|
73
74
|
} | {
|
|
74
75
|
kind: "guest-object";
|
|
75
76
|
state: GuestObjectState<T>;
|
|
77
|
+
errorType?: SandboxErrorName;
|
|
76
78
|
} | {
|
|
77
79
|
kind: "guest-array";
|
|
78
80
|
state: GuestObjectState<T>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getClosureOrigin, getGeneratorOrigin } from "../interp/closure-origin.js";
|
|
2
2
|
import { boundFunctionStates } from "../interp/bound-function-state.js";
|
|
3
|
+
import { sandboxErrorTypes } from "../error/shape.js";
|
|
3
4
|
import { getGeneratorProperties } from "../interp/generator-properties.js";
|
|
4
5
|
import { getIntrinsicIdentity } from "../interp/intrinsics.js";
|
|
5
6
|
import { getSandboxPrototype, hasExplicitSandboxPrototype, hasGuestObjectState, isGuestClosure, materializeFunctionProperties } from "../interp/object-model.js";
|
|
@@ -151,8 +152,11 @@ export function captureGuestHeapNode(value, encode) {
|
|
|
151
152
|
isSandboxRegExpIterator(value))
|
|
152
153
|
return undefined;
|
|
153
154
|
const prototype = Object.getPrototypeOf(value);
|
|
154
|
-
if ((prototype === null || prototype === Object.prototype) && hasGuestObjectState(value))
|
|
155
|
-
|
|
155
|
+
if ((prototype === null || prototype === Object.prototype) && hasGuestObjectState(value)) {
|
|
156
|
+
const errorType = sandboxErrorTypes.get(value);
|
|
157
|
+
return { kind: "guest-object", state: captureObjectState(value, encode),
|
|
158
|
+
...(errorType === undefined ? {} : { errorType }) };
|
|
159
|
+
}
|
|
156
160
|
return undefined;
|
|
157
161
|
}
|
|
158
162
|
if (origin.node.nodeId === undefined)
|
|
@@ -17,12 +17,12 @@ import { awaitSandboxValue } from "../interp/cancel.js";
|
|
|
17
17
|
import { runAsyncPrefix } from "../interp/jobs.js";
|
|
18
18
|
import { toPropertyKey } from "../interp/property-key.js";
|
|
19
19
|
import { CompileScope } from "../interp/regex/compile-guard.js";
|
|
20
|
-
import { decodeFloat32Storage } from "./float32array.js";
|
|
20
|
+
import { decodeFloat32Storage, restoreFloat32Properties } from "./float32array.js";
|
|
21
21
|
import { restoreDateTime } from "../interp/date.js";
|
|
22
22
|
import { createRawJson } from "../interp/raw-json.js";
|
|
23
23
|
import { createSandboxBox } from "../interp/boxed.js";
|
|
24
24
|
import { restoreBoxedProperties } from "./boxed.js";
|
|
25
|
-
import { sandboxErrorTypes } from "../error/shape.js";
|
|
25
|
+
import { sandboxErrorNames, sandboxErrorTypes } from "../error/shape.js";
|
|
26
26
|
import { SnapshotMismatchError } from "../restore.js";
|
|
27
27
|
import { evaluateNode, Scope, setSandboxProperty } from "../interp/interpreter.js";
|
|
28
28
|
import { getGuestFunctionProperties, getGuestFunctionProperty, getSandboxDataProperty, isGuestClosure, materializeFunctionProperties, registerGuestClosure, setSandboxPrototype } from "../interp/object-model.js";
|
|
@@ -398,7 +398,24 @@ function initializeIntrinsicRealm(state) {
|
|
|
398
398
|
const method = state.heap[String(value.id)];
|
|
399
399
|
return method?.kind === "intrinsic" && method.id === '["%FunctionPrototype%",{"symbol":"hasInstance"}]';
|
|
400
400
|
});
|
|
401
|
-
|
|
401
|
+
const errorConstructors = Object.values(state.heap).filter(node => node.kind === "intrinsic" && sandboxErrorNames.some(name => node.id === JSON.stringify([name])));
|
|
402
|
+
const errorPrototypes = errorConstructors.every(node => node.kind === "intrinsic" &&
|
|
403
|
+
node.state?.properties.properties.some(([key, descriptor]) => {
|
|
404
|
+
if (key !== "prototype" || descriptor.kind !== "data" || descriptor.writable ||
|
|
405
|
+
descriptor.enumerable || descriptor.configurable)
|
|
406
|
+
return false;
|
|
407
|
+
const value = descriptor.value;
|
|
408
|
+
if (value === null || typeof value !== "object" || !("kind" in value) || value.kind !== "ref")
|
|
409
|
+
return false;
|
|
410
|
+
const prototype = state.heap[String(value.id)];
|
|
411
|
+
return prototype?.kind === "intrinsic" &&
|
|
412
|
+
prototype.id === JSON.stringify([...JSON.parse(node.id), "prototype"]);
|
|
413
|
+
}));
|
|
414
|
+
const float32 = Object.values(state.heap).find(node => node.kind === "intrinsic" && node.id === '["Float32Array"]');
|
|
415
|
+
const float32Prototypes = float32?.kind !== "intrinsic" ||
|
|
416
|
+
float32.state?.properties.properties.some(([key, descriptor]) => key === "prototype" && descriptor.kind === "data" &&
|
|
417
|
+
!descriptor.writable && !descriptor.enumerable && !descriptor.configurable) === true;
|
|
418
|
+
createBuiltinBindings({ budget: state.budget, compileOwner: state.compilation.owner, functionHasInstance, errorPrototypes, float32Prototypes });
|
|
402
419
|
state.intrinsicsInitialized = true;
|
|
403
420
|
}
|
|
404
421
|
function restoreHeapValue(id, state) {
|
|
@@ -440,8 +457,19 @@ function restoreHeapValue(id, state) {
|
|
|
440
457
|
return value;
|
|
441
458
|
}
|
|
442
459
|
if (serialized.kind === "float32array") {
|
|
460
|
+
if (serialized.state !== undefined)
|
|
461
|
+
initializeIntrinsicRealm(state);
|
|
443
462
|
const value = decodeFloat32Storage(serialized, (reference) => deserializeValue(reference, state));
|
|
444
463
|
state.heapValueById.set(id, value);
|
|
464
|
+
if (serialized.state !== undefined) {
|
|
465
|
+
const objectState = serialized.state;
|
|
466
|
+
state.initializeIterators.push(() => {
|
|
467
|
+
if (objectState.prototype !== undefined)
|
|
468
|
+
setSandboxPrototype(value, deserializeValue(objectState.prototype, state), state.budget);
|
|
469
|
+
restoreFloat32Properties(value, objectState, entry => deserializeValue(entry, state));
|
|
470
|
+
});
|
|
471
|
+
return value;
|
|
472
|
+
}
|
|
445
473
|
for (const [key, entry] of Object.entries(serialized.entries)) {
|
|
446
474
|
Object.defineProperty(value, key, {
|
|
447
475
|
value: deserializeValue(entry, state),
|
|
@@ -653,6 +681,8 @@ function restoreHeapValue(id, state) {
|
|
|
653
681
|
throw new TypeError(`Missing restored function properties for ${serialized.kind === "intrinsic" ? serialized.id : serialized.kind}.`);
|
|
654
682
|
if (objectState.prototype !== undefined)
|
|
655
683
|
setSandboxPrototype(value, deserializeValue(objectState.prototype, state), state.budget);
|
|
684
|
+
if (serialized.kind === "guest-object" && serialized.errorType !== undefined)
|
|
685
|
+
sandboxErrorTypes.set(value, serialized.errorType);
|
|
656
686
|
restorePropertyDescriptors(target, objectState.properties, entry => deserializeValue(entry, state));
|
|
657
687
|
if (serialized.kind === "guest-array" && serialized.templateNodeId !== undefined) {
|
|
658
688
|
const node = state.nodeById.get(serialized.templateNodeId);
|
|
@@ -4,7 +4,7 @@ import { type SerializedSymbol, type SerializedSymbolProperty } from "./symbols.
|
|
|
4
4
|
import { type CollectionIterationMethod, type SandboxCollectionIterator } from "../interp/collection-iterator.js";
|
|
5
5
|
import { type SandboxRegExpIterator } from "../interp/regexp-iterator.js";
|
|
6
6
|
import { type SandboxErrorName } from "../error/shape.js";
|
|
7
|
-
import { type GuestHeapNode } from "./guest-heap.js";
|
|
7
|
+
import { type GuestHeapNode, type GuestObjectState } from "./guest-heap.js";
|
|
8
8
|
import { type SerializedArguments } from "./arguments.js";
|
|
9
9
|
import { type SerializedArray } from "./arrays.js";
|
|
10
10
|
import { type Float32Data } from "./float32array.js";
|
|
@@ -75,6 +75,7 @@ export type SerializedHeapValue = GuestHeapNode<SerializedSnapshotValue> | {
|
|
|
75
75
|
entries: Record<string, SerializedSnapshotValue>;
|
|
76
76
|
} | SerializedDate<SerializedSnapshotValue> | (Float32Data<SerializedReferenceValue> & {
|
|
77
77
|
entries: Record<string, SerializedSnapshotValue>;
|
|
78
|
+
state?: GuestObjectState<SerializedSnapshotValue>;
|
|
78
79
|
}) | SerializedArguments<SerializedSnapshotValue> | SerializedArray<SerializedSnapshotValue> | {
|
|
79
80
|
kind: "object";
|
|
80
81
|
sandboxNullPrototype?: true;
|
|
@@ -11,8 +11,8 @@ import { captureGuestHeapNode } from "./guest-heap.js";
|
|
|
11
11
|
import { getGeneratorOrigin } from "../interp/closure-origin.js";
|
|
12
12
|
import { serializeArguments } from "./arguments.js";
|
|
13
13
|
import { requiresArrayEntries, serializeArray } from "./arrays.js";
|
|
14
|
-
import {
|
|
15
|
-
import { encodeFloat32Storage } from "./float32array.js";
|
|
14
|
+
import { isFloat32Array } from "../interp/float32.js";
|
|
15
|
+
import { captureFloat32State, encodeFloat32Storage } from "./float32array.js";
|
|
16
16
|
import { dateDataProperties, isSandboxDate } from "../interp/date.js";
|
|
17
17
|
import { serializeDate } from "./date-properties.js";
|
|
18
18
|
import { boxedDataProperties, isSandboxBox } from "../interp/boxed.js";
|
|
@@ -104,7 +104,7 @@ function serializeValue(value, path, state) {
|
|
|
104
104
|
}
|
|
105
105
|
return { kind: "ref", id };
|
|
106
106
|
}
|
|
107
|
-
if (typeof value === "object" && value !== null && hasGuestObjectState(value) && !isSandboxMap(value) && !isSandboxSet(value)) {
|
|
107
|
+
if (typeof value === "object" && value !== null && hasGuestObjectState(value) && !isSandboxMap(value) && !isSandboxSet(value) && !isFloat32Array(value)) {
|
|
108
108
|
throw new TypeError("Guest function properties and prototype links cannot be serialized.");
|
|
109
109
|
}
|
|
110
110
|
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
@@ -265,10 +265,8 @@ function serializeHeapReference(value, path, state) {
|
|
|
265
265
|
kind: "ref",
|
|
266
266
|
id
|
|
267
267
|
}));
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
for (const [key, descriptor] of float32DataProperties(value))
|
|
271
|
-
entries[key] = serializeValue(descriptor.value, `${path}.${key}`, state);
|
|
268
|
+
state.heap[String(id)] = { ...storage, entries: {},
|
|
269
|
+
state: captureFloat32State(value, entry => serializeValue(entry, `${path}.<typed-array>`, state)) };
|
|
272
270
|
}
|
|
273
271
|
else if (isSandboxArguments(value)) {
|
|
274
272
|
state.heap[String(id)] = serializeArguments(value, (entry, key) => serializeValue(entry, `${path}.${key}`, state));
|
|
@@ -431,9 +429,12 @@ function collectContainerStats(value, stats, ancestors, guestValues, depth = 0)
|
|
|
431
429
|
stat.expanded = true;
|
|
432
430
|
ancestors.add(value);
|
|
433
431
|
const guestEntries = [];
|
|
434
|
-
const guest =
|
|
432
|
+
const guest = isFloat32Array(value)
|
|
433
|
+
? { kind: "float32array", state: captureFloat32State(value, entry => { guestEntries.push(entry); return null; }) }
|
|
434
|
+
: captureGuestHeapNode(value, entry => { guestEntries.push(entry); return null; });
|
|
435
435
|
if (guest !== undefined) {
|
|
436
|
-
|
|
436
|
+
if (!isFloat32Array(value))
|
|
437
|
+
guestValues.add(value);
|
|
437
438
|
for (const entry of guestEntries) {
|
|
438
439
|
collectContainerStats(entry, stats, ancestors, guestValues, depth + 1);
|
|
439
440
|
if (entry !== null && typeof entry === "object") {
|
|
@@ -120,6 +120,11 @@ function validateDumpHeap(root, state) {
|
|
|
120
120
|
if (entry.kind === "float32array") {
|
|
121
121
|
validateFloat32Storage(entry);
|
|
122
122
|
requireRecord(entry.entries, `${path}.entries`);
|
|
123
|
+
if (Object.hasOwn(entry, "state")) {
|
|
124
|
+
if (Object.keys(entry.entries).length !== 0)
|
|
125
|
+
fail("invalidValue", path, "ambiguous Float32Array property state");
|
|
126
|
+
validateGuestHeapNode({ kind: "guest-object", state: entry.state }, heap, state.limits.maxEntries);
|
|
127
|
+
}
|
|
123
128
|
continue;
|
|
124
129
|
}
|
|
125
130
|
if (entry.kind === "arguments") {
|
|
@@ -551,6 +556,11 @@ function validateHeapValue(value, path, state, heap) {
|
|
|
551
556
|
if (record.kind === "float32array") {
|
|
552
557
|
validateFloat32Storage(record);
|
|
553
558
|
requireRecord(record.entries, `${path}.entries`);
|
|
559
|
+
if (Object.hasOwn(record, "state")) {
|
|
560
|
+
if (Object.keys(record.entries).length !== 0)
|
|
561
|
+
fail("invalidValue", path, "ambiguous Float32Array property state");
|
|
562
|
+
validateGuestHeapNode({ kind: "guest-object", state: record.state }, heap, state.limits.maxEntries);
|
|
563
|
+
}
|
|
554
564
|
}
|
|
555
565
|
if (record.kind === "map") {
|
|
556
566
|
const entries = requireArray(record.entries, `${path}.entries`, state);
|
|
@@ -706,7 +716,7 @@ function validateArrayHeap(record, path, state) {
|
|
|
706
716
|
function validateErrorType(record, path) {
|
|
707
717
|
if (!Object.hasOwn(record, "errorType"))
|
|
708
718
|
return;
|
|
709
|
-
if (record.kind !== "object" ||
|
|
719
|
+
if ((record.kind !== "object" && record.kind !== "guest-object") ||
|
|
710
720
|
!sandboxErrorNames.includes(record.errorType)) {
|
|
711
721
|
fail("invalidValue", `${path}.errorType`, "invalid error metadata");
|
|
712
722
|
}
|