poe-code 14.0.56 → 14.0.58
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 +401 -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-SRYQTOX4.js → chunk-3VTLNK4E.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-XI33TU4X.js → chunk-DHD453E5.js} +393 -336
- package/packages/safe-js/dist/chunks/chunk-DHD453E5.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/globals/misc.js +20 -7
- package/packages/safe-js/dist/interp/interpreter.js +194 -213
- package/packages/safe-js/dist/interp/methods/regex.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/regex.js +18 -6
- package/packages/safe-js/dist/interp/methods/string.js +59 -26
- package/packages/safe-js/dist/interp/regex/engine.d.ts +1 -0
- package/packages/safe-js/dist/interp/regex/engine.js +3 -3
- package/packages/safe-js/dist/interp/resources.d.ts +1 -0
- package/packages/safe-js/dist/interp/resources.js +4 -0
- package/packages/safe-js/dist/interp/values.d.ts +6 -3
- package/packages/safe-js/dist/interp/values.js +19 -6
- package/packages/safe-js/dist/realm.js +6 -2
- package/packages/safe-js/dist/snapshot/replay-data.d.ts +1 -1
- package/packages/safe-js/dist/snapshot/replay-data.js +4 -4
- package/packages/safe-js/dist/snapshot/restore.js +8 -0
- package/packages/safe-js/dist/snapshot/serialize.d.ts +6 -1
- package/packages/safe-js/dist/snapshot/serialize.js +14 -1
- package/packages/safe-js/dist/snapshot/validation.js +8 -2
- package/packages/safe-js/dist/chunks/chunk-XI33TU4X.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-SRYQTOX4.js.map → chunk-3VTLNK4E.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-3VTLNK4E.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-DHD453E5.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-3VTLNK4E.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-DHD453E5.js";
|
|
54
54
|
import "./chunks/chunk-UXMKEUH3.js";
|
|
55
55
|
import "./chunks/chunk-5DYEOCT5.js";
|
|
56
56
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { isSandboxCollectionIterator } from "../collection-iterator.js";
|
|
2
2
|
import { assertSandboxGraphDepth } from "../../graph-depth.js";
|
|
3
|
-
import {
|
|
3
|
+
import { CompileScope } from "../regex/compile-guard.js";
|
|
4
|
+
import { allocateProducedSandboxValue, cloneSandboxValue, createSandboxClosure, isSandboxClosure, isSandboxMap, isSandboxPromise, isSandboxSet, reconcileCompiledValues } from "../values.js";
|
|
4
5
|
export function createMiscGlobals(options) {
|
|
5
6
|
return {
|
|
6
7
|
structuredClone: createSandboxClosure({
|
|
7
8
|
sandbox: true,
|
|
8
|
-
call: ([value]) => structuredCloneSandboxValue(value, options.budget),
|
|
9
|
+
call: ([value], context) => structuredCloneSandboxValue(value, options.budget, context?.compilation),
|
|
9
10
|
name: "structuredClone"
|
|
10
11
|
}),
|
|
11
12
|
parseInt: createSandboxClosure({
|
|
@@ -30,11 +31,23 @@ export function createMiscGlobals(options) {
|
|
|
30
31
|
})
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
|
-
function structuredCloneSandboxValue(value, budget) {
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
function structuredCloneSandboxValue(value, budget, parent) {
|
|
35
|
+
const operation = budget.acquireCompileOwner(false, parent?.owner);
|
|
36
|
+
const compilation = parent?.owner === operation.owner ? parent : new CompileScope(operation.owner);
|
|
37
|
+
try {
|
|
38
|
+
const clone = cloneSandboxValue(value, { compilation, resetRegexLastIndex: true });
|
|
39
|
+
assertSandboxGraphDepth(clone);
|
|
40
|
+
assertStructuredCloneable(clone, new WeakSet());
|
|
41
|
+
allocateProducedSandboxValue(clone, budget);
|
|
42
|
+
if (compilation !== parent)
|
|
43
|
+
reconcileCompiledValues(budget, [clone], compilation);
|
|
44
|
+
return clone;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
if (compilation !== parent)
|
|
48
|
+
compilation.dispose();
|
|
49
|
+
operation.release();
|
|
50
|
+
}
|
|
38
51
|
}
|
|
39
52
|
function assertStructuredCloneable(value, seen) {
|
|
40
53
|
if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value)) {
|
|
@@ -4,6 +4,7 @@ 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";
|
|
7
|
+
import { runResources } from "./resources.js";
|
|
7
8
|
import { attachErrorSpan, formatErrorStack, replaceErrorStack } from "../error/shape.js";
|
|
8
9
|
import { evaluateArrowFunctionExpression, evaluateFunctionExpression, evaluateAwaitExpression, emitResumeBreakpoint, createInterpretedClosure, normalizeClosureResult } from "./async.js";
|
|
9
10
|
import { HostCallResumabilityError } from "./host-call.js";
|
|
@@ -519,66 +520,61 @@ async function evaluateMemberAssignmentExpression(node, context) {
|
|
|
519
520
|
if (node.left.type !== "MemberExpression") {
|
|
520
521
|
throw new TypeError("Expected member assignment target.");
|
|
521
522
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
523
|
+
return evaluateMemberAccess(node.left, context, async (member) => {
|
|
524
|
+
if (member.kind === "nullish") {
|
|
525
|
+
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
526
|
+
}
|
|
527
|
+
let property;
|
|
528
|
+
let current = undefined;
|
|
529
|
+
if (node.operator !== "=") {
|
|
530
|
+
if (member.object === null || member.object === undefined) {
|
|
531
|
+
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
532
|
+
}
|
|
533
|
+
property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
534
|
+
current = getPropertyValue(member.object, property, context);
|
|
535
|
+
}
|
|
536
|
+
if (node.operator === "&&=" && !isTruthy(current)) {
|
|
537
|
+
return {
|
|
538
|
+
kind: "normal",
|
|
539
|
+
hasValue: true,
|
|
540
|
+
value: current
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
if (node.operator === "||=" && isTruthy(current)) {
|
|
544
|
+
return {
|
|
545
|
+
kind: "normal",
|
|
546
|
+
hasValue: true,
|
|
547
|
+
value: current
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
if (node.operator === "??=" && current !== null && current !== undefined) {
|
|
551
|
+
return {
|
|
552
|
+
kind: "normal",
|
|
553
|
+
hasValue: true,
|
|
554
|
+
value: current
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
const right = await evaluateNode(node.right, context);
|
|
558
|
+
if (right.kind !== "normal") {
|
|
559
|
+
return right;
|
|
560
|
+
}
|
|
561
|
+
const value = node.operator === "=" ||
|
|
562
|
+
node.operator === "&&=" ||
|
|
563
|
+
node.operator === "||=" ||
|
|
564
|
+
node.operator === "??="
|
|
565
|
+
? right.value
|
|
566
|
+
: await applyCompoundAssignmentOperator(node.operator, current, right.value, context);
|
|
535
567
|
if (member.object === null || member.object === undefined) {
|
|
536
568
|
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
537
569
|
}
|
|
538
|
-
property
|
|
539
|
-
|
|
540
|
-
}
|
|
541
|
-
if (node.operator === "&&=" && !isTruthy(current)) {
|
|
542
|
-
return {
|
|
543
|
-
kind: "normal",
|
|
544
|
-
hasValue: true,
|
|
545
|
-
value: current
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
if (node.operator === "||=" && isTruthy(current)) {
|
|
570
|
+
property ??= await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
571
|
+
setSandboxProperty(member.object, property, value, context.budget);
|
|
549
572
|
return {
|
|
550
573
|
kind: "normal",
|
|
551
574
|
hasValue: true,
|
|
552
|
-
value
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
if (node.operator === "??=" && current !== null && current !== undefined) {
|
|
556
|
-
return {
|
|
557
|
-
kind: "normal",
|
|
558
|
-
hasValue: true,
|
|
559
|
-
value: current
|
|
575
|
+
value
|
|
560
576
|
};
|
|
561
|
-
}
|
|
562
|
-
const right = await evaluateNode(node.right, context);
|
|
563
|
-
if (right.kind !== "normal") {
|
|
564
|
-
return right;
|
|
565
|
-
}
|
|
566
|
-
const value = node.operator === "=" ||
|
|
567
|
-
node.operator === "&&=" ||
|
|
568
|
-
node.operator === "||=" ||
|
|
569
|
-
node.operator === "??="
|
|
570
|
-
? right.value
|
|
571
|
-
: await applyCompoundAssignmentOperator(node.operator, current, right.value, context);
|
|
572
|
-
if (member.object === null || member.object === undefined) {
|
|
573
|
-
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
574
|
-
}
|
|
575
|
-
property ??= await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
576
|
-
setSandboxProperty(member.object, property, value, context.budget);
|
|
577
|
-
return {
|
|
578
|
-
kind: "normal",
|
|
579
|
-
hasValue: true,
|
|
580
|
-
value
|
|
581
|
-
};
|
|
577
|
+
});
|
|
582
578
|
}
|
|
583
579
|
async function evaluateLogicalExpression(node, context) {
|
|
584
580
|
const left = await evaluateNode(node.left, context);
|
|
@@ -1572,33 +1568,28 @@ async function evaluateDeleteExpression(node, context) {
|
|
|
1572
1568
|
if (node.argument.type !== "MemberExpression") {
|
|
1573
1569
|
throw createError("UNSUPPORTED_NODE", node, "Unary operator 'delete' requires a member target.");
|
|
1574
1570
|
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
kind: "normal",
|
|
1586
|
-
hasValue: true,
|
|
1587
|
-
value: true
|
|
1588
|
-
};
|
|
1571
|
+
return evaluateMemberAccess(node.argument, context, async (member) => {
|
|
1572
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1573
|
+
if (member.kind === "nullish") {
|
|
1574
|
+
return {
|
|
1575
|
+
kind: "normal",
|
|
1576
|
+
hasValue: true,
|
|
1577
|
+
value: true
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
throw new TypeError("Cannot delete properties of null or undefined.");
|
|
1589
1581
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
};
|
|
1582
|
+
if (!isIndexableSandboxValue(member.object)) {
|
|
1583
|
+
throw new TypeError("Unary operator 'delete' requires a sandbox object property.");
|
|
1584
|
+
}
|
|
1585
|
+
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
1586
|
+
const deleted = deleteSandboxProperty(member.object, property);
|
|
1587
|
+
return {
|
|
1588
|
+
kind: "normal",
|
|
1589
|
+
hasValue: true,
|
|
1590
|
+
value: deleted
|
|
1591
|
+
};
|
|
1592
|
+
});
|
|
1602
1593
|
}
|
|
1603
1594
|
async function evaluateUpdateExpression(node, context) {
|
|
1604
1595
|
if (node.argument.type === "Identifier") {
|
|
@@ -1630,42 +1621,34 @@ async function evaluateMemberUpdateExpression(node, context) {
|
|
|
1630
1621
|
if (node.argument.type !== "MemberExpression") {
|
|
1631
1622
|
throw new TypeError("Expected member update target.");
|
|
1632
1623
|
}
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
return {
|
|
1648
|
-
kind: "normal",
|
|
1649
|
-
hasValue: true,
|
|
1650
|
-
value: node.prefix ? next : current
|
|
1651
|
-
};
|
|
1624
|
+
return evaluateMemberAccess(node.argument, context, async (member) => {
|
|
1625
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1626
|
+
throw new TypeError("Cannot update properties of null or undefined.");
|
|
1627
|
+
}
|
|
1628
|
+
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
1629
|
+
const current = toNumber(await toNumericPrimitive(getPropertyValue(member.object, property, context), context));
|
|
1630
|
+
const next = node.operator === "++" ? current + 1 : current - 1;
|
|
1631
|
+
setSandboxProperty(member.object, property, next, context.budget);
|
|
1632
|
+
return {
|
|
1633
|
+
kind: "normal",
|
|
1634
|
+
hasValue: true,
|
|
1635
|
+
value: node.prefix ? next : current
|
|
1636
|
+
};
|
|
1637
|
+
});
|
|
1652
1638
|
}
|
|
1653
1639
|
async function evaluateMemberExpression(node, context) {
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
hasValue: true,
|
|
1667
|
-
value: getPropertyValue(member.object, await toPropertyKey(member.property, context.budget, createCoercionContext(context)), context)
|
|
1668
|
-
};
|
|
1640
|
+
return evaluateMemberAccess(node, context, async (member) => {
|
|
1641
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1642
|
+
if (member.kind === "nullish")
|
|
1643
|
+
return { kind: "normal", hasValue: true, value: undefined };
|
|
1644
|
+
throw new TypeError("Cannot read properties of null or undefined.");
|
|
1645
|
+
}
|
|
1646
|
+
return {
|
|
1647
|
+
kind: "normal",
|
|
1648
|
+
hasValue: true,
|
|
1649
|
+
value: getPropertyValue(member.object, await toPropertyKey(member.property, context.budget, createCoercionContext(context)), context)
|
|
1650
|
+
};
|
|
1651
|
+
});
|
|
1669
1652
|
}
|
|
1670
1653
|
function getPropertyValue(target, property, context) {
|
|
1671
1654
|
if (isGuestHostObject(target))
|
|
@@ -1778,29 +1761,32 @@ function attachFatalSandboxErrorContext(error, node, stackFrames) {
|
|
|
1778
1761
|
attachErrorSpan(error, node.span);
|
|
1779
1762
|
replaceErrorStack(error, stackFrames);
|
|
1780
1763
|
}
|
|
1781
|
-
async function evaluateMemberAccess(node, context) {
|
|
1764
|
+
async function evaluateMemberAccess(node, context, consume) {
|
|
1782
1765
|
const object = await evaluateNode(node.object, context);
|
|
1783
|
-
if (object.kind !== "normal")
|
|
1784
|
-
return
|
|
1785
|
-
kind: "completion",
|
|
1786
|
-
result: object
|
|
1787
|
-
};
|
|
1788
|
-
}
|
|
1766
|
+
if (object.kind !== "normal")
|
|
1767
|
+
return object;
|
|
1789
1768
|
if ((object.value === null || object.value === undefined) && node.optional) {
|
|
1790
|
-
return {
|
|
1791
|
-
|
|
1792
|
-
|
|
1769
|
+
return consume({ kind: "nullish" });
|
|
1770
|
+
}
|
|
1771
|
+
const retained = {};
|
|
1772
|
+
let property;
|
|
1773
|
+
context.budget.setRetainedValues(retained, () => [object.value, property]);
|
|
1774
|
+
const release = () => context.budget.setRetainedValues(retained, undefined);
|
|
1775
|
+
const pending = runResources.getStore()?.referenceReleases;
|
|
1776
|
+
pending?.add(release);
|
|
1777
|
+
try {
|
|
1778
|
+
const result = node.computed
|
|
1779
|
+
? await evaluateNode(node.property, context)
|
|
1780
|
+
: { kind: "normal", value: getStaticPropertyName(node.property) };
|
|
1781
|
+
if (result.kind !== "normal")
|
|
1782
|
+
return result;
|
|
1783
|
+
property = result.value;
|
|
1784
|
+
return await consume({ kind: "resolved", object: object.value, property });
|
|
1785
|
+
}
|
|
1786
|
+
finally {
|
|
1787
|
+
release();
|
|
1788
|
+
pending?.delete(release);
|
|
1793
1789
|
}
|
|
1794
|
-
const property = node.computed
|
|
1795
|
-
? await evaluateNode(node.property, context)
|
|
1796
|
-
: { kind: "normal", value: getStaticPropertyName(node.property) };
|
|
1797
|
-
if (property.kind !== "normal")
|
|
1798
|
-
return { kind: "completion", result: property };
|
|
1799
|
-
return {
|
|
1800
|
-
kind: "resolved",
|
|
1801
|
-
object: object.value,
|
|
1802
|
-
property: property.value
|
|
1803
|
-
};
|
|
1804
1790
|
}
|
|
1805
1791
|
async function evaluateMemberProperty(node, context) {
|
|
1806
1792
|
const property = await evaluateNode(node, context);
|
|
@@ -1837,89 +1823,84 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1837
1823
|
if (node.callee.type !== "MemberExpression") {
|
|
1838
1824
|
throw new TypeError("Expected member call expression.");
|
|
1839
1825
|
}
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
kind: "normal",
|
|
1851
|
-
hasValue: true,
|
|
1852
|
-
value: undefined
|
|
1853
|
-
};
|
|
1826
|
+
return evaluateMemberAccess(node.callee, context, async (reference) => {
|
|
1827
|
+
if (reference.kind === "nullish" || reference.object === null || reference.object === undefined) {
|
|
1828
|
+
if (reference.kind === "nullish") {
|
|
1829
|
+
return {
|
|
1830
|
+
kind: "normal",
|
|
1831
|
+
hasValue: true,
|
|
1832
|
+
value: undefined
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
throw new TypeError("Cannot read properties of null or undefined.");
|
|
1854
1836
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
if (typeof member.object === "string" && isStringMethodName(member.property)) {
|
|
1862
|
-
return evaluateStringMethodCall(node, member.object, member.property, context);
|
|
1863
|
-
}
|
|
1864
|
-
if (typeof member.object === "number" && isNumberMethodName(member.property)) {
|
|
1865
|
-
return evaluateNumberMethodCall(node, member.object, member.property, context);
|
|
1866
|
-
}
|
|
1867
|
-
if (Array.isArray(member.object) &&
|
|
1868
|
-
isArrayMethodName(member.property) &&
|
|
1869
|
-
!Object.hasOwn(member.object, member.property)) {
|
|
1870
|
-
return evaluateArrayMethodCall(node, member.object, member.property, context);
|
|
1871
|
-
}
|
|
1872
|
-
if (isSandboxMap(member.object) && isMapMethodName(member.property)) {
|
|
1873
|
-
return evaluateMapMethodCall(node, member.object, member.property, context);
|
|
1874
|
-
}
|
|
1875
|
-
if (isSandboxSet(member.object) && isSetMethodName(member.property)) {
|
|
1876
|
-
return evaluateSetMethodCall(node, member.object, member.property, context);
|
|
1877
|
-
}
|
|
1878
|
-
if (typeof member.object === "string") {
|
|
1879
|
-
return evaluatePrimitiveMemberCall(node, "String", member.property, getStringMember(member.object, member.property, context.budget), context);
|
|
1880
|
-
}
|
|
1881
|
-
if (typeof member.object === "number") {
|
|
1882
|
-
return evaluatePrimitiveMemberCall(node, "Number", member.property, getNumberMember(member.property, context.budget), context);
|
|
1883
|
-
}
|
|
1884
|
-
if (Array.isArray(member.object) && !Object.hasOwn(member.object, member.property)) {
|
|
1885
|
-
return evaluatePrimitiveMemberCall(node, "Array", member.property, getArrayMemberValue(member.object, member.property, context), context);
|
|
1886
|
-
}
|
|
1887
|
-
if (isSandboxMap(member.object)) {
|
|
1888
|
-
return evaluatePrimitiveMemberCall(node, "Map", member.property, getMapMember(member.object, member.property, createMapMethodOptions(context)), context);
|
|
1889
|
-
}
|
|
1890
|
-
if (isSandboxDate(member.object)) {
|
|
1891
|
-
return evaluateResolvedCallExpression(node, getDateMember(member.property, context.budget, context.compilation?.owner), context, member.object);
|
|
1892
|
-
}
|
|
1893
|
-
if (isFloat32Array(member.object)) {
|
|
1894
|
-
return evaluateResolvedCallExpression(node, getFloat32Member(member.object, member.property, context.budget), context, member.object);
|
|
1895
|
-
}
|
|
1896
|
-
if (isSandboxSet(member.object)) {
|
|
1897
|
-
return evaluatePrimitiveMemberCall(node, "Set", member.property, getSetMember(member.object, member.property, createSetMethodOptions(context)), context);
|
|
1898
|
-
}
|
|
1899
|
-
if (isSandboxGenerator(member.object)) {
|
|
1900
|
-
const memberValue = getGeneratorMember(member.object, member.property, context.budget);
|
|
1901
|
-
if (memberValue === undefined) {
|
|
1902
|
-
throw new TypeError(`Generator#${String(member.property)} is not a supported method.`);
|
|
1837
|
+
const member = {
|
|
1838
|
+
...reference,
|
|
1839
|
+
property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
|
|
1840
|
+
};
|
|
1841
|
+
if (typeof member.object === "string" && isStringMethodName(member.property)) {
|
|
1842
|
+
return evaluateStringMethodCall(node, member.object, member.property, context);
|
|
1903
1843
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
if (isSandboxClosure(member.object)) {
|
|
1907
|
-
const memberValue = getClosureMemberValue(member.object, member.property, context);
|
|
1908
|
-
if (memberValue === undefined) {
|
|
1909
|
-
throw new TypeError(`Function#${String(member.property)} is not a supported method.`);
|
|
1844
|
+
if (typeof member.object === "number" && isNumberMethodName(member.property)) {
|
|
1845
|
+
return evaluateNumberMethodCall(node, member.object, member.property, context);
|
|
1910
1846
|
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1847
|
+
if (Array.isArray(member.object) &&
|
|
1848
|
+
isArrayMethodName(member.property) &&
|
|
1849
|
+
!Object.hasOwn(member.object, member.property)) {
|
|
1850
|
+
return evaluateArrayMethodCall(node, member.object, member.property, context);
|
|
1851
|
+
}
|
|
1852
|
+
if (isSandboxMap(member.object) && isMapMethodName(member.property)) {
|
|
1853
|
+
return evaluateMapMethodCall(node, member.object, member.property, context);
|
|
1854
|
+
}
|
|
1855
|
+
if (isSandboxSet(member.object) && isSetMethodName(member.property)) {
|
|
1856
|
+
return evaluateSetMethodCall(node, member.object, member.property, context);
|
|
1857
|
+
}
|
|
1858
|
+
if (typeof member.object === "string") {
|
|
1859
|
+
return evaluatePrimitiveMemberCall(node, "String", member.property, getStringMember(member.object, member.property, context.budget), context);
|
|
1860
|
+
}
|
|
1861
|
+
if (typeof member.object === "number") {
|
|
1862
|
+
return evaluatePrimitiveMemberCall(node, "Number", member.property, getNumberMember(member.property, context.budget), context);
|
|
1863
|
+
}
|
|
1864
|
+
if (Array.isArray(member.object) && !Object.hasOwn(member.object, member.property)) {
|
|
1865
|
+
return evaluatePrimitiveMemberCall(node, "Array", member.property, getArrayMemberValue(member.object, member.property, context), context);
|
|
1866
|
+
}
|
|
1867
|
+
if (isSandboxMap(member.object)) {
|
|
1868
|
+
return evaluatePrimitiveMemberCall(node, "Map", member.property, getMapMember(member.object, member.property, createMapMethodOptions(context)), context);
|
|
1869
|
+
}
|
|
1870
|
+
if (isSandboxDate(member.object)) {
|
|
1871
|
+
return evaluateResolvedCallExpression(node, getDateMember(member.property, context.budget, context.compilation?.owner), context, member.object);
|
|
1872
|
+
}
|
|
1873
|
+
if (isFloat32Array(member.object)) {
|
|
1874
|
+
return evaluateResolvedCallExpression(node, getFloat32Member(member.object, member.property, context.budget), context, member.object);
|
|
1875
|
+
}
|
|
1876
|
+
if (isSandboxSet(member.object)) {
|
|
1877
|
+
return evaluatePrimitiveMemberCall(node, "Set", member.property, getSetMember(member.object, member.property, createSetMethodOptions(context)), context);
|
|
1878
|
+
}
|
|
1879
|
+
if (isSandboxGenerator(member.object)) {
|
|
1880
|
+
const memberValue = getGeneratorMember(member.object, member.property, context.budget);
|
|
1881
|
+
if (memberValue === undefined) {
|
|
1882
|
+
throw new TypeError(`Generator#${String(member.property)} is not a supported method.`);
|
|
1883
|
+
}
|
|
1884
|
+
return evaluateResolvedCallExpression(node, memberValue, context, member.object);
|
|
1885
|
+
}
|
|
1886
|
+
if (isSandboxClosure(member.object)) {
|
|
1887
|
+
const memberValue = getClosureMemberValue(member.object, member.property, context);
|
|
1888
|
+
if (memberValue === undefined) {
|
|
1889
|
+
throw new TypeError(`Function#${String(member.property)} is not a supported method.`);
|
|
1890
|
+
}
|
|
1891
|
+
return evaluateResolvedCallExpression(node, memberValue, context, member.object);
|
|
1892
|
+
}
|
|
1893
|
+
if (isSandboxPromise(member.object)) {
|
|
1894
|
+
return evaluateResolvedCallExpression(node, getPromiseMember(member.property, context.budget), context, member.object);
|
|
1895
|
+
}
|
|
1896
|
+
if (isSandboxRegex(member.object) && isRegexMethodName(member.property)) {
|
|
1897
|
+
return evaluateResolvedCallExpression(node, getRegexMember(member.object, member.property, context.budget), context, member.object);
|
|
1898
|
+
}
|
|
1899
|
+
if (!isIndexableSandboxValue(member.object)) {
|
|
1900
|
+
throw new TypeError("Attempted to read a property from a non-object value.");
|
|
1901
|
+
}
|
|
1902
|
+
return evaluateResolvedCallExpression(node, getMemberValue(member.object, member.property, context), context, member.object);
|
|
1903
|
+
});
|
|
1923
1904
|
}
|
|
1924
1905
|
function evaluatePrimitiveMemberCall(node, receiverType, property, value, context) {
|
|
1925
1906
|
if (value === undefined) {
|
|
@@ -6,5 +6,5 @@ export declare function isRegexMethodName(property: string | number): property i
|
|
|
6
6
|
export declare function getRegexMember(target: SandboxRegex, property: string | number, budget: Budget): SandboxValue | undefined;
|
|
7
7
|
export declare function setRegexMember(target: SandboxRegex, property: string | number, value: SandboxValue): void;
|
|
8
8
|
export declare function callRegexMethod(target: SandboxValue, methodName: RegexMethodName, args: readonly SandboxValue[], budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
|
|
9
|
-
export declare function executeRegex(target: SandboxRegex, input: string): RegexMatch | null;
|
|
9
|
+
export declare function executeRegex(target: SandboxRegex, input: string, lastIndex: number): RegexMatch | null;
|
|
10
10
|
export declare function toMatchArray(match: RegexMatch | null, input: string): SandboxValue;
|
|
@@ -2,8 +2,12 @@ import { createSandboxClosure, getSandboxRegexPattern, isSandboxClosure, isSandb
|
|
|
2
2
|
import { matchRegex } from "../regex/engine.js";
|
|
3
3
|
import { invokeBuiltinClosure } from "../builtin-call.js";
|
|
4
4
|
import { getSandboxDataProperty } from "../object-model.js";
|
|
5
|
-
import { sandboxString } from "../string-coercion.js";
|
|
5
|
+
import { sandboxNumber, sandboxString } from "../string-coercion.js";
|
|
6
6
|
const regexMethodNames = new Set(["exec", "test"]);
|
|
7
|
+
const regexFlagProperties = {
|
|
8
|
+
hasIndices: "d", global: "g", ignoreCase: "i", multiline: "m",
|
|
9
|
+
dotAll: "s", unicode: "u", unicodeSets: "v", sticky: "y"
|
|
10
|
+
};
|
|
7
11
|
export function isRegexMethodName(property) {
|
|
8
12
|
return typeof property === "string" && regexMethodNames.has(property);
|
|
9
13
|
}
|
|
@@ -16,6 +20,8 @@ export function getRegexMember(target, property, budget) {
|
|
|
16
20
|
}
|
|
17
21
|
if (property === "lastIndex")
|
|
18
22
|
return target.lastIndex;
|
|
23
|
+
if (Object.hasOwn(regexFlagProperties, property))
|
|
24
|
+
return target.flags.includes(regexFlagProperties[property]);
|
|
19
25
|
if (!isRegexMethodName(property)) {
|
|
20
26
|
return undefined;
|
|
21
27
|
}
|
|
@@ -64,14 +70,16 @@ export function setRegexMember(target, property, value) {
|
|
|
64
70
|
if (property !== "lastIndex") {
|
|
65
71
|
throw new TypeError(`RegExp#${String(property)} is not writable.`);
|
|
66
72
|
}
|
|
67
|
-
target.lastIndex =
|
|
73
|
+
target.lastIndex = value;
|
|
68
74
|
}
|
|
69
75
|
export async function callRegexMethod(target, methodName, args, budget, context) {
|
|
70
76
|
if (target === null || typeof target !== "object" || (methodName === "exec" && !isSandboxRegex(target))) {
|
|
71
77
|
throw new TypeError(`RegExp#${methodName} requires ${methodName === "exec" ? "a regex" : "an object"} receiver.`);
|
|
72
78
|
}
|
|
73
79
|
const retained = {};
|
|
74
|
-
|
|
80
|
+
let cursor;
|
|
81
|
+
let convertedInput;
|
|
82
|
+
budget.setRetainedValues(retained, () => [target, ...args, cursor, convertedInput]);
|
|
75
83
|
try {
|
|
76
84
|
const input = await sandboxString(args[0], budget, context);
|
|
77
85
|
if (methodName === "test") {
|
|
@@ -87,16 +95,20 @@ export async function callRegexMethod(target, methodName, args, budget, context)
|
|
|
87
95
|
}
|
|
88
96
|
if (!isSandboxRegex(target))
|
|
89
97
|
throw new TypeError("RegExp execution requires a regex receiver.");
|
|
90
|
-
|
|
98
|
+
if (typeof args[0] !== "string")
|
|
99
|
+
convertedInput = input;
|
|
100
|
+
cursor = target.lastIndex;
|
|
101
|
+
const lastIndex = await sandboxNumber(cursor, budget, context);
|
|
102
|
+
const match = executeRegex(target, input, lastIndex);
|
|
91
103
|
return methodName === "test" ? match !== null : toMatchArray(match, input);
|
|
92
104
|
}
|
|
93
105
|
finally {
|
|
94
106
|
budget.setRetainedValues(retained, undefined);
|
|
95
107
|
}
|
|
96
108
|
}
|
|
97
|
-
export function executeRegex(target, input) {
|
|
109
|
+
export function executeRegex(target, input, lastIndex) {
|
|
98
110
|
const pattern = getSandboxRegexPattern(target);
|
|
99
|
-
const match = matchRegex(pattern, input,
|
|
111
|
+
const match = matchRegex(pattern, input, lastIndex);
|
|
100
112
|
if (pattern.flags.global) {
|
|
101
113
|
target.lastIndex = match === null ? 0 : match.index + match.text.length;
|
|
102
114
|
}
|