poe-code 14.0.64 → 14.0.66
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 +8832 -7273
- 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-3EXDJDQM.js → chunk-MKTUVVEB.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-XO7B4P27.js → chunk-YKISHTWT.js} +4474 -2978
- package/packages/safe-js/dist/chunks/chunk-YKISHTWT.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/index.js.map +1 -1
- package/packages/safe-js/dist/interp/accessors.d.ts +9 -0
- package/packages/safe-js/dist/interp/accessors.js +68 -0
- package/packages/safe-js/dist/interp/async.d.ts +13 -2
- package/packages/safe-js/dist/interp/async.js +19 -9
- package/packages/safe-js/dist/interp/classes.d.ts +4 -0
- package/packages/safe-js/dist/interp/classes.js +182 -0
- package/packages/safe-js/dist/interp/exceptions.d.ts +1 -1
- package/packages/safe-js/dist/interp/exceptions.js +51 -9
- package/packages/safe-js/dist/interp/globals/collections.js +53 -16
- package/packages/safe-js/dist/interp/globals/console-json.js +41 -26
- package/packages/safe-js/dist/interp/globals/object-array.d.ts +2 -1
- package/packages/safe-js/dist/interp/globals/object-array.js +230 -69
- package/packages/safe-js/dist/interp/globals/object.js +13 -2
- package/packages/safe-js/dist/interp/globals/primitives.js +16 -5
- package/packages/safe-js/dist/interp/interpreter.d.ts +2 -2
- package/packages/safe-js/dist/interp/interpreter.js +168 -61
- package/packages/safe-js/dist/interp/iteration.js +13 -0
- package/packages/safe-js/dist/interp/methods/array.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/array.js +368 -109
- package/packages/safe-js/dist/interp/methods/function.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/function.js +56 -20
- package/packages/safe-js/dist/interp/methods/regex.js +1 -1
- package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
- package/packages/safe-js/dist/interp/object-model.js +48 -10
- package/packages/safe-js/dist/interp/patterns.d.ts +3 -3
- package/packages/safe-js/dist/interp/patterns.js +36 -17
- package/packages/safe-js/dist/interp/promise.d.ts +1 -1
- package/packages/safe-js/dist/interp/promise.js +103 -63
- package/packages/safe-js/dist/interp/string-coercion.d.ts +1 -0
- package/packages/safe-js/dist/interp/string-coercion.js +47 -37
- package/packages/safe-js/dist/interp/values.d.ts +4 -2
- package/packages/safe-js/dist/interp/values.js +26 -1
- package/packages/safe-js/dist/lint/class-elements.d.ts +5 -0
- package/packages/safe-js/dist/lint/class-elements.js +20 -0
- package/packages/safe-js/dist/lint/rules/AS-async-not-needed.js +16 -0
- package/packages/safe-js/dist/lint/rules/AS-destructure-null-default.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-export-import-meta.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-floating-promise.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-frontmatter-field-unused.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-jsdoc-type.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-large-literal.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-missing-async.js +16 -0
- package/packages/safe-js/dist/lint/rules/AS-mutating-frozen.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-needless-template.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-shadow-global.js +12 -0
- package/packages/safe-js/dist/lint/rules/AS-unbounded-loop.js +11 -0
- package/packages/safe-js/dist/lint/rules/AS-unreachable.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-unused-import.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS001.js +0 -1
- package/packages/safe-js/dist/lint/rules/AS003.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS006-007.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS009.js +20 -1
- package/packages/safe-js/dist/lint/rules/AS010.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS011.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS015.js +9 -0
- package/packages/safe-js/dist/parse/function-source.d.ts +2 -2
- package/packages/safe-js/dist/parse/parser.d.ts +42 -2
- package/packages/safe-js/dist/parse/parser.js +208 -35
- package/packages/safe-js/dist/parse/tokenizer.js +3 -0
- package/packages/safe-js/dist/parse.d.ts +1 -1
- package/packages/safe-js/dist/chunks/chunk-XO7B4P27.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-3EXDJDQM.js.map → chunk-MKTUVVEB.js.map} +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { promiseReplayContext } from "./promise-replay.js";
|
|
2
|
+
import { readPropertyDescriptor, writePropertyDescriptor } from "./accessors.js";
|
|
2
3
|
import { deleteHostObjectMember, getHostObjectKeys, getHostObjectMember, hasHostObjectMember, isGuestHostObject, setHostObjectMember } from "./host-capabilities.js";
|
|
3
4
|
import { toPropertyKey } from "./property-key.js";
|
|
4
5
|
import { assertPromiseExecutionAllowed } from "./promise-tracker.js";
|
|
5
6
|
import { SandboxJobQueue, runAsyncPrefix, suspendJob } from "./jobs.js";
|
|
6
7
|
import { withCancellationSignal } from "./cancel.js";
|
|
7
8
|
import { retainValues } from "./resources.js";
|
|
9
|
+
import { evaluateClass } from "./classes.js";
|
|
8
10
|
import { sandboxString } from "./string-coercion.js";
|
|
9
11
|
import { attachErrorSpan, formatErrorStack, replaceErrorStack } from "../error/shape.js";
|
|
10
12
|
import { evaluateArrowFunctionExpression, evaluateFunctionExpression, evaluateAwaitExpression, emitResumeBreakpoint, createInterpretedClosure, normalizeClosureResult } from "./async.js";
|
|
@@ -14,7 +16,7 @@ import { CompileScope, RegexCompileGuard } from "./regex/compile-guard.js";
|
|
|
14
16
|
import { createCapturedException, createThrowCompletion, evaluateThrowStatement as evaluateThrowStatementResult, evaluateTryStatement as evaluateTryStatementResult, isCapturedException, isInterpreterError, surfaceThrownValue } from "./exceptions.js";
|
|
15
17
|
import { callArrayMethod, getArrayMember, isArrayMethodName } from "./methods/array.js";
|
|
16
18
|
import { getFunctionMember } from "./methods/function.js";
|
|
17
|
-
import { getBoxedPrototype,
|
|
19
|
+
import { getBoxedPrototype, getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype, isDefaultBoxedMethod, isGuestClosure, materializeFunctionProperties, setSandboxPrototype } from "./object-model.js";
|
|
18
20
|
import { getStringIndex } from "./methods/string.js";
|
|
19
21
|
import { assertSandboxDataDepth } from "../graph-depth.js";
|
|
20
22
|
import { callMapMethod, getMapMember, isMapMethodName } from "./methods/map.js";
|
|
@@ -50,6 +52,15 @@ const dispatchTable = {
|
|
|
50
52
|
BlockStatement: evaluateBlockStatement,
|
|
51
53
|
BooleanLiteral: evaluatePrimitiveLiteral,
|
|
52
54
|
CallExpression: evaluateCallExpression,
|
|
55
|
+
ClassDeclaration: (node, context) => evaluateClass(node, context, evaluateNode, createCoercionContext(context)),
|
|
56
|
+
ClassExpression: (node, context) => evaluateClass(node, context, evaluateNode, createCoercionContext(context)),
|
|
57
|
+
NewTargetExpression: async (_node, context) => ({ kind: "normal", hasValue: true, value: context.functionEnvironment?.newTarget }),
|
|
58
|
+
Super: async (_node, context) => {
|
|
59
|
+
const home = context.functionEnvironment?.homeObject;
|
|
60
|
+
if (home === undefined)
|
|
61
|
+
throw new ReferenceError("Super binding is unavailable.");
|
|
62
|
+
return { kind: "normal", hasValue: true, value: getSandboxPrototype(home, context.budget) };
|
|
63
|
+
},
|
|
53
64
|
ConditionalExpression: evaluateConditionalExpression,
|
|
54
65
|
ContinueStatement: evaluateContinueStatement,
|
|
55
66
|
DoWhileStatement: evaluateDoWhileStatement,
|
|
@@ -182,6 +193,8 @@ export async function interpret(node, options = {}) {
|
|
|
182
193
|
export { Scope } from "./scope.js";
|
|
183
194
|
async function evaluateNode(node, context) {
|
|
184
195
|
context.assertActive?.();
|
|
196
|
+
if (context.inferredName !== undefined && node.type !== "ClassExpression")
|
|
197
|
+
context = { ...context, inferredName: undefined };
|
|
185
198
|
const replayWait = promiseReplayContext.getStore()?.beforeNode(node.nodeId);
|
|
186
199
|
if (replayWait !== undefined)
|
|
187
200
|
await suspendJob(replayWait);
|
|
@@ -332,7 +345,13 @@ async function evaluateObjectExpression(node, context) {
|
|
|
332
345
|
const releaseKey = retainValues(context.budget, () => [key.value]);
|
|
333
346
|
let value;
|
|
334
347
|
try {
|
|
335
|
-
value = await evaluateNode(property.value,
|
|
348
|
+
value = await evaluateNode(property.value, {
|
|
349
|
+
...context,
|
|
350
|
+
inferredName: String(key.value),
|
|
351
|
+
...(property.value.type === "FunctionExpression" && property.value.method === true
|
|
352
|
+
? { functionEnvironment: { homeObject: object } }
|
|
353
|
+
: {})
|
|
354
|
+
});
|
|
336
355
|
}
|
|
337
356
|
finally {
|
|
338
357
|
releaseKey();
|
|
@@ -359,7 +378,8 @@ async function evaluateObjectExpression(node, context) {
|
|
|
359
378
|
}
|
|
360
379
|
}
|
|
361
380
|
function isObjectPrototypeSetterProperty(property, key) {
|
|
362
|
-
return !property.computed && !property.shorthand && key === "__proto__"
|
|
381
|
+
return !property.computed && !property.shorthand && key === "__proto__" &&
|
|
382
|
+
!(property.value.type === "FunctionExpression" && property.value.method === true);
|
|
363
383
|
}
|
|
364
384
|
async function evaluateTemplateLiteral(node, context) {
|
|
365
385
|
let value = context.budget.allocateString(node.quasis[0]?.value.cooked ?? "");
|
|
@@ -390,22 +410,33 @@ async function evaluateTemplateLiteral(node, context) {
|
|
|
390
410
|
}
|
|
391
411
|
}
|
|
392
412
|
async function evaluateTaggedTemplateExpression(node, context) {
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
413
|
+
const invokeTag = async (tag, receiver) => {
|
|
414
|
+
if (!isSandboxClosure(tag))
|
|
415
|
+
throw new TypeError("Tagged template tag must be a function.");
|
|
416
|
+
const release = retainValues(context.budget, () => [tag, receiver]);
|
|
417
|
+
try {
|
|
418
|
+
const values = await evaluateTemplateExpressionValues(node.quasi, context);
|
|
419
|
+
if (!values.ok)
|
|
420
|
+
return values.result;
|
|
421
|
+
return {
|
|
422
|
+
kind: "normal", hasValue: true,
|
|
423
|
+
value: await invokeSandboxClosure(tag, [createTaggedTemplateStrings(node.quasi, context), ...values.value], context, [...context.callStack, formatStackFrame(node, tag.name)], node.span, receiver)
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
finally {
|
|
427
|
+
release();
|
|
428
|
+
}
|
|
408
429
|
};
|
|
430
|
+
if (node.tag.type === "MemberExpression")
|
|
431
|
+
return evaluateMemberAccess(node.tag, context, async (member) => {
|
|
432
|
+
if (member.kind === "nullish")
|
|
433
|
+
throw new TypeError("Tagged template tag must be a function.");
|
|
434
|
+
const key = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
435
|
+
const receiver = member.superReceiver === undefined ? member.object : member.superReceiver.value;
|
|
436
|
+
return invokeTag(await getPropertyValue(member.object, key, context, receiver), receiver);
|
|
437
|
+
});
|
|
438
|
+
const tag = await evaluateNode(node.tag, context);
|
|
439
|
+
return tag.kind === "normal" ? invokeTag(tag.value, undefined) : tag;
|
|
409
440
|
}
|
|
410
441
|
async function evaluateTemplateExpressionValues(node, context) {
|
|
411
442
|
const values = [];
|
|
@@ -490,7 +521,8 @@ async function evaluateBinaryExpression(node, context) {
|
|
|
490
521
|
if (isSandboxBox(rightValue) && (!equality || (left.value !== null && left.value !== undefined && typeof left.value !== "object")))
|
|
491
522
|
rightValue = await toNumericPrimitive(rightValue, context);
|
|
492
523
|
}
|
|
493
|
-
const
|
|
524
|
+
const operation = applyBinaryOperator(node, leftValue, rightValue, context);
|
|
525
|
+
const value = operation instanceof Promise ? await operation : operation;
|
|
494
526
|
return {
|
|
495
527
|
kind: "normal",
|
|
496
528
|
hasValue: true,
|
|
@@ -552,7 +584,7 @@ async function evaluateAssignmentExpression(node, context) {
|
|
|
552
584
|
value: current
|
|
553
585
|
};
|
|
554
586
|
}
|
|
555
|
-
const right = await evaluateNode(node.right, context);
|
|
587
|
+
const right = await evaluateNode(node.right, { ...context, inferredName: node.left.type === "Identifier" ? node.left.name : undefined });
|
|
556
588
|
if (right.kind !== "normal") {
|
|
557
589
|
return right;
|
|
558
590
|
}
|
|
@@ -584,7 +616,7 @@ async function evaluateMemberAssignmentExpression(node, context) {
|
|
|
584
616
|
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
585
617
|
}
|
|
586
618
|
property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
587
|
-
current = getPropertyValue(member.object, property, context);
|
|
619
|
+
current = await getPropertyValue(member.object, property, context, member.superReceiver === undefined ? member.object : member.superReceiver.value);
|
|
588
620
|
}
|
|
589
621
|
if (node.operator === "&&=" && !isTruthy(current)) {
|
|
590
622
|
return {
|
|
@@ -626,7 +658,10 @@ async function evaluateMemberAssignmentExpression(node, context) {
|
|
|
626
658
|
}
|
|
627
659
|
operands = [value];
|
|
628
660
|
property ??= await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
629
|
-
|
|
661
|
+
if (member.superReceiver === undefined)
|
|
662
|
+
await setSandboxProperty(member.object, property, value, context.budget, true, createCoercionContext(context));
|
|
663
|
+
else
|
|
664
|
+
await setSuperProperty(member.object, member.superReceiver.value, property, value, context);
|
|
630
665
|
return {
|
|
631
666
|
kind: "normal",
|
|
632
667
|
hasValue: true,
|
|
@@ -772,7 +807,7 @@ async function evaluateVariableDeclaration(node, context) {
|
|
|
772
807
|
hasValue: true,
|
|
773
808
|
value: undefined
|
|
774
809
|
}
|
|
775
|
-
: await evaluateNode(declarator.init, context);
|
|
810
|
+
: await evaluateNode(declarator.init, { ...context, inferredName: declarator.id.type === "Identifier" ? declarator.id.name : undefined });
|
|
776
811
|
if (value.kind !== "normal") {
|
|
777
812
|
return value;
|
|
778
813
|
}
|
|
@@ -946,6 +981,11 @@ function predeclareStatementListBindings(statements, context, functionBody = fal
|
|
|
946
981
|
const { scope } = context;
|
|
947
982
|
const names = new Set();
|
|
948
983
|
for (const statement of statements) {
|
|
984
|
+
if (statement.type === "ClassDeclaration") {
|
|
985
|
+
scope.predeclare(statement.id.name, "let");
|
|
986
|
+
names.add(statement.id.name);
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
949
989
|
if (statement.type === "FunctionDeclaration") {
|
|
950
990
|
const name = statement.id.name;
|
|
951
991
|
if (names.has(name) && !(functionBody && scope.getOwnBindingKind(name) === "var")) {
|
|
@@ -1646,6 +1686,8 @@ async function evaluateDeleteExpression(node, context) {
|
|
|
1646
1686
|
throw createError("UNSUPPORTED_NODE", node, "Unary operator 'delete' requires a member target.");
|
|
1647
1687
|
}
|
|
1648
1688
|
return evaluateMemberAccess(node.argument, context, async (member) => {
|
|
1689
|
+
if (member.kind === "resolved" && member.superReceiver !== undefined)
|
|
1690
|
+
throw new ReferenceError("Cannot delete a super property.");
|
|
1649
1691
|
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1650
1692
|
if (member.kind === "nullish") {
|
|
1651
1693
|
return {
|
|
@@ -1703,9 +1745,12 @@ async function evaluateMemberUpdateExpression(node, context) {
|
|
|
1703
1745
|
throw new TypeError("Cannot update properties of null or undefined.");
|
|
1704
1746
|
}
|
|
1705
1747
|
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
1706
|
-
const current = toNumber(await toNumericPrimitive(getPropertyValue(member.object, property, context), context));
|
|
1748
|
+
const current = toNumber(await toNumericPrimitive(await getPropertyValue(member.object, property, context, member.superReceiver === undefined ? member.object : member.superReceiver.value), context));
|
|
1707
1749
|
const next = node.operator === "++" ? current + 1 : current - 1;
|
|
1708
|
-
|
|
1750
|
+
if (member.superReceiver === undefined)
|
|
1751
|
+
await setSandboxProperty(member.object, property, next, context.budget, true, createCoercionContext(context));
|
|
1752
|
+
else
|
|
1753
|
+
await setSuperProperty(member.object, member.superReceiver.value, property, next, context);
|
|
1709
1754
|
return {
|
|
1710
1755
|
kind: "normal",
|
|
1711
1756
|
hasValue: true,
|
|
@@ -1723,19 +1768,23 @@ async function evaluateMemberExpression(node, context) {
|
|
|
1723
1768
|
return {
|
|
1724
1769
|
kind: "normal",
|
|
1725
1770
|
hasValue: true,
|
|
1726
|
-
value: getPropertyValue(member.object, await toPropertyKey(member.property, context.budget, createCoercionContext(context)), context)
|
|
1771
|
+
value: await getPropertyValue(member.object, await toPropertyKey(member.property, context.budget, createCoercionContext(context)), context, member.superReceiver === undefined ? member.object : member.superReceiver.value)
|
|
1727
1772
|
};
|
|
1728
1773
|
});
|
|
1729
1774
|
}
|
|
1730
|
-
function getPropertyValue(target, property, context) {
|
|
1775
|
+
function getPropertyValue(target, property, context, receiver = target) {
|
|
1731
1776
|
if (isGuestHostObject(target))
|
|
1732
1777
|
return getHostObjectMember(target, String(property));
|
|
1778
|
+
const descriptor = getSandboxPropertyDescriptor(target, property, context.budget);
|
|
1779
|
+
if (descriptor !== undefined)
|
|
1780
|
+
return readPropertyDescriptor(descriptor, receiver, createCoercionContext(context), true);
|
|
1733
1781
|
if (typeof target === "string" || typeof target === "number" || typeof target === "boolean") {
|
|
1734
1782
|
const prototype = getBoxedPrototype(target, context.budget);
|
|
1735
1783
|
if (prototype !== undefined) {
|
|
1736
|
-
if (typeof target === "string" &&
|
|
1784
|
+
if (typeof target === "string" &&
|
|
1785
|
+
(property === "length" || getStringIndex(property) !== undefined))
|
|
1737
1786
|
return getStringMember(target, property, context.budget);
|
|
1738
|
-
return
|
|
1787
|
+
return getPropertyValue(prototype, property, context, receiver);
|
|
1739
1788
|
}
|
|
1740
1789
|
}
|
|
1741
1790
|
if (typeof target === "string")
|
|
@@ -1771,13 +1820,22 @@ export function createPatternContext(context, scope = context.scope, evaluate =
|
|
|
1771
1820
|
const evaluationContext = { ...context, scope };
|
|
1772
1821
|
return {
|
|
1773
1822
|
budget: context.budget,
|
|
1774
|
-
evaluate: node => evaluate(node, evaluationContext),
|
|
1775
|
-
toPropertyKey: value => toPropertyKey(value, context.budget, createCoercionContext(evaluationContext)),
|
|
1823
|
+
evaluate: (node, inferredName) => evaluate(node, { ...evaluationContext, inferredName }),
|
|
1824
|
+
toPropertyKey: (value) => toPropertyKey(value, context.budget, createCoercionContext(evaluationContext)),
|
|
1776
1825
|
getProperty: (value, key) => getPropertyValue(value, key, evaluationContext),
|
|
1777
|
-
setProperty: (target, key, value) => setSandboxProperty(target, key, value, context.budget)
|
|
1826
|
+
setProperty: (target, key, value) => setSandboxProperty(target, key, value, context.budget, true, createCoercionContext(evaluationContext))
|
|
1778
1827
|
};
|
|
1779
1828
|
}
|
|
1780
1829
|
async function evaluateCallExpression(node, context) {
|
|
1830
|
+
if (node.callee.type === "Super") {
|
|
1831
|
+
const construction = context.functionEnvironment?.construction;
|
|
1832
|
+
if (construction === undefined)
|
|
1833
|
+
throw new ReferenceError("Super constructor binding is unavailable.");
|
|
1834
|
+
const args = await evaluateCallArguments(node.arguments, context);
|
|
1835
|
+
if (!args.ok)
|
|
1836
|
+
return args.result;
|
|
1837
|
+
return { kind: "normal", hasValue: true, value: await construction.superCall(args.value) };
|
|
1838
|
+
}
|
|
1781
1839
|
if (node.callee.type === "MemberExpression") {
|
|
1782
1840
|
context.budget.visitNode();
|
|
1783
1841
|
context.stats.nodeVisits += 1;
|
|
@@ -1847,6 +1905,7 @@ function attachFatalSandboxErrorContext(error, node, stackFrames) {
|
|
|
1847
1905
|
replaceErrorStack(error, stackFrames);
|
|
1848
1906
|
}
|
|
1849
1907
|
async function evaluateMemberAccess(node, context, consume) {
|
|
1908
|
+
const superReceiver = node.object.type === "Super" ? { value: context.scope.lookup("this") } : undefined;
|
|
1850
1909
|
const object = await evaluateNode(node.object, context);
|
|
1851
1910
|
if (object.kind !== "normal")
|
|
1852
1911
|
return object;
|
|
@@ -1862,7 +1921,8 @@ async function evaluateMemberAccess(node, context, consume) {
|
|
|
1862
1921
|
if (result.kind !== "normal")
|
|
1863
1922
|
return result;
|
|
1864
1923
|
property = result.value;
|
|
1865
|
-
return await consume({ kind: "resolved", object: object.value, property
|
|
1924
|
+
return await consume({ kind: "resolved", object: object.value, property,
|
|
1925
|
+
...(superReceiver === undefined ? {} : { superReceiver: { value: superReceiver.value.found ? superReceiver.value.value : undefined } }) });
|
|
1866
1926
|
}
|
|
1867
1927
|
finally {
|
|
1868
1928
|
release();
|
|
@@ -1918,6 +1978,8 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1918
1978
|
...reference,
|
|
1919
1979
|
property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
|
|
1920
1980
|
};
|
|
1981
|
+
if (member.superReceiver !== undefined)
|
|
1982
|
+
return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context, member.superReceiver.value), context, member.superReceiver.value);
|
|
1921
1983
|
if ((typeof member.object === "string" || typeof member.object === "number" || typeof member.object === "boolean") &&
|
|
1922
1984
|
getBoxedPrototype(member.object, context.budget) !== undefined) {
|
|
1923
1985
|
if (isDefaultBoxedMethod(member.object, member.property, context.budget)) {
|
|
@@ -1926,7 +1988,7 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1926
1988
|
if (typeof member.object === "number" && isNumberMethodName(member.property))
|
|
1927
1989
|
return evaluateNumberMethodCall(node, member.object, member.property, context);
|
|
1928
1990
|
}
|
|
1929
|
-
return evaluateResolvedCallExpression(node, getPropertyValue(member.object, member.property, context), context, member.object);
|
|
1991
|
+
return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
|
|
1930
1992
|
}
|
|
1931
1993
|
if (typeof member.object === "string" && isStringMethodName(member.property)) {
|
|
1932
1994
|
return evaluateStringMethodCall(node, member.object, member.property, context);
|
|
@@ -1974,7 +2036,7 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1974
2036
|
return evaluateResolvedCallExpression(node, memberValue, context, member.object);
|
|
1975
2037
|
}
|
|
1976
2038
|
if (isSandboxClosure(member.object)) {
|
|
1977
|
-
const memberValue =
|
|
2039
|
+
const memberValue = await getPropertyValue(member.object, member.property, context);
|
|
1978
2040
|
if (memberValue === undefined) {
|
|
1979
2041
|
throw new TypeError(`Function#${String(member.property)} is not a supported method.`);
|
|
1980
2042
|
}
|
|
@@ -1989,7 +2051,7 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1989
2051
|
if (!isIndexableSandboxValue(member.object)) {
|
|
1990
2052
|
throw new TypeError("Attempted to read a property from a non-object value.");
|
|
1991
2053
|
}
|
|
1992
|
-
return evaluateResolvedCallExpression(node,
|
|
2054
|
+
return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
|
|
1993
2055
|
});
|
|
1994
2056
|
}
|
|
1995
2057
|
function evaluatePrimitiveMemberCall(node, receiverType, property, value, context) {
|
|
@@ -2174,7 +2236,8 @@ function applyBinaryOperator(node, left, right, context) {
|
|
|
2174
2236
|
if (isFloat32ArrayConstructor(right))
|
|
2175
2237
|
return isFloat32Array(left);
|
|
2176
2238
|
if (isDateConstructor(right))
|
|
2177
|
-
return isSandboxDate(left) &&
|
|
2239
|
+
return (isSandboxDate(left) &&
|
|
2240
|
+
getDatePrototype(left, context.budget, context.compilation?.owner) !== null);
|
|
2178
2241
|
if (isSandboxSetConstructor(right) && isSandboxSet(left)) {
|
|
2179
2242
|
return true;
|
|
2180
2243
|
}
|
|
@@ -2184,17 +2247,21 @@ function applyBinaryOperator(node, left, right, context) {
|
|
|
2184
2247
|
if (isGuestClosure(right)) {
|
|
2185
2248
|
if (typeof left !== "object" || left === null)
|
|
2186
2249
|
return false;
|
|
2187
|
-
const
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2250
|
+
const check = (prototype) => {
|
|
2251
|
+
if (typeof prototype !== "object" || prototype === null) {
|
|
2252
|
+
throw new TypeError("Function has a non-object prototype in instanceof check.");
|
|
2253
|
+
}
|
|
2254
|
+
let depth = 0;
|
|
2255
|
+
for (let current = getSandboxPrototype(left, context.budget); current !== null; current = getSandboxPrototype(current, context.budget)) {
|
|
2256
|
+
context.budget.visitNode();
|
|
2257
|
+
assertSandboxDataDepth(depth++);
|
|
2258
|
+
if (current === prototype)
|
|
2259
|
+
return true;
|
|
2260
|
+
}
|
|
2261
|
+
return false;
|
|
2262
|
+
};
|
|
2263
|
+
const prototype = getPropertyValue(right, "prototype", context);
|
|
2264
|
+
return prototype instanceof Promise ? prototype.then(check) : check(prototype);
|
|
2198
2265
|
}
|
|
2199
2266
|
return false;
|
|
2200
2267
|
case "in":
|
|
@@ -2372,7 +2439,7 @@ async function toNumericPrimitive(value, context) {
|
|
|
2372
2439
|
}
|
|
2373
2440
|
if (isIndexableSandboxValue(value)) {
|
|
2374
2441
|
for (const methodName of ["valueOf", "toString"]) {
|
|
2375
|
-
const method =
|
|
2442
|
+
const method = await getPropertyValue(value, methodName, context);
|
|
2376
2443
|
if (methodName === "toString" && method === undefined && !Object.hasOwn(value, methodName)) {
|
|
2377
2444
|
return toString(value);
|
|
2378
2445
|
}
|
|
@@ -2468,7 +2535,7 @@ function getArrayMemberValue(target, property, context) {
|
|
|
2468
2535
|
}
|
|
2469
2536
|
return getArrayMember(target, property, createArrayMethodOptions(context));
|
|
2470
2537
|
}
|
|
2471
|
-
export function setSandboxProperty(target, property, value, budget) {
|
|
2538
|
+
export function setSandboxProperty(target, property, value, budget, checkInherited = true, context) {
|
|
2472
2539
|
if (isSandboxDate(target))
|
|
2473
2540
|
throw new TypeError("Date own properties are not supported.");
|
|
2474
2541
|
if (isGuestHostObject(target)) {
|
|
@@ -2476,6 +2543,11 @@ export function setSandboxProperty(target, property, value, budget) {
|
|
|
2476
2543
|
return;
|
|
2477
2544
|
}
|
|
2478
2545
|
const prototypeOwner = target;
|
|
2546
|
+
if (checkInherited) {
|
|
2547
|
+
const descriptor = getSandboxPropertyDescriptor(target, property, budget);
|
|
2548
|
+
if (descriptor !== undefined && !("value" in descriptor))
|
|
2549
|
+
return writePropertyDescriptor(descriptor, target, value, context);
|
|
2550
|
+
}
|
|
2479
2551
|
if (isGuestClosure(target))
|
|
2480
2552
|
target = materializeFunctionProperties(target);
|
|
2481
2553
|
if (isFloat32Array(target)) {
|
|
@@ -2505,7 +2577,7 @@ export function setSandboxProperty(target, property, value, budget) {
|
|
|
2505
2577
|
Object.defineProperty(target, key, { value });
|
|
2506
2578
|
}
|
|
2507
2579
|
else {
|
|
2508
|
-
if (typeof prototypeOwner === "object" && prototypeOwner !== null) {
|
|
2580
|
+
if (checkInherited && typeof prototypeOwner === "object" && prototypeOwner !== null) {
|
|
2509
2581
|
let depth = 0;
|
|
2510
2582
|
for (let prototype = getSandboxPrototype(prototypeOwner, budget); prototype !== null; prototype = getSandboxPrototype(prototype, budget)) {
|
|
2511
2583
|
budget.visitNode();
|
|
@@ -2522,6 +2594,28 @@ export function setSandboxProperty(target, property, value, budget) {
|
|
|
2522
2594
|
defineSandboxProperty(target, key, value);
|
|
2523
2595
|
}
|
|
2524
2596
|
}
|
|
2597
|
+
function setSuperProperty(base, receiver, key, value, context) {
|
|
2598
|
+
const budget = context.budget;
|
|
2599
|
+
if (typeof base !== "object" || base === null)
|
|
2600
|
+
throw new TypeError("Cannot assign a property of null.");
|
|
2601
|
+
let depth = 0;
|
|
2602
|
+
for (let current = base; current !== null; current = getSandboxPrototype(current, budget)) {
|
|
2603
|
+
budget.visitNode();
|
|
2604
|
+
assertSandboxDataDepth(depth++);
|
|
2605
|
+
const properties = isSandboxClosure(current) ? current.properties : current;
|
|
2606
|
+
const descriptor = properties === undefined ? undefined : Object.getOwnPropertyDescriptor(properties, key);
|
|
2607
|
+
if (descriptor === undefined)
|
|
2608
|
+
continue;
|
|
2609
|
+
if (!("value" in descriptor))
|
|
2610
|
+
return writePropertyDescriptor(descriptor, receiver, value, createCoercionContext(context));
|
|
2611
|
+
if (descriptor.writable !== true)
|
|
2612
|
+
throw new TypeError(`Cannot assign to read only property '${key}'.`);
|
|
2613
|
+
break;
|
|
2614
|
+
}
|
|
2615
|
+
if (typeof receiver !== "object" || receiver === null)
|
|
2616
|
+
throw new TypeError("Super assignment requires an object receiver.");
|
|
2617
|
+
return setSandboxProperty(receiver, key, value, budget, false);
|
|
2618
|
+
}
|
|
2525
2619
|
function deleteSandboxProperty(target, property) {
|
|
2526
2620
|
if (isGuestHostObject(target))
|
|
2527
2621
|
return deleteHostObjectMember(target, String(property));
|
|
@@ -2580,7 +2674,7 @@ function createArrayMethodOptions(context) {
|
|
|
2580
2674
|
budget: context.budget,
|
|
2581
2675
|
context: createCoercionContext(context),
|
|
2582
2676
|
hasProperty: (value, property) => hasSandboxProperty(value, property, context),
|
|
2583
|
-
setProperty: (value, property, entry) => setSandboxProperty(value, property, entry, context.budget),
|
|
2677
|
+
setProperty: (value, property, entry) => setSandboxProperty(value, property, entry, context.budget, true, createCoercionContext(context)),
|
|
2584
2678
|
deleteProperty: deleteSandboxProperty,
|
|
2585
2679
|
callClosure: (closure, args, stack, thisValue) => invokeSandboxClosure(closure, args, context, stack, undefined, thisValue)
|
|
2586
2680
|
};
|
|
@@ -2600,10 +2694,10 @@ function createSetMethodOptions(context) {
|
|
|
2600
2694
|
function createFunctionMethodOptions(context) {
|
|
2601
2695
|
return {
|
|
2602
2696
|
budget: context.budget,
|
|
2603
|
-
callClosure: (closure, args, stack, thisValue, construct) => invokeSandboxClosure(closure, args, context, stack, undefined, thisValue, construct)
|
|
2697
|
+
callClosure: (closure, args, stack, thisValue, construct, newTarget) => invokeSandboxClosure(closure, args, context, stack, undefined, thisValue, construct, newTarget)
|
|
2604
2698
|
};
|
|
2605
2699
|
}
|
|
2606
|
-
async function invokeSandboxClosure(callee, args, context, stack, span, thisValue = undefined, construct = false) {
|
|
2700
|
+
async function invokeSandboxClosure(callee, args, context, stack, span, thisValue = undefined, construct = false, newTarget) {
|
|
2607
2701
|
const leaveCall = context.budget.enterCall();
|
|
2608
2702
|
try {
|
|
2609
2703
|
const invoke = construct ? callee.construct : callee.call;
|
|
@@ -2614,10 +2708,11 @@ async function invokeSandboxClosure(callee, args, context, stack, span, thisValu
|
|
|
2614
2708
|
{
|
|
2615
2709
|
stack,
|
|
2616
2710
|
thisValue,
|
|
2711
|
+
newTarget: construct ? newTarget ?? callee : undefined,
|
|
2617
2712
|
compilation: context.compilation,
|
|
2618
2713
|
getProperty: (value, property) => getPropertyValue(value, property, context),
|
|
2619
2714
|
reconcileData: (value) => reconcileDataBudget(context.budget, context.stats, context.scope, value, context.compilation, context.compilation?.parent),
|
|
2620
|
-
invokeClosure: (closure, argumentsList, receiver, asConstructor) => invokeSandboxClosure(closure, argumentsList, context, stack, span, receiver, asConstructor),
|
|
2715
|
+
invokeClosure: (closure, argumentsList, receiver, asConstructor, target) => invokeSandboxClosure(closure, argumentsList, context, stack, span, receiver, asConstructor, target),
|
|
2621
2716
|
...(span === undefined ? {} : { span })
|
|
2622
2717
|
}
|
|
2623
2718
|
]);
|
|
@@ -2728,16 +2823,28 @@ async function evaluateObjectSpread(node, context) {
|
|
|
2728
2823
|
}
|
|
2729
2824
|
return { ok: true, value: entries };
|
|
2730
2825
|
}
|
|
2731
|
-
if ((isSandboxClosure(value.value) && !isGuestClosure(value.value)) ||
|
|
2826
|
+
if ((isSandboxClosure(value.value) && !isGuestClosure(value.value)) ||
|
|
2827
|
+
isSandboxPromise(value.value)) {
|
|
2732
2828
|
throw new TypeError(`Cannot spread ${describeObjectSpreadValue(value.value)} into object literal.`);
|
|
2733
2829
|
}
|
|
2734
|
-
const spreadValue = isGuestClosure(value.value)
|
|
2830
|
+
const spreadValue = isGuestClosure(value.value)
|
|
2831
|
+
? (value.value.properties ?? {})
|
|
2832
|
+
: Object(value.value);
|
|
2735
2833
|
const keys = Object.keys(spreadValue);
|
|
2736
2834
|
context.budget.allocateArrayLength(keys.length);
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2835
|
+
const entries = [];
|
|
2836
|
+
const release = retainValues(context.budget, () => [value.value, entries]);
|
|
2837
|
+
try {
|
|
2838
|
+
for (const key of keys) {
|
|
2839
|
+
if (!hasOwnSandboxProperty(value.value, key, true))
|
|
2840
|
+
continue;
|
|
2841
|
+
entries.push([key, await getPropertyValue(value.value, key, context)]);
|
|
2842
|
+
}
|
|
2843
|
+
return { ok: true, value: entries };
|
|
2844
|
+
}
|
|
2845
|
+
finally {
|
|
2846
|
+
release();
|
|
2847
|
+
}
|
|
2741
2848
|
}
|
|
2742
2849
|
function describeObjectSpreadValue(value) {
|
|
2743
2850
|
if (value === null) {
|
|
@@ -44,6 +44,19 @@ export function getSandboxIterator(value, budget, context) {
|
|
|
44
44
|
if (isSandboxSet(value)) {
|
|
45
45
|
return collectionIterator(value.values);
|
|
46
46
|
}
|
|
47
|
+
if (Array.isArray(value) && context?.getProperty !== undefined) {
|
|
48
|
+
let index = 0;
|
|
49
|
+
return {
|
|
50
|
+
asynchronous: true,
|
|
51
|
+
snapshotIndex: () => index,
|
|
52
|
+
next: async () => {
|
|
53
|
+
if (index >= value.length)
|
|
54
|
+
return { done: true, value: undefined };
|
|
55
|
+
budget?.visitNode();
|
|
56
|
+
return { done: false, value: await context.getProperty(value, index++) };
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
47
60
|
if ((typeof value !== "object" && typeof value !== "function") || value === null) {
|
|
48
61
|
return undefined;
|
|
49
62
|
}
|
|
@@ -9,7 +9,7 @@ export type ArrayMethodOptions = {
|
|
|
9
9
|
budget: Budget;
|
|
10
10
|
context?: SandboxCallContext;
|
|
11
11
|
hasProperty?: (value: SandboxValue, property: string) => boolean;
|
|
12
|
-
setProperty?: (value: SandboxValue, property: string, entry: SandboxValue) => void
|
|
12
|
+
setProperty?: (value: SandboxValue, property: string, entry: SandboxValue) => void | Promise<void>;
|
|
13
13
|
deleteProperty?: (value: SandboxValue, property: string | number) => boolean;
|
|
14
14
|
callClosure: (closure: SandboxClosure, args: readonly SandboxValue[], stack: readonly string[], thisValue?: SandboxValue) => Promise<SandboxValue>;
|
|
15
15
|
};
|