poe-code 14.0.57 → 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.
@@ -22,7 +22,7 @@ import {
22
22
  resolveFsConfig,
23
23
  splitFrontmatter,
24
24
  withBrokenPipeGuard
25
- } from "./chunks/chunk-H4O5OPM2.js";
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-N3CN2ACZ.js";
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";
@@ -5,7 +5,7 @@ import {
5
5
  defineExtension,
6
6
  lint,
7
7
  run
8
- } from "./chunks/chunk-N3CN2ACZ.js";
8
+ } from "./chunks/chunk-DHD453E5.js";
9
9
  import "./chunks/chunk-4YIDX44G.js";
10
10
  export {
11
11
  Budget,
@@ -26,7 +26,7 @@ import {
26
26
  runWithSpawnUsageAccumulator,
27
27
  splitFrontmatter,
28
28
  supportsSpawnMode
29
- } from "./chunks/chunk-H4O5OPM2.js";
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-N3CN2ACZ.js";
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";
@@ -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
- const member = await evaluateMemberAccess(node.left, context);
523
- if (member.kind === "error") {
524
- return member;
525
- }
526
- if (member.kind === "completion") {
527
- return member.result;
528
- }
529
- if (member.kind === "nullish") {
530
- throw new TypeError("Cannot assign properties of null or undefined.");
531
- }
532
- let property;
533
- let current = undefined;
534
- if (node.operator !== "=") {
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 = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
539
- current = getPropertyValue(member.object, property, context);
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: current
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
- const member = await evaluateMemberAccess(node.argument, context);
1576
- if (member.kind === "error") {
1577
- return member;
1578
- }
1579
- if (member.kind === "completion") {
1580
- return member.result;
1581
- }
1582
- if (member.kind === "nullish" || member.object === null || member.object === undefined) {
1583
- if (member.kind === "nullish" && node.argument.optional) {
1584
- return {
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
- throw new TypeError("Cannot delete properties of null or undefined.");
1591
- }
1592
- if (!isIndexableSandboxValue(member.object)) {
1593
- throw new TypeError("Unary operator 'delete' requires a sandbox object property.");
1594
- }
1595
- const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
1596
- const deleted = deleteSandboxProperty(member.object, property);
1597
- return {
1598
- kind: "normal",
1599
- hasValue: true,
1600
- value: deleted
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
- const member = await evaluateMemberAccess(node.argument, context);
1634
- if (member.kind === "error") {
1635
- return member;
1636
- }
1637
- if (member.kind === "completion") {
1638
- return member.result;
1639
- }
1640
- if (member.kind === "nullish" || member.object === null || member.object === undefined) {
1641
- throw new TypeError("Cannot update properties of null or undefined.");
1642
- }
1643
- const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
1644
- const current = toNumber(await toNumericPrimitive(getPropertyValue(member.object, property, context), context));
1645
- const next = node.operator === "++" ? current + 1 : current - 1;
1646
- setSandboxProperty(member.object, property, next, context.budget);
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
- const member = await evaluateMemberAccess(node, context);
1655
- if (member.kind === "error")
1656
- return member;
1657
- if (member.kind === "completion")
1658
- return member.result;
1659
- if (member.kind === "nullish" || member.object === null || member.object === undefined) {
1660
- if (member.kind === "nullish" && node.optional)
1661
- return { kind: "normal", hasValue: true, value: undefined };
1662
- throw new TypeError("Cannot read properties of null or undefined.");
1663
- }
1664
- return {
1665
- kind: "normal",
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
- kind: "nullish"
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
- const reference = await evaluateMemberAccess(node.callee, context);
1841
- if (reference.kind === "error") {
1842
- return reference;
1843
- }
1844
- if (reference.kind === "completion") {
1845
- return reference.result;
1846
- }
1847
- if (reference.kind === "nullish" || reference.object === null || reference.object === undefined) {
1848
- if (reference.kind === "nullish") {
1849
- return {
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
- throw new TypeError("Cannot read properties of null or undefined.");
1856
- }
1857
- const member = {
1858
- ...reference,
1859
- property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
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
- return evaluateResolvedCallExpression(node, memberValue, context, member.object);
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
- return evaluateResolvedCallExpression(node, memberValue, context, member.object);
1912
- }
1913
- if (isSandboxPromise(member.object)) {
1914
- return evaluateResolvedCallExpression(node, getPromiseMember(member.property, context.budget), context, member.object);
1915
- }
1916
- if (isSandboxRegex(member.object) && isRegexMethodName(member.property)) {
1917
- return evaluateResolvedCallExpression(node, getRegexMember(member.object, member.property, context.budget), context, member.object);
1918
- }
1919
- if (!isIndexableSandboxValue(member.object)) {
1920
- throw new TypeError("Attempted to read a property from a non-object value.");
1921
- }
1922
- return evaluateResolvedCallExpression(node, getMemberValue(member.object, member.property, context), context, member.object);
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) {
@@ -1,6 +1,7 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
  export type RunResources = {
3
3
  signal: AbortSignal;
4
+ referenceReleases: Set<() => void>;
4
5
  add(close: () => Promise<void>): void;
5
6
  };
6
7
  export declare const runResources: AsyncLocalStorage<RunResources>;
@@ -6,6 +6,7 @@ export async function withRunResources(signal, execute) {
6
6
  const cleanups = new Set();
7
7
  const resources = {
8
8
  signal: controller.signal,
9
+ referenceReleases: new Set(),
9
10
  add(close) {
10
11
  cleanups.add(close);
11
12
  }
@@ -25,6 +26,9 @@ export async function withRunResources(signal, execute) {
25
26
  finally {
26
27
  signal?.removeEventListener("abort", cancel);
27
28
  controller.abort(new Error("SafeJS run finished."));
29
+ for (const release of resources.referenceReleases)
30
+ release();
31
+ resources.referenceReleases.clear();
28
32
  const outcomes = await Promise.allSettled([...cleanups].map((close) => Promise.resolve().then(close)));
29
33
  errors = outcomes.flatMap((outcome) => (outcome.status === "rejected" ? [outcome.reason] : []));
30
34
  }
@@ -34,6 +34,7 @@ class RealmState {
34
34
  extensions;
35
35
  consoleExtension;
36
36
  cleanups = [];
37
+ referenceReleases = new Set();
37
38
  callbacks = new Map();
38
39
  pendingCallbacks = new Set();
39
40
  callbackCache = new WeakMap();
@@ -458,7 +459,7 @@ class RealmState {
458
459
  };
459
460
  try {
460
461
  const active = this.active !== undefined;
461
- const pending = withSandboxPromiseRejectionTracker(this.tracker, () => runResources.run({ signal: this.controller.signal, add: this.onCleanup }, () => withCancellationSignal(this.controller.signal, () => active && this.phase.getStore()?.active ? runAsyncPrefix(invoke) : this.queue.run(invoke))));
462
+ const pending = withSandboxPromiseRejectionTracker(this.tracker, () => runResources.run({ signal: this.controller.signal, referenceReleases: this.referenceReleases, add: this.onCleanup }, () => withCancellationSignal(this.controller.signal, () => active && this.phase.getStore()?.active ? runAsyncPrefix(invoke) : this.queue.run(invoke))));
462
463
  record.promise = active ? pending : this.perform(() => pending);
463
464
  return await record.promise;
464
465
  }
@@ -645,7 +646,7 @@ class RealmState {
645
646
  this.assertOpen();
646
647
  if (this.active !== undefined)
647
648
  throw new SandboxError("reentry");
648
- const pending = Promise.resolve().then(() => withSandboxPromiseRejectionTracker(this.tracker, () => runResources.run({ signal: this.controller.signal, add: this.onCleanup }, () => withCancellationSignal(this.controller.signal, task))));
649
+ const pending = Promise.resolve().then(() => withSandboxPromiseRejectionTracker(this.tracker, () => runResources.run({ signal: this.controller.signal, referenceReleases: this.referenceReleases, add: this.onCleanup }, () => withCancellationSignal(this.controller.signal, task))));
649
650
  this.active = pending;
650
651
  try {
651
652
  const result = await pending;
@@ -701,6 +702,9 @@ class RealmState {
701
702
  for (const reference of this.guestReferences.keys())
702
703
  revokeGuestReference(reference, this);
703
704
  this.guestReferences.clear();
705
+ for (const release of this.referenceReleases)
706
+ release();
707
+ this.referenceReleases.clear();
704
708
  this.budget.setRetainedValues(this, undefined);
705
709
  releaseObjectPrototype(this.budget);
706
710
  this.disposal = (async () => {