poe-code 14.0.79 → 14.0.81
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 +772 -341
- 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-B3AL4KJ3.js → chunk-2LNBLFJ3.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-BGSPSHLP.js → chunk-ZSYBRZU6.js} +644 -292
- package/packages/safe-js/dist/chunks/chunk-ZSYBRZU6.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/graph-depth.js +2 -1
- package/packages/safe-js/dist/index.js +2 -2
- package/packages/safe-js/dist/interp/async.d.ts +1 -1
- package/packages/safe-js/dist/interp/async.js +65 -43
- package/packages/safe-js/dist/interp/bound-function-state.d.ts +7 -0
- package/packages/safe-js/dist/interp/bound-function-state.js +1 -0
- package/packages/safe-js/dist/interp/bound-function.d.ts +4 -0
- package/packages/safe-js/dist/interp/bound-function.js +18 -0
- package/packages/safe-js/dist/interp/generator-properties.d.ts +3 -0
- package/packages/safe-js/dist/interp/generator-properties.js +9 -0
- package/packages/safe-js/dist/interp/generator-prototypes.d.ts +6 -0
- package/packages/safe-js/dist/interp/generator-prototypes.js +1 -0
- package/packages/safe-js/dist/interp/globals/function.d.ts +2 -0
- package/packages/safe-js/dist/interp/globals/function.js +32 -0
- package/packages/safe-js/dist/interp/globals/generator.d.ts +2 -0
- package/packages/safe-js/dist/interp/globals/generator.js +51 -0
- package/packages/safe-js/dist/interp/globals/object-array.js +28 -7
- package/packages/safe-js/dist/interp/globals/object.js +2 -1
- package/packages/safe-js/dist/interp/globals.d.ts +1 -0
- package/packages/safe-js/dist/interp/globals.js +4 -0
- package/packages/safe-js/dist/interp/instanceof.d.ts +4 -0
- package/packages/safe-js/dist/interp/instanceof.js +58 -0
- package/packages/safe-js/dist/interp/interpreter.js +16 -47
- package/packages/safe-js/dist/interp/iteration.js +76 -5
- package/packages/safe-js/dist/interp/methods/function.d.ts +5 -2
- package/packages/safe-js/dist/interp/methods/function.js +55 -42
- package/packages/safe-js/dist/interp/methods/generator.d.ts +4 -1
- package/packages/safe-js/dist/interp/methods/generator.js +12 -6
- package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
- package/packages/safe-js/dist/interp/object-model.js +69 -17
- package/packages/safe-js/dist/interp/string-coercion.js +3 -2
- package/packages/safe-js/dist/interp/values.js +21 -3
- package/packages/safe-js/dist/snapshot/guest-heap-validation.js +27 -3
- package/packages/safe-js/dist/snapshot/guest-heap.d.ts +9 -0
- package/packages/safe-js/dist/snapshot/guest-heap.js +11 -0
- package/packages/safe-js/dist/snapshot/restore.js +61 -7
- package/packages/safe-js/dist/chunks/chunk-BGSPSHLP.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-B3AL4KJ3.js.map → chunk-2LNBLFJ3.js.map} +0 -0
|
@@ -29,17 +29,18 @@ import { getPromiseMember } from "./promise.js";
|
|
|
29
29
|
import { acquireSandboxIterator, closeIterator, readIteratorResult, restoreSandboxIterator } from "./iteration.js";
|
|
30
30
|
import { assertCollectionMutable } from "./running-state.js";
|
|
31
31
|
import { getGeneratorMember } from "./methods/generator.js";
|
|
32
|
+
import { getGeneratorProperties } from "./generator-properties.js";
|
|
32
33
|
import { getRegexMember, setRegexMember } from "./methods/regex.js";
|
|
33
34
|
import { bindPattern } from "./patterns.js";
|
|
34
35
|
import { callStringMethod, getStringMember, isStringMethodName, validateStringMethodArguments } from "./methods/string.js";
|
|
35
36
|
import { callSetMethod, getSetMember, isSetMethodName } from "./methods/set.js";
|
|
36
|
-
import {
|
|
37
|
+
import { evaluateInstanceof } from "./instanceof.js";
|
|
37
38
|
import { hasOwnSandboxProperty } from "./globals/object.js";
|
|
38
39
|
import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
|
|
39
40
|
import { getCollectionIteratorMember } from "./methods/collection-iterator.js";
|
|
40
41
|
import { isSandboxRegExpIterator, regexpIteratorState } from "./regexp-iterator.js";
|
|
41
42
|
import { getRegExpIteratorMember } from "./methods/regexp-iterator.js";
|
|
42
|
-
import { getFloat32Member,
|
|
43
|
+
import { getFloat32Member, setFloat32Member } from "./globals/float32array.js";
|
|
43
44
|
import { isFloat32Array } from "./float32.js";
|
|
44
45
|
import { dateString, dateTime, isSandboxDate } from "./date.js";
|
|
45
46
|
import { createSandboxRegex, allocateProducedSandboxValue, ownEnumerableSandboxKeys, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, getPromiseProperties, isSandboxRegex, getRegexProperties, getCollectionProperties, isSandboxSet, reconcileCompiledValues } from "./values.js";
|
|
@@ -1494,7 +1495,7 @@ function forInKeys(object, budget) {
|
|
|
1494
1495
|
if (depth > 0)
|
|
1495
1496
|
budget.visitNode();
|
|
1496
1497
|
assertSandboxDataDepth(depth++);
|
|
1497
|
-
const properties = isSandboxPromise(current) ? getPromiseProperties(current) : isGuestClosure(current) ? materializeFunctionProperties(current) : isSandboxClosure(current) ? current.properties ?? {} : isSandboxRegex(current) ? getRegexProperties(current) : isSandboxMap(current) || isSandboxSet(current) ? getCollectionProperties(current) : current;
|
|
1498
|
+
const properties = isSandboxGenerator(current) ? getGeneratorProperties(current) : isSandboxPromise(current) ? getPromiseProperties(current) : isGuestClosure(current) ? materializeFunctionProperties(current) : isSandboxClosure(current) ? current.properties ?? {} : isSandboxRegex(current) ? getRegexProperties(current) : isSandboxMap(current) || isSandboxSet(current) ? getCollectionProperties(current) : current;
|
|
1498
1499
|
for (const key of Object.getOwnPropertyNames(properties)) {
|
|
1499
1500
|
if (seen.has(key))
|
|
1500
1501
|
continue;
|
|
@@ -1515,7 +1516,7 @@ function hasForInProperty(object, key, budget) {
|
|
|
1515
1516
|
if (depth > 0)
|
|
1516
1517
|
budget.visitNode();
|
|
1517
1518
|
assertSandboxDataDepth(depth++);
|
|
1518
|
-
const properties = isSandboxPromise(current) ? getPromiseProperties(current) : isGuestClosure(current) ? materializeFunctionProperties(current) : isSandboxClosure(current) ? current.properties ?? {} : isSandboxRegex(current) ? getRegexProperties(current) : isSandboxMap(current) || isSandboxSet(current) ? getCollectionProperties(current) : current;
|
|
1519
|
+
const properties = isSandboxGenerator(current) ? getGeneratorProperties(current) : isSandboxPromise(current) ? getPromiseProperties(current) : isGuestClosure(current) ? materializeFunctionProperties(current) : isSandboxClosure(current) ? current.properties ?? {} : isSandboxRegex(current) ? getRegexProperties(current) : isSandboxMap(current) || isSandboxSet(current) ? getCollectionProperties(current) : current;
|
|
1519
1520
|
if (Object.hasOwn(properties, key))
|
|
1520
1521
|
return true;
|
|
1521
1522
|
}
|
|
@@ -2097,7 +2098,8 @@ function getPropertyValue(target, property, context, receiver = target) {
|
|
|
2097
2098
|
if (isSandboxCollectionIterator(target))
|
|
2098
2099
|
return getCollectionIteratorMember(target, property, context.budget);
|
|
2099
2100
|
if (isSandboxGenerator(target))
|
|
2100
|
-
return
|
|
2101
|
+
return hasExplicitSandboxPrototype(target)
|
|
2102
|
+
? undefined : getGeneratorMember(target, property, context.budget);
|
|
2101
2103
|
if (isSandboxClosure(target))
|
|
2102
2104
|
return getClosureMemberValue(target, property, context);
|
|
2103
2105
|
if (isSandboxPromise(target))
|
|
@@ -2384,7 +2386,7 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
2384
2386
|
return evaluatePrimitiveMemberCall(node, "Set", member.property, getSetMember(member.object, member.property, createSetMethodOptions(context)), context);
|
|
2385
2387
|
}
|
|
2386
2388
|
if (isSandboxGenerator(member.object)) {
|
|
2387
|
-
const memberValue =
|
|
2389
|
+
const memberValue = await getPropertyValue(member.object, member.property, context);
|
|
2388
2390
|
if (memberValue === undefined) {
|
|
2389
2391
|
throw new TypeError(`Generator#${String(member.property)} is not a supported method.`);
|
|
2390
2392
|
}
|
|
@@ -2602,48 +2604,11 @@ function applyBinaryOperator(node, left, right, context) {
|
|
|
2602
2604
|
case ">>>":
|
|
2603
2605
|
return toNumber(left) >>> toNumber(right);
|
|
2604
2606
|
case "instanceof":
|
|
2605
|
-
return evaluateInstanceof(left, right, context);
|
|
2607
|
+
return evaluateInstanceof(left, right, context.budget, createCoercionContext(context));
|
|
2606
2608
|
case "in":
|
|
2607
2609
|
return hasSandboxProperty(right, left, context);
|
|
2608
2610
|
}
|
|
2609
2611
|
}
|
|
2610
|
-
async function evaluateInstanceof(left, right, context) {
|
|
2611
|
-
while (true) {
|
|
2612
|
-
if (right === null || (typeof right !== "object" && typeof right !== "function"))
|
|
2613
|
-
throw new TypeError("Right-hand side of 'instanceof' must be an object.");
|
|
2614
|
-
const method = await getPropertyValue(right, Symbol.hasInstance, context);
|
|
2615
|
-
if (method !== undefined && method !== null) {
|
|
2616
|
-
if (!isSandboxClosure(method))
|
|
2617
|
-
throw new TypeError("Symbol.hasInstance must be callable.");
|
|
2618
|
-
return Boolean(await invokeSandboxClosure(method, [left], context, context.callStack, undefined, right));
|
|
2619
|
-
}
|
|
2620
|
-
if (!isSandboxClosure(right))
|
|
2621
|
-
throw new TypeError("Right-hand side of 'instanceof' is not a function.");
|
|
2622
|
-
if (right.boundTarget === undefined)
|
|
2623
|
-
break;
|
|
2624
|
-
context.budget.visitNode();
|
|
2625
|
-
right = right.boundTarget;
|
|
2626
|
-
}
|
|
2627
|
-
if (isFloat32ArrayConstructor(right))
|
|
2628
|
-
return isFloat32Array(left);
|
|
2629
|
-
if (isSandboxErrorConstructorInstance(left, right))
|
|
2630
|
-
return true;
|
|
2631
|
-
if (isGuestClosure(right)) {
|
|
2632
|
-
if (typeof left !== "object" || left === null)
|
|
2633
|
-
return false;
|
|
2634
|
-
const prototype = await getPropertyValue(right, "prototype", context);
|
|
2635
|
-
if (typeof prototype !== "object" || prototype === null)
|
|
2636
|
-
throw new TypeError("Function has a non-object prototype in instanceof check.");
|
|
2637
|
-
let depth = 0;
|
|
2638
|
-
for (let current = getSandboxPrototype(left, context.budget); current !== null; current = getSandboxPrototype(current, context.budget)) {
|
|
2639
|
-
context.budget.visitNode();
|
|
2640
|
-
assertSandboxDataDepth(depth++);
|
|
2641
|
-
if (current === prototype)
|
|
2642
|
-
return true;
|
|
2643
|
-
}
|
|
2644
|
-
}
|
|
2645
|
-
return false;
|
|
2646
|
-
}
|
|
2647
2612
|
export function createCoercionContext(context) {
|
|
2648
2613
|
return {
|
|
2649
2614
|
stack: context.callStack,
|
|
@@ -2662,7 +2627,7 @@ function hasSandboxProperty(value, key, context) {
|
|
|
2662
2627
|
return typeof key === "symbol" ? false : hasHostObjectMember(current, String(key));
|
|
2663
2628
|
if (hasOwnSandboxProperty(current, key, false))
|
|
2664
2629
|
return true;
|
|
2665
|
-
if (!isSandboxDate(current) && !isSandboxRegex(current) && !isSandboxMap(current) && !isSandboxSet(current) && !((isGuestClosure(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) &&
|
|
2630
|
+
if (!isSandboxDate(current) && !isSandboxRegex(current) && !isSandboxMap(current) && !isSandboxSet(current) && !((isGuestClosure(current) || isSandboxGenerator(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) &&
|
|
2666
2631
|
(Array.isArray(current) || !isPlainSandboxObject(current) ||
|
|
2667
2632
|
isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isSandboxRegExpIterator(current))) {
|
|
2668
2633
|
return getPropertyValue(current, key, context) !== undefined;
|
|
@@ -2941,6 +2906,8 @@ export function setSandboxProperty(target, property, value, budget, checkInherit
|
|
|
2941
2906
|
target = materializeFunctionProperties(target);
|
|
2942
2907
|
if (isSandboxPromise(target))
|
|
2943
2908
|
target = getPromiseProperties(target);
|
|
2909
|
+
if (isSandboxGenerator(target))
|
|
2910
|
+
target = getGeneratorProperties(target);
|
|
2944
2911
|
if (isSandboxMap(target) || isSandboxSet(target))
|
|
2945
2912
|
target = getCollectionProperties(target);
|
|
2946
2913
|
if (isFloat32Array(target)) {
|
|
@@ -2977,7 +2944,7 @@ export function setSandboxProperty(target, property, value, budget, checkInherit
|
|
|
2977
2944
|
for (let prototype = getSandboxPrototype(prototypeOwner, budget); prototype !== null; prototype = getSandboxPrototype(prototype, budget)) {
|
|
2978
2945
|
budget.visitNode();
|
|
2979
2946
|
assertSandboxDataDepth(depth++);
|
|
2980
|
-
const properties = isSandboxClosure(prototype) ? prototype.properties : prototype;
|
|
2947
|
+
const properties = isSandboxGenerator(prototype) ? getGeneratorProperties(prototype) : isSandboxClosure(prototype) ? prototype.properties : prototype;
|
|
2981
2948
|
const inherited = properties === undefined ? undefined : Object.getOwnPropertyDescriptor(properties, key);
|
|
2982
2949
|
if (inherited === undefined)
|
|
2983
2950
|
continue;
|
|
@@ -2997,7 +2964,7 @@ function setSuperProperty(base, receiver, key, value, context) {
|
|
|
2997
2964
|
for (let current = base; current !== null; current = getSandboxPrototype(current, budget)) {
|
|
2998
2965
|
budget.visitNode();
|
|
2999
2966
|
assertSandboxDataDepth(depth++);
|
|
3000
|
-
const properties = isSandboxClosure(current) ? current.properties : current;
|
|
2967
|
+
const properties = isSandboxGenerator(current) ? getGeneratorProperties(current) : isSandboxClosure(current) ? current.properties : current;
|
|
3001
2968
|
const descriptor = properties === undefined ? undefined : Object.getOwnPropertyDescriptor(properties, key);
|
|
3002
2969
|
if (descriptor === undefined)
|
|
3003
2970
|
continue;
|
|
@@ -3020,6 +2987,8 @@ export function deleteSandboxProperty(target, property) {
|
|
|
3020
2987
|
target = getRegexProperties(target);
|
|
3021
2988
|
if (isSandboxPromise(target))
|
|
3022
2989
|
target = getPromiseProperties(target);
|
|
2990
|
+
if (isSandboxGenerator(target))
|
|
2991
|
+
target = getGeneratorProperties(target);
|
|
3023
2992
|
if (isSandboxMap(target) || isSandboxSet(target))
|
|
3024
2993
|
target = getCollectionProperties(target);
|
|
3025
2994
|
if (Array.isArray(target)) {
|
|
@@ -14,6 +14,7 @@ import { suspendJob } from "./jobs.js";
|
|
|
14
14
|
import { invokeBuiltinClosure } from "./builtin-call.js";
|
|
15
15
|
import { getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype } from "./object-model.js";
|
|
16
16
|
import { getIntrinsicIdentity } from "./intrinsics.js";
|
|
17
|
+
import { readPropertyDescriptor } from "./accessors.js";
|
|
17
18
|
export function mapIteratorSnapshot(snapshot, map) {
|
|
18
19
|
if (snapshot.kind === "unsupported")
|
|
19
20
|
throw new TypeError("Host-owned iterator cannot be portably snapshotted.");
|
|
@@ -31,8 +32,9 @@ export async function restoreSandboxIterator(snapshot, budget, context, signal)
|
|
|
31
32
|
return asyncFromSyncIterator(await restoreSandboxIterator(snapshot.inner, budget, context, signal), budget, signal, context);
|
|
32
33
|
if (Array.isArray(snapshot.value))
|
|
33
34
|
return arrayIterator(snapshot.value, context, budget, snapshot.index);
|
|
34
|
-
const iterator = isSandboxGenerator(snapshot.value)
|
|
35
|
-
?
|
|
35
|
+
const iterator = isSandboxGenerator(snapshot.value)
|
|
36
|
+
? { ...generatorObjectIterator(snapshot.value, budget, context),
|
|
37
|
+
...(snapshot.value.async ? { asyncProtocol: true } : {}) }
|
|
36
38
|
: getSandboxIterator(snapshot.value, budget, context);
|
|
37
39
|
if (iterator === undefined)
|
|
38
40
|
throw new TypeError("Invalid builtin iterator snapshot.");
|
|
@@ -49,11 +51,15 @@ export async function acquireSandboxIterator(value, budget, context, asyncProtoc
|
|
|
49
51
|
: getSandboxIterator(value, budget, context);
|
|
50
52
|
if (getSandboxPropertyDescriptor(value, key, budget) === undefined &&
|
|
51
53
|
!(isSandboxRegExpIterator(value) && !asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== undefined)) {
|
|
54
|
+
if (isSandboxGenerator(value)) {
|
|
55
|
+
if (!hasExplicitSandboxPrototype(value) && (value.async === true) === asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== undefined)
|
|
56
|
+
return guestIterator(value, await context.getProperty(value, "next"), asyncProtocol, budget, context, signal);
|
|
57
|
+
}
|
|
52
58
|
if (!asyncProtocol && Array.isArray(value) && getSandboxPrototype(value, budget) !== null)
|
|
53
59
|
return undefined;
|
|
54
60
|
if (!asyncProtocol)
|
|
55
61
|
return getSandboxIterator(value, budget, context);
|
|
56
|
-
if (isSandboxGenerator(value) && value.async)
|
|
62
|
+
if (isSandboxGenerator(value) && value.async && !hasExplicitSandboxPrototype(value))
|
|
57
63
|
return getSandboxAsyncIterator(value, budget, context, signal);
|
|
58
64
|
const iterator = await acquireSandboxIterator(value, budget, context);
|
|
59
65
|
return iterator === undefined ? undefined : asyncFromSyncIterator(iterator, budget, signal, context);
|
|
@@ -130,7 +136,9 @@ export async function readIteratorResult(iterator, result, property) {
|
|
|
130
136
|
}
|
|
131
137
|
export function getSandboxAsyncIterator(value, budget, context, signal) {
|
|
132
138
|
if (isSandboxGenerator(value) && value.async) {
|
|
133
|
-
return
|
|
139
|
+
return hasExplicitSandboxPrototype(value) ? context?.getProperty === undefined
|
|
140
|
+
? generatorProtocolAdapter(value, budget, context, true, signal) : undefined
|
|
141
|
+
: { ...generatorObjectIterator(value, budget, context), asyncProtocol: true };
|
|
134
142
|
}
|
|
135
143
|
if (value !== null &&
|
|
136
144
|
(typeof value === "object" || typeof value === "function") &&
|
|
@@ -288,7 +296,12 @@ export function getSandboxIterator(value, budget, context) {
|
|
|
288
296
|
return syncIterator(Float32Array.prototype.values.call(value));
|
|
289
297
|
}
|
|
290
298
|
if (isSandboxGenerator(value)) {
|
|
291
|
-
|
|
299
|
+
if (value.async)
|
|
300
|
+
return undefined;
|
|
301
|
+
if (hasExplicitSandboxPrototype(value))
|
|
302
|
+
return context?.getProperty === undefined
|
|
303
|
+
? generatorProtocolAdapter(value, budget ?? new Budget(), context, false) : undefined;
|
|
304
|
+
return generatorObjectIterator(value, budget, context);
|
|
292
305
|
}
|
|
293
306
|
if (typeof value === "string") {
|
|
294
307
|
const iterator = value[Symbol.iterator]();
|
|
@@ -373,6 +386,64 @@ function collectionIterator(collection, value) {
|
|
|
373
386
|
return adapter;
|
|
374
387
|
}
|
|
375
388
|
const asyncGeneratorRequests = new WeakMap();
|
|
389
|
+
function generatorProtocolAdapter(value, budget, context, asyncProtocol, signal) {
|
|
390
|
+
// Direct host adapters still need guest property reads, receiver binding and
|
|
391
|
+
// cached next methods, but retain their asynchronous generator result channel.
|
|
392
|
+
const bridge = {
|
|
393
|
+
...context,
|
|
394
|
+
stack: context?.stack ?? [],
|
|
395
|
+
thisValue: value,
|
|
396
|
+
invokeClosure: (closure, args, receiver, construct) => invokeBuiltinClosure(closure, args, budget, context, receiver, construct),
|
|
397
|
+
getProperty: (target, key) => {
|
|
398
|
+
const descriptor = getSandboxPropertyDescriptor(target, key, budget);
|
|
399
|
+
return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, target, bridge, true);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
let resolved;
|
|
403
|
+
let pending;
|
|
404
|
+
const initialize = () => pending ??= acquireSandboxIterator(value, budget, bridge, asyncProtocol, signal).then(iterator => {
|
|
405
|
+
if (iterator === undefined)
|
|
406
|
+
throw new TypeError("Generator does not provide an iterator protocol.");
|
|
407
|
+
return resolved = iterator;
|
|
408
|
+
});
|
|
409
|
+
return {
|
|
410
|
+
asynchronous: true,
|
|
411
|
+
...(asyncProtocol ? { asyncProtocol: true } : {}),
|
|
412
|
+
get retainedValue() { return [value, resolved?.retainedValue]; },
|
|
413
|
+
snapshot: () => resolved?.snapshot?.() ?? { kind: "unsupported" },
|
|
414
|
+
next: async (...args) => (await initialize()).next(...args),
|
|
415
|
+
getOperation: async (method) => {
|
|
416
|
+
const iterator = await initialize();
|
|
417
|
+
return iterator.getOperation === undefined ? iterator[method] : iterator.getOperation(method);
|
|
418
|
+
},
|
|
419
|
+
readResultProperty: async (result, property) => readIteratorResult(await initialize(), result, property)
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
function generatorObjectIterator(generator, budget, context) {
|
|
423
|
+
const iterator = generatorIterator(generator, budget, context);
|
|
424
|
+
if (context?.getProperty === undefined)
|
|
425
|
+
return iterator;
|
|
426
|
+
return {
|
|
427
|
+
...iterator,
|
|
428
|
+
getOperation: async (method) => {
|
|
429
|
+
if (method === "next" || (!hasExplicitSandboxPrototype(generator) &&
|
|
430
|
+
getSandboxPropertyDescriptor(generator, method, budget) === undefined))
|
|
431
|
+
return iterator[method];
|
|
432
|
+
const operation = await context.getProperty(generator, method);
|
|
433
|
+
if (operation === undefined || operation === null)
|
|
434
|
+
return undefined;
|
|
435
|
+
if (!isSandboxClosure(operation))
|
|
436
|
+
throw new TypeError("Iterator operation must be callable.");
|
|
437
|
+
return async (...args) => {
|
|
438
|
+
const result = await invokeBuiltinClosure(operation, args, budget ?? new Budget(), context, generator);
|
|
439
|
+
return (generator.async ? await awaitSandboxValue(result, undefined, budget, context) : result);
|
|
440
|
+
};
|
|
441
|
+
},
|
|
442
|
+
readResultProperty: async (result, property) => ({
|
|
443
|
+
value: await context.getProperty(result, property)
|
|
444
|
+
})
|
|
445
|
+
};
|
|
446
|
+
}
|
|
376
447
|
export function generatorIterator(generator, budget, context) {
|
|
377
448
|
const invoke = async (method, value) => {
|
|
378
449
|
const leaveRunning = enterRunningState(generator);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { type SandboxClosure, type SandboxValue } from "../values.js";
|
|
2
|
-
import
|
|
1
|
+
import { type SandboxCallContext, type SandboxClosure, type SandboxValue } from "../values.js";
|
|
2
|
+
import { Budget } from "../budget.js";
|
|
3
3
|
export type FunctionMethodOptions = {
|
|
4
4
|
budget?: Budget;
|
|
5
5
|
callClosure: (closure: SandboxClosure, args: readonly SandboxValue[], stack: readonly string[], thisValue: SandboxValue, construct?: boolean, newTarget?: SandboxClosure) => Promise<SandboxValue> | SandboxValue;
|
|
6
6
|
};
|
|
7
|
+
type FunctionMethodName = "apply" | "bind" | "call" | "toString";
|
|
7
8
|
export declare function getFunctionMember(target: SandboxClosure, property: string | number, options: FunctionMethodOptions): SandboxValue | undefined;
|
|
9
|
+
export declare function callFunctionMethod(target: SandboxValue, methodName: FunctionMethodName, args: readonly SandboxValue[], options: FunctionMethodOptions, stack: readonly string[], context?: SandboxCallContext): Promise<SandboxValue> | SandboxValue;
|
|
10
|
+
export {};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { createSandboxClosure, isSandboxClosure } from "../values.js";
|
|
2
|
-
import { getGuestFunctionProperty, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure, setSandboxPrototype } from "../object-model.js";
|
|
2
|
+
import { getGuestFunctionProperty, getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure, setSandboxPrototype } from "../object-model.js";
|
|
3
3
|
import { assertSandboxDataDepth } from "../../graph-depth.js";
|
|
4
|
+
import { Budget } from "../budget.js";
|
|
4
5
|
import { functionString } from "../function-string.js";
|
|
5
|
-
import { runResources } from "../resources.js";
|
|
6
|
+
import { retainValues, runResources } from "../resources.js";
|
|
7
|
+
import { createBoundFunction } from "../bound-function.js";
|
|
8
|
+
import { sandboxNumber } from "../string-coercion.js";
|
|
9
|
+
import { readPropertyDescriptor } from "../accessors.js";
|
|
6
10
|
const functionMethodNames = new Set(["apply", "bind", "call", "toString"]);
|
|
7
11
|
export function getFunctionMember(target, property, options) {
|
|
8
12
|
let current = target;
|
|
@@ -22,7 +26,7 @@ export function getFunctionMember(target, property, options) {
|
|
|
22
26
|
else if (Object.hasOwn(current, String(property))) {
|
|
23
27
|
return current[String(property)];
|
|
24
28
|
}
|
|
25
|
-
if (isSandboxClosure(current) && !hasExplicitSandboxPrototype(current))
|
|
29
|
+
if (isSandboxClosure(current) && !hasExplicitSandboxPrototype(current) && getSandboxPrototype(current, options.budget) === null)
|
|
26
30
|
break;
|
|
27
31
|
current = getSandboxPrototype(current, options.budget);
|
|
28
32
|
if (current !== null) {
|
|
@@ -47,7 +51,7 @@ export function getFunctionMember(target, property, options) {
|
|
|
47
51
|
function isFunctionMethodName(property) {
|
|
48
52
|
return typeof property === "string" && functionMethodNames.has(property);
|
|
49
53
|
}
|
|
50
|
-
function callFunctionMethod(target, methodName, args, options, stack, context) {
|
|
54
|
+
export function callFunctionMethod(target, methodName, args, options, stack, context) {
|
|
51
55
|
if (!isSandboxClosure(target)) {
|
|
52
56
|
throw new TypeError(`Function#${methodName} requires a callable receiver.`);
|
|
53
57
|
}
|
|
@@ -58,40 +62,36 @@ function callFunctionMethod(target, methodName, args, options, stack, context) {
|
|
|
58
62
|
const thisValue = args[0];
|
|
59
63
|
if (methodName === "bind") {
|
|
60
64
|
const boundArgs = args.slice(1);
|
|
65
|
+
const explicitPrototype = hasExplicitSandboxPrototype(target);
|
|
66
|
+
const prototype = getSandboxPrototype(target, options.budget);
|
|
61
67
|
const bind = (length, name) => {
|
|
62
|
-
const bound =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
name: `bound ${name}`,
|
|
66
|
-
length,
|
|
67
|
-
boundTarget: target,
|
|
68
|
-
retainedValues: () => [target, thisValue, ...boundArgs, bound.name],
|
|
69
|
-
call: (callArgs, context) => options.callClosure(target, [...boundArgs, ...callArgs], context?.stack ?? [], thisValue),
|
|
70
|
-
...(target.construct === undefined
|
|
71
|
-
? {}
|
|
72
|
-
: {
|
|
73
|
-
construct: (callArgs, context) => options.callClosure(target, [...boundArgs, ...callArgs], context?.stack ?? [], undefined, true, context?.newTarget === bound ? target : context?.newTarget)
|
|
74
|
-
})
|
|
75
|
-
});
|
|
76
|
-
if (hasExplicitSandboxPrototype(target))
|
|
77
|
-
setSandboxPrototype(bound, getSandboxPrototype(target, options.budget), options.budget);
|
|
68
|
+
const bound = createBoundFunction({ target, thisValue, args: boundArgs }, `bound ${name}`, length, options.callClosure);
|
|
69
|
+
if (explicitPrototype)
|
|
70
|
+
setSandboxPrototype(bound, prototype, options.budget);
|
|
78
71
|
return bound;
|
|
79
72
|
};
|
|
80
73
|
if (context?.getProperty === undefined)
|
|
81
74
|
return bind(target.length === undefined ? undefined : Math.max(0, target.length - boundArgs.length), target.name ?? "");
|
|
82
75
|
return (async () => {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
target.properties
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
76
|
+
const release = options.budget !== undefined && explicitPrototype && prototype !== null
|
|
77
|
+
? retainValues(options.budget, () => [prototype]) : undefined;
|
|
78
|
+
try {
|
|
79
|
+
const properties = target.properties;
|
|
80
|
+
const defaultName = target.name;
|
|
81
|
+
const hasLength = !isGuestClosure(target) ||
|
|
82
|
+
target.properties === undefined ||
|
|
83
|
+
Object.hasOwn(target.properties, "length");
|
|
84
|
+
const length = hasLength ? await context.getProperty(target, "length") : undefined;
|
|
85
|
+
const name = !isGuestClosure(target) && !Object.hasOwn(properties ?? {}, "name")
|
|
86
|
+
? defaultName
|
|
87
|
+
: await context.getProperty(target, "name");
|
|
88
|
+
return bind(typeof length === "number" && !Number.isNaN(length)
|
|
89
|
+
? Math.max(0, Math.trunc(length) - boundArgs.length)
|
|
90
|
+
: 0, typeof name === "string" ? name : "");
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
release?.();
|
|
94
|
+
}
|
|
95
95
|
})();
|
|
96
96
|
}
|
|
97
97
|
if (methodName === "call") {
|
|
@@ -101,26 +101,39 @@ function callFunctionMethod(target, methodName, args, options, stack, context) {
|
|
|
101
101
|
if (applyArgs === null || applyArgs === undefined) {
|
|
102
102
|
return options.callClosure(target, [], stack, thisValue);
|
|
103
103
|
}
|
|
104
|
-
if (
|
|
105
|
-
throw new TypeError("Function#apply requires an
|
|
104
|
+
if (typeof applyArgs !== "object") {
|
|
105
|
+
throw new TypeError("Function#apply requires an object or nullish arguments value.");
|
|
106
106
|
}
|
|
107
|
-
if (context?.getProperty === undefined)
|
|
107
|
+
if (context?.getProperty === undefined && Array.isArray(applyArgs))
|
|
108
108
|
return options.callClosure(target, applyArgs, stack, thisValue);
|
|
109
109
|
return (async () => {
|
|
110
|
+
const budget = options.budget ?? new Budget();
|
|
111
|
+
const invocationContext = {
|
|
112
|
+
...context,
|
|
113
|
+
stack,
|
|
114
|
+
thisValue: context?.thisValue,
|
|
115
|
+
invokeClosure: context?.invokeClosure ?? ((callee, values, receiver) => Promise.resolve(options.callClosure(callee, values, stack, receiver)))
|
|
116
|
+
};
|
|
117
|
+
const read = (value, key) => {
|
|
118
|
+
if (context?.getProperty !== undefined)
|
|
119
|
+
return context.getProperty(value, key);
|
|
120
|
+
const descriptor = getSandboxPropertyDescriptor(value, key, budget);
|
|
121
|
+
return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, value, invocationContext);
|
|
122
|
+
};
|
|
110
123
|
const values = [];
|
|
111
|
-
const
|
|
112
|
-
options.budget?.allocateArrayLength(length);
|
|
113
|
-
const retained = {};
|
|
114
|
-
options.budget?.setRetainedValues(retained, () => values);
|
|
124
|
+
const release = retainValues(budget, () => [applyArgs, ...values]);
|
|
115
125
|
try {
|
|
126
|
+
const number = await sandboxNumber(await read(applyArgs, "length"), budget, invocationContext);
|
|
127
|
+
const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
|
|
128
|
+
budget.allocateArrayLength(length);
|
|
116
129
|
for (let index = 0; index < length; index++) {
|
|
117
|
-
|
|
118
|
-
values.push(await
|
|
130
|
+
budget.visitNode();
|
|
131
|
+
values.push(await read(applyArgs, String(index)));
|
|
119
132
|
}
|
|
120
133
|
return await options.callClosure(target, values, stack, thisValue);
|
|
121
134
|
}
|
|
122
135
|
finally {
|
|
123
|
-
|
|
136
|
+
release();
|
|
124
137
|
}
|
|
125
138
|
})();
|
|
126
139
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import { type SandboxGenerator, type SandboxValue } from "../values.js";
|
|
1
|
+
import { type SandboxCallContext, type SandboxGenerator, type SandboxValue } from "../values.js";
|
|
2
2
|
import type { Budget } from "../budget.js";
|
|
3
|
+
type GeneratorMethodName = "next" | "return" | "throw";
|
|
3
4
|
export declare function getGeneratorMember(target: SandboxGenerator, property: string | number, budget: Budget): SandboxValue | undefined;
|
|
5
|
+
export declare function callGeneratorMethod(target: SandboxValue, method: GeneratorMethodName, value: SandboxValue, budget: Budget, context: SandboxCallContext | undefined, async: boolean): SandboxValue | Promise<SandboxValue>;
|
|
6
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generatorIterator } from "../iteration.js";
|
|
2
|
-
import { allocateProducedSandboxValue, createSandboxClosure, createSandboxPromise } from "../values.js";
|
|
2
|
+
import { allocateProducedSandboxValue, createSandboxClosure, createSandboxPromise, isSandboxGenerator } from "../values.js";
|
|
3
3
|
const generatorMethodNames = new Set(["next", "return", "throw"]);
|
|
4
4
|
export function getGeneratorMember(target, property, budget) {
|
|
5
5
|
if (typeof property !== "string" || !generatorMethodNames.has(property)) {
|
|
@@ -8,10 +8,16 @@ export function getGeneratorMember(target, property, budget) {
|
|
|
8
8
|
return createSandboxClosure({
|
|
9
9
|
sandbox: true,
|
|
10
10
|
name: property,
|
|
11
|
-
call: ([value], context) =>
|
|
12
|
-
const iterator = generatorIterator(target, budget, context);
|
|
13
|
-
const result = Promise.resolve(iterator[property](value)).then(result => allocateProducedSandboxValue({ value: result.value, done: result.done === true }, budget));
|
|
14
|
-
return target.async ? createSandboxPromise(result) : result;
|
|
15
|
-
}
|
|
11
|
+
call: ([value], context) => callGeneratorMethod(target, property, value, budget, context, target.async === true)
|
|
16
12
|
});
|
|
17
13
|
}
|
|
14
|
+
export function callGeneratorMethod(target, method, value, budget, context, async) {
|
|
15
|
+
const result = (async () => {
|
|
16
|
+
if (!isSandboxGenerator(target) || (target.async === true) !== async)
|
|
17
|
+
throw new TypeError(`${async ? "AsyncGenerator" : "Generator"}.${method} requires a matching generator receiver.`);
|
|
18
|
+
const iterator = generatorIterator(target, budget, context);
|
|
19
|
+
const result = await iterator[method](value);
|
|
20
|
+
return allocateProducedSandboxValue({ value: result.value, done: result.done === true }, budget);
|
|
21
|
+
})();
|
|
22
|
+
return async ? createSandboxPromise(result) : result;
|
|
23
|
+
}
|
|
@@ -7,6 +7,7 @@ export declare function getGuestFunctionProperties(closure: SandboxClosure): San
|
|
|
7
7
|
export declare function materializeFunctionProperties(closure: SandboxClosure): SandboxObject;
|
|
8
8
|
export declare function getGuestFunctionProperty(closure: SandboxClosure, key: PropertyKey): SandboxValue;
|
|
9
9
|
export declare function installObjectPrototype(budget: Budget, prototype: SandboxObject, constructor: SandboxClosure): void;
|
|
10
|
+
export declare function installFunctionPrototype(budget: Budget, prototype: SandboxClosure): void;
|
|
10
11
|
export declare function installBoxedPrototype(budget: Budget, prototype: SandboxObject, constructor: SandboxClosure, kind?: BoxedKind): void;
|
|
11
12
|
export declare function getBoxedPrototype(value: BoxedPrimitive, budget: Budget): SandboxObject | undefined;
|
|
12
13
|
export declare function installRegexPrototype(budget: Budget, prototype: SandboxObject, constructor: SandboxClosure): void;
|