poe-code 14.0.41 → 14.0.42
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 +219 -159
- 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-L4NMOY6O.js → chunk-IRDBTJYC.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-5J6BX3HD.js → chunk-M4M56OCI.js} +198 -150
- package/packages/safe-js/dist/chunks/chunk-M4M56OCI.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/exceptions.d.ts +1 -0
- package/packages/safe-js/dist/interp/exceptions.js +2 -4
- package/packages/safe-js/dist/interp/interpreter.js +55 -62
- package/packages/safe-js/dist/interp/patterns.d.ts +1 -0
- package/packages/safe-js/dist/interp/patterns.js +8 -11
- package/packages/safe-js/dist/interp/property-key.d.ts +3 -0
- package/packages/safe-js/dist/interp/property-key.js +53 -0
- package/packages/safe-js/dist/snapshot/restore.js +3 -0
- package/packages/safe-js/dist/chunks/chunk-5J6BX3HD.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-L4NMOY6O.js.map → chunk-IRDBTJYC.js.map} +0 -0
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveFsConfig,
|
|
23
23
|
splitFrontmatter,
|
|
24
24
|
withBrokenPipeGuard
|
|
25
|
-
} from "./chunks/chunk-
|
|
25
|
+
} from "./chunks/chunk-IRDBTJYC.js";
|
|
26
26
|
import {
|
|
27
27
|
Budget,
|
|
28
28
|
SandboxError,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
replaceErrorStack,
|
|
35
35
|
restore,
|
|
36
36
|
run
|
|
37
|
-
} from "./chunks/chunk-
|
|
37
|
+
} from "./chunks/chunk-M4M56OCI.js";
|
|
38
38
|
import "./chunks/chunk-UXMKEUH3.js";
|
|
39
39
|
import "./chunks/chunk-5DYEOCT5.js";
|
|
40
40
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
runWithSpawnUsageAccumulator,
|
|
27
27
|
splitFrontmatter,
|
|
28
28
|
supportsSpawnMode
|
|
29
|
-
} from "./chunks/chunk-
|
|
29
|
+
} from "./chunks/chunk-IRDBTJYC.js";
|
|
30
30
|
import {
|
|
31
31
|
Budget,
|
|
32
32
|
FileSnapshotBackend,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
registerPendingHostCallPolicy,
|
|
51
51
|
restore,
|
|
52
52
|
run
|
|
53
|
-
} from "./chunks/chunk-
|
|
53
|
+
} from "./chunks/chunk-M4M56OCI.js";
|
|
54
54
|
import "./chunks/chunk-UXMKEUH3.js";
|
|
55
55
|
import "./chunks/chunk-5DYEOCT5.js";
|
|
56
56
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -29,6 +29,7 @@ type ExceptionContext = {
|
|
|
29
29
|
budget: Budget;
|
|
30
30
|
callStack: readonly string[];
|
|
31
31
|
scope: Scope;
|
|
32
|
+
toPropertyKey?: (value: SandboxValue) => Promise<string>;
|
|
32
33
|
};
|
|
33
34
|
type EvaluateExceptionNode<TContext, TError> = (node: ParseResult, context: TContext) => Promise<EvaluationResult<TError>>;
|
|
34
35
|
export declare function evaluateThrowStatement<TContext extends ExceptionContext, TError>(node: ThrowStatement, context: TContext, evaluateNode: EvaluateExceptionNode<TContext, TError>): Promise<EvaluationResult<TError>>;
|
|
@@ -3,6 +3,7 @@ import { SandboxError } from "./budget.js";
|
|
|
3
3
|
import { HostCallResumabilityError } from "./host-call.js";
|
|
4
4
|
import { withFatalPromiseCleanup } from "./promise-tracker.js";
|
|
5
5
|
import { deepCopyToSandbox } from "./values.js";
|
|
6
|
+
import { toPropertyKey } from "./property-key.js";
|
|
6
7
|
const capturedExceptionBrand = Symbol("CapturedException");
|
|
7
8
|
export async function evaluateThrowStatement(node, context, evaluateNode) {
|
|
8
9
|
const argument = await evaluateNode(node.argument, context);
|
|
@@ -389,12 +390,9 @@ async function resolvePatternPropertyKey(property, context, evaluateNode) {
|
|
|
389
390
|
result: computedKey
|
|
390
391
|
};
|
|
391
392
|
}
|
|
392
|
-
if (typeof computedKey.value !== "string" && typeof computedKey.value !== "number") {
|
|
393
|
-
throw new TypeError("Computed catch binding keys must evaluate to a string or number.");
|
|
394
|
-
}
|
|
395
393
|
return {
|
|
396
394
|
ok: true,
|
|
397
|
-
value: computedKey.value
|
|
395
|
+
value: await (context.toPropertyKey?.(computedKey.value) ?? toPropertyKey(computedKey.value, context.budget, { stack: context.callStack, thisValue: undefined }))
|
|
398
396
|
};
|
|
399
397
|
}
|
|
400
398
|
function getStaticPropertyKey(property) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promiseReplayContext } from "./promise-replay.js";
|
|
2
2
|
import { deleteHostObjectMember, getHostObjectKeys, getHostObjectMember, hasHostObjectMember, isGuestHostObject, setHostObjectMember } from "./host-capabilities.js";
|
|
3
|
-
import {
|
|
3
|
+
import { toPropertyKey } from "./property-key.js";
|
|
4
4
|
import { assertPromiseExecutionAllowed } from "./promise-tracker.js";
|
|
5
5
|
import { SandboxJobQueue, runAsyncPrefix, suspendJob } from "./jobs.js";
|
|
6
6
|
import { withCancellationSignal } from "./cancel.js";
|
|
@@ -444,7 +444,7 @@ async function evaluateBinaryExpression(node, context) {
|
|
|
444
444
|
if (typeof right.value !== "object" || right.value === null) {
|
|
445
445
|
throw new TypeError("Right-hand side of 'in' must be an object.");
|
|
446
446
|
}
|
|
447
|
-
leftValue = await toPropertyKey(leftValue, context);
|
|
447
|
+
leftValue = await toPropertyKey(leftValue, context.budget, createCoercionContext(context));
|
|
448
448
|
}
|
|
449
449
|
const value = applyBinaryOperator(node, leftValue, right.value, context);
|
|
450
450
|
return {
|
|
@@ -535,7 +535,15 @@ async function evaluateMemberAssignmentExpression(node, context) {
|
|
|
535
535
|
if (member.kind === "nullish") {
|
|
536
536
|
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
537
537
|
}
|
|
538
|
-
|
|
538
|
+
let property;
|
|
539
|
+
let current = undefined;
|
|
540
|
+
if (node.operator !== "=") {
|
|
541
|
+
if (member.object === null || member.object === undefined) {
|
|
542
|
+
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
543
|
+
}
|
|
544
|
+
property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
545
|
+
current = getPropertyValue(member.object, property, context);
|
|
546
|
+
}
|
|
539
547
|
if (node.operator === "&&=" && !isTruthy(current)) {
|
|
540
548
|
return {
|
|
541
549
|
kind: "normal",
|
|
@@ -567,7 +575,11 @@ async function evaluateMemberAssignmentExpression(node, context) {
|
|
|
567
575
|
node.operator === "??="
|
|
568
576
|
? right.value
|
|
569
577
|
: await applyCompoundAssignmentOperator(node.operator, current, right.value, context);
|
|
570
|
-
|
|
578
|
+
if (member.object === null || member.object === undefined) {
|
|
579
|
+
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
580
|
+
}
|
|
581
|
+
property ??= await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
582
|
+
setSandboxProperty(member.object, property, value, context.budget);
|
|
571
583
|
return {
|
|
572
584
|
kind: "normal",
|
|
573
585
|
hasValue: true,
|
|
@@ -1523,7 +1535,10 @@ async function evaluateThrowStatement(node, context) {
|
|
|
1523
1535
|
return evaluateThrowStatementResult(node, context, evaluateNode);
|
|
1524
1536
|
}
|
|
1525
1537
|
async function evaluateTryStatement(node, context) {
|
|
1526
|
-
return evaluateTryStatementResult(node,
|
|
1538
|
+
return evaluateTryStatementResult(node, {
|
|
1539
|
+
...context,
|
|
1540
|
+
toPropertyKey: (value) => toPropertyKey(value, context.budget, createCoercionContext(context))
|
|
1541
|
+
}, evaluateNode);
|
|
1527
1542
|
}
|
|
1528
1543
|
async function evaluateUnaryExpression(node, context) {
|
|
1529
1544
|
if (node.operator === "delete") {
|
|
@@ -1566,8 +1581,8 @@ async function evaluateDeleteExpression(node, context) {
|
|
|
1566
1581
|
if (member.kind === "completion") {
|
|
1567
1582
|
return member.result;
|
|
1568
1583
|
}
|
|
1569
|
-
if (member.kind === "nullish") {
|
|
1570
|
-
if (node.argument.optional) {
|
|
1584
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1585
|
+
if (member.kind === "nullish" && node.argument.optional) {
|
|
1571
1586
|
return {
|
|
1572
1587
|
kind: "normal",
|
|
1573
1588
|
hasValue: true,
|
|
@@ -1579,7 +1594,8 @@ async function evaluateDeleteExpression(node, context) {
|
|
|
1579
1594
|
if (!isIndexableSandboxValue(member.object)) {
|
|
1580
1595
|
throw new TypeError("Unary operator 'delete' requires a sandbox object property.");
|
|
1581
1596
|
}
|
|
1582
|
-
const
|
|
1597
|
+
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
1598
|
+
const deleted = deleteSandboxProperty(member.object, property);
|
|
1583
1599
|
return {
|
|
1584
1600
|
kind: "normal",
|
|
1585
1601
|
hasValue: true,
|
|
@@ -1623,12 +1639,13 @@ async function evaluateMemberUpdateExpression(node, context) {
|
|
|
1623
1639
|
if (member.kind === "completion") {
|
|
1624
1640
|
return member.result;
|
|
1625
1641
|
}
|
|
1626
|
-
if (member.kind === "nullish") {
|
|
1642
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1627
1643
|
throw new TypeError("Cannot update properties of null or undefined.");
|
|
1628
1644
|
}
|
|
1629
|
-
const
|
|
1645
|
+
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
1646
|
+
const current = toNumber(await toNumericPrimitive(getPropertyValue(member.object, property, context), context));
|
|
1630
1647
|
const next = node.operator === "++" ? current + 1 : current - 1;
|
|
1631
|
-
setSandboxProperty(member.object,
|
|
1648
|
+
setSandboxProperty(member.object, property, next, context.budget);
|
|
1632
1649
|
return {
|
|
1633
1650
|
kind: "normal",
|
|
1634
1651
|
hasValue: true,
|
|
@@ -1641,15 +1658,15 @@ async function evaluateMemberExpression(node, context) {
|
|
|
1641
1658
|
return member;
|
|
1642
1659
|
if (member.kind === "completion")
|
|
1643
1660
|
return member.result;
|
|
1644
|
-
if (member.kind === "nullish") {
|
|
1645
|
-
if (node.optional)
|
|
1661
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1662
|
+
if (member.kind === "nullish" && node.optional)
|
|
1646
1663
|
return { kind: "normal", hasValue: true, value: undefined };
|
|
1647
1664
|
throw new TypeError("Cannot read properties of null or undefined.");
|
|
1648
1665
|
}
|
|
1649
1666
|
return {
|
|
1650
1667
|
kind: "normal",
|
|
1651
1668
|
hasValue: true,
|
|
1652
|
-
value: getPropertyValue(member.object, member.property, context)
|
|
1669
|
+
value: getPropertyValue(member.object, await toPropertyKey(member.property, context.budget, createCoercionContext(context)), context)
|
|
1653
1670
|
};
|
|
1654
1671
|
}
|
|
1655
1672
|
function getPropertyValue(target, property, context) {
|
|
@@ -1686,6 +1703,7 @@ export function createPatternContext(context, scope = context.scope, evaluate =
|
|
|
1686
1703
|
const evaluationContext = { ...context, scope };
|
|
1687
1704
|
return {
|
|
1688
1705
|
evaluate: node => evaluate(node, evaluationContext),
|
|
1706
|
+
toPropertyKey: value => toPropertyKey(value, context.budget, createCoercionContext(evaluationContext)),
|
|
1689
1707
|
getProperty: (value, key) => getPropertyValue(value, key, evaluationContext),
|
|
1690
1708
|
setProperty: (target, key, value) => setSandboxProperty(target, key, value, context.budget)
|
|
1691
1709
|
};
|
|
@@ -1773,24 +1791,10 @@ async function evaluateMemberAccess(node, context) {
|
|
|
1773
1791
|
};
|
|
1774
1792
|
}
|
|
1775
1793
|
const property = node.computed
|
|
1776
|
-
? await
|
|
1777
|
-
: {
|
|
1778
|
-
if (
|
|
1779
|
-
return
|
|
1780
|
-
? {
|
|
1781
|
-
kind: "error",
|
|
1782
|
-
error: property.result.error
|
|
1783
|
-
}
|
|
1784
|
-
: {
|
|
1785
|
-
kind: "completion",
|
|
1786
|
-
result: property.result
|
|
1787
|
-
};
|
|
1788
|
-
}
|
|
1789
|
-
if (object.value === null || object.value === undefined) {
|
|
1790
|
-
return {
|
|
1791
|
-
kind: "nullish"
|
|
1792
|
-
};
|
|
1793
|
-
}
|
|
1794
|
+
? await evaluateNode(node.property, context)
|
|
1795
|
+
: { kind: "normal", value: getStaticPropertyName(node.property) };
|
|
1796
|
+
if (property.kind !== "normal")
|
|
1797
|
+
return { kind: "completion", result: property };
|
|
1794
1798
|
return {
|
|
1795
1799
|
kind: "resolved",
|
|
1796
1800
|
object: object.value,
|
|
@@ -1805,13 +1809,10 @@ async function evaluateMemberProperty(node, context) {
|
|
|
1805
1809
|
result: property
|
|
1806
1810
|
};
|
|
1807
1811
|
}
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
};
|
|
1813
|
-
}
|
|
1814
|
-
throw new TypeError("Computed property access requires a string or number key.");
|
|
1812
|
+
return {
|
|
1813
|
+
ok: true,
|
|
1814
|
+
value: await toPropertyKey(property.value, context.budget, createCoercionContext(context))
|
|
1815
|
+
};
|
|
1815
1816
|
}
|
|
1816
1817
|
async function evaluateObjectPropertyKey(node, context) {
|
|
1817
1818
|
if (!node.computed) {
|
|
@@ -1835,15 +1836,15 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1835
1836
|
if (node.callee.type !== "MemberExpression") {
|
|
1836
1837
|
throw new TypeError("Expected member call expression.");
|
|
1837
1838
|
}
|
|
1838
|
-
const
|
|
1839
|
-
if (
|
|
1840
|
-
return
|
|
1839
|
+
const reference = await evaluateMemberAccess(node.callee, context);
|
|
1840
|
+
if (reference.kind === "error") {
|
|
1841
|
+
return reference;
|
|
1841
1842
|
}
|
|
1842
|
-
if (
|
|
1843
|
-
return
|
|
1843
|
+
if (reference.kind === "completion") {
|
|
1844
|
+
return reference.result;
|
|
1844
1845
|
}
|
|
1845
|
-
if (
|
|
1846
|
-
if (
|
|
1846
|
+
if (reference.kind === "nullish" || reference.object === null || reference.object === undefined) {
|
|
1847
|
+
if (reference.kind === "nullish") {
|
|
1847
1848
|
return {
|
|
1848
1849
|
kind: "normal",
|
|
1849
1850
|
hasValue: true,
|
|
@@ -1852,6 +1853,10 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1852
1853
|
}
|
|
1853
1854
|
throw new TypeError("Cannot read properties of null or undefined.");
|
|
1854
1855
|
}
|
|
1856
|
+
const member = {
|
|
1857
|
+
...reference,
|
|
1858
|
+
property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
|
|
1859
|
+
};
|
|
1855
1860
|
if (typeof member.object === "string" && isStringMethodName(member.property)) {
|
|
1856
1861
|
return evaluateStringMethodCall(node, member.object, member.property, context);
|
|
1857
1862
|
}
|
|
@@ -2124,25 +2129,13 @@ function applyBinaryOperator(node, left, right, context) {
|
|
|
2124
2129
|
return hasSandboxProperty(right, left, context);
|
|
2125
2130
|
}
|
|
2126
2131
|
}
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
!isSandboxGenerator(value) && !isGuestHostObject(value)) {
|
|
2130
|
-
for (const name of ["toString", "valueOf"]) {
|
|
2131
|
-
const method = getMemberValue(value, name, context);
|
|
2132
|
-
if (!isSandboxClosure(method))
|
|
2133
|
-
continue;
|
|
2134
|
-
const primitive = await invokeSandboxClosure(method, [], context, context.callStack, undefined, value);
|
|
2135
|
-
if (primitive === null || typeof primitive !== "object") {
|
|
2136
|
-
return context.budget.allocateString(String(primitive));
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
throw new TypeError("Cannot convert object to primitive value.");
|
|
2140
|
-
}
|
|
2141
|
-
return sandboxString(value, context.budget, {
|
|
2132
|
+
function createCoercionContext(context) {
|
|
2133
|
+
return {
|
|
2142
2134
|
stack: context.callStack,
|
|
2143
2135
|
thisValue: undefined,
|
|
2136
|
+
compilation: context.compilation,
|
|
2144
2137
|
invokeClosure: (closure, args, thisValue) => invokeSandboxClosure(closure, args, context, context.callStack, undefined, thisValue)
|
|
2145
|
-
}
|
|
2138
|
+
};
|
|
2146
2139
|
}
|
|
2147
2140
|
function hasSandboxProperty(value, key, context) {
|
|
2148
2141
|
let current = value;
|
|
@@ -11,6 +11,7 @@ export type PatternTarget = {
|
|
|
11
11
|
};
|
|
12
12
|
export type PatternContext = {
|
|
13
13
|
evaluate(node: ParseResult): Promise<AsyncEvaluationResult>;
|
|
14
|
+
toPropertyKey(value: SandboxValue): Promise<string>;
|
|
14
15
|
getProperty(value: SandboxValue, key: string | number): SandboxValue;
|
|
15
16
|
setProperty(target: SandboxValue, key: string | number, value: SandboxValue): void;
|
|
16
17
|
};
|
|
@@ -90,19 +90,19 @@ async function bindMemberExpression(pattern, value, scope, context) {
|
|
|
90
90
|
if (object.kind !== "normal") {
|
|
91
91
|
return { ok: false, result: object };
|
|
92
92
|
}
|
|
93
|
+
const property = pattern.computed
|
|
94
|
+
? await context.evaluate(pattern.property)
|
|
95
|
+
: { kind: "normal", value: getStaticPropertyName(pattern.property) };
|
|
96
|
+
if (property.kind !== "normal") {
|
|
97
|
+
return { ok: false, result: property };
|
|
98
|
+
}
|
|
93
99
|
if (object.value === null || object.value === undefined) {
|
|
94
100
|
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
95
101
|
}
|
|
96
102
|
if (!isIndexableValue(object.value)) {
|
|
97
103
|
throw new TypeError("Assignment expressions require a sandbox object property.");
|
|
98
104
|
}
|
|
99
|
-
|
|
100
|
-
? await evaluateProperty(pattern.property, context)
|
|
101
|
-
: { ok: true, value: getStaticPropertyName(pattern.property) };
|
|
102
|
-
if (!property.ok) {
|
|
103
|
-
return property;
|
|
104
|
-
}
|
|
105
|
-
context.setProperty(object.value, property.value, value);
|
|
105
|
+
context.setProperty(object.value, await context.toPropertyKey(property.value), value);
|
|
106
106
|
return { ok: true };
|
|
107
107
|
}
|
|
108
108
|
async function evaluatePatternKey(property, context) {
|
|
@@ -115,10 +115,7 @@ async function evaluateProperty(property, context) {
|
|
|
115
115
|
if (result.kind !== "normal") {
|
|
116
116
|
return { ok: false, result };
|
|
117
117
|
}
|
|
118
|
-
|
|
119
|
-
throw new TypeError("Computed property access requires a string or number key.");
|
|
120
|
-
}
|
|
121
|
-
return { ok: true, value: result.value };
|
|
118
|
+
return { ok: true, value: await context.toPropertyKey(result.value) };
|
|
122
119
|
}
|
|
123
120
|
function getStaticPropertyName(property) {
|
|
124
121
|
if (property.type === "Identifier") {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isSandboxDate } from "./date.js";
|
|
2
|
+
import { isFloat32Array } from "./float32.js";
|
|
3
|
+
import { isGuestHostObject } from "./host-capabilities.js";
|
|
4
|
+
import { getSandboxDataProperty } from "./object-model.js";
|
|
5
|
+
import { sandboxString } from "./string-coercion.js";
|
|
6
|
+
import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "./values.js";
|
|
7
|
+
export async function toPropertyKey(value, budget, context) {
|
|
8
|
+
if (typeof value === "string")
|
|
9
|
+
return value;
|
|
10
|
+
const invocation = context.invokeClosure === undefined
|
|
11
|
+
? {
|
|
12
|
+
...context,
|
|
13
|
+
invokeClosure: async (closure, args, thisValue) => {
|
|
14
|
+
const leaveCall = budget.enterCall();
|
|
15
|
+
try {
|
|
16
|
+
const result = closure.call(args, { ...invocation, thisValue });
|
|
17
|
+
if (isSandboxPromise(result)) {
|
|
18
|
+
await result.synchronousPrefix;
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
return await result;
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
leaveCall();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
: context;
|
|
29
|
+
if (typeof value === "object" &&
|
|
30
|
+
value !== null &&
|
|
31
|
+
!Array.isArray(value) &&
|
|
32
|
+
!isSandboxClosure(value) &&
|
|
33
|
+
!isSandboxMap(value) &&
|
|
34
|
+
!isSandboxSet(value) &&
|
|
35
|
+
!isSandboxPromise(value) &&
|
|
36
|
+
!isSandboxRegex(value) &&
|
|
37
|
+
!isSandboxDate(value) &&
|
|
38
|
+
!isFloat32Array(value) &&
|
|
39
|
+
!isSandboxGenerator(value) &&
|
|
40
|
+
!isGuestHostObject(value)) {
|
|
41
|
+
for (const name of ["toString", "valueOf"]) {
|
|
42
|
+
const method = getSandboxDataProperty(value, name, budget);
|
|
43
|
+
if (!isSandboxClosure(method))
|
|
44
|
+
continue;
|
|
45
|
+
const primitive = await invocation.invokeClosure(method, [], value);
|
|
46
|
+
if (primitive === null || typeof primitive !== "object") {
|
|
47
|
+
return budget.allocateString(String(primitive));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
throw new TypeError("Cannot convert object to primitive value.");
|
|
51
|
+
}
|
|
52
|
+
return sandboxString(value, budget, invocation);
|
|
53
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Budget, SandboxError } from "../interp/budget.js";
|
|
2
2
|
import { executeAsyncFunction } from "../interp/async.js";
|
|
3
|
+
import { toPropertyKey } from "../interp/property-key.js";
|
|
3
4
|
import { CompileScope } from "../interp/regex/compile-guard.js";
|
|
4
5
|
import { decodeFloat32Storage } from "./float32array.js";
|
|
5
6
|
import { restoreDateTime } from "../interp/date.js";
|
|
@@ -500,6 +501,7 @@ async function executeRestoredClosure(node, capturedScopeId, closure, args, this
|
|
|
500
501
|
const rest = args.slice(index);
|
|
501
502
|
state.budget.allocateArrayLength(rest.length);
|
|
502
503
|
const binding = await bindPattern(param, rest, { kind: "let" }, scope, {
|
|
504
|
+
toPropertyKey: value => toPropertyKey(value, state.budget, { ...callContext, stack: callContext?.stack ?? [], thisValue, compilation }),
|
|
503
505
|
getProperty: (value, key) => getSandboxDataProperty(value, key, state.budget),
|
|
504
506
|
setProperty: (target, key, value) => setSandboxProperty(target, key, value, state.budget),
|
|
505
507
|
evaluate: async (defaultNode) => {
|
|
@@ -530,6 +532,7 @@ async function executeRestoredClosure(node, capturedScopeId, closure, args, this
|
|
|
530
532
|
break;
|
|
531
533
|
}
|
|
532
534
|
const binding = await bindPattern(param, args[index], { kind: "let" }, scope, {
|
|
535
|
+
toPropertyKey: value => toPropertyKey(value, state.budget, { ...callContext, stack: callContext?.stack ?? [], thisValue, compilation }),
|
|
533
536
|
getProperty: (value, key) => getSandboxDataProperty(value, key, state.budget),
|
|
534
537
|
setProperty: (target, key, value) => setSandboxProperty(target, key, value, state.budget),
|
|
535
538
|
evaluate: async (defaultNode) => {
|