@poe-platform/safe-js 0.1.292 → 0.1.293

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.
@@ -7790,6 +7790,8 @@ var regexPrototypes = /* @__PURE__ */ new WeakMap();
7790
7790
  var collectionPrototypes = /* @__PURE__ */ new WeakMap();
7791
7791
  var promisePrototypes = /* @__PURE__ */ new WeakMap();
7792
7792
  var datePrototypes = /* @__PURE__ */ new WeakMap();
7793
+ var arrayPrototypes = /* @__PURE__ */ new WeakMap();
7794
+ var initialArrayMethods = /* @__PURE__ */ new WeakMap();
7793
7795
  var initialRegexDescriptors = /* @__PURE__ */ new WeakMap();
7794
7796
  var intrinsicPrototypeRoots = /* @__PURE__ */ new WeakMap();
7795
7797
  var intrinsicConstructors = /* @__PURE__ */ new WeakMap();
@@ -7873,6 +7875,16 @@ function installDatePrototype(budget, prototype, constructor) {
7873
7875
  datePrototypes.set(budget, prototype);
7874
7876
  registerIntrinsicPrototype(budget, prototype, constructor);
7875
7877
  }
7878
+ function installArrayPrototype(budget, prototype, constructor) {
7879
+ arrayPrototypes.set(budget, prototype);
7880
+ prototypes.set(prototype, intrinsicPrototypes.get(budget) ?? null);
7881
+ initialArrayMethods.set(prototype, new Map(Object.entries(Object.getOwnPropertyDescriptors(prototype)).map(([key, descriptor]) => [key, descriptor.value])));
7882
+ registerIntrinsicPrototype(budget, prototype, constructor);
7883
+ }
7884
+ function isDefaultArrayMethod(value, key, budget) {
7885
+ const prototype = arrayPrototypes.get(budget);
7886
+ return prototype !== void 0 && getSandboxPrototype(value, budget) === prototype && !Object.hasOwn(value, key) && initialArrayMethods.get(prototype)?.has(key) === true && Object.getOwnPropertyDescriptor(prototype, key)?.value === initialArrayMethods.get(prototype)?.get(key);
7887
+ }
7876
7888
  function hasRegexPropertyOverride(value, keys, budget) {
7877
7889
  const initial = initialRegexDescriptors.get(budget);
7878
7890
  const prototype = regexPrototypes.get(budget);
@@ -7954,11 +7966,13 @@ function releaseObjectPrototype(budget) {
7954
7966
  collectionPrototypes.delete(budget);
7955
7967
  promisePrototypes.delete(budget);
7956
7968
  datePrototypes.delete(budget);
7969
+ arrayPrototypes.delete(budget);
7957
7970
  initialRegexDescriptors.delete(budget);
7958
7971
  intrinsicPrototypes.delete(budget);
7959
7972
  }
7960
7973
  function getSandboxPrototype(value, budget) {
7961
7974
  if (prototypes.has(value)) return prototypes.get(value) ?? null;
7975
+ if (budget !== void 0 && Array.isArray(value)) return arrayPrototypes.get(budget) ?? null;
7962
7976
  if (budget !== void 0 && isSandboxDate(value)) return datePrototypes.get(budget) ?? null;
7963
7977
  if (budget !== void 0 && isSandboxPromise(value)) return promisePrototypes.get(budget) ?? null;
7964
7978
  if (budget !== void 0 && (isSandboxMap(value) || isSandboxSet(value)))
@@ -11590,2060 +11604,2124 @@ function createPrimitiveConstructor(options, budget) {
11590
11604
  return constructor;
11591
11605
  }
11592
11606
 
11593
- // packages/safe-js/src/interp/globals/object-array.ts
11594
- function createObjectArrayGlobals(options) {
11595
- return {
11596
- Object: createObjectGlobal(
11597
- {
11598
- keys: createSandboxClosure({
11599
- sandbox: true,
11600
- call: ([value]) => budgetSandboxValue(ownEnumerableSandboxKeys(value), options.budget),
11601
- name: "keys"
11602
- }),
11603
- values: createSandboxClosure({
11604
- sandbox: true,
11605
- call: ([value], context) => context === void 0 ? allocateProducedSandboxValue(
11606
- ownEnumerableSandboxEntries(value).map(([, entry]) => entry),
11607
- options.budget
11608
- ) : getOwnEnumerableEntries(value, options.budget, context).then(
11609
- (entries) => allocateProducedSandboxValue(
11610
- entries.map(([, entry]) => entry),
11611
- options.budget
11612
- )
11613
- ),
11614
- name: "values"
11615
- }),
11616
- entries: createSandboxClosure({
11617
- sandbox: true,
11618
- call: ([value], context) => context === void 0 ? allocateProducedSandboxValue(ownEnumerableSandboxEntries(value), options.budget) : getOwnEnumerableEntries(value, options.budget, context).then(
11619
- (entries) => allocateProducedSandboxValue(entries, options.budget)
11620
- ),
11621
- name: "entries"
11622
- }),
11623
- hasOwn: createSandboxClosure({
11624
- sandbox: true,
11625
- call: ([value, key], context) => {
11626
- if (value === null || value === void 0)
11627
- throw new TypeError("Cannot convert undefined or null to object.");
11628
- const name = toPropertyKey(key, options.budget, context);
11629
- return typeof name === "string" || typeof name === "symbol" ? hasOwnSandboxProperty(value, name, false) : name.then((property) => hasOwnSandboxProperty(value, property, false));
11630
- },
11631
- name: "hasOwn"
11632
- }),
11633
- getOwnPropertyDescriptor: createSandboxClosure({
11634
- sandbox: true,
11635
- call: async ([value, key], context) => {
11636
- const descriptor = Object.getOwnPropertyDescriptor(
11637
- reflectionProperties(value),
11638
- await toPropertyKey(key, options.budget, context)
11639
- );
11640
- if (descriptor === void 0) return void 0;
11641
- return allocateProducedSandboxValue(
11642
- exposePropertyDescriptor(descriptor),
11643
- options.budget
11644
- );
11645
- },
11646
- name: "getOwnPropertyDescriptor"
11647
- }),
11648
- getOwnPropertyDescriptors: createSandboxClosure({
11649
- sandbox: true,
11650
- call: ([value]) => {
11651
- const descriptors2 = /* @__PURE__ */ Object.create(null);
11652
- const properties = reflectionProperties(value);
11653
- for (const key of [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(value)])
11654
- defineOwnDataProperty(descriptors2, key, exposePropertyDescriptor(Object.getOwnPropertyDescriptor(properties, key)));
11655
- return allocateProducedSandboxValue(descriptors2, options.budget);
11656
- },
11657
- name: "getOwnPropertyDescriptors"
11658
- }),
11659
- getOwnPropertyNames: createSandboxClosure({
11660
- sandbox: true,
11661
- call: ([value]) => budgetSandboxValue(Object.getOwnPropertyNames(reflectionProperties(value)), options.budget),
11662
- name: "getOwnPropertyNames"
11663
- }),
11664
- getOwnPropertySymbols: createSandboxClosure({
11665
- sandbox: true,
11666
- call: ([value]) => allocateProducedSandboxValue(ownSandboxSymbolKeys(value), options.budget),
11667
- name: "getOwnPropertySymbols"
11668
- }),
11669
- defineProperty: createSandboxClosure({
11670
- sandbox: true,
11671
- call: async ([value, key, descriptor], context) => {
11672
- objectProperties(value, true);
11673
- const property = await toPropertyKey(key, options.budget, context);
11674
- defineDataProperty(
11675
- value,
11676
- property,
11677
- await propertyDescriptor(descriptor, options.budget, context),
11678
- options.budget
11679
- );
11680
- return value;
11681
- },
11682
- name: "defineProperty"
11683
- }),
11684
- defineProperties: createSandboxClosure({
11685
- sandbox: true,
11686
- call: async ([value, descriptors2], context) => {
11687
- await definePropertiesFromObject(value, descriptors2, options.budget, context);
11688
- return value;
11689
- },
11690
- name: "defineProperties"
11691
- }),
11692
- getPrototypeOf: createSandboxClosure({
11693
- sandbox: true,
11694
- call: ([value]) => {
11695
- if (isSandboxMap(value) || isSandboxSet(value))
11696
- return getSandboxPrototype(value, options.budget);
11697
- if (value !== null && value !== void 0 && typeof value !== "object")
11698
- value = createSandboxBox(value);
11699
- objectProperties(value);
11700
- return getSandboxPrototype(value, options.budget);
11701
- },
11702
- name: "getPrototypeOf"
11703
- }),
11704
- setPrototypeOf: createSandboxClosure({
11705
- sandbox: true,
11706
- call: ([value, prototype]) => {
11707
- if (value === null || value === void 0)
11708
- throw new TypeError("Cannot set the prototype of null or undefined.");
11709
- if (prototype !== null && typeof prototype !== "object")
11710
- throw new TypeError("Prototype must be an object or null.");
11711
- if (typeof value !== "object") return value;
11712
- objectProperties(value, true);
11713
- if (prototype !== null) objectProperties(prototype);
11714
- setSandboxPrototype(value, prototype, options.budget);
11715
- return value;
11716
- },
11717
- name: "setPrototypeOf"
11718
- }),
11719
- create: createSandboxClosure({
11720
- sandbox: true,
11721
- call: async ([prototype, descriptors2], context) => {
11722
- if (prototype !== null) objectProperties(prototype);
11723
- const value = /* @__PURE__ */ Object.create(null);
11724
- setSandboxPrototype(value, prototype, options.budget);
11725
- if (descriptors2 !== void 0) {
11726
- await definePropertiesFromObject(value, descriptors2, options.budget, context);
11727
- }
11728
- return allocateProducedSandboxValue(value, options.budget);
11729
- },
11730
- name: "create"
11731
- }),
11732
- is: createSandboxClosure({
11733
- sandbox: true,
11734
- call: ([left, right]) => Reflect.apply(Object.is, Object, [left, right]),
11735
- name: "is"
11736
- }),
11737
- fromEntries: createSandboxClosure({
11738
- sandbox: true,
11739
- call: ([value], context) => {
11740
- if (context !== void 0) return acquireSandboxIterator(value, options.budget, context).then((iterator2) => {
11741
- if (iterator2 === void 0) throw new TypeError("Object.fromEntries requires an iterable.");
11742
- return objectFromSandboxEntries(value, iterator2, options.budget, context);
11743
- });
11744
- const iterator = getSandboxIterator(value, options.budget, context);
11745
- if (iterator === void 0) {
11746
- throw new TypeError("Object.fromEntries requires an iterable.");
11747
- }
11748
- if (context === void 0 && !iterator.generator && !iterator.asynchronous) {
11749
- return allocateProducedSandboxValue(
11750
- Object.setPrototypeOf(
11751
- Reflect.apply(Object.fromEntries, Object, [
11752
- { [Symbol.iterator]: () => iterator }
11753
- ]),
11754
- null
11755
- ),
11756
- options.budget
11757
- );
11758
- }
11759
- return objectFromSandboxEntries(value, iterator, options.budget, context);
11760
- },
11761
- name: "fromEntries"
11762
- }),
11763
- preventExtensions: createSandboxClosure({
11764
- sandbox: true,
11765
- call: ([value]) => {
11766
- if (isGuestHostObject(value))
11767
- throw new TypeError("Live host objects cannot be made non-extensible.");
11768
- Object.preventExtensions(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
11769
- return value;
11770
- },
11771
- name: "preventExtensions"
11772
- }),
11773
- isExtensible: createSandboxClosure({
11774
- sandbox: true,
11775
- call: ([value]) => Object.isExtensible(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
11776
- name: "isExtensible"
11777
- }),
11778
- seal: createSandboxClosure({
11779
- sandbox: true,
11780
- call: ([value]) => {
11781
- if (isGuestHostObject(value))
11782
- throw new TypeError("Live host objects cannot be sealed.");
11783
- Object.seal(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
11784
- return value;
11785
- },
11786
- name: "seal"
11787
- }),
11788
- isSealed: createSandboxClosure({
11789
- sandbox: true,
11790
- call: ([value]) => Object.isSealed(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
11791
- name: "isSealed"
11792
- }),
11793
- freeze: createSandboxClosure({
11794
- sandbox: true,
11795
- call: ([value]) => {
11796
- if (isGuestHostObject(value))
11797
- throw new TypeError("Live host objects cannot be frozen.");
11798
- if (typeof value === "object" && value !== null) {
11799
- Object.freeze(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
11800
- }
11801
- return value;
11802
- },
11803
- name: "freeze"
11804
- }),
11805
- isFrozen: createSandboxClosure({
11806
- sandbox: true,
11807
- call: ([value]) => Object.isFrozen(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
11808
- name: "isFrozen"
11809
- }),
11810
- assign: createSandboxClosure({
11811
- sandbox: true,
11812
- call: ([target, ...sources], context) => assignSandboxValues(target, sources, options.budget, context),
11813
- name: "assign"
11814
- })
11815
- },
11816
- options.budget
11817
- ),
11818
- Array: createSandboxClosure({
11607
+ // packages/safe-js/src/interp/methods/array.ts
11608
+ var arrayLikeSources = /* @__PURE__ */ new WeakMap();
11609
+ var activeArrayCallbacks = /* @__PURE__ */ new WeakMap();
11610
+ var localeArrays = /* @__PURE__ */ new WeakSet();
11611
+ var arrayMethodNames = /* @__PURE__ */ new Set([
11612
+ "map",
11613
+ "filter",
11614
+ "find",
11615
+ "findIndex",
11616
+ "findLast",
11617
+ "findLastIndex",
11618
+ "some",
11619
+ "every",
11620
+ "reduce",
11621
+ "reduceRight",
11622
+ "forEach",
11623
+ "flatMap",
11624
+ "flat",
11625
+ "includes",
11626
+ "indexOf",
11627
+ "lastIndexOf",
11628
+ "join",
11629
+ "toLocaleString",
11630
+ "slice",
11631
+ "concat",
11632
+ "splice",
11633
+ "fill",
11634
+ "copyWithin",
11635
+ "at",
11636
+ "sort",
11637
+ "reverse",
11638
+ "toSorted",
11639
+ "toReversed",
11640
+ "toSpliced",
11641
+ "with",
11642
+ "push",
11643
+ "pop",
11644
+ "shift",
11645
+ "unshift"
11646
+ ]);
11647
+ function getArrayMember(value, property, options) {
11648
+ const index = getArrayIndex(property);
11649
+ if (index !== void 0) {
11650
+ return Object.hasOwn(value, index) ? value[index] : void 0;
11651
+ }
11652
+ if (property === "length") {
11653
+ return value.length;
11654
+ }
11655
+ if (Object.hasOwn(value, property)) {
11656
+ return value[String(property)];
11657
+ }
11658
+ if (isArrayMethodName(property)) {
11659
+ return createSandboxClosure({
11819
11660
  sandbox: true,
11820
- call: (args) => createArrayFromConstructorArgs(args, options.budget),
11821
- construct: (args) => createArrayFromConstructorArgs(args, options.budget),
11822
- name: "Array",
11823
- properties: {
11824
- isArray: createSandboxClosure({
11825
- sandbox: true,
11826
- call: ([value]) => Array.isArray(value),
11827
- name: "isArray"
11828
- }),
11829
- from: createSandboxClosure({
11830
- sandbox: true,
11831
- call: (args, context) => arrayFromSandboxValues(args, options.budget, context),
11832
- name: "from"
11833
- }),
11834
- of: createSandboxClosure({
11835
- sandbox: true,
11836
- call: (args) => budgetSandboxValue(Reflect.apply(Array.of, Array, [...args]), options.budget),
11837
- name: "of"
11838
- })
11661
+ name: `Array#${property}`,
11662
+ call: (args, context) => callArrayMethod(
11663
+ context?.thisValue,
11664
+ property,
11665
+ args,
11666
+ { ...options, context },
11667
+ context?.stack ?? []
11668
+ )
11669
+ });
11670
+ }
11671
+ return void 0;
11672
+ }
11673
+ function getArrayIndex(property) {
11674
+ const index = typeof property === "number" ? property : Number(property);
11675
+ if (!Number.isSafeInteger(index) || index < 0 || index >= 2 ** 32 - 1 || String(index) !== String(property)) {
11676
+ return void 0;
11677
+ }
11678
+ return index;
11679
+ }
11680
+ function isArrayMethodName(property) {
11681
+ return typeof property === "string" && arrayMethodNames.has(property);
11682
+ }
11683
+ async function callArrayMethod(receiver, methodName, args, options, stack = []) {
11684
+ if (receiver === null || receiver === void 0)
11685
+ throw new TypeError("Array method requires a receiver.");
11686
+ if (typeof receiver !== "object") {
11687
+ receiver = createSandboxBox(receiver);
11688
+ options.budget.chargeDataUsage(measureSandboxData([receiver]));
11689
+ }
11690
+ const retainedReceiver = {};
11691
+ options.budget.setRetainedValues(retainedReceiver, () => [receiver]);
11692
+ try {
11693
+ const value = Array.isArray(receiver) || methodName === "concat" ? receiver : await arrayLikeView(receiver, options);
11694
+ if (isMutatingArrayMethod(methodName)) {
11695
+ assertCollectionMutable(receiver);
11696
+ }
11697
+ if (isCallbackArrayMethod(methodName)) {
11698
+ let callbackState = activeArrayCallbacks.get(receiver);
11699
+ if (callbackState === void 0) {
11700
+ callbackState = { depth: 0, leave: enterRunningState(receiver) };
11701
+ activeArrayCallbacks.set(receiver, callbackState);
11839
11702
  }
11840
- }),
11841
- String: createPrimitiveConstructor(
11842
- {
11843
- call: (args, context) => typeof args[0] === "symbol" ? options.budget.allocateString(String(args[0])) : sandboxString(args.length === 0 ? "" : args[0], options.budget, context),
11844
- name: "String",
11845
- properties: {
11846
- raw: createSandboxClosure({
11847
- sandbox: true,
11848
- call: (args, context) => stringRaw(args, options.budget, context),
11849
- name: "raw"
11850
- }),
11851
- fromCharCode: createSandboxClosure({
11852
- sandbox: true,
11853
- call: (args, context) => stringFromCodes(args, String.fromCharCode, options.budget, context),
11854
- name: "fromCharCode"
11855
- }),
11856
- fromCodePoint: createSandboxClosure({
11857
- sandbox: true,
11858
- call: (args, context) => stringFromCodes(args, String.fromCodePoint, options.budget, context),
11859
- name: "fromCodePoint"
11860
- })
11703
+ callbackState.depth += 1;
11704
+ try {
11705
+ const result2 = await callArrayMethodUnlocked(value, methodName, args, options, stack);
11706
+ return result2 === value ? receiver : result2;
11707
+ } finally {
11708
+ callbackState.depth -= 1;
11709
+ if (callbackState.depth === 0) {
11710
+ activeArrayCallbacks.delete(receiver);
11711
+ callbackState.leave();
11861
11712
  }
11713
+ }
11714
+ }
11715
+ const result = await callArrayMethodUnlocked(value, methodName, args, options, stack);
11716
+ return result === value ? receiver : result;
11717
+ } finally {
11718
+ options.budget.setRetainedValues(retainedReceiver, void 0);
11719
+ }
11720
+ }
11721
+ async function arrayLikeView(receiver, options) {
11722
+ const rawLength = options.context?.getProperty !== void 0 ? await options.context.getProperty(receiver, "length") : getSandboxDataProperty(receiver, "length", options.budget);
11723
+ const number = await sandboxNumber(rawLength, options.budget, options.context);
11724
+ const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
11725
+ const view = new Proxy(
11726
+ /* @__PURE__ */ Object.create(null),
11727
+ {
11728
+ get: (_target, key) => {
11729
+ options.budget.visitNode();
11730
+ if (key === "length") return length;
11731
+ if (typeof key !== "string") return void 0;
11732
+ return options.context?.getProperty !== void 0 ? options.context.getProperty(receiver, key) : getSandboxDataProperty(receiver, key, options.budget);
11862
11733
  },
11863
- options.budget
11864
- ),
11865
- Number: createPrimitiveConstructor(
11866
- {
11867
- call: (args, context) => sandboxNumber(args.length === 0 ? 0 : args[0], options.budget, context, true),
11868
- name: "Number",
11869
- properties: {
11870
- isFinite: createSandboxClosure({
11871
- guest: true,
11872
- sandbox: true,
11873
- call: ([value]) => typeof value === "number" && Number.isFinite(value),
11874
- name: "isFinite"
11875
- }),
11876
- isNaN: createSandboxClosure({
11877
- guest: true,
11878
- sandbox: true,
11879
- call: ([value]) => typeof value === "number" && Number.isNaN(value),
11880
- name: "isNaN"
11881
- }),
11882
- isInteger: createSandboxClosure({
11883
- guest: true,
11884
- sandbox: true,
11885
- call: ([value]) => typeof value === "number" && Number.isInteger(value),
11886
- name: "isInteger"
11887
- }),
11888
- ...createNumericParsers(options.budget),
11889
- isSafeInteger: createSandboxClosure({
11890
- guest: true,
11891
- sandbox: true,
11892
- call: ([value]) => typeof value === "number" && Number.isSafeInteger(value),
11893
- name: "isSafeInteger"
11894
- }),
11895
- MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER,
11896
- MIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER,
11897
- EPSILON: Number.EPSILON,
11898
- MAX_VALUE: Number.MAX_VALUE,
11899
- MIN_VALUE: Number.MIN_VALUE,
11900
- NaN: Number.NaN,
11901
- NEGATIVE_INFINITY: Number.NEGATIVE_INFINITY,
11902
- POSITIVE_INFINITY: Number.POSITIVE_INFINITY
11734
+ has: (_target, key) => {
11735
+ options.budget.visitNode();
11736
+ if (typeof key === "string" && options.hasProperty !== void 0)
11737
+ return options.hasProperty(receiver, key);
11738
+ for (let current = receiver; current !== null; current = getSandboxPrototype(current, options.budget)) {
11739
+ options.budget.visitNode();
11740
+ if (Object.hasOwn(current, key)) return true;
11903
11741
  }
11742
+ return false;
11904
11743
  },
11905
- options.budget
11906
- ),
11907
- Boolean: createPrimitiveConstructor(
11908
- {
11909
- call: ([value]) => Boolean(value),
11910
- name: "Boolean"
11744
+ set: (_target, key, entry) => {
11745
+ options.budget.visitNode();
11746
+ if (typeof key !== "string") throw new TypeError("Array indices must be string keys.");
11747
+ if (options.setProperty !== void 0) options.setProperty(receiver, key, entry);
11748
+ else if (!Reflect.set(receiver, key, entry))
11749
+ throw new TypeError(`Cannot assign property '${key}'.`);
11750
+ return true;
11911
11751
  },
11912
- options.budget
11913
- )
11914
- };
11915
- }
11916
- async function objectFromSandboxEntries(items, iterator, budget, context) {
11917
- const object = /* @__PURE__ */ Object.create(null);
11918
- let entry;
11919
- let key;
11920
- let value;
11921
- let failure;
11922
- const retained = {};
11923
- budget.setRetainedValues(retained, () => [
11924
- items,
11925
- iterator.retainedValue,
11926
- object,
11927
- entry,
11928
- key,
11929
- value,
11930
- failure
11931
- ]);
11932
- const checkData = createDataCheckpoint(budget, context);
11933
- const closeOnThrow = async (error) => {
11934
- failure = isCapturedException(error) ? error.reason : error;
11935
- try {
11936
- await closeIterator(iterator, true);
11937
- } catch (closeError) {
11938
- if (!isFatalSandboxError(error) && isFatalSandboxError(closeError)) throw closeError;
11939
- }
11940
- throw error;
11941
- };
11942
- try {
11943
- checkData(object, 0, true);
11944
- while (true) {
11945
- try {
11946
- budget.visitNode();
11947
- } catch (error) {
11948
- await closeOnThrow(error);
11949
- }
11950
- const result = await iterator.next();
11951
- if (typeof result !== "object" || result === null) {
11952
- throw new TypeError("Iterator result must be an object.");
11752
+ deleteProperty: (_target, key) => {
11753
+ options.budget.visitNode();
11754
+ if (typeof key === "string" && options.deleteProperty !== void 0)
11755
+ return options.deleteProperty(receiver, key);
11756
+ return Reflect.deleteProperty(receiver, key);
11953
11757
  }
11954
- if ((await readIteratorResult(iterator, result, "done")).value) break;
11955
- entry = (await readIteratorResult(iterator, result, "value")).value;
11758
+ }
11759
+ );
11760
+ arrayLikeSources.set(view, receiver);
11761
+ return view;
11762
+ }
11763
+ async function callArrayMethodUnlocked(value, methodName, args, options, stack) {
11764
+ switch (methodName) {
11765
+ case "toLocaleString": {
11766
+ const receiver = arrayLikeSources.get(value) ?? value;
11767
+ const length = value.length;
11768
+ if (localeArrays.has(receiver)) return "";
11769
+ localeArrays.add(receiver);
11770
+ let text = "";
11771
+ const release = retainValues(options.budget, () => [receiver, text, ...args]);
11956
11772
  try {
11957
- if (typeof entry !== "object" || entry === null) {
11958
- throw new TypeError("Object.fromEntries requires entry objects.");
11773
+ for (let index = 0; index < length; index++) {
11774
+ options.budget.visitNode();
11775
+ const element = options.context?.getProperty === void 0 ? getSandboxDataProperty(receiver, String(index), options.budget) : await options.context.getProperty(receiver, String(index));
11776
+ let part = "";
11777
+ if (element !== null && element !== void 0) {
11778
+ const method = options.context?.getProperty === void 0 ? getSandboxDataProperty(element, "toLocaleString", options.budget) : await options.context.getProperty(element, "toLocaleString");
11779
+ if (!isSandboxClosure(method)) throw new TypeError("Element toLocaleString must be callable.");
11780
+ const converted = await invokeBuiltinClosure(method, [args[0], args[1]], options.budget, options.context, element);
11781
+ part = await sandboxString(converted, options.budget, options.context);
11782
+ }
11783
+ text = options.budget.allocateString(text + (index === 0 ? "" : ",") + part);
11959
11784
  }
11960
- key = context?.getProperty !== void 0 ? await context.getProperty(entry, 0) : getSandboxDataProperty(entry, 0, budget);
11961
- value = context?.getProperty !== void 0 ? await context.getProperty(entry, 1) : getSandboxDataProperty(entry, 1, budget);
11962
- const property = await toPropertyKey(key, budget, context);
11963
- const growth = (typeof property === "symbol" ? property.description?.length ?? 0 : property.length) + 1 + (budget.limits.dataSize === void 0 ? 0 : measureSandboxData([value]));
11964
- budget.visitNode();
11965
- defineOwnDataProperty(object, property, value);
11966
- entry = key = value = void 0;
11967
- checkData(object, growth);
11968
- } catch (error) {
11969
- await closeOnThrow(error);
11785
+ return text;
11786
+ } finally {
11787
+ release();
11788
+ localeArrays.delete(receiver);
11970
11789
  }
11971
11790
  }
11972
- checkData(object, 0, true);
11973
- return allocateProducedSandboxValue(object, budget);
11974
- } finally {
11975
- budget.setRetainedValues(retained, void 0);
11976
- }
11977
- }
11978
- function assignSandboxValues(target, sources, budget, context) {
11979
- if (target === null || target === void 0) {
11980
- throw new TypeError("Object.assign(target, ...sources) requires a non-null target.");
11981
- }
11982
- if (typeof target !== "object") {
11983
- target = createSandboxBox(target);
11984
- budget.chargeDataUsage(measureSandboxData([target]));
11985
- }
11986
- if (!isGuestHostObject(target)) objectProperties(target, true);
11987
- if (context === void 0) {
11988
- for (const source of sources) {
11989
- if (source === null || source === void 0) continue;
11990
- const properties = isGuestHostObject(source) ? void 0 : reflectionProperties(source);
11991
- const keys = properties === void 0 ? ownEnumerableSandboxKeys(source, true) : [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(source)];
11992
- for (const key of keys) {
11993
- if (!hasOwnSandboxProperty(source, key, true)) continue;
11994
- const value = properties === void 0 ? getSandboxDataProperty(source, key, budget) : Reflect.get(properties, key, source);
11995
- setSandboxProperty(target, key, value, budget);
11791
+ case "map":
11792
+ return budgetProducedValue(
11793
+ await mapArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
11794
+ options.budget
11795
+ );
11796
+ case "filter":
11797
+ return budgetProducedValue(
11798
+ await filterArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
11799
+ options.budget
11800
+ );
11801
+ case "find":
11802
+ return budgetProducedValue(
11803
+ await findInArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
11804
+ options.budget
11805
+ );
11806
+ case "findIndex":
11807
+ return await findIndexInArray(
11808
+ value,
11809
+ getRequiredCallback(methodName, args[0]),
11810
+ options,
11811
+ stack,
11812
+ args[1]
11813
+ );
11814
+ case "findLast":
11815
+ return budgetProducedValue(
11816
+ await findLastInArray(
11817
+ value,
11818
+ getRequiredCallback(methodName, args[0]),
11819
+ options,
11820
+ stack,
11821
+ args[1]
11822
+ ),
11823
+ options.budget
11824
+ );
11825
+ case "findLastIndex":
11826
+ return await findLastIndexInArray(
11827
+ value,
11828
+ getRequiredCallback(methodName, args[0]),
11829
+ options,
11830
+ stack,
11831
+ args[1]
11832
+ );
11833
+ case "some":
11834
+ return await someInArray(
11835
+ value,
11836
+ getRequiredCallback(methodName, args[0]),
11837
+ options,
11838
+ stack,
11839
+ args[1]
11840
+ );
11841
+ case "every":
11842
+ return await everyInArray(
11843
+ value,
11844
+ getRequiredCallback(methodName, args[0]),
11845
+ options,
11846
+ stack,
11847
+ args[1]
11848
+ );
11849
+ case "reduce":
11850
+ return budgetProducedValue(
11851
+ await reduceArray(
11852
+ value,
11853
+ getRequiredCallback(methodName, args[0]),
11854
+ args.length > 1,
11855
+ args[1],
11856
+ options,
11857
+ stack
11858
+ ),
11859
+ options.budget
11860
+ );
11861
+ case "reduceRight":
11862
+ return budgetProducedValue(
11863
+ await reduceRightArray(
11864
+ value,
11865
+ getRequiredCallback(methodName, args[0]),
11866
+ args.length > 1,
11867
+ args[1],
11868
+ options,
11869
+ stack
11870
+ ),
11871
+ options.budget
11872
+ );
11873
+ case "forEach":
11874
+ await forEachArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]);
11875
+ return void 0;
11876
+ case "flatMap":
11877
+ return budgetProducedValue(
11878
+ await flatMapArray(
11879
+ value,
11880
+ getRequiredCallback(methodName, args[0]),
11881
+ options,
11882
+ stack,
11883
+ args[1]
11884
+ ),
11885
+ options.budget
11886
+ );
11887
+ case "flat":
11888
+ return budgetProducedValue(
11889
+ await flattenArray(
11890
+ value,
11891
+ args[0] === void 0 ? 1 : toIntegerOrInfinity(await sandboxNumber(args[0], options.budget, options.context)),
11892
+ options
11893
+ ),
11894
+ options.budget
11895
+ );
11896
+ case "includes":
11897
+ case "indexOf":
11898
+ case "lastIndexOf": {
11899
+ const length = value.length;
11900
+ if (length === 0) return methodName === "includes" ? false : -1;
11901
+ const reverse = methodName === "lastIndexOf";
11902
+ const start = reverse && args.length < 2 ? length - 1 : toIntegerOrInfinity(await sandboxNumber(args[1], options.budget, options.context));
11903
+ let index = reverse ? Math.min(start < 0 ? length + start : start, length - 1) : start < 0 ? Math.max(length + start, 0) : start;
11904
+ for (; index >= 0 && index < length; index += reverse ? -1 : 1) {
11905
+ options.budget.visitNode();
11906
+ if (methodName !== "includes" && !(index in value)) continue;
11907
+ const entry = await readArrayElement(value, index, options);
11908
+ if (entry === args[0] || methodName === "includes" && Number.isNaN(entry) && Number.isNaN(args[0]))
11909
+ return methodName === "includes" ? true : index;
11996
11910
  }
11911
+ return methodName === "includes" ? false : -1;
11997
11912
  }
11998
- return target;
11999
- }
12000
- return (async () => {
12001
- const release = retainValues(budget, () => [target, ...sources]);
12002
- try {
12003
- for (const source of sources) {
12004
- if (source === null || source === void 0) continue;
12005
- const properties = isGuestHostObject(source) ? void 0 : reflectionProperties(source);
12006
- const keys = properties === void 0 ? ownEnumerableSandboxKeys(source, true) : [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(source)];
12007
- for (const key of keys) {
12008
- if (!hasOwnSandboxProperty(source, key, true)) continue;
12009
- const value = await (context?.getProperty !== void 0 ? context.getProperty(source, key) : isGuestHostObject(source) ? getSandboxDataProperty(source, key, budget) : readPropertyDescriptor(Object.getOwnPropertyDescriptor(properties, key), source, context, true));
12010
- await setSandboxProperty(target, key, value, budget, true, context);
11913
+ case "join": {
11914
+ const length = value.length;
11915
+ const separator = args[0] === void 0 ? "," : await sandboxString(args[0], options.budget, options.context);
11916
+ return joinSandboxArray(
11917
+ arrayLikeSources.get(value) ?? value,
11918
+ length,
11919
+ separator,
11920
+ options.budget,
11921
+ options.context
11922
+ );
11923
+ }
11924
+ case "slice": {
11925
+ const length = value.length;
11926
+ const start = toIntegerOrInfinity(
11927
+ await sandboxNumber(args[0], options.budget, options.context)
11928
+ );
11929
+ const end = args[1] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[1], options.budget, options.context));
11930
+ const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
11931
+ const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
11932
+ const count = Math.max(final - first, 0);
11933
+ options.budget.allocateArrayLength(count);
11934
+ const result = new Array(count);
11935
+ const release = retainValues(options.budget, () => [result]);
11936
+ try {
11937
+ for (let index = 0; index < count; index += 1) {
11938
+ options.budget.visitNode();
11939
+ if (first + index in value)
11940
+ result[index] = await readArrayElement(value, first + index, options);
12011
11941
  }
11942
+ return budgetProducedValue(result, options.budget);
11943
+ } finally {
11944
+ release();
12012
11945
  }
12013
- return target;
12014
- } finally {
12015
- release();
12016
11946
  }
12017
- })();
12018
- }
12019
- function reflectionProperties(value) {
12020
- if (value !== null && value !== void 0 && typeof value !== "object")
12021
- value = createSandboxBox(value);
12022
- return objectProperties(value);
12023
- }
12024
- function objectProperties(value, mutable = false) {
12025
- if (isSandboxPromise(value)) return getPromiseProperties(value);
12026
- if (isSandboxMap(value) || isSandboxSet(value)) return getCollectionProperties(value);
12027
- if (isSandboxRegex(value)) return getRegexProperties(value);
12028
- if (isSandboxDate(value)) {
12029
- return value;
12030
- }
12031
- if (isGuestHostObject(value))
12032
- throw new TypeError("Live host object descriptors are not supported.");
12033
- if (isGuestClosure(value)) return materializeFunctionProperties(value);
12034
- if (isSandboxClosure(value)) {
12035
- if (mutable) throw new TypeError("Host function properties are read only.");
12036
- return value.properties ?? /* @__PURE__ */ Object.create(null);
12037
- }
12038
- if (!isAssignableSandboxTarget(value))
12039
- throw new TypeError("Expected a sandbox object or function.");
12040
- return value;
12041
- }
12042
- function exposePropertyDescriptor(descriptor) {
12043
- return "value" in descriptor ? descriptor : {
12044
- get: accessorClosure(descriptor.get),
12045
- set: accessorClosure(descriptor.set),
12046
- enumerable: descriptor.enumerable,
12047
- configurable: descriptor.configurable
12048
- };
12049
- }
12050
- async function propertyDescriptor(input, budget, context) {
12051
- objectProperties(input);
12052
- const descriptor = {};
12053
- const release = retainValues(budget, () => [
12054
- input,
12055
- descriptor.value,
12056
- ...retainedAccessorClosures(descriptor)
12057
- ]);
12058
- try {
12059
- for (const field of [
12060
- "enumerable",
12061
- "configurable",
12062
- "value",
12063
- "writable",
12064
- "get",
12065
- "set"
12066
- ]) {
12067
- if (getSandboxPropertyDescriptor(input, field, budget) === void 0 && !hasOwnSandboxProperty(input, field, false))
12068
- continue;
12069
- const value = await (context?.getProperty !== void 0 ? context.getProperty(input, field) : getSandboxDataProperty(input, field, budget));
12070
- if (field === "get" || field === "set") {
12071
- if (value !== void 0 && !isSandboxClosure(value))
12072
- throw new TypeError("Accessor must be a function or undefined.");
12073
- descriptor[field] = value === void 0 ? void 0 : accessorAdapter(value, field);
12074
- } else if (field === "value") {
12075
- descriptor.value = value;
12076
- } else {
12077
- descriptor[field] = Boolean(value);
11947
+ case "concat": {
11948
+ const result = [];
11949
+ const retained = {};
11950
+ options.budget.setRetainedValues(retained, () => [result]);
11951
+ try {
11952
+ for (const entry of [value, ...args]) {
11953
+ let spread = false;
11954
+ if (entry !== null && (typeof entry === "object" || typeof entry === "function")) {
11955
+ const flag = options.context?.getProperty !== void 0 ? await options.context.getProperty(entry, Symbol.isConcatSpreadable) : getSandboxDataProperty(entry, Symbol.isConcatSpreadable, options.budget);
11956
+ spread = flag === void 0 ? Array.isArray(entry) : Boolean(flag);
11957
+ }
11958
+ if (!spread) {
11959
+ options.budget.allocateArrayLength(result.length + 1);
11960
+ result.push(entry);
11961
+ continue;
11962
+ }
11963
+ const start = result.length;
11964
+ const source = await arrayLikeView(entry, options);
11965
+ const length = source.length;
11966
+ options.budget.allocateArrayLength(start + length);
11967
+ result.length += length;
11968
+ for (let index = 0; index < length; index++) {
11969
+ options.budget.visitNode();
11970
+ if (index in source)
11971
+ result[start + index] = await readArrayElement(source, index, options);
11972
+ }
11973
+ }
11974
+ return budgetProducedValue(result, options.budget);
11975
+ } finally {
11976
+ options.budget.setRetainedValues(retained, void 0);
12078
11977
  }
12079
11978
  }
12080
- if (("get" in descriptor || "set" in descriptor) && ("value" in descriptor || "writable" in descriptor))
12081
- throw new TypeError("A property cannot be both a data property and an accessor.");
12082
- return descriptor;
12083
- } finally {
12084
- release();
12085
- }
12086
- }
12087
- async function definePropertiesFromObject(target, descriptors2, budget, context) {
12088
- objectProperties(target, true);
12089
- const properties = [];
12090
- const release = retainValues(budget, () => [
12091
- target,
12092
- descriptors2,
12093
- properties,
12094
- ...properties.flatMap(([, descriptor]) => retainedAccessorClosures(descriptor))
12095
- ]);
12096
- try {
12097
- for (const key of ownEnumerableSandboxKeys(descriptors2, true)) {
12098
- if (!hasOwnSandboxProperty(descriptors2, key, true)) continue;
12099
- const descriptor = await (context?.getProperty !== void 0 ? context.getProperty(descriptors2, key) : getSandboxDataProperty(descriptors2, key, budget));
12100
- properties.push([key, await propertyDescriptor(descriptor, budget, context)]);
12101
- }
12102
- for (const [key, descriptor] of properties) defineDataProperty(target, key, descriptor, budget);
12103
- } finally {
12104
- release();
12105
- }
12106
- }
12107
- function defineDataProperty(target, key, descriptor, budget) {
12108
- budget.visitNode();
12109
- if (isFloat32Array(target))
12110
- throw new TypeError("Typed array property descriptors are not supported.");
12111
- const properties = objectProperties(target, true);
12112
- if (Array.isArray(properties)) {
12113
- if (key === "length" && "value" in descriptor)
12114
- budget.allocateArrayLength(Number(descriptor.value));
12115
- else if (typeof key !== "symbol") {
12116
- const index = Number(key);
12117
- if (Number.isInteger(index) && index >= 0 && index < 4294967295 && String(index) === key) {
12118
- budget.allocateArrayLength(index + 1);
11979
+ case "splice": {
11980
+ const length = value.length;
11981
+ const start = toIntegerOrInfinity(
11982
+ await sandboxNumber(args[0], options.budget, options.context)
11983
+ );
11984
+ const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
11985
+ const inserted = Math.max(args.length - 2, 0);
11986
+ const deleted = args.length === 0 ? 0 : args.length === 1 ? length - first : Math.min(
11987
+ Math.max(
11988
+ toIntegerOrInfinity(
11989
+ await sandboxNumber(args[1], options.budget, options.context)
11990
+ ),
11991
+ 0
11992
+ ),
11993
+ length - first
11994
+ );
11995
+ const nextLength = length + inserted - deleted;
11996
+ if (nextLength > Number.MAX_SAFE_INTEGER)
11997
+ throw new TypeError("Array-like length exceeds the safe integer limit.");
11998
+ options.budget.allocateArrayLength(deleted);
11999
+ const removed = new Array(deleted);
12000
+ const retained = {};
12001
+ options.budget.setRetainedValues(retained, () => [removed]);
12002
+ try {
12003
+ for (let index = 0; index < deleted; index++) {
12004
+ options.budget.visitNode();
12005
+ if (first + index in value)
12006
+ removed[index] = await readArrayElement(value, first + index, options);
12007
+ }
12008
+ if (inserted < deleted) {
12009
+ for (let index = first; index < length - deleted; index++)
12010
+ await moveArrayElement(value, index + deleted, index + inserted, options);
12011
+ for (let index = length; index > nextLength; index--)
12012
+ deleteArrayElement(value, index - 1, options);
12013
+ } else if (inserted > deleted) {
12014
+ for (let index = length - deleted; index > first; index--)
12015
+ await moveArrayElement(value, index + deleted - 1, index + inserted - 1, options);
12016
+ }
12017
+ for (let index = 0; index < inserted; index++)
12018
+ await writeArrayProperty(value, first + index, args[index + 2], options);
12019
+ await writeArrayProperty(value, "length", nextLength, options);
12020
+ } finally {
12021
+ options.budget.setRetainedValues(retained, void 0);
12119
12022
  }
12023
+ budgetProducedValue(removed, options.budget);
12024
+ budgetProducedValue(value, options.budget);
12025
+ return removed;
12120
12026
  }
12121
- }
12122
- Object.defineProperty(properties, key, descriptor);
12123
- markDescriptorObject(properties);
12124
- }
12125
- function isAssignableSandboxTarget(value) {
12126
- return typeof value === "object" && value !== null && !isSandboxClosure(value) && !isSandboxGenerator(value) && !isSandboxMap(value) && !isSandboxSet(value) && !isSandboxPromise(value) && !isSandboxRegex(value);
12127
- }
12128
- async function arrayFromSandboxValues(args, budget, context) {
12129
- const [items, mapFn, thisValue] = args;
12130
- if (mapFn !== void 0 && !isSandboxClosure(mapFn)) {
12131
- throw new TypeError("Array.from mapping callback must be a function.");
12132
- }
12133
- if (items === null || items === void 0) {
12134
- throw new TypeError("Array.from requires a non-null input.");
12135
- }
12136
- const read = (property) => context?.getProperty !== void 0 ? context.getProperty(items, property) : getSandboxDataProperty(items, property, budget);
12137
- const iterator = context === void 0 ? getSandboxIterator(items, budget) : await acquireSandboxIterator(items, budget, context);
12138
- const constructor = context?.thisValue;
12139
- let result;
12140
- let currentValue;
12141
- let failure;
12142
- const retained = {};
12143
- budget.setRetainedValues(retained, () => [
12144
- items,
12145
- iterator?.retainedValue,
12146
- mapFn,
12147
- constructor,
12148
- result,
12149
- currentValue,
12150
- failure
12151
- ]);
12152
- const checkData = createDataCheckpoint(budget, context);
12153
- const closeOnThrow = async (error) => {
12154
- failure = isCapturedException(error) ? error.reason : error;
12155
- try {
12156
- if (iterator !== void 0) await closeIterator(iterator, true);
12157
- } catch (closeError) {
12158
- if (!isFatalSandboxError(error) && isFatalSandboxError(closeError)) throw closeError;
12159
- }
12160
- throw error;
12161
- };
12162
- try {
12163
- let length = 0;
12164
- if (iterator === void 0) {
12165
- const number = await sandboxNumber(await read("length"), budget, context);
12166
- length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
12027
+ case "fill": {
12028
+ const length = value.length;
12029
+ const start = toIntegerOrInfinity(
12030
+ await sandboxNumber(args[1], options.budget, options.context)
12031
+ );
12032
+ const end = args[2] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[2], options.budget, options.context));
12033
+ const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12034
+ const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12035
+ for (let index = first; index < final; index++)
12036
+ await writeArrayProperty(value, index, args[0], options);
12037
+ budgetProducedValue(value, options.budget);
12038
+ return value;
12167
12039
  }
12168
- result = isSandboxClosure(constructor) && constructor.construct !== void 0 ? await invokeBuiltinClosure(
12169
- constructor,
12170
- iterator === void 0 ? [length] : [],
12171
- budget,
12172
- context,
12173
- void 0,
12174
- true
12175
- ) : createArrayFromConstructorArgs([length], budget);
12176
- checkData(result, 0, true);
12177
- let index = 0;
12178
- while (iterator !== void 0 || index < length) {
12179
- try {
12180
- budget.visitNode();
12181
- if (iterator !== void 0 && index >= Number.MAX_SAFE_INTEGER)
12182
- throw new TypeError("Array.from input is too long.");
12183
- } catch (error) {
12184
- await closeOnThrow(error);
12185
- }
12186
- if (iterator !== void 0) {
12187
- const next = await iterator.next();
12188
- if (typeof next !== "object" || next === null)
12189
- throw new TypeError("Iterator result must be an object.");
12190
- if ((await readIteratorResult(iterator, next, "done")).value) break;
12191
- currentValue = (await readIteratorResult(iterator, next, "value")).value;
12192
- } else {
12193
- currentValue = await read(index);
12040
+ case "copyWithin": {
12041
+ const length = value.length;
12042
+ const target = toIntegerOrInfinity(
12043
+ await sandboxNumber(args[0], options.budget, options.context)
12044
+ );
12045
+ const start = toIntegerOrInfinity(
12046
+ await sandboxNumber(args[1], options.budget, options.context)
12047
+ );
12048
+ const end = args[2] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[2], options.budget, options.context));
12049
+ let to = target < 0 ? Math.max(length + target, 0) : Math.min(target, length);
12050
+ let from = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12051
+ const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12052
+ let count = Math.min(final - from, length - to);
12053
+ const direction = from < to && to < from + count ? -1 : 1;
12054
+ if (direction < 0) {
12055
+ from += count - 1;
12056
+ to += count - 1;
12194
12057
  }
12195
- try {
12196
- if (Array.isArray(result)) budget.allocateArrayLength(index + 1);
12197
- if (mapFn !== void 0)
12198
- currentValue = await invokeBuiltinClosure(
12199
- mapFn,
12200
- [currentValue, index],
12201
- budget,
12202
- context,
12203
- thisValue
12204
- );
12205
- const key = String(index);
12206
- const growth = key.length + 1 + (Array.isArray(result) ? Math.max(0, index + 1 - result.length) : 0) + (budget.limits.dataSize === void 0 ? 0 : measureSandboxData([currentValue]));
12207
- budget.visitNode();
12208
- defineOwnDataProperty(objectProperties(result, true), key, currentValue);
12209
- currentValue = void 0;
12210
- checkData(result, growth, isSandboxClosure(result));
12211
- } catch (error) {
12212
- await closeOnThrow(error);
12058
+ while (count-- > 0) {
12059
+ await moveArrayElement(value, from, to, options);
12060
+ from += direction;
12061
+ to += direction;
12213
12062
  }
12214
- index += 1;
12063
+ budgetProducedValue(value, options.budget);
12064
+ return value;
12215
12065
  }
12216
- setSandboxProperty(result, "length", index, budget);
12217
- checkData(result, 0, true);
12218
- return allocateProducedSandboxValue(result, budget);
12219
- } finally {
12220
- budget.setRetainedValues(retained, void 0);
12221
- }
12222
- }
12223
- function createArrayFromConstructorArgs(args, budget) {
12224
- if (args.length !== 1) {
12225
- return budgetSandboxValue(Reflect.apply(Array, Array, [...args]), budget);
12226
- }
12227
- const [lengthOrValue] = args;
12228
- if (typeof lengthOrValue !== "number") {
12229
- return budgetSandboxValue([lengthOrValue], budget);
12230
- }
12231
- if (!Number.isInteger(lengthOrValue) || lengthOrValue < 0 || lengthOrValue > 4294967295) {
12232
- throw new RangeError("Invalid array length.");
12233
- }
12234
- budget.allocateArrayLength(lengthOrValue);
12235
- const release = budget.provisionDataUsage(lengthOrValue + 1);
12236
- try {
12237
- return new Array(lengthOrValue);
12238
- } finally {
12239
- release();
12240
- }
12241
- }
12242
- async function getOwnEnumerableEntries(value, budget, context) {
12243
- const entries = [];
12244
- const release = retainValues(budget, () => [value, entries]);
12245
- try {
12246
- for (const key of ownEnumerableSandboxKeys(value)) {
12247
- if (!hasOwnSandboxProperty(value, key, true)) continue;
12248
- entries.push([
12249
- key,
12250
- await (context?.getProperty !== void 0 ? context.getProperty(value, key) : getSandboxDataProperty(value, key, budget))
12251
- ]);
12252
- }
12253
- return entries;
12254
- } finally {
12255
- release();
12256
- }
12257
- }
12258
- function budgetSandboxValue(value, budget) {
12259
- const sandboxValue = deepCopyToSandbox(value);
12260
- return allocateProducedSandboxValue(sandboxValue, budget);
12261
- }
12262
- function stringFromCodes(args, convert, budget, context) {
12263
- let result = "";
12264
- let index = 0;
12265
- const release = retainValues(budget, () => [...args, result]);
12266
- try {
12267
- const output = advance();
12268
- if (typeof output !== "string") return output.finally(release);
12269
- release();
12270
- return output;
12271
- } catch (error) {
12272
- release();
12273
- throw error;
12274
- }
12275
- function advance() {
12276
- while (index < args.length) {
12277
- budget.visitNode();
12278
- const number = sandboxNumber(args[index++], budget, context);
12279
- if (number instanceof Promise) return number.then((value) => {
12280
- result = budget.allocateString(result + convert(value));
12281
- return advance();
12282
- });
12283
- result = budget.allocateString(result + convert(number));
12066
+ case "at": {
12067
+ const length = value.length;
12068
+ const index = toIntegerOrInfinity(
12069
+ await sandboxNumber(args[0], options.budget, options.context)
12070
+ );
12071
+ const actual = index < 0 ? length + index : index;
12072
+ return actual < 0 || actual >= length ? void 0 : budgetProducedValue(await readArrayElement(value, actual, options), options.budget);
12284
12073
  }
12285
- return result;
12286
- }
12287
- }
12288
- function stringRaw(args, budget, context) {
12289
- const [template, ...substitutions] = args;
12290
- if (context?.getProperty !== void 0)
12291
- return (async () => {
12292
- if (template === null || template === void 0)
12293
- throw new TypeError("String.raw requires a template object.");
12294
- const raw2 = await context.getProperty(template, "raw");
12295
- if (raw2 === null || raw2 === void 0)
12296
- throw new TypeError("String.raw requires raw strings.");
12297
- const number = await sandboxNumber(
12298
- await context.getProperty(raw2, "length"),
12299
- budget,
12300
- context
12074
+ case "sort":
12075
+ await sortArray(
12076
+ value,
12077
+ args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
12078
+ options,
12079
+ stack
12301
12080
  );
12302
- const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
12303
- let result2 = "";
12304
- const retained = {};
12305
- budget.setRetainedValues(retained, () => [raw2, result2]);
12081
+ budgetProducedValue(value, options.budget);
12082
+ return value;
12083
+ case "reverse": {
12084
+ const length = value.length;
12085
+ let lowerValue;
12086
+ let upperValue;
12087
+ const release = retainValues(options.budget, () => [lowerValue, upperValue]);
12306
12088
  try {
12307
- for (let index = 0; index < length; index++) {
12308
- budget.visitNode();
12309
- result2 = budget.allocateString(
12310
- result2 + await sandboxString(await context.getProperty(raw2, index), budget, context)
12311
- );
12312
- if (index + 1 < length && index < substitutions.length)
12313
- result2 = budget.allocateString(
12314
- result2 + await sandboxString(substitutions[index], budget, context)
12315
- );
12089
+ for (let lower = 0; lower < Math.floor(length / 2); lower++) {
12090
+ options.budget.visitNode();
12091
+ lowerValue = upperValue = void 0;
12092
+ const upper = length - lower - 1;
12093
+ const lowerExists = lower in value;
12094
+ lowerValue = lowerExists ? await readArrayElement(value, lower, options) : void 0;
12095
+ const upperExists = upper in value;
12096
+ upperValue = upperExists ? await readArrayElement(value, upper, options) : void 0;
12097
+ if (lowerExists && upperExists) {
12098
+ await writeArrayProperty(value, lower, upperValue, options);
12099
+ await writeArrayProperty(value, upper, lowerValue, options);
12100
+ } else if (!lowerExists && upperExists) {
12101
+ await writeArrayProperty(value, lower, upperValue, options);
12102
+ deleteArrayElement(value, upper, options);
12103
+ } else if (lowerExists) {
12104
+ deleteArrayElement(value, lower, options);
12105
+ await writeArrayProperty(value, upper, lowerValue, options);
12106
+ }
12316
12107
  }
12317
- return result2;
12108
+ budgetProducedValue(value, options.budget);
12109
+ return value;
12318
12110
  } finally {
12319
- budget.setRetainedValues(retained, void 0);
12111
+ release();
12320
12112
  }
12321
- })();
12322
- const raw = getTemplateRawParts(template);
12323
- let result = "";
12324
- for (let index = 0; index < raw.length; index += 1) {
12325
- result += String(raw[index]);
12326
- if (index < raw.length - 1 && index < substitutions.length) {
12327
- result += String(substitutions[index]);
12328
- }
12329
- }
12330
- return budget.allocateString(result);
12331
- }
12332
- function getTemplateRawParts(template) {
12333
- const raw = typeof template === "object" && template !== null ? template.raw : void 0;
12334
- if (typeof template !== "object" || template === null || isSandboxClosure(template) || isSandboxPromise(template) || !Array.isArray(raw)) {
12335
- throw new TypeError("String.raw requires a raw strings array.");
12336
- }
12337
- return raw;
12338
- }
12339
-
12340
- // packages/safe-js/src/interp/classes.ts
12341
- async function evaluateClass(node, context, evaluateNode2, callContext) {
12342
- const scope = context.scope.child();
12343
- if (node.id !== void 0) scope.predeclare(node.id.name, "const");
12344
- const classContext = { ...context, scope, inferredName: void 0 };
12345
- let parent;
12346
- let prototypeParent;
12347
- const fields2 = [];
12348
- const statics = [];
12349
- let constructor;
12350
- const release = retainValues(context.budget, () => [parent, prototypeParent, constructor, ...fields2.map((field) => field.key), ...statics.flatMap((field) => "key" in field ? [field.key] : [])]);
12351
- try {
12352
- if (node.superClass !== void 0) {
12353
- const result = await evaluateNode2(node.superClass, classContext);
12354
- if (result.kind !== "normal") return result;
12355
- parent = result.value;
12356
- if (parent !== null && (!isSandboxClosure(parent) || parent.construct === void 0))
12357
- throw new TypeError("Class extends value is not a constructor or null.");
12358
- prototypeParent = parent === null ? null : await callContext.getProperty(parent, "prototype");
12359
- if (prototypeParent !== null && typeof prototypeParent !== "object")
12360
- throw new TypeError("Class extends value has an invalid prototype.");
12361
12113
  }
12362
- const derived = node.superClass !== void 0;
12363
- constructor = createClassConstructor(node, { ...classContext, inferredName: context.inferredName }, evaluateNode2, fields2);
12364
- const properties = materializeFunctionProperties(constructor);
12365
- const prototype = properties.prototype;
12366
- Object.defineProperty(properties, "prototype", { writable: false });
12367
- if (derived) setSandboxPrototype(prototype, prototypeParent, context.budget);
12368
- if (isSandboxClosure(parent)) setSandboxPrototype(constructor, parent, context.budget);
12369
- const pattern = createPatternContext(classContext, scope, evaluateNode2);
12370
- for (const element of node.body.body) {
12371
- context.budget.visitNode();
12372
- if (element.type === "StaticBlock") {
12373
- statics.push({ element });
12374
- continue;
12375
- }
12376
- if (element.type === "MethodDefinition" && element.kind === "constructor") continue;
12377
- let key;
12378
- if (element.computed) {
12379
- const result = await evaluateNode2(element.key, classContext);
12380
- if (result.kind !== "normal") return result;
12381
- key = await pattern.toPropertyKey(result.value);
12382
- } else {
12383
- key = element.key.type === "Identifier" ? element.key.name : String(element.key.value);
12384
- }
12385
- if (typeof key === "string") context.budget.allocateString(key);
12386
- if (element.type === "PropertyDefinition") {
12387
- (element.static ? statics : fields2).push({ element, key });
12388
- } else {
12389
- const home = element.static ? constructor : prototype;
12390
- const method = createInterpretedClosure(element.value, classContext, evaluateNode2, home);
12391
- const accessor = element.kind === "get" || element.kind === "set" ? element.kind : void 0;
12392
- Object.defineProperty(materializeFunctionProperties(method), "name", {
12393
- value: accessor === void 0 ? propertyFunctionName(key) : `${accessor} ${propertyFunctionName(key)}`
12394
- });
12395
- Object.defineProperty(
12396
- element.static ? properties : prototype,
12397
- key,
12398
- accessor === void 0 ? { value: method, configurable: true, writable: true, enumerable: false } : { [accessor]: accessorAdapter(method, accessor), configurable: true, enumerable: false }
12114
+ case "toSorted": {
12115
+ const length = value.length;
12116
+ options.budget.allocateArrayLength(length);
12117
+ const result = new Array(length);
12118
+ const release = retainValues(options.budget, () => [result]);
12119
+ try {
12120
+ for (let index = 0; index < length; index += 1) {
12121
+ options.budget.visitNode();
12122
+ result[index] = await readArrayElement(value, index, options);
12123
+ }
12124
+ await sortArray(
12125
+ result,
12126
+ args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
12127
+ options,
12128
+ stack
12399
12129
  );
12130
+ return budgetProducedValue(result, options.budget);
12131
+ } finally {
12132
+ release();
12400
12133
  }
12401
12134
  }
12402
- if (node.id !== void 0) scope.declare(node.id.name, "const", constructor);
12403
- for (const element of statics) await initializeElement(element, constructor, constructor, classContext, evaluateNode2);
12404
- classOrigins.get(constructor).initialized = true;
12405
- if (node.type === "ClassDeclaration") {
12406
- context.scope.declare(node.id.name, "let", constructor);
12407
- return { kind: "normal", hasValue: false, value: void 0 };
12135
+ case "toReversed": {
12136
+ const length = value.length;
12137
+ options.budget.allocateArrayLength(length);
12138
+ const result = new Array(length);
12139
+ const release = retainValues(options.budget, () => [result]);
12140
+ try {
12141
+ for (let index = 0; index < length; index += 1) {
12142
+ options.budget.visitNode();
12143
+ result[index] = await readArrayElement(value, length - index - 1, options);
12144
+ }
12145
+ return budgetProducedValue(result, options.budget);
12146
+ } finally {
12147
+ release();
12148
+ }
12408
12149
  }
12409
- return { kind: "normal", hasValue: true, value: constructor };
12410
- } finally {
12411
- release();
12412
- }
12413
- }
12414
- var classOrigins = /* @__PURE__ */ new WeakMap();
12415
- function createClassConstructor(node, context, evaluateNode2, fields2) {
12416
- const scope = context.scope;
12417
- const classContext = { ...context, inferredName: void 0 };
12418
- const constructorElement = node.body.body.find((element) => element.type === "MethodDefinition" && element.kind === "constructor");
12419
- const derived = node.superClass !== void 0;
12420
- const constructor = createSandboxClosure({
12421
- guest: true,
12422
- sandbox: true,
12423
- name: node.id?.name ?? context.inferredName ?? "",
12424
- length: constructorElement === void 0 ? 0 : getFunctionLength(constructorElement.value.params),
12425
- sourceRange: functionSources.get(node),
12426
- retainedValues: () => [...scope.retainedValues(), ...fields2.map((field) => field.key)],
12427
- call: () => {
12428
- throw new TypeError("Class constructor cannot be invoked without 'new'.");
12429
- },
12430
- construct: async (args, invocation) => {
12431
- const prototype = materializeFunctionProperties(constructor).prototype;
12432
- const newTarget = invocation?.newTarget ?? constructor;
12433
- let thisValue;
12434
- let thisScope;
12435
- let initialized = !derived;
12436
- const initializeFields = async (receiver) => {
12437
- for (const field of fields2) {
12438
- await initializeElement(field, receiver, prototype, classContext, evaluateNode2);
12150
+ case "toSpliced": {
12151
+ const length = value.length;
12152
+ const start = toIntegerOrInfinity(
12153
+ await sandboxNumber(args[0], options.budget, options.context)
12154
+ );
12155
+ const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12156
+ const inserted = Math.max(args.length - 2, 0);
12157
+ const deleted = args.length === 0 ? 0 : args.length === 1 ? length - first : Math.min(
12158
+ Math.max(
12159
+ toIntegerOrInfinity(
12160
+ await sandboxNumber(args[1], options.budget, options.context)
12161
+ ),
12162
+ 0
12163
+ ),
12164
+ length - first
12165
+ );
12166
+ const resultLength = length + inserted - deleted;
12167
+ if (resultLength > Number.MAX_SAFE_INTEGER)
12168
+ throw new TypeError("Array-like length exceeds the safe integer limit.");
12169
+ options.budget.allocateArrayLength(resultLength);
12170
+ const result = new Array(resultLength);
12171
+ const release = retainValues(options.budget, () => [result]);
12172
+ try {
12173
+ for (let index = 0; index < resultLength; index += 1) {
12174
+ options.budget.visitNode();
12175
+ result[index] = index < first ? await readArrayElement(value, index, options) : index < first + inserted ? args[index - first + 2] : await readArrayElement(value, index - inserted + deleted, options);
12439
12176
  }
12440
- };
12441
- const superCall = async (argumentsList) => {
12442
- const superConstructor = getSandboxPrototype(constructor, context.budget);
12443
- if (!isSandboxClosure(superConstructor) || superConstructor.construct === void 0)
12444
- throw new TypeError("Super constructor is not a constructor.");
12445
- const receiver = await invocation.invokeClosure(superConstructor, argumentsList, void 0, true, newTarget);
12446
- if (initialized) throw new ReferenceError("Super constructor may only initialize this once.");
12447
- initialized = true;
12448
- thisValue = receiver;
12449
- thisScope?.declare("this", "const", receiver);
12450
- await initializeFields(receiver);
12451
- return receiver;
12452
- };
12453
- if (!derived) {
12454
- thisValue = {};
12455
- const targetPrototype = await invocation.getProperty(newTarget, "prototype");
12456
- if (typeof targetPrototype === "object" && targetPrototype !== null)
12457
- setSandboxPrototype(thisValue, targetPrototype, context.budget);
12177
+ return budgetProducedValue(result, options.budget);
12178
+ } finally {
12179
+ release();
12458
12180
  }
12459
- if (constructorElement === void 0) {
12460
- if (derived) return superCall(args);
12461
- await initializeFields(thisValue);
12462
- return thisValue;
12181
+ }
12182
+ case "with": {
12183
+ const length = value.length;
12184
+ const index = toIntegerOrInfinity(
12185
+ options.context === void 0 ? args[0] : await sandboxNumber(args[0], options.budget, options.context)
12186
+ );
12187
+ const actualIndex = index < 0 ? length + index : index;
12188
+ if (actualIndex < 0 || actualIndex >= length) {
12189
+ throw new RangeError("Invalid index");
12463
12190
  }
12464
- const result = await executeClosure(constructorElement.value, args, thisValue, {
12465
- ...classContext,
12466
- compilation: invocation?.compilation ?? context.compilation,
12467
- callStack: [...invocation?.stack ?? context.callStack],
12468
- functionEnvironment: {
12469
- newTarget,
12470
- homeObject: prototype,
12471
- construction: {
12472
- derived,
12473
- superCall,
12474
- initialize: async (functionScope) => {
12475
- thisScope = functionScope;
12476
- if (!derived) await initializeFields(thisValue);
12477
- }
12478
- }
12191
+ options.budget.allocateArrayLength(length);
12192
+ const result = [];
12193
+ const release = retainValues(options.budget, () => [result]);
12194
+ try {
12195
+ for (let position = 0; position < length; position += 1) {
12196
+ options.budget.visitNode();
12197
+ result[position] = position === actualIndex ? args[1] : await readArrayElement(value, position, options);
12479
12198
  }
12480
- }, evaluateNode2);
12481
- if (typeof result === "object" && result !== null) return result;
12482
- if (derived && result !== void 0) throw new TypeError("Derived constructors may only return an object or undefined.");
12483
- if (!initialized) throw new ReferenceError("Must call super constructor before returning from derived constructor.");
12484
- return thisValue;
12199
+ return budgetProducedValue(result, options.budget);
12200
+ } finally {
12201
+ release();
12202
+ }
12485
12203
  }
12486
- });
12487
- classOrigins.set(constructor, { node, scope, fields: fields2, initialized: false });
12488
- return constructor;
12204
+ case "push": {
12205
+ const nextLength = await appendArrayValues(value, args, options);
12206
+ budgetProducedValue(value, options.budget);
12207
+ return nextLength;
12208
+ }
12209
+ case "pop":
12210
+ case "shift": {
12211
+ const length = value.length;
12212
+ if (length === 0) {
12213
+ await writeArrayProperty(value, "length", 0, options);
12214
+ return void 0;
12215
+ }
12216
+ const result = await readArrayElement(value, methodName === "pop" ? length - 1 : 0, options);
12217
+ const retained = {};
12218
+ options.budget.setRetainedValues(retained, () => [result]);
12219
+ try {
12220
+ if (methodName === "shift")
12221
+ for (let index = 1; index < length; index++)
12222
+ await moveArrayElement(value, index, index - 1, options);
12223
+ deleteArrayElement(value, length - 1, options);
12224
+ await writeArrayProperty(value, "length", length - 1, options);
12225
+ return budgetProducedValue(result, options.budget);
12226
+ } finally {
12227
+ options.budget.setRetainedValues(retained, void 0);
12228
+ }
12229
+ }
12230
+ case "unshift": {
12231
+ const nextLength = await prependArrayValues(value, args, options);
12232
+ budgetProducedValue(value, options.budget);
12233
+ return nextLength;
12234
+ }
12235
+ }
12489
12236
  }
12490
- async function initializeElement(definition, receiver, homeObject, context, evaluateNode2) {
12491
- const scope = context.scope.child({}, { functionBoundary: true });
12492
- scope.declare("this", "const", receiver);
12493
- const element = definition.element;
12494
- const initializer = element.type === "StaticBlock" ? element.body : element.value;
12495
- let value;
12496
- if (initializer !== void 0) {
12497
- if (element.type === "StaticBlock") hoistVarDeclarations(element.body, scope);
12498
- const result = await evaluateNode2(initializer, { ...context, scope, functionEnvironment: { homeObject }, inferredName: "key" in definition ? propertyFunctionName(definition.key) : void 0 });
12499
- if (result.kind === "error") throw result.error;
12500
- if (result.kind === "throw") throw result.value;
12501
- value = result.hasValue ? result.value : void 0;
12237
+ async function appendArrayValues(target, values, options) {
12238
+ let length = target.length;
12239
+ if (length + values.length > Number.MAX_SAFE_INTEGER)
12240
+ throw new TypeError("Array-like length exceeds the safe integer limit.");
12241
+ for (const value of values) {
12242
+ await writeArrayProperty(target, length++, value, options);
12502
12243
  }
12503
- if ("key" in definition) {
12504
- defineDataProperty(receiver, definition.key, { value, configurable: true, writable: true, enumerable: true }, context.budget);
12244
+ await writeArrayProperty(target, "length", length, options);
12245
+ return length;
12246
+ }
12247
+ async function prependArrayValues(target, values, options) {
12248
+ const originalLength = target.length;
12249
+ const length = originalLength + values.length;
12250
+ if (length > Number.MAX_SAFE_INTEGER)
12251
+ throw new TypeError("Array-like length exceeds the safe integer limit.");
12252
+ for (let index = values.length === 0 ? -1 : originalLength - 1; index >= 0; index -= 1) {
12253
+ const targetIndex = index + values.length;
12254
+ await moveArrayElement(target, index, targetIndex, options);
12255
+ }
12256
+ for (let index = 0; index < values.length; index += 1) {
12257
+ await writeArrayProperty(target, index, values[index], options);
12505
12258
  }
12259
+ await writeArrayProperty(target, "length", length, options);
12260
+ return length;
12506
12261
  }
12507
-
12508
- // packages/safe-js/src/interp/resume-target.ts
12509
- function containsResumeTarget(node, targetNodeIds) {
12510
- if (targetNodeIds === void 0 ? node.type === "YieldExpression" : node.nodeId !== void 0 && targetNodeIds.has(node.nodeId)) {
12511
- return true;
12262
+ function isCallbackArrayMethod(methodName) {
12263
+ return methodName === "map" || methodName === "filter" || methodName === "find" || methodName === "findIndex" || methodName === "findLast" || methodName === "findLastIndex" || methodName === "some" || methodName === "every" || methodName === "reduce" || methodName === "reduceRight" || methodName === "forEach" || methodName === "flatMap" || methodName === "sort";
12264
+ }
12265
+ function isMutatingArrayMethod(methodName) {
12266
+ return methodName === "splice" || methodName === "fill" || methodName === "copyWithin" || methodName === "sort" || methodName === "reverse" || methodName === "push" || methodName === "pop" || methodName === "shift" || methodName === "unshift";
12267
+ }
12268
+ function getRequiredCallback(methodName, value) {
12269
+ if (!isSandboxClosure(value)) {
12270
+ throw new TypeError(`Array#${methodName} requires a sandbox closure callback.`);
12512
12271
  }
12513
- if (node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression") {
12514
- return false;
12272
+ return value;
12273
+ }
12274
+ function readArrayElement(value, index, options) {
12275
+ const receiver = arrayLikeSources.get(value) ?? value;
12276
+ return options.context?.getProperty !== void 0 ? options.context.getProperty(receiver, index) : getSandboxDataProperty(receiver, index, options.budget);
12277
+ }
12278
+ function writeArrayProperty(value, key, entry, options) {
12279
+ options.budget.visitNode();
12280
+ const receiver = arrayLikeSources.get(value) ?? value;
12281
+ if (Array.isArray(receiver)) {
12282
+ if (key === "length") options.budget.allocateArrayLength(Number(entry));
12283
+ else if (typeof key === "number") options.budget.allocateArrayLength(key + 1);
12515
12284
  }
12516
- for (const value of Object.values(node)) {
12517
- if (Array.isArray(value)) {
12518
- if (value.some((entry) => isParseResult(entry) && containsResumeTarget(entry, targetNodeIds))) {
12519
- return true;
12285
+ if (options.setProperty !== void 0) return options.setProperty(receiver, String(key), entry);
12286
+ if (!Reflect.set(receiver, key, entry))
12287
+ throw new TypeError(`Cannot assign to read only property '${key}'.`);
12288
+ }
12289
+ function deleteArrayElement(value, index, options) {
12290
+ options.budget.visitNode();
12291
+ const receiver = arrayLikeSources.get(value) ?? value;
12292
+ const deleted = options.deleteProperty === void 0 ? Reflect.deleteProperty(receiver, String(index)) : options.deleteProperty(receiver, String(index));
12293
+ if (!deleted) throw new TypeError(`Cannot delete property '${index}'.`);
12294
+ }
12295
+ async function moveArrayElement(value, from, to, options) {
12296
+ options.budget.visitNode();
12297
+ if (from in value)
12298
+ await writeArrayProperty(value, to, await readArrayElement(value, from, options), options);
12299
+ else deleteArrayElement(value, to, options);
12300
+ }
12301
+ async function mapArray(value, callback, options, stack, thisValue) {
12302
+ const length = value.length;
12303
+ options.budget.allocateArrayLength(length);
12304
+ const result = new Array(length);
12305
+ options.budget.setRetainedValues(result, () => [result]);
12306
+ try {
12307
+ for (let index = 0; index < length; index += 1) {
12308
+ options.budget.visitNode();
12309
+ if (!(index in value)) {
12310
+ continue;
12520
12311
  }
12521
- continue;
12522
- }
12523
- if (isParseResult(value) && containsResumeTarget(value, targetNodeIds)) {
12524
- return true;
12312
+ result[index] = await callArrayCallback(
12313
+ callback,
12314
+ await readArrayElement(value, index, options),
12315
+ index,
12316
+ value,
12317
+ options,
12318
+ stack,
12319
+ thisValue
12320
+ );
12525
12321
  }
12322
+ return result;
12323
+ } finally {
12324
+ options.budget.setRetainedValues(result, void 0);
12526
12325
  }
12527
- return false;
12528
- }
12529
- function isParseResult(value) {
12530
- return typeof value === "object" && value !== null && typeof value.type === "string" && Object.hasOwn(value, "span");
12531
12326
  }
12532
-
12533
- // packages/safe-js/src/interp/methods/array.ts
12534
- var arrayLikeSources = /* @__PURE__ */ new WeakMap();
12535
- var activeArrayCallbacks = /* @__PURE__ */ new WeakMap();
12536
- var arrayMethodNames = /* @__PURE__ */ new Set([
12537
- "map",
12538
- "filter",
12539
- "find",
12540
- "findIndex",
12541
- "findLast",
12542
- "findLastIndex",
12543
- "some",
12544
- "every",
12545
- "reduce",
12546
- "reduceRight",
12547
- "forEach",
12548
- "flatMap",
12549
- "flat",
12550
- "includes",
12551
- "indexOf",
12552
- "lastIndexOf",
12553
- "join",
12554
- "slice",
12555
- "concat",
12556
- "splice",
12557
- "fill",
12558
- "copyWithin",
12559
- "at",
12560
- "sort",
12561
- "reverse",
12562
- "toSorted",
12563
- "toReversed",
12564
- "toSpliced",
12565
- "with",
12566
- "push",
12567
- "pop",
12568
- "shift",
12569
- "unshift"
12570
- ]);
12571
- function getArrayMember(value, property, options) {
12572
- const index = getArrayIndex(property);
12573
- if (index !== void 0) {
12574
- return Object.hasOwn(value, index) ? value[index] : void 0;
12327
+ async function filterArray(value, callback, options, stack, thisValue) {
12328
+ const length = value.length;
12329
+ const result = [];
12330
+ options.budget.setRetainedValues(result, () => [result]);
12331
+ try {
12332
+ for (let index = 0; index < length; index += 1) {
12333
+ options.budget.visitNode();
12334
+ if (!(index in value)) {
12335
+ continue;
12336
+ }
12337
+ const entry = await readArrayElement(value, index, options);
12338
+ if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
12339
+ result.push(entry);
12340
+ }
12341
+ }
12342
+ return result;
12343
+ } finally {
12344
+ options.budget.setRetainedValues(result, void 0);
12575
12345
  }
12576
- if (property === "length") {
12577
- return value.length;
12346
+ }
12347
+ async function findInArray(value, callback, options, stack, thisValue) {
12348
+ const length = value.length;
12349
+ for (let index = 0; index < length; index += 1) {
12350
+ options.budget.visitNode();
12351
+ const entry = await readArrayElement(value, index, options);
12352
+ if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
12353
+ return entry;
12354
+ }
12578
12355
  }
12579
- if (Object.hasOwn(value, property)) {
12580
- return value[String(property)];
12356
+ return void 0;
12357
+ }
12358
+ async function findIndexInArray(value, callback, options, stack, thisValue) {
12359
+ const length = value.length;
12360
+ for (let index = 0; index < length; index += 1) {
12361
+ options.budget.visitNode();
12362
+ const entry = await readArrayElement(value, index, options);
12363
+ if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
12364
+ return index;
12365
+ }
12581
12366
  }
12582
- if (isArrayMethodName(property)) {
12583
- return createSandboxClosure({
12584
- sandbox: true,
12585
- name: `Array#${property}`,
12586
- call: (args, context) => callArrayMethod(
12587
- context?.thisValue,
12588
- property,
12589
- args,
12590
- { ...options, context },
12591
- context?.stack ?? []
12592
- )
12593
- });
12367
+ return -1;
12368
+ }
12369
+ async function findLastInArray(value, callback, options, stack, thisValue) {
12370
+ const length = value.length;
12371
+ for (let index = length - 1; index >= 0; index -= 1) {
12372
+ options.budget.visitNode();
12373
+ const entry = await readArrayElement(value, index, options);
12374
+ if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
12375
+ return entry;
12376
+ }
12594
12377
  }
12595
12378
  return void 0;
12596
12379
  }
12597
- function getArrayIndex(property) {
12598
- const index = typeof property === "number" ? property : Number(property);
12599
- if (!Number.isSafeInteger(index) || index < 0 || index >= 2 ** 32 - 1 || String(index) !== String(property)) {
12600
- return void 0;
12380
+ async function findLastIndexInArray(value, callback, options, stack, thisValue) {
12381
+ const length = value.length;
12382
+ for (let index = length - 1; index >= 0; index -= 1) {
12383
+ options.budget.visitNode();
12384
+ const entry = await readArrayElement(value, index, options);
12385
+ if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
12386
+ return index;
12387
+ }
12601
12388
  }
12602
- return index;
12389
+ return -1;
12603
12390
  }
12604
- function isArrayMethodName(property) {
12605
- return typeof property === "string" && arrayMethodNames.has(property);
12391
+ async function someInArray(value, callback, options, stack, thisValue) {
12392
+ const length = value.length;
12393
+ for (let index = 0; index < length; index += 1) {
12394
+ options.budget.visitNode();
12395
+ if (!(index in value)) {
12396
+ continue;
12397
+ }
12398
+ if (await callArrayCallback(
12399
+ callback,
12400
+ await readArrayElement(value, index, options),
12401
+ index,
12402
+ value,
12403
+ options,
12404
+ stack,
12405
+ thisValue
12406
+ )) {
12407
+ return true;
12408
+ }
12409
+ }
12410
+ return false;
12606
12411
  }
12607
- async function callArrayMethod(receiver, methodName, args, options, stack = []) {
12608
- if (receiver === null || receiver === void 0)
12609
- throw new TypeError("Array method requires a receiver.");
12610
- if (typeof receiver !== "object") {
12611
- receiver = createSandboxBox(receiver);
12612
- options.budget.chargeDataUsage(measureSandboxData([receiver]));
12412
+ async function everyInArray(value, callback, options, stack, thisValue) {
12413
+ const length = value.length;
12414
+ for (let index = 0; index < length; index += 1) {
12415
+ options.budget.visitNode();
12416
+ if (!(index in value)) {
12417
+ continue;
12418
+ }
12419
+ if (!await callArrayCallback(
12420
+ callback,
12421
+ await readArrayElement(value, index, options),
12422
+ index,
12423
+ value,
12424
+ options,
12425
+ stack,
12426
+ thisValue
12427
+ )) {
12428
+ return false;
12429
+ }
12613
12430
  }
12614
- const retainedReceiver = {};
12615
- options.budget.setRetainedValues(retainedReceiver, () => [receiver]);
12431
+ return true;
12432
+ }
12433
+ async function reduceArray(value, callback, hasInitialValue, initialValue, options, stack) {
12434
+ const length = value.length;
12435
+ if (hasInitialValue) {
12436
+ return reduceFromLeft(value, callback, initialValue, 0, length, options, stack);
12437
+ }
12438
+ const start = findNextDefinedIndex(value, 0, 1, length, options.budget);
12439
+ if (start < 0) {
12440
+ throw new TypeError("Reduce of empty array with no initial value.");
12441
+ }
12442
+ return reduceFromLeft(
12443
+ value,
12444
+ callback,
12445
+ await readArrayElement(value, start, options),
12446
+ start + 1,
12447
+ length,
12448
+ options,
12449
+ stack
12450
+ );
12451
+ }
12452
+ async function reduceRightArray(value, callback, hasInitialValue, initialValue, options, stack) {
12453
+ const length = value.length;
12454
+ if (hasInitialValue) {
12455
+ return reduceFromRight(value, callback, initialValue, length - 1, length, options, stack);
12456
+ }
12457
+ const start = findNextDefinedIndex(value, length - 1, -1, length, options.budget);
12458
+ if (start < 0) {
12459
+ throw new TypeError("Reduce of empty array with no initial value.");
12460
+ }
12461
+ return reduceFromRight(
12462
+ value,
12463
+ callback,
12464
+ await readArrayElement(value, start, options),
12465
+ start - 1,
12466
+ length,
12467
+ options,
12468
+ stack
12469
+ );
12470
+ }
12471
+ async function reduceFromLeft(value, callback, accumulator, startIndex, length, options, stack) {
12472
+ let current = accumulator;
12473
+ const retainedAccumulator = {};
12474
+ options.budget.setRetainedValues(retainedAccumulator, () => [current]);
12616
12475
  try {
12617
- const value = Array.isArray(receiver) || methodName === "concat" ? receiver : await arrayLikeView(receiver, options);
12618
- if (isMutatingArrayMethod(methodName)) {
12619
- assertCollectionMutable(receiver);
12620
- }
12621
- if (isCallbackArrayMethod(methodName)) {
12622
- let callbackState = activeArrayCallbacks.get(receiver);
12623
- if (callbackState === void 0) {
12624
- callbackState = { depth: 0, leave: enterRunningState(receiver) };
12625
- activeArrayCallbacks.set(receiver, callbackState);
12626
- }
12627
- callbackState.depth += 1;
12628
- try {
12629
- const result2 = await callArrayMethodUnlocked(value, methodName, args, options, stack);
12630
- return result2 === value ? receiver : result2;
12631
- } finally {
12632
- callbackState.depth -= 1;
12633
- if (callbackState.depth === 0) {
12634
- activeArrayCallbacks.delete(receiver);
12635
- callbackState.leave();
12636
- }
12476
+ for (let index = startIndex; index < length; index += 1) {
12477
+ options.budget.visitNode();
12478
+ if (!(index in value)) {
12479
+ continue;
12637
12480
  }
12481
+ current = await options.callClosure(
12482
+ callback,
12483
+ [
12484
+ current,
12485
+ await readArrayElement(value, index, options),
12486
+ index,
12487
+ arrayLikeSources.get(value) ?? value
12488
+ ],
12489
+ stack
12490
+ );
12638
12491
  }
12639
- const result = await callArrayMethodUnlocked(value, methodName, args, options, stack);
12640
- return result === value ? receiver : result;
12492
+ return current;
12641
12493
  } finally {
12642
- options.budget.setRetainedValues(retainedReceiver, void 0);
12494
+ options.budget.setRetainedValues(retainedAccumulator, void 0);
12643
12495
  }
12644
12496
  }
12645
- async function arrayLikeView(receiver, options) {
12646
- const rawLength = options.context?.getProperty !== void 0 ? await options.context.getProperty(receiver, "length") : getSandboxDataProperty(receiver, "length", options.budget);
12647
- const number = await sandboxNumber(rawLength, options.budget, options.context);
12648
- const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
12649
- const view = new Proxy(
12650
- /* @__PURE__ */ Object.create(null),
12651
- {
12652
- get: (_target, key) => {
12653
- options.budget.visitNode();
12654
- if (key === "length") return length;
12655
- if (typeof key !== "string") return void 0;
12656
- return options.context?.getProperty !== void 0 ? options.context.getProperty(receiver, key) : getSandboxDataProperty(receiver, key, options.budget);
12657
- },
12658
- has: (_target, key) => {
12659
- options.budget.visitNode();
12660
- if (typeof key === "string" && options.hasProperty !== void 0)
12661
- return options.hasProperty(receiver, key);
12662
- for (let current = receiver; current !== null; current = getSandboxPrototype(current, options.budget)) {
12663
- options.budget.visitNode();
12664
- if (Object.hasOwn(current, key)) return true;
12665
- }
12666
- return false;
12667
- },
12668
- set: (_target, key, entry) => {
12669
- options.budget.visitNode();
12670
- if (typeof key !== "string") throw new TypeError("Array indices must be string keys.");
12671
- if (options.setProperty !== void 0) options.setProperty(receiver, key, entry);
12672
- else if (!Reflect.set(receiver, key, entry))
12673
- throw new TypeError(`Cannot assign property '${key}'.`);
12674
- return true;
12675
- },
12676
- deleteProperty: (_target, key) => {
12677
- options.budget.visitNode();
12678
- if (typeof key === "string" && options.deleteProperty !== void 0)
12679
- return options.deleteProperty(receiver, key);
12680
- return Reflect.deleteProperty(receiver, key);
12497
+ async function reduceFromRight(value, callback, accumulator, startIndex, length, options, stack) {
12498
+ let current = accumulator;
12499
+ const retainedAccumulator = {};
12500
+ options.budget.setRetainedValues(retainedAccumulator, () => [current]);
12501
+ try {
12502
+ for (let index = Math.min(startIndex, length - 1); index >= 0; index -= 1) {
12503
+ options.budget.visitNode();
12504
+ if (!(index in value)) {
12505
+ continue;
12681
12506
  }
12507
+ current = await options.callClosure(
12508
+ callback,
12509
+ [
12510
+ current,
12511
+ await readArrayElement(value, index, options),
12512
+ index,
12513
+ arrayLikeSources.get(value) ?? value
12514
+ ],
12515
+ stack
12516
+ );
12682
12517
  }
12683
- );
12684
- arrayLikeSources.set(view, receiver);
12685
- return view;
12518
+ return current;
12519
+ } finally {
12520
+ options.budget.setRetainedValues(retainedAccumulator, void 0);
12521
+ }
12686
12522
  }
12687
- async function callArrayMethodUnlocked(value, methodName, args, options, stack) {
12688
- switch (methodName) {
12689
- case "map":
12690
- return budgetProducedValue(
12691
- await mapArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
12692
- options.budget
12693
- );
12694
- case "filter":
12695
- return budgetProducedValue(
12696
- await filterArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
12697
- options.budget
12698
- );
12699
- case "find":
12700
- return budgetProducedValue(
12701
- await findInArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
12702
- options.budget
12703
- );
12704
- case "findIndex":
12705
- return await findIndexInArray(
12706
- value,
12707
- getRequiredCallback(methodName, args[0]),
12708
- options,
12709
- stack,
12710
- args[1]
12711
- );
12712
- case "findLast":
12713
- return budgetProducedValue(
12714
- await findLastInArray(
12715
- value,
12716
- getRequiredCallback(methodName, args[0]),
12717
- options,
12718
- stack,
12719
- args[1]
12720
- ),
12721
- options.budget
12722
- );
12723
- case "findLastIndex":
12724
- return await findLastIndexInArray(
12725
- value,
12726
- getRequiredCallback(methodName, args[0]),
12727
- options,
12728
- stack,
12729
- args[1]
12730
- );
12731
- case "some":
12732
- return await someInArray(
12733
- value,
12734
- getRequiredCallback(methodName, args[0]),
12735
- options,
12736
- stack,
12737
- args[1]
12738
- );
12739
- case "every":
12740
- return await everyInArray(
12523
+ async function forEachArray(value, callback, options, stack, thisValue) {
12524
+ const length = value.length;
12525
+ for (let index = 0; index < length; index += 1) {
12526
+ options.budget.visitNode();
12527
+ if (!(index in value)) {
12528
+ continue;
12529
+ }
12530
+ await callArrayCallback(
12531
+ callback,
12532
+ await readArrayElement(value, index, options),
12533
+ index,
12534
+ value,
12535
+ options,
12536
+ stack,
12537
+ thisValue
12538
+ );
12539
+ }
12540
+ }
12541
+ async function flatMapArray(value, callback, options, stack, thisValue) {
12542
+ const length = value.length;
12543
+ const result = [];
12544
+ options.budget.setRetainedValues(result, () => [result]);
12545
+ try {
12546
+ for (let index = 0; index < length; index += 1) {
12547
+ options.budget.visitNode();
12548
+ if (!(index in value)) {
12549
+ continue;
12550
+ }
12551
+ const mapped = await callArrayCallback(
12552
+ callback,
12553
+ await readArrayElement(value, index, options),
12554
+ index,
12741
12555
  value,
12742
- getRequiredCallback(methodName, args[0]),
12743
12556
  options,
12744
12557
  stack,
12745
- args[1]
12746
- );
12747
- case "reduce":
12748
- return budgetProducedValue(
12749
- await reduceArray(
12750
- value,
12751
- getRequiredCallback(methodName, args[0]),
12752
- args.length > 1,
12753
- args[1],
12754
- options,
12755
- stack
12756
- ),
12757
- options.budget
12758
- );
12759
- case "reduceRight":
12760
- return budgetProducedValue(
12761
- await reduceRightArray(
12762
- value,
12763
- getRequiredCallback(methodName, args[0]),
12764
- args.length > 1,
12765
- args[1],
12766
- options,
12767
- stack
12768
- ),
12769
- options.budget
12770
- );
12771
- case "forEach":
12772
- await forEachArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]);
12773
- return void 0;
12774
- case "flatMap":
12775
- return budgetProducedValue(
12776
- await flatMapArray(
12777
- value,
12778
- getRequiredCallback(methodName, args[0]),
12779
- options,
12780
- stack,
12781
- args[1]
12782
- ),
12783
- options.budget
12784
- );
12785
- case "flat":
12786
- return budgetProducedValue(
12787
- await flattenArray(
12788
- value,
12789
- args[0] === void 0 ? 1 : toIntegerOrInfinity(await sandboxNumber(args[0], options.budget, options.context)),
12790
- options
12791
- ),
12792
- options.budget
12793
- );
12794
- case "includes":
12795
- case "indexOf":
12796
- case "lastIndexOf": {
12797
- const length = value.length;
12798
- if (length === 0) return methodName === "includes" ? false : -1;
12799
- const reverse = methodName === "lastIndexOf";
12800
- const start = reverse && args.length < 2 ? length - 1 : toIntegerOrInfinity(await sandboxNumber(args[1], options.budget, options.context));
12801
- let index = reverse ? Math.min(start < 0 ? length + start : start, length - 1) : start < 0 ? Math.max(length + start, 0) : start;
12802
- for (; index >= 0 && index < length; index += reverse ? -1 : 1) {
12803
- options.budget.visitNode();
12804
- if (methodName !== "includes" && !(index in value)) continue;
12805
- const entry = await readArrayElement(value, index, options);
12806
- if (entry === args[0] || methodName === "includes" && Number.isNaN(entry) && Number.isNaN(args[0]))
12807
- return methodName === "includes" ? true : index;
12808
- }
12809
- return methodName === "includes" ? false : -1;
12810
- }
12811
- case "join": {
12812
- const length = value.length;
12813
- const separator = args[0] === void 0 ? "," : await sandboxString(args[0], options.budget, options.context);
12814
- return joinSandboxArray(
12815
- arrayLikeSources.get(value) ?? value,
12816
- length,
12817
- separator,
12818
- options.budget,
12819
- options.context
12820
- );
12821
- }
12822
- case "slice": {
12823
- const length = value.length;
12824
- const start = toIntegerOrInfinity(
12825
- await sandboxNumber(args[0], options.budget, options.context)
12558
+ thisValue
12826
12559
  );
12827
- const end = args[1] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[1], options.budget, options.context));
12828
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12829
- const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12830
- const count = Math.max(final - first, 0);
12831
- options.budget.allocateArrayLength(count);
12832
- const result = new Array(count);
12833
- const release = retainValues(options.budget, () => [result]);
12834
- try {
12835
- for (let index = 0; index < count; index += 1) {
12560
+ if (Array.isArray(mapped)) {
12561
+ for (let mappedIndex = 0; mappedIndex < mapped.length; mappedIndex += 1) {
12836
12562
  options.budget.visitNode();
12837
- if (first + index in value)
12838
- result[index] = await readArrayElement(value, first + index, options);
12563
+ if (!(mappedIndex in mapped)) {
12564
+ continue;
12565
+ }
12566
+ result.push(await readArrayElement(mapped, mappedIndex, options));
12567
+ options.budget.allocateArrayLength(result.length);
12839
12568
  }
12840
- return budgetProducedValue(result, options.budget);
12841
- } finally {
12842
- release();
12569
+ continue;
12843
12570
  }
12571
+ result.push(mapped);
12572
+ options.budget.allocateArrayLength(result.length);
12844
12573
  }
12845
- case "concat": {
12846
- const result = [];
12847
- const retained = {};
12848
- options.budget.setRetainedValues(retained, () => [result]);
12849
- try {
12850
- for (const entry of [value, ...args]) {
12851
- let spread = false;
12852
- if (entry !== null && (typeof entry === "object" || typeof entry === "function")) {
12853
- const flag = options.context?.getProperty !== void 0 ? await options.context.getProperty(entry, Symbol.isConcatSpreadable) : getSandboxDataProperty(entry, Symbol.isConcatSpreadable, options.budget);
12854
- spread = flag === void 0 ? Array.isArray(entry) : Boolean(flag);
12855
- }
12856
- if (!spread) {
12857
- options.budget.allocateArrayLength(result.length + 1);
12858
- result.push(entry);
12859
- continue;
12860
- }
12861
- const start = result.length;
12862
- const source = await arrayLikeView(entry, options);
12863
- const length = source.length;
12864
- options.budget.allocateArrayLength(start + length);
12865
- result.length += length;
12866
- for (let index = 0; index < length; index++) {
12867
- options.budget.visitNode();
12868
- if (index in source)
12869
- result[start + index] = await readArrayElement(source, index, options);
12870
- }
12871
- }
12872
- return budgetProducedValue(result, options.budget);
12873
- } finally {
12874
- options.budget.setRetainedValues(retained, void 0);
12574
+ return result;
12575
+ } finally {
12576
+ options.budget.setRetainedValues(result, void 0);
12577
+ }
12578
+ }
12579
+ async function flattenArray(value, depth, options) {
12580
+ const result = [];
12581
+ const retained = {};
12582
+ options.budget.setRetainedValues(retained, () => [result]);
12583
+ try {
12584
+ await appendFlattenedEntries(value, depth, result, options);
12585
+ return result;
12586
+ } finally {
12587
+ options.budget.setRetainedValues(retained, void 0);
12588
+ }
12589
+ }
12590
+ async function appendFlattenedEntries(value, depth, result, options) {
12591
+ const length = value.length;
12592
+ for (let index = 0; index < length; index += 1) {
12593
+ options.budget.visitNode();
12594
+ if (!(index in value)) {
12595
+ continue;
12596
+ }
12597
+ const entry = await readArrayElement(value, index, options);
12598
+ if (depth > 0 && Array.isArray(entry)) {
12599
+ await appendFlattenedEntries(entry, depth - 1, result, options);
12600
+ continue;
12601
+ }
12602
+ result.push(entry);
12603
+ options.budget.allocateArrayLength(result.length);
12604
+ }
12605
+ }
12606
+ async function sortArray(value, comparator, options, stack) {
12607
+ const length = value.length;
12608
+ const definedValues = [];
12609
+ let undefinedCount = 0;
12610
+ let currentEntry;
12611
+ options.budget.setRetainedValues(definedValues, () => [definedValues, currentEntry]);
12612
+ try {
12613
+ for (let index = 0; index < length; index += 1) {
12614
+ options.budget.visitNode();
12615
+ if (!(index in value)) {
12616
+ continue;
12875
12617
  }
12618
+ const entry = await readArrayElement(value, index, options);
12619
+ if (entry === void 0) {
12620
+ undefinedCount += 1;
12621
+ continue;
12622
+ }
12623
+ definedValues.push(entry);
12876
12624
  }
12877
- case "splice": {
12878
- const length = value.length;
12879
- const start = toIntegerOrInfinity(
12880
- await sandboxNumber(args[0], options.budget, options.context)
12881
- );
12882
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12883
- const inserted = Math.max(args.length - 2, 0);
12884
- const deleted = args.length === 0 ? 0 : args.length === 1 ? length - first : Math.min(
12885
- Math.max(
12886
- toIntegerOrInfinity(
12887
- await sandboxNumber(args[1], options.budget, options.context)
12888
- ),
12889
- 0
12890
- ),
12891
- length - first
12892
- );
12893
- const nextLength = length + inserted - deleted;
12894
- if (nextLength > Number.MAX_SAFE_INTEGER)
12895
- throw new TypeError("Array-like length exceeds the safe integer limit.");
12896
- options.budget.allocateArrayLength(deleted);
12897
- const removed = new Array(deleted);
12898
- const retained = {};
12899
- options.budget.setRetainedValues(retained, () => [removed]);
12900
- try {
12901
- for (let index = 0; index < deleted; index++) {
12902
- options.budget.visitNode();
12903
- if (first + index in value)
12904
- removed[index] = await readArrayElement(value, first + index, options);
12905
- }
12906
- if (inserted < deleted) {
12907
- for (let index = first; index < length - deleted; index++)
12908
- await moveArrayElement(value, index + deleted, index + inserted, options);
12909
- for (let index = length; index > nextLength; index--)
12910
- deleteArrayElement(value, index - 1, options);
12911
- } else if (inserted > deleted) {
12912
- for (let index = length - deleted; index > first; index--)
12913
- await moveArrayElement(value, index + deleted - 1, index + inserted - 1, options);
12914
- }
12915
- for (let index = 0; index < inserted; index++)
12916
- await writeArrayProperty(value, first + index, args[index + 2], options);
12917
- await writeArrayProperty(value, "length", nextLength, options);
12918
- } finally {
12919
- options.budget.setRetainedValues(retained, void 0);
12625
+ for (let index = 1; index < definedValues.length; index += 1) {
12626
+ currentEntry = definedValues[index];
12627
+ let cursor = index - 1;
12628
+ while (cursor >= 0 && await compareEntries(definedValues[cursor], currentEntry, comparator, options, stack) > 0) {
12629
+ definedValues[cursor + 1] = definedValues[cursor];
12630
+ cursor -= 1;
12920
12631
  }
12921
- budgetProducedValue(removed, options.budget);
12922
- budgetProducedValue(value, options.budget);
12923
- return removed;
12632
+ definedValues[cursor + 1] = currentEntry;
12924
12633
  }
12925
- case "fill": {
12926
- const length = value.length;
12927
- const start = toIntegerOrInfinity(
12928
- await sandboxNumber(args[1], options.budget, options.context)
12929
- );
12930
- const end = args[2] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[2], options.budget, options.context));
12931
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12932
- const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12933
- for (let index = first; index < final; index++)
12934
- await writeArrayProperty(value, index, args[0], options);
12935
- budgetProducedValue(value, options.budget);
12936
- return value;
12634
+ currentEntry = void 0;
12635
+ for (let index = 0; index < definedValues.length; index += 1) {
12636
+ await writeArrayProperty(value, index, definedValues[index], options);
12937
12637
  }
12938
- case "copyWithin": {
12939
- const length = value.length;
12940
- const target = toIntegerOrInfinity(
12941
- await sandboxNumber(args[0], options.budget, options.context)
12942
- );
12943
- const start = toIntegerOrInfinity(
12944
- await sandboxNumber(args[1], options.budget, options.context)
12945
- );
12946
- const end = args[2] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[2], options.budget, options.context));
12947
- let to = target < 0 ? Math.max(length + target, 0) : Math.min(target, length);
12948
- let from = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12949
- const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12950
- let count = Math.min(final - from, length - to);
12951
- const direction = from < to && to < from + count ? -1 : 1;
12952
- if (direction < 0) {
12953
- from += count - 1;
12954
- to += count - 1;
12955
- }
12956
- while (count-- > 0) {
12957
- await moveArrayElement(value, from, to, options);
12958
- from += direction;
12959
- to += direction;
12960
- }
12961
- budgetProducedValue(value, options.budget);
12962
- return value;
12638
+ for (let index = 0; index < undefinedCount; index += 1) {
12639
+ await writeArrayProperty(value, definedValues.length + index, void 0, options);
12963
12640
  }
12964
- case "at": {
12965
- const length = value.length;
12966
- const index = toIntegerOrInfinity(
12967
- await sandboxNumber(args[0], options.budget, options.context)
12968
- );
12969
- const actual = index < 0 ? length + index : index;
12970
- return actual < 0 || actual >= length ? void 0 : budgetProducedValue(await readArrayElement(value, actual, options), options.budget);
12641
+ for (let index = definedValues.length + undefinedCount; index < length; index += 1) {
12642
+ options.budget.visitNode();
12643
+ deleteArrayElement(value, index, options);
12971
12644
  }
12972
- case "sort":
12973
- await sortArray(
12974
- value,
12975
- args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
12976
- options,
12977
- stack
12978
- );
12979
- budgetProducedValue(value, options.budget);
12980
- return value;
12981
- case "reverse": {
12982
- const length = value.length;
12983
- let lowerValue;
12984
- let upperValue;
12985
- const release = retainValues(options.budget, () => [lowerValue, upperValue]);
12986
- try {
12987
- for (let lower = 0; lower < Math.floor(length / 2); lower++) {
12988
- options.budget.visitNode();
12989
- lowerValue = upperValue = void 0;
12990
- const upper = length - lower - 1;
12991
- const lowerExists = lower in value;
12992
- lowerValue = lowerExists ? await readArrayElement(value, lower, options) : void 0;
12993
- const upperExists = upper in value;
12994
- upperValue = upperExists ? await readArrayElement(value, upper, options) : void 0;
12995
- if (lowerExists && upperExists) {
12996
- await writeArrayProperty(value, lower, upperValue, options);
12997
- await writeArrayProperty(value, upper, lowerValue, options);
12998
- } else if (!lowerExists && upperExists) {
12999
- await writeArrayProperty(value, lower, upperValue, options);
13000
- deleteArrayElement(value, upper, options);
13001
- } else if (lowerExists) {
13002
- deleteArrayElement(value, lower, options);
13003
- await writeArrayProperty(value, upper, lowerValue, options);
13004
- }
13005
- }
13006
- budgetProducedValue(value, options.budget);
13007
- return value;
13008
- } finally {
13009
- release();
13010
- }
12645
+ } finally {
12646
+ options.budget.setRetainedValues(definedValues, void 0);
12647
+ }
12648
+ }
12649
+ async function compareEntries(left, right, comparator, options, stack) {
12650
+ options.budget.visitNode();
12651
+ if (comparator === void 0) {
12652
+ const leftString = await sandboxString(left, options.budget, options.context);
12653
+ const release = retainValues(options.budget, () => [leftString]);
12654
+ try {
12655
+ const rightString = await sandboxString(right, options.budget, options.context);
12656
+ return leftString < rightString ? -1 : leftString > rightString ? 1 : 0;
12657
+ } finally {
12658
+ release();
13011
12659
  }
13012
- case "toSorted": {
13013
- const length = value.length;
13014
- options.budget.allocateArrayLength(length);
13015
- const result = new Array(length);
13016
- const release = retainValues(options.budget, () => [result]);
13017
- try {
13018
- for (let index = 0; index < length; index += 1) {
13019
- options.budget.visitNode();
13020
- result[index] = await readArrayElement(value, index, options);
13021
- }
13022
- await sortArray(
13023
- result,
13024
- args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
13025
- options,
13026
- stack
13027
- );
13028
- return budgetProducedValue(result, options.budget);
13029
- } finally {
13030
- release();
13031
- }
12660
+ }
12661
+ const result = await sandboxNumber(
12662
+ await options.callClosure(comparator, [left, right], stack),
12663
+ options.budget,
12664
+ options.context
12665
+ );
12666
+ return Number.isNaN(result) ? 0 : result;
12667
+ }
12668
+ async function callArrayCallback(callback, value, index, array2, options, stack, thisValue) {
12669
+ return options.callClosure(
12670
+ callback,
12671
+ [value, index, arrayLikeSources.get(array2) ?? array2],
12672
+ stack,
12673
+ thisValue
12674
+ );
12675
+ }
12676
+ function findNextDefinedIndex(value, startIndex, direction, length, budget) {
12677
+ for (let index = startIndex; direction > 0 ? index < length : index >= 0; index += direction) {
12678
+ budget.visitNode();
12679
+ if (index in value) {
12680
+ return index;
13032
12681
  }
13033
- case "toReversed": {
13034
- const length = value.length;
13035
- options.budget.allocateArrayLength(length);
13036
- const result = new Array(length);
13037
- const release = retainValues(options.budget, () => [result]);
13038
- try {
13039
- for (let index = 0; index < length; index += 1) {
13040
- options.budget.visitNode();
13041
- result[index] = await readArrayElement(value, length - index - 1, options);
13042
- }
13043
- return budgetProducedValue(result, options.budget);
13044
- } finally {
13045
- release();
13046
- }
12682
+ }
12683
+ return -1;
12684
+ }
12685
+ function budgetProducedValue(value, budget) {
12686
+ if (typeof value === "object" && value !== null) value = arrayLikeSources.get(value) ?? value;
12687
+ allocateProducedValue(value, budget, /* @__PURE__ */ new WeakSet());
12688
+ return value;
12689
+ }
12690
+ function allocateProducedValue(value, budget, seen) {
12691
+ if (typeof value === "string") {
12692
+ budget.allocateString(value);
12693
+ return;
12694
+ }
12695
+ if (Array.isArray(value)) {
12696
+ budget.allocateArrayLength(value.length);
12697
+ if (seen.has(value)) {
12698
+ return;
13047
12699
  }
13048
- case "toSpliced": {
13049
- const length = value.length;
13050
- const start = toIntegerOrInfinity(
13051
- await sandboxNumber(args[0], options.budget, options.context)
13052
- );
13053
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
13054
- const inserted = Math.max(args.length - 2, 0);
13055
- const deleted = args.length === 0 ? 0 : args.length === 1 ? length - first : Math.min(
13056
- Math.max(
13057
- toIntegerOrInfinity(
13058
- await sandboxNumber(args[1], options.budget, options.context)
12700
+ seen.add(value);
12701
+ for (const entry of value) {
12702
+ allocateProducedValue(entry, budget, seen);
12703
+ }
12704
+ return;
12705
+ }
12706
+ if (isSandboxMap(value)) {
12707
+ budget.allocateCollectionEntries(value.entries.size);
12708
+ if (seen.has(value)) {
12709
+ return;
12710
+ }
12711
+ seen.add(value);
12712
+ for (const [key, entry] of value.entries) {
12713
+ allocateProducedValue(key, budget, seen);
12714
+ allocateProducedValue(entry, budget, seen);
12715
+ }
12716
+ return;
12717
+ }
12718
+ if (isSandboxSet(value)) {
12719
+ budget.allocateCollectionEntries(value.values.size);
12720
+ if (seen.has(value)) {
12721
+ return;
12722
+ }
12723
+ seen.add(value);
12724
+ for (const entry of value.values) {
12725
+ allocateProducedValue(entry, budget, seen);
12726
+ }
12727
+ return;
12728
+ }
12729
+ if (typeof value !== "object" || value === null || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value)) {
12730
+ return;
12731
+ }
12732
+ if (seen.has(value)) {
12733
+ return;
12734
+ }
12735
+ seen.add(value);
12736
+ for (const entry of Object.values(value)) {
12737
+ allocateProducedValue(entry, budget, seen);
12738
+ }
12739
+ }
12740
+ function toIntegerOrInfinity(value) {
12741
+ const number = Number(value);
12742
+ if (Number.isNaN(number) || Object.is(number, 0) || Object.is(number, -0)) {
12743
+ return 0;
12744
+ }
12745
+ if (!Number.isFinite(number)) {
12746
+ return number;
12747
+ }
12748
+ return Math.trunc(number);
12749
+ }
12750
+
12751
+ // packages/safe-js/src/interp/globals/object-array.ts
12752
+ function createObjectArrayGlobals(options) {
12753
+ return {
12754
+ Object: createObjectGlobal(
12755
+ {
12756
+ keys: createSandboxClosure({
12757
+ sandbox: true,
12758
+ call: ([value]) => budgetSandboxValue(ownEnumerableSandboxKeys(value), options.budget),
12759
+ name: "keys"
12760
+ }),
12761
+ values: createSandboxClosure({
12762
+ sandbox: true,
12763
+ call: ([value], context) => context === void 0 ? allocateProducedSandboxValue(
12764
+ ownEnumerableSandboxEntries(value).map(([, entry]) => entry),
12765
+ options.budget
12766
+ ) : getOwnEnumerableEntries(value, options.budget, context).then(
12767
+ (entries) => allocateProducedSandboxValue(
12768
+ entries.map(([, entry]) => entry),
12769
+ options.budget
12770
+ )
13059
12771
  ),
13060
- 0
13061
- ),
13062
- length - first
13063
- );
13064
- const resultLength = length + inserted - deleted;
13065
- if (resultLength > Number.MAX_SAFE_INTEGER)
13066
- throw new TypeError("Array-like length exceeds the safe integer limit.");
13067
- options.budget.allocateArrayLength(resultLength);
13068
- const result = new Array(resultLength);
13069
- const release = retainValues(options.budget, () => [result]);
13070
- try {
13071
- for (let index = 0; index < resultLength; index += 1) {
13072
- options.budget.visitNode();
13073
- result[index] = index < first ? await readArrayElement(value, index, options) : index < first + inserted ? args[index - first + 2] : await readArrayElement(value, index - inserted + deleted, options);
12772
+ name: "values"
12773
+ }),
12774
+ entries: createSandboxClosure({
12775
+ sandbox: true,
12776
+ call: ([value], context) => context === void 0 ? allocateProducedSandboxValue(ownEnumerableSandboxEntries(value), options.budget) : getOwnEnumerableEntries(value, options.budget, context).then(
12777
+ (entries) => allocateProducedSandboxValue(entries, options.budget)
12778
+ ),
12779
+ name: "entries"
12780
+ }),
12781
+ hasOwn: createSandboxClosure({
12782
+ sandbox: true,
12783
+ call: ([value, key], context) => {
12784
+ if (value === null || value === void 0)
12785
+ throw new TypeError("Cannot convert undefined or null to object.");
12786
+ const name = toPropertyKey(key, options.budget, context);
12787
+ return typeof name === "string" || typeof name === "symbol" ? hasOwnSandboxProperty(value, name, false) : name.then((property) => hasOwnSandboxProperty(value, property, false));
12788
+ },
12789
+ name: "hasOwn"
12790
+ }),
12791
+ getOwnPropertyDescriptor: createSandboxClosure({
12792
+ sandbox: true,
12793
+ call: async ([value, key], context) => {
12794
+ const descriptor = Object.getOwnPropertyDescriptor(
12795
+ reflectionProperties(value),
12796
+ await toPropertyKey(key, options.budget, context)
12797
+ );
12798
+ if (descriptor === void 0) return void 0;
12799
+ return allocateProducedSandboxValue(
12800
+ exposePropertyDescriptor(descriptor),
12801
+ options.budget
12802
+ );
12803
+ },
12804
+ name: "getOwnPropertyDescriptor"
12805
+ }),
12806
+ getOwnPropertyDescriptors: createSandboxClosure({
12807
+ sandbox: true,
12808
+ call: ([value]) => {
12809
+ const descriptors2 = /* @__PURE__ */ Object.create(null);
12810
+ const properties = reflectionProperties(value);
12811
+ for (const key of [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(value)])
12812
+ defineOwnDataProperty(descriptors2, key, exposePropertyDescriptor(Object.getOwnPropertyDescriptor(properties, key)));
12813
+ return allocateProducedSandboxValue(descriptors2, options.budget);
12814
+ },
12815
+ name: "getOwnPropertyDescriptors"
12816
+ }),
12817
+ getOwnPropertyNames: createSandboxClosure({
12818
+ sandbox: true,
12819
+ call: ([value]) => budgetSandboxValue(Object.getOwnPropertyNames(reflectionProperties(value)), options.budget),
12820
+ name: "getOwnPropertyNames"
12821
+ }),
12822
+ getOwnPropertySymbols: createSandboxClosure({
12823
+ sandbox: true,
12824
+ call: ([value]) => allocateProducedSandboxValue(ownSandboxSymbolKeys(value), options.budget),
12825
+ name: "getOwnPropertySymbols"
12826
+ }),
12827
+ defineProperty: createSandboxClosure({
12828
+ sandbox: true,
12829
+ call: async ([value, key, descriptor], context) => {
12830
+ objectProperties(value, true);
12831
+ const property = await toPropertyKey(key, options.budget, context);
12832
+ defineDataProperty(
12833
+ value,
12834
+ property,
12835
+ await propertyDescriptor(descriptor, options.budget, context),
12836
+ options.budget
12837
+ );
12838
+ return value;
12839
+ },
12840
+ name: "defineProperty"
12841
+ }),
12842
+ defineProperties: createSandboxClosure({
12843
+ sandbox: true,
12844
+ call: async ([value, descriptors2], context) => {
12845
+ await definePropertiesFromObject(value, descriptors2, options.budget, context);
12846
+ return value;
12847
+ },
12848
+ name: "defineProperties"
12849
+ }),
12850
+ getPrototypeOf: createSandboxClosure({
12851
+ sandbox: true,
12852
+ call: ([value]) => {
12853
+ if (isSandboxMap(value) || isSandboxSet(value))
12854
+ return getSandboxPrototype(value, options.budget);
12855
+ if (value !== null && value !== void 0 && typeof value !== "object")
12856
+ value = createSandboxBox(value);
12857
+ objectProperties(value);
12858
+ return getSandboxPrototype(value, options.budget);
12859
+ },
12860
+ name: "getPrototypeOf"
12861
+ }),
12862
+ setPrototypeOf: createSandboxClosure({
12863
+ sandbox: true,
12864
+ call: ([value, prototype]) => {
12865
+ if (value === null || value === void 0)
12866
+ throw new TypeError("Cannot set the prototype of null or undefined.");
12867
+ if (prototype !== null && typeof prototype !== "object")
12868
+ throw new TypeError("Prototype must be an object or null.");
12869
+ if (typeof value !== "object") return value;
12870
+ objectProperties(value, true);
12871
+ if (prototype !== null) objectProperties(prototype);
12872
+ setSandboxPrototype(value, prototype, options.budget);
12873
+ return value;
12874
+ },
12875
+ name: "setPrototypeOf"
12876
+ }),
12877
+ create: createSandboxClosure({
12878
+ sandbox: true,
12879
+ call: async ([prototype, descriptors2], context) => {
12880
+ if (prototype !== null) objectProperties(prototype);
12881
+ const value = /* @__PURE__ */ Object.create(null);
12882
+ setSandboxPrototype(value, prototype, options.budget);
12883
+ if (descriptors2 !== void 0) {
12884
+ await definePropertiesFromObject(value, descriptors2, options.budget, context);
12885
+ }
12886
+ return allocateProducedSandboxValue(value, options.budget);
12887
+ },
12888
+ name: "create"
12889
+ }),
12890
+ is: createSandboxClosure({
12891
+ sandbox: true,
12892
+ call: ([left, right]) => Reflect.apply(Object.is, Object, [left, right]),
12893
+ name: "is"
12894
+ }),
12895
+ fromEntries: createSandboxClosure({
12896
+ sandbox: true,
12897
+ call: ([value], context) => {
12898
+ if (context !== void 0) return acquireSandboxIterator(value, options.budget, context).then((iterator2) => {
12899
+ if (iterator2 === void 0) throw new TypeError("Object.fromEntries requires an iterable.");
12900
+ return objectFromSandboxEntries(value, iterator2, options.budget, context);
12901
+ });
12902
+ const iterator = getSandboxIterator(value, options.budget, context);
12903
+ if (iterator === void 0) {
12904
+ throw new TypeError("Object.fromEntries requires an iterable.");
12905
+ }
12906
+ if (context === void 0 && !iterator.generator && !iterator.asynchronous) {
12907
+ return allocateProducedSandboxValue(
12908
+ Object.setPrototypeOf(
12909
+ Reflect.apply(Object.fromEntries, Object, [
12910
+ { [Symbol.iterator]: () => iterator }
12911
+ ]),
12912
+ null
12913
+ ),
12914
+ options.budget
12915
+ );
12916
+ }
12917
+ return objectFromSandboxEntries(value, iterator, options.budget, context);
12918
+ },
12919
+ name: "fromEntries"
12920
+ }),
12921
+ preventExtensions: createSandboxClosure({
12922
+ sandbox: true,
12923
+ call: ([value]) => {
12924
+ if (isGuestHostObject(value))
12925
+ throw new TypeError("Live host objects cannot be made non-extensible.");
12926
+ Object.preventExtensions(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
12927
+ return value;
12928
+ },
12929
+ name: "preventExtensions"
12930
+ }),
12931
+ isExtensible: createSandboxClosure({
12932
+ sandbox: true,
12933
+ call: ([value]) => Object.isExtensible(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
12934
+ name: "isExtensible"
12935
+ }),
12936
+ seal: createSandboxClosure({
12937
+ sandbox: true,
12938
+ call: ([value]) => {
12939
+ if (isGuestHostObject(value))
12940
+ throw new TypeError("Live host objects cannot be sealed.");
12941
+ Object.seal(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
12942
+ return value;
12943
+ },
12944
+ name: "seal"
12945
+ }),
12946
+ isSealed: createSandboxClosure({
12947
+ sandbox: true,
12948
+ call: ([value]) => Object.isSealed(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
12949
+ name: "isSealed"
12950
+ }),
12951
+ freeze: createSandboxClosure({
12952
+ sandbox: true,
12953
+ call: ([value]) => {
12954
+ if (isGuestHostObject(value))
12955
+ throw new TypeError("Live host objects cannot be frozen.");
12956
+ if (typeof value === "object" && value !== null) {
12957
+ Object.freeze(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
12958
+ }
12959
+ return value;
12960
+ },
12961
+ name: "freeze"
12962
+ }),
12963
+ isFrozen: createSandboxClosure({
12964
+ sandbox: true,
12965
+ call: ([value]) => Object.isFrozen(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
12966
+ name: "isFrozen"
12967
+ }),
12968
+ assign: createSandboxClosure({
12969
+ sandbox: true,
12970
+ call: ([target, ...sources], context) => assignSandboxValues(target, sources, options.budget, context),
12971
+ name: "assign"
12972
+ })
12973
+ },
12974
+ options.budget
12975
+ ),
12976
+ Array: createArrayGlobal(options.budget),
12977
+ String: createPrimitiveConstructor(
12978
+ {
12979
+ call: (args, context) => typeof args[0] === "symbol" ? options.budget.allocateString(String(args[0])) : sandboxString(args.length === 0 ? "" : args[0], options.budget, context),
12980
+ name: "String",
12981
+ properties: {
12982
+ raw: createSandboxClosure({
12983
+ sandbox: true,
12984
+ call: (args, context) => stringRaw(args, options.budget, context),
12985
+ name: "raw"
12986
+ }),
12987
+ fromCharCode: createSandboxClosure({
12988
+ sandbox: true,
12989
+ call: (args, context) => stringFromCodes(args, String.fromCharCode, options.budget, context),
12990
+ name: "fromCharCode"
12991
+ }),
12992
+ fromCodePoint: createSandboxClosure({
12993
+ sandbox: true,
12994
+ call: (args, context) => stringFromCodes(args, String.fromCodePoint, options.budget, context),
12995
+ name: "fromCodePoint"
12996
+ })
13074
12997
  }
13075
- return budgetProducedValue(result, options.budget);
13076
- } finally {
13077
- release();
12998
+ },
12999
+ options.budget
13000
+ ),
13001
+ Number: createPrimitiveConstructor(
13002
+ {
13003
+ call: (args, context) => sandboxNumber(args.length === 0 ? 0 : args[0], options.budget, context, true),
13004
+ name: "Number",
13005
+ properties: {
13006
+ isFinite: createSandboxClosure({
13007
+ guest: true,
13008
+ sandbox: true,
13009
+ call: ([value]) => typeof value === "number" && Number.isFinite(value),
13010
+ name: "isFinite"
13011
+ }),
13012
+ isNaN: createSandboxClosure({
13013
+ guest: true,
13014
+ sandbox: true,
13015
+ call: ([value]) => typeof value === "number" && Number.isNaN(value),
13016
+ name: "isNaN"
13017
+ }),
13018
+ isInteger: createSandboxClosure({
13019
+ guest: true,
13020
+ sandbox: true,
13021
+ call: ([value]) => typeof value === "number" && Number.isInteger(value),
13022
+ name: "isInteger"
13023
+ }),
13024
+ ...createNumericParsers(options.budget),
13025
+ isSafeInteger: createSandboxClosure({
13026
+ guest: true,
13027
+ sandbox: true,
13028
+ call: ([value]) => typeof value === "number" && Number.isSafeInteger(value),
13029
+ name: "isSafeInteger"
13030
+ }),
13031
+ MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER,
13032
+ MIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER,
13033
+ EPSILON: Number.EPSILON,
13034
+ MAX_VALUE: Number.MAX_VALUE,
13035
+ MIN_VALUE: Number.MIN_VALUE,
13036
+ NaN: Number.NaN,
13037
+ NEGATIVE_INFINITY: Number.NEGATIVE_INFINITY,
13038
+ POSITIVE_INFINITY: Number.POSITIVE_INFINITY
13039
+ }
13040
+ },
13041
+ options.budget
13042
+ ),
13043
+ Boolean: createPrimitiveConstructor(
13044
+ {
13045
+ call: ([value]) => Boolean(value),
13046
+ name: "Boolean"
13047
+ },
13048
+ options.budget
13049
+ )
13050
+ };
13051
+ }
13052
+ function createArrayGlobal(budget) {
13053
+ const prototype = [];
13054
+ const objectToString = Object.getOwnPropertyDescriptor(getSandboxPrototype(/* @__PURE__ */ Object.create(null), budget), "toString").value;
13055
+ const constructor = createSandboxClosure({
13056
+ guest: true,
13057
+ sandbox: true,
13058
+ call: (args) => createArrayFromConstructorArgs(args, budget),
13059
+ construct: (args) => createArrayFromConstructorArgs(args, budget),
13060
+ name: "Array",
13061
+ length: 1
13062
+ });
13063
+ const properties = materializeFunctionProperties(constructor);
13064
+ Object.defineProperty(properties, "prototype", { value: prototype, writable: false });
13065
+ Object.defineProperty(prototype, "constructor", { value: constructor, writable: true, configurable: true });
13066
+ for (const name of arrayMethodNames) {
13067
+ const method = createSandboxClosure({
13068
+ guest: true,
13069
+ sandbox: true,
13070
+ name,
13071
+ length: Object.getOwnPropertyDescriptor(Array.prototype, name).value.length,
13072
+ call: (args, context) => callArrayMethod(context?.thisValue, name, args, {
13073
+ budget,
13074
+ context,
13075
+ hasProperty: (value, key) => hasOwnSandboxProperty(value, key, false) || getSandboxPropertyDescriptor(value, key, budget) !== void 0,
13076
+ deleteProperty: deleteSandboxProperty,
13077
+ setProperty: (value, key, entry) => setSandboxProperty(value, key, entry, budget, true, context),
13078
+ callClosure: (closure, values, _stack, receiver) => invokeBuiltinClosure(closure, values, budget, context, receiver)
13079
+ }, context?.stack ?? [])
13080
+ });
13081
+ Object.defineProperty(prototype, name, { value: method, writable: true, configurable: true });
13082
+ }
13083
+ Object.defineProperty(prototype, "toString", {
13084
+ value: createSandboxClosure({
13085
+ guest: true,
13086
+ sandbox: true,
13087
+ name: "toString",
13088
+ length: 0,
13089
+ call: async (_args, context) => {
13090
+ const receiver = context?.thisValue;
13091
+ if (receiver === null || receiver === void 0) throw new TypeError("Array toString requires a receiver.");
13092
+ const object = typeof receiver === "object" ? receiver : createSandboxBox(receiver);
13093
+ const method = context?.getProperty === void 0 ? getSandboxDataProperty(object, "join", budget) : await context.getProperty(object, "join");
13094
+ return invokeBuiltinClosure(isSandboxClosure(method) ? method : objectToString, [], budget, context, object);
13078
13095
  }
13096
+ }),
13097
+ writable: true,
13098
+ configurable: true
13099
+ });
13100
+ const statics = {
13101
+ isArray: createSandboxClosure({ sandbox: true, name: "isArray", call: ([value]) => Array.isArray(value) }),
13102
+ from: createSandboxClosure({ sandbox: true, name: "from", call: (args, context) => arrayFromSandboxValues(args, budget, context) }),
13103
+ of: createSandboxClosure({ sandbox: true, name: "of", call: (args) => budgetSandboxValue(Reflect.apply(Array.of, Array, [...args]), budget) })
13104
+ };
13105
+ for (const [name, value] of Object.entries(statics))
13106
+ Object.defineProperty(properties, name, { value, writable: true, configurable: true });
13107
+ installArrayPrototype(budget, prototype, constructor);
13108
+ return constructor;
13109
+ }
13110
+ async function objectFromSandboxEntries(items, iterator, budget, context) {
13111
+ const object = /* @__PURE__ */ Object.create(null);
13112
+ let entry;
13113
+ let key;
13114
+ let value;
13115
+ let failure;
13116
+ const retained = {};
13117
+ budget.setRetainedValues(retained, () => [
13118
+ items,
13119
+ iterator.retainedValue,
13120
+ object,
13121
+ entry,
13122
+ key,
13123
+ value,
13124
+ failure
13125
+ ]);
13126
+ const checkData = createDataCheckpoint(budget, context);
13127
+ const closeOnThrow = async (error) => {
13128
+ failure = isCapturedException(error) ? error.reason : error;
13129
+ try {
13130
+ await closeIterator(iterator, true);
13131
+ } catch (closeError) {
13132
+ if (!isFatalSandboxError(error) && isFatalSandboxError(closeError)) throw closeError;
13079
13133
  }
13080
- case "with": {
13081
- const length = value.length;
13082
- const index = toIntegerOrInfinity(
13083
- options.context === void 0 ? args[0] : await sandboxNumber(args[0], options.budget, options.context)
13084
- );
13085
- const actualIndex = index < 0 ? length + index : index;
13086
- if (actualIndex < 0 || actualIndex >= length) {
13087
- throw new RangeError("Invalid index");
13088
- }
13089
- options.budget.allocateArrayLength(length);
13090
- const result = [];
13091
- const release = retainValues(options.budget, () => [result]);
13134
+ throw error;
13135
+ };
13136
+ try {
13137
+ checkData(object, 0, true);
13138
+ while (true) {
13092
13139
  try {
13093
- for (let position = 0; position < length; position += 1) {
13094
- options.budget.visitNode();
13095
- result[position] = position === actualIndex ? args[1] : await readArrayElement(value, position, options);
13096
- }
13097
- return budgetProducedValue(result, options.budget);
13098
- } finally {
13099
- release();
13140
+ budget.visitNode();
13141
+ } catch (error) {
13142
+ await closeOnThrow(error);
13100
13143
  }
13101
- }
13102
- case "push": {
13103
- const nextLength = await appendArrayValues(value, args, options);
13104
- budgetProducedValue(value, options.budget);
13105
- return nextLength;
13106
- }
13107
- case "pop":
13108
- case "shift": {
13109
- const length = value.length;
13110
- if (length === 0) {
13111
- await writeArrayProperty(value, "length", 0, options);
13112
- return void 0;
13144
+ const result = await iterator.next();
13145
+ if (typeof result !== "object" || result === null) {
13146
+ throw new TypeError("Iterator result must be an object.");
13113
13147
  }
13114
- const result = await readArrayElement(value, methodName === "pop" ? length - 1 : 0, options);
13115
- const retained = {};
13116
- options.budget.setRetainedValues(retained, () => [result]);
13148
+ if ((await readIteratorResult(iterator, result, "done")).value) break;
13149
+ entry = (await readIteratorResult(iterator, result, "value")).value;
13117
13150
  try {
13118
- if (methodName === "shift")
13119
- for (let index = 1; index < length; index++)
13120
- await moveArrayElement(value, index, index - 1, options);
13121
- deleteArrayElement(value, length - 1, options);
13122
- await writeArrayProperty(value, "length", length - 1, options);
13123
- return budgetProducedValue(result, options.budget);
13124
- } finally {
13125
- options.budget.setRetainedValues(retained, void 0);
13151
+ if (typeof entry !== "object" || entry === null) {
13152
+ throw new TypeError("Object.fromEntries requires entry objects.");
13153
+ }
13154
+ key = context?.getProperty !== void 0 ? await context.getProperty(entry, 0) : getSandboxDataProperty(entry, 0, budget);
13155
+ value = context?.getProperty !== void 0 ? await context.getProperty(entry, 1) : getSandboxDataProperty(entry, 1, budget);
13156
+ const property = await toPropertyKey(key, budget, context);
13157
+ const growth = (typeof property === "symbol" ? property.description?.length ?? 0 : property.length) + 1 + (budget.limits.dataSize === void 0 ? 0 : measureSandboxData([value]));
13158
+ budget.visitNode();
13159
+ defineOwnDataProperty(object, property, value);
13160
+ entry = key = value = void 0;
13161
+ checkData(object, growth);
13162
+ } catch (error) {
13163
+ await closeOnThrow(error);
13126
13164
  }
13127
13165
  }
13128
- case "unshift": {
13129
- const nextLength = await prependArrayValues(value, args, options);
13130
- budgetProducedValue(value, options.budget);
13131
- return nextLength;
13132
- }
13166
+ checkData(object, 0, true);
13167
+ return allocateProducedSandboxValue(object, budget);
13168
+ } finally {
13169
+ budget.setRetainedValues(retained, void 0);
13133
13170
  }
13134
13171
  }
13135
- async function appendArrayValues(target, values, options) {
13136
- let length = target.length;
13137
- if (length + values.length > Number.MAX_SAFE_INTEGER)
13138
- throw new TypeError("Array-like length exceeds the safe integer limit.");
13139
- for (const value of values) {
13140
- await writeArrayProperty(target, length++, value, options);
13172
+ function assignSandboxValues(target, sources, budget, context) {
13173
+ if (target === null || target === void 0) {
13174
+ throw new TypeError("Object.assign(target, ...sources) requires a non-null target.");
13141
13175
  }
13142
- await writeArrayProperty(target, "length", length, options);
13143
- return length;
13144
- }
13145
- async function prependArrayValues(target, values, options) {
13146
- const originalLength = target.length;
13147
- const length = originalLength + values.length;
13148
- if (length > Number.MAX_SAFE_INTEGER)
13149
- throw new TypeError("Array-like length exceeds the safe integer limit.");
13150
- for (let index = values.length === 0 ? -1 : originalLength - 1; index >= 0; index -= 1) {
13151
- const targetIndex = index + values.length;
13152
- await moveArrayElement(target, index, targetIndex, options);
13176
+ if (typeof target !== "object") {
13177
+ target = createSandboxBox(target);
13178
+ budget.chargeDataUsage(measureSandboxData([target]));
13153
13179
  }
13154
- for (let index = 0; index < values.length; index += 1) {
13155
- await writeArrayProperty(target, index, values[index], options);
13180
+ if (!isGuestHostObject(target)) objectProperties(target, true);
13181
+ if (context === void 0) {
13182
+ for (const source of sources) {
13183
+ if (source === null || source === void 0) continue;
13184
+ const properties = isGuestHostObject(source) ? void 0 : reflectionProperties(source);
13185
+ const keys = properties === void 0 ? ownEnumerableSandboxKeys(source, true) : [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(source)];
13186
+ for (const key of keys) {
13187
+ if (!hasOwnSandboxProperty(source, key, true)) continue;
13188
+ const value = properties === void 0 ? getSandboxDataProperty(source, key, budget) : Reflect.get(properties, key, source);
13189
+ setSandboxProperty(target, key, value, budget);
13190
+ }
13191
+ }
13192
+ return target;
13156
13193
  }
13157
- await writeArrayProperty(target, "length", length, options);
13158
- return length;
13159
- }
13160
- function isCallbackArrayMethod(methodName) {
13161
- return methodName === "map" || methodName === "filter" || methodName === "find" || methodName === "findIndex" || methodName === "findLast" || methodName === "findLastIndex" || methodName === "some" || methodName === "every" || methodName === "reduce" || methodName === "reduceRight" || methodName === "forEach" || methodName === "flatMap" || methodName === "sort";
13194
+ return (async () => {
13195
+ const release = retainValues(budget, () => [target, ...sources]);
13196
+ try {
13197
+ for (const source of sources) {
13198
+ if (source === null || source === void 0) continue;
13199
+ const properties = isGuestHostObject(source) ? void 0 : reflectionProperties(source);
13200
+ const keys = properties === void 0 ? ownEnumerableSandboxKeys(source, true) : [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(source)];
13201
+ for (const key of keys) {
13202
+ if (!hasOwnSandboxProperty(source, key, true)) continue;
13203
+ const value = await (context?.getProperty !== void 0 ? context.getProperty(source, key) : isGuestHostObject(source) ? getSandboxDataProperty(source, key, budget) : readPropertyDescriptor(Object.getOwnPropertyDescriptor(properties, key), source, context, true));
13204
+ await setSandboxProperty(target, key, value, budget, true, context);
13205
+ }
13206
+ }
13207
+ return target;
13208
+ } finally {
13209
+ release();
13210
+ }
13211
+ })();
13162
13212
  }
13163
- function isMutatingArrayMethod(methodName) {
13164
- return methodName === "splice" || methodName === "fill" || methodName === "copyWithin" || methodName === "sort" || methodName === "reverse" || methodName === "push" || methodName === "pop" || methodName === "shift" || methodName === "unshift";
13213
+ function reflectionProperties(value) {
13214
+ if (value !== null && value !== void 0 && typeof value !== "object")
13215
+ value = createSandboxBox(value);
13216
+ return objectProperties(value);
13165
13217
  }
13166
- function getRequiredCallback(methodName, value) {
13167
- if (!isSandboxClosure(value)) {
13168
- throw new TypeError(`Array#${methodName} requires a sandbox closure callback.`);
13218
+ function objectProperties(value, mutable = false) {
13219
+ if (isSandboxPromise(value)) return getPromiseProperties(value);
13220
+ if (isSandboxMap(value) || isSandboxSet(value)) return getCollectionProperties(value);
13221
+ if (isSandboxRegex(value)) return getRegexProperties(value);
13222
+ if (isSandboxDate(value)) {
13223
+ return value;
13169
13224
  }
13170
- return value;
13171
- }
13172
- function readArrayElement(value, index, options) {
13173
- const receiver = arrayLikeSources.get(value) ?? value;
13174
- return options.context?.getProperty !== void 0 ? options.context.getProperty(receiver, index) : getSandboxDataProperty(receiver, index, options.budget);
13175
- }
13176
- function writeArrayProperty(value, key, entry, options) {
13177
- options.budget.visitNode();
13178
- const receiver = arrayLikeSources.get(value) ?? value;
13179
- if (Array.isArray(receiver)) {
13180
- if (key === "length") options.budget.allocateArrayLength(Number(entry));
13181
- else if (typeof key === "number") options.budget.allocateArrayLength(key + 1);
13225
+ if (isGuestHostObject(value))
13226
+ throw new TypeError("Live host object descriptors are not supported.");
13227
+ if (isGuestClosure(value)) return materializeFunctionProperties(value);
13228
+ if (isSandboxClosure(value)) {
13229
+ if (mutable) throw new TypeError("Host function properties are read only.");
13230
+ return value.properties ?? /* @__PURE__ */ Object.create(null);
13182
13231
  }
13183
- if (options.setProperty !== void 0) return options.setProperty(receiver, String(key), entry);
13184
- if (!Reflect.set(receiver, key, entry))
13185
- throw new TypeError(`Cannot assign to read only property '${key}'.`);
13186
- }
13187
- function deleteArrayElement(value, index, options) {
13188
- options.budget.visitNode();
13189
- const receiver = arrayLikeSources.get(value) ?? value;
13190
- const deleted = options.deleteProperty === void 0 ? Reflect.deleteProperty(receiver, String(index)) : options.deleteProperty(receiver, String(index));
13191
- if (!deleted) throw new TypeError(`Cannot delete property '${index}'.`);
13232
+ if (!isAssignableSandboxTarget(value))
13233
+ throw new TypeError("Expected a sandbox object or function.");
13234
+ return value;
13192
13235
  }
13193
- async function moveArrayElement(value, from, to, options) {
13194
- options.budget.visitNode();
13195
- if (from in value)
13196
- await writeArrayProperty(value, to, await readArrayElement(value, from, options), options);
13197
- else deleteArrayElement(value, to, options);
13236
+ function exposePropertyDescriptor(descriptor) {
13237
+ return "value" in descriptor ? descriptor : {
13238
+ get: accessorClosure(descriptor.get),
13239
+ set: accessorClosure(descriptor.set),
13240
+ enumerable: descriptor.enumerable,
13241
+ configurable: descriptor.configurable
13242
+ };
13198
13243
  }
13199
- async function mapArray(value, callback, options, stack, thisValue) {
13200
- const length = value.length;
13201
- options.budget.allocateArrayLength(length);
13202
- const result = new Array(length);
13203
- options.budget.setRetainedValues(result, () => [result]);
13244
+ async function propertyDescriptor(input, budget, context) {
13245
+ objectProperties(input);
13246
+ const descriptor = {};
13247
+ const release = retainValues(budget, () => [
13248
+ input,
13249
+ descriptor.value,
13250
+ ...retainedAccessorClosures(descriptor)
13251
+ ]);
13204
13252
  try {
13205
- for (let index = 0; index < length; index += 1) {
13206
- options.budget.visitNode();
13207
- if (!(index in value)) {
13253
+ for (const field of [
13254
+ "enumerable",
13255
+ "configurable",
13256
+ "value",
13257
+ "writable",
13258
+ "get",
13259
+ "set"
13260
+ ]) {
13261
+ if (getSandboxPropertyDescriptor(input, field, budget) === void 0 && !hasOwnSandboxProperty(input, field, false))
13208
13262
  continue;
13263
+ const value = await (context?.getProperty !== void 0 ? context.getProperty(input, field) : getSandboxDataProperty(input, field, budget));
13264
+ if (field === "get" || field === "set") {
13265
+ if (value !== void 0 && !isSandboxClosure(value))
13266
+ throw new TypeError("Accessor must be a function or undefined.");
13267
+ descriptor[field] = value === void 0 ? void 0 : accessorAdapter(value, field);
13268
+ } else if (field === "value") {
13269
+ descriptor.value = value;
13270
+ } else {
13271
+ descriptor[field] = Boolean(value);
13209
13272
  }
13210
- result[index] = await callArrayCallback(
13211
- callback,
13212
- await readArrayElement(value, index, options),
13213
- index,
13214
- value,
13215
- options,
13216
- stack,
13217
- thisValue
13218
- );
13219
13273
  }
13220
- return result;
13274
+ if (("get" in descriptor || "set" in descriptor) && ("value" in descriptor || "writable" in descriptor))
13275
+ throw new TypeError("A property cannot be both a data property and an accessor.");
13276
+ return descriptor;
13221
13277
  } finally {
13222
- options.budget.setRetainedValues(result, void 0);
13278
+ release();
13223
13279
  }
13224
13280
  }
13225
- async function filterArray(value, callback, options, stack, thisValue) {
13226
- const length = value.length;
13227
- const result = [];
13228
- options.budget.setRetainedValues(result, () => [result]);
13281
+ async function definePropertiesFromObject(target, descriptors2, budget, context) {
13282
+ objectProperties(target, true);
13283
+ const properties = [];
13284
+ const release = retainValues(budget, () => [
13285
+ target,
13286
+ descriptors2,
13287
+ properties,
13288
+ ...properties.flatMap(([, descriptor]) => retainedAccessorClosures(descriptor))
13289
+ ]);
13229
13290
  try {
13230
- for (let index = 0; index < length; index += 1) {
13231
- options.budget.visitNode();
13232
- if (!(index in value)) {
13233
- continue;
13234
- }
13235
- const entry = await readArrayElement(value, index, options);
13236
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13237
- result.push(entry);
13238
- }
13291
+ for (const key of ownEnumerableSandboxKeys(descriptors2, true)) {
13292
+ if (!hasOwnSandboxProperty(descriptors2, key, true)) continue;
13293
+ const descriptor = await (context?.getProperty !== void 0 ? context.getProperty(descriptors2, key) : getSandboxDataProperty(descriptors2, key, budget));
13294
+ properties.push([key, await propertyDescriptor(descriptor, budget, context)]);
13239
13295
  }
13240
- return result;
13296
+ for (const [key, descriptor] of properties) defineDataProperty(target, key, descriptor, budget);
13241
13297
  } finally {
13242
- options.budget.setRetainedValues(result, void 0);
13243
- }
13244
- }
13245
- async function findInArray(value, callback, options, stack, thisValue) {
13246
- const length = value.length;
13247
- for (let index = 0; index < length; index += 1) {
13248
- options.budget.visitNode();
13249
- const entry = await readArrayElement(value, index, options);
13250
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13251
- return entry;
13252
- }
13298
+ release();
13253
13299
  }
13254
- return void 0;
13255
13300
  }
13256
- async function findIndexInArray(value, callback, options, stack, thisValue) {
13257
- const length = value.length;
13258
- for (let index = 0; index < length; index += 1) {
13259
- options.budget.visitNode();
13260
- const entry = await readArrayElement(value, index, options);
13261
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13262
- return index;
13301
+ function defineDataProperty(target, key, descriptor, budget) {
13302
+ budget.visitNode();
13303
+ if (isFloat32Array(target))
13304
+ throw new TypeError("Typed array property descriptors are not supported.");
13305
+ const properties = objectProperties(target, true);
13306
+ if (Array.isArray(properties)) {
13307
+ if (key === "length" && "value" in descriptor)
13308
+ budget.allocateArrayLength(Number(descriptor.value));
13309
+ else if (typeof key !== "symbol") {
13310
+ const index = Number(key);
13311
+ if (Number.isInteger(index) && index >= 0 && index < 4294967295 && String(index) === key) {
13312
+ budget.allocateArrayLength(index + 1);
13313
+ }
13263
13314
  }
13264
13315
  }
13265
- return -1;
13316
+ Object.defineProperty(properties, key, descriptor);
13317
+ markDescriptorObject(properties);
13266
13318
  }
13267
- async function findLastInArray(value, callback, options, stack, thisValue) {
13268
- const length = value.length;
13269
- for (let index = length - 1; index >= 0; index -= 1) {
13270
- options.budget.visitNode();
13271
- const entry = await readArrayElement(value, index, options);
13272
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13273
- return entry;
13274
- }
13275
- }
13276
- return void 0;
13319
+ function isAssignableSandboxTarget(value) {
13320
+ return typeof value === "object" && value !== null && !isSandboxClosure(value) && !isSandboxGenerator(value) && !isSandboxMap(value) && !isSandboxSet(value) && !isSandboxPromise(value) && !isSandboxRegex(value);
13277
13321
  }
13278
- async function findLastIndexInArray(value, callback, options, stack, thisValue) {
13279
- const length = value.length;
13280
- for (let index = length - 1; index >= 0; index -= 1) {
13281
- options.budget.visitNode();
13282
- const entry = await readArrayElement(value, index, options);
13283
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13284
- return index;
13285
- }
13322
+ async function arrayFromSandboxValues(args, budget, context) {
13323
+ const [items, mapFn, thisValue] = args;
13324
+ if (mapFn !== void 0 && !isSandboxClosure(mapFn)) {
13325
+ throw new TypeError("Array.from mapping callback must be a function.");
13286
13326
  }
13287
- return -1;
13288
- }
13289
- async function someInArray(value, callback, options, stack, thisValue) {
13290
- const length = value.length;
13291
- for (let index = 0; index < length; index += 1) {
13292
- options.budget.visitNode();
13293
- if (!(index in value)) {
13294
- continue;
13295
- }
13296
- if (await callArrayCallback(
13297
- callback,
13298
- await readArrayElement(value, index, options),
13299
- index,
13300
- value,
13301
- options,
13302
- stack,
13303
- thisValue
13304
- )) {
13305
- return true;
13306
- }
13327
+ if (items === null || items === void 0) {
13328
+ throw new TypeError("Array.from requires a non-null input.");
13307
13329
  }
13308
- return false;
13309
- }
13310
- async function everyInArray(value, callback, options, stack, thisValue) {
13311
- const length = value.length;
13312
- for (let index = 0; index < length; index += 1) {
13313
- options.budget.visitNode();
13314
- if (!(index in value)) {
13315
- continue;
13316
- }
13317
- if (!await callArrayCallback(
13318
- callback,
13319
- await readArrayElement(value, index, options),
13320
- index,
13321
- value,
13322
- options,
13323
- stack,
13324
- thisValue
13325
- )) {
13326
- return false;
13330
+ const read = (property) => context?.getProperty !== void 0 ? context.getProperty(items, property) : getSandboxDataProperty(items, property, budget);
13331
+ const iterator = context === void 0 ? getSandboxIterator(items, budget) : await acquireSandboxIterator(items, budget, context);
13332
+ const constructor = context?.thisValue;
13333
+ let result;
13334
+ let currentValue;
13335
+ let failure;
13336
+ const retained = {};
13337
+ budget.setRetainedValues(retained, () => [
13338
+ items,
13339
+ iterator?.retainedValue,
13340
+ mapFn,
13341
+ constructor,
13342
+ result,
13343
+ currentValue,
13344
+ failure
13345
+ ]);
13346
+ const checkData = createDataCheckpoint(budget, context);
13347
+ const closeOnThrow = async (error) => {
13348
+ failure = isCapturedException(error) ? error.reason : error;
13349
+ try {
13350
+ if (iterator !== void 0) await closeIterator(iterator, true);
13351
+ } catch (closeError) {
13352
+ if (!isFatalSandboxError(error) && isFatalSandboxError(closeError)) throw closeError;
13327
13353
  }
13328
- }
13329
- return true;
13330
- }
13331
- async function reduceArray(value, callback, hasInitialValue, initialValue, options, stack) {
13332
- const length = value.length;
13333
- if (hasInitialValue) {
13334
- return reduceFromLeft(value, callback, initialValue, 0, length, options, stack);
13335
- }
13336
- const start = findNextDefinedIndex(value, 0, 1, length, options.budget);
13337
- if (start < 0) {
13338
- throw new TypeError("Reduce of empty array with no initial value.");
13339
- }
13340
- return reduceFromLeft(
13341
- value,
13342
- callback,
13343
- await readArrayElement(value, start, options),
13344
- start + 1,
13345
- length,
13346
- options,
13347
- stack
13348
- );
13349
- }
13350
- async function reduceRightArray(value, callback, hasInitialValue, initialValue, options, stack) {
13351
- const length = value.length;
13352
- if (hasInitialValue) {
13353
- return reduceFromRight(value, callback, initialValue, length - 1, length, options, stack);
13354
- }
13355
- const start = findNextDefinedIndex(value, length - 1, -1, length, options.budget);
13356
- if (start < 0) {
13357
- throw new TypeError("Reduce of empty array with no initial value.");
13358
- }
13359
- return reduceFromRight(
13360
- value,
13361
- callback,
13362
- await readArrayElement(value, start, options),
13363
- start - 1,
13364
- length,
13365
- options,
13366
- stack
13367
- );
13368
- }
13369
- async function reduceFromLeft(value, callback, accumulator, startIndex, length, options, stack) {
13370
- let current = accumulator;
13371
- const retainedAccumulator = {};
13372
- options.budget.setRetainedValues(retainedAccumulator, () => [current]);
13354
+ throw error;
13355
+ };
13373
13356
  try {
13374
- for (let index = startIndex; index < length; index += 1) {
13375
- options.budget.visitNode();
13376
- if (!(index in value)) {
13377
- continue;
13357
+ let length = 0;
13358
+ if (iterator === void 0) {
13359
+ const number = await sandboxNumber(await read("length"), budget, context);
13360
+ length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
13361
+ }
13362
+ result = isSandboxClosure(constructor) && constructor.construct !== void 0 ? await invokeBuiltinClosure(
13363
+ constructor,
13364
+ iterator === void 0 ? [length] : [],
13365
+ budget,
13366
+ context,
13367
+ void 0,
13368
+ true
13369
+ ) : createArrayFromConstructorArgs([length], budget);
13370
+ checkData(result, 0, true);
13371
+ let index = 0;
13372
+ while (iterator !== void 0 || index < length) {
13373
+ try {
13374
+ budget.visitNode();
13375
+ if (iterator !== void 0 && index >= Number.MAX_SAFE_INTEGER)
13376
+ throw new TypeError("Array.from input is too long.");
13377
+ } catch (error) {
13378
+ await closeOnThrow(error);
13378
13379
  }
13379
- current = await options.callClosure(
13380
- callback,
13381
- [
13382
- current,
13383
- await readArrayElement(value, index, options),
13384
- index,
13385
- arrayLikeSources.get(value) ?? value
13386
- ],
13387
- stack
13388
- );
13380
+ if (iterator !== void 0) {
13381
+ const next = await iterator.next();
13382
+ if (typeof next !== "object" || next === null)
13383
+ throw new TypeError("Iterator result must be an object.");
13384
+ if ((await readIteratorResult(iterator, next, "done")).value) break;
13385
+ currentValue = (await readIteratorResult(iterator, next, "value")).value;
13386
+ } else {
13387
+ currentValue = await read(index);
13388
+ }
13389
+ try {
13390
+ if (Array.isArray(result)) budget.allocateArrayLength(index + 1);
13391
+ if (mapFn !== void 0)
13392
+ currentValue = await invokeBuiltinClosure(
13393
+ mapFn,
13394
+ [currentValue, index],
13395
+ budget,
13396
+ context,
13397
+ thisValue
13398
+ );
13399
+ const key = String(index);
13400
+ const growth = key.length + 1 + (Array.isArray(result) ? Math.max(0, index + 1 - result.length) : 0) + (budget.limits.dataSize === void 0 ? 0 : measureSandboxData([currentValue]));
13401
+ budget.visitNode();
13402
+ defineOwnDataProperty(objectProperties(result, true), key, currentValue);
13403
+ currentValue = void 0;
13404
+ checkData(result, growth, isSandboxClosure(result));
13405
+ } catch (error) {
13406
+ await closeOnThrow(error);
13407
+ }
13408
+ index += 1;
13389
13409
  }
13390
- return current;
13410
+ setSandboxProperty(result, "length", index, budget);
13411
+ checkData(result, 0, true);
13412
+ return allocateProducedSandboxValue(result, budget);
13391
13413
  } finally {
13392
- options.budget.setRetainedValues(retainedAccumulator, void 0);
13414
+ budget.setRetainedValues(retained, void 0);
13393
13415
  }
13394
13416
  }
13395
- async function reduceFromRight(value, callback, accumulator, startIndex, length, options, stack) {
13396
- let current = accumulator;
13397
- const retainedAccumulator = {};
13398
- options.budget.setRetainedValues(retainedAccumulator, () => [current]);
13417
+ function createArrayFromConstructorArgs(args, budget) {
13418
+ if (args.length !== 1) {
13419
+ return budgetSandboxValue(Reflect.apply(Array, Array, [...args]), budget);
13420
+ }
13421
+ const [lengthOrValue] = args;
13422
+ if (typeof lengthOrValue !== "number") {
13423
+ return budgetSandboxValue([lengthOrValue], budget);
13424
+ }
13425
+ if (!Number.isInteger(lengthOrValue) || lengthOrValue < 0 || lengthOrValue > 4294967295) {
13426
+ throw new RangeError("Invalid array length.");
13427
+ }
13428
+ budget.allocateArrayLength(lengthOrValue);
13429
+ const release = budget.provisionDataUsage(lengthOrValue + 1);
13399
13430
  try {
13400
- for (let index = Math.min(startIndex, length - 1); index >= 0; index -= 1) {
13401
- options.budget.visitNode();
13402
- if (!(index in value)) {
13403
- continue;
13404
- }
13405
- current = await options.callClosure(
13406
- callback,
13407
- [
13408
- current,
13409
- await readArrayElement(value, index, options),
13410
- index,
13411
- arrayLikeSources.get(value) ?? value
13412
- ],
13413
- stack
13414
- );
13415
- }
13416
- return current;
13431
+ return new Array(lengthOrValue);
13417
13432
  } finally {
13418
- options.budget.setRetainedValues(retainedAccumulator, void 0);
13419
- }
13420
- }
13421
- async function forEachArray(value, callback, options, stack, thisValue) {
13422
- const length = value.length;
13423
- for (let index = 0; index < length; index += 1) {
13424
- options.budget.visitNode();
13425
- if (!(index in value)) {
13426
- continue;
13427
- }
13428
- await callArrayCallback(
13429
- callback,
13430
- await readArrayElement(value, index, options),
13431
- index,
13432
- value,
13433
- options,
13434
- stack,
13435
- thisValue
13436
- );
13433
+ release();
13437
13434
  }
13438
13435
  }
13439
- async function flatMapArray(value, callback, options, stack, thisValue) {
13440
- const length = value.length;
13441
- const result = [];
13442
- options.budget.setRetainedValues(result, () => [result]);
13436
+ async function getOwnEnumerableEntries(value, budget, context) {
13437
+ const entries = [];
13438
+ const release = retainValues(budget, () => [value, entries]);
13443
13439
  try {
13444
- for (let index = 0; index < length; index += 1) {
13445
- options.budget.visitNode();
13446
- if (!(index in value)) {
13447
- continue;
13448
- }
13449
- const mapped = await callArrayCallback(
13450
- callback,
13451
- await readArrayElement(value, index, options),
13452
- index,
13453
- value,
13454
- options,
13455
- stack,
13456
- thisValue
13457
- );
13458
- if (Array.isArray(mapped)) {
13459
- for (let mappedIndex = 0; mappedIndex < mapped.length; mappedIndex += 1) {
13460
- options.budget.visitNode();
13461
- if (!(mappedIndex in mapped)) {
13462
- continue;
13463
- }
13464
- result.push(await readArrayElement(mapped, mappedIndex, options));
13465
- options.budget.allocateArrayLength(result.length);
13466
- }
13467
- continue;
13468
- }
13469
- result.push(mapped);
13470
- options.budget.allocateArrayLength(result.length);
13440
+ for (const key of ownEnumerableSandboxKeys(value)) {
13441
+ if (!hasOwnSandboxProperty(value, key, true)) continue;
13442
+ entries.push([
13443
+ key,
13444
+ await (context?.getProperty !== void 0 ? context.getProperty(value, key) : getSandboxDataProperty(value, key, budget))
13445
+ ]);
13471
13446
  }
13472
- return result;
13447
+ return entries;
13473
13448
  } finally {
13474
- options.budget.setRetainedValues(result, void 0);
13449
+ release();
13475
13450
  }
13476
13451
  }
13477
- async function flattenArray(value, depth, options) {
13478
- const result = [];
13479
- const retained = {};
13480
- options.budget.setRetainedValues(retained, () => [result]);
13452
+ function budgetSandboxValue(value, budget) {
13453
+ const sandboxValue = deepCopyToSandbox(value);
13454
+ return allocateProducedSandboxValue(sandboxValue, budget);
13455
+ }
13456
+ function stringFromCodes(args, convert, budget, context) {
13457
+ let result = "";
13458
+ let index = 0;
13459
+ const release = retainValues(budget, () => [...args, result]);
13481
13460
  try {
13482
- await appendFlattenedEntries(value, depth, result, options);
13461
+ const output = advance();
13462
+ if (typeof output !== "string") return output.finally(release);
13463
+ release();
13464
+ return output;
13465
+ } catch (error) {
13466
+ release();
13467
+ throw error;
13468
+ }
13469
+ function advance() {
13470
+ while (index < args.length) {
13471
+ budget.visitNode();
13472
+ const number = sandboxNumber(args[index++], budget, context);
13473
+ if (number instanceof Promise) return number.then((value) => {
13474
+ result = budget.allocateString(result + convert(value));
13475
+ return advance();
13476
+ });
13477
+ result = budget.allocateString(result + convert(number));
13478
+ }
13483
13479
  return result;
13484
- } finally {
13485
- options.budget.setRetainedValues(retained, void 0);
13486
13480
  }
13487
13481
  }
13488
- async function appendFlattenedEntries(value, depth, result, options) {
13489
- const length = value.length;
13490
- for (let index = 0; index < length; index += 1) {
13491
- options.budget.visitNode();
13492
- if (!(index in value)) {
13493
- continue;
13494
- }
13495
- const entry = await readArrayElement(value, index, options);
13496
- if (depth > 0 && Array.isArray(entry)) {
13497
- await appendFlattenedEntries(entry, depth - 1, result, options);
13498
- continue;
13482
+ function stringRaw(args, budget, context) {
13483
+ const [template, ...substitutions] = args;
13484
+ if (context?.getProperty !== void 0)
13485
+ return (async () => {
13486
+ if (template === null || template === void 0)
13487
+ throw new TypeError("String.raw requires a template object.");
13488
+ const raw2 = await context.getProperty(template, "raw");
13489
+ if (raw2 === null || raw2 === void 0)
13490
+ throw new TypeError("String.raw requires raw strings.");
13491
+ const number = await sandboxNumber(
13492
+ await context.getProperty(raw2, "length"),
13493
+ budget,
13494
+ context
13495
+ );
13496
+ const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
13497
+ let result2 = "";
13498
+ const retained = {};
13499
+ budget.setRetainedValues(retained, () => [raw2, result2]);
13500
+ try {
13501
+ for (let index = 0; index < length; index++) {
13502
+ budget.visitNode();
13503
+ result2 = budget.allocateString(
13504
+ result2 + await sandboxString(await context.getProperty(raw2, index), budget, context)
13505
+ );
13506
+ if (index + 1 < length && index < substitutions.length)
13507
+ result2 = budget.allocateString(
13508
+ result2 + await sandboxString(substitutions[index], budget, context)
13509
+ );
13510
+ }
13511
+ return result2;
13512
+ } finally {
13513
+ budget.setRetainedValues(retained, void 0);
13514
+ }
13515
+ })();
13516
+ const raw = getTemplateRawParts(template);
13517
+ let result = "";
13518
+ for (let index = 0; index < raw.length; index += 1) {
13519
+ result += String(raw[index]);
13520
+ if (index < raw.length - 1 && index < substitutions.length) {
13521
+ result += String(substitutions[index]);
13499
13522
  }
13500
- result.push(entry);
13501
- options.budget.allocateArrayLength(result.length);
13502
13523
  }
13524
+ return budget.allocateString(result);
13503
13525
  }
13504
- async function sortArray(value, comparator, options, stack) {
13505
- const length = value.length;
13506
- const definedValues = [];
13507
- let undefinedCount = 0;
13508
- let currentEntry;
13509
- options.budget.setRetainedValues(definedValues, () => [definedValues, currentEntry]);
13526
+ function getTemplateRawParts(template) {
13527
+ const raw = typeof template === "object" && template !== null ? template.raw : void 0;
13528
+ if (typeof template !== "object" || template === null || isSandboxClosure(template) || isSandboxPromise(template) || !Array.isArray(raw)) {
13529
+ throw new TypeError("String.raw requires a raw strings array.");
13530
+ }
13531
+ return raw;
13532
+ }
13533
+
13534
+ // packages/safe-js/src/interp/classes.ts
13535
+ async function evaluateClass(node, context, evaluateNode2, callContext) {
13536
+ const scope = context.scope.child();
13537
+ if (node.id !== void 0) scope.predeclare(node.id.name, "const");
13538
+ const classContext = { ...context, scope, inferredName: void 0 };
13539
+ let parent;
13540
+ let prototypeParent;
13541
+ const fields2 = [];
13542
+ const statics = [];
13543
+ let constructor;
13544
+ const release = retainValues(context.budget, () => [parent, prototypeParent, constructor, ...fields2.map((field) => field.key), ...statics.flatMap((field) => "key" in field ? [field.key] : [])]);
13510
13545
  try {
13511
- for (let index = 0; index < length; index += 1) {
13512
- options.budget.visitNode();
13513
- if (!(index in value)) {
13546
+ if (node.superClass !== void 0) {
13547
+ const result = await evaluateNode2(node.superClass, classContext);
13548
+ if (result.kind !== "normal") return result;
13549
+ parent = result.value;
13550
+ if (parent !== null && (!isSandboxClosure(parent) || parent.construct === void 0))
13551
+ throw new TypeError("Class extends value is not a constructor or null.");
13552
+ prototypeParent = parent === null ? null : await callContext.getProperty(parent, "prototype");
13553
+ if (prototypeParent !== null && typeof prototypeParent !== "object")
13554
+ throw new TypeError("Class extends value has an invalid prototype.");
13555
+ }
13556
+ const derived = node.superClass !== void 0;
13557
+ constructor = createClassConstructor(node, { ...classContext, inferredName: context.inferredName }, evaluateNode2, fields2);
13558
+ const properties = materializeFunctionProperties(constructor);
13559
+ const prototype = properties.prototype;
13560
+ Object.defineProperty(properties, "prototype", { writable: false });
13561
+ if (derived) setSandboxPrototype(prototype, prototypeParent, context.budget);
13562
+ if (isSandboxClosure(parent)) setSandboxPrototype(constructor, parent, context.budget);
13563
+ const pattern = createPatternContext(classContext, scope, evaluateNode2);
13564
+ for (const element of node.body.body) {
13565
+ context.budget.visitNode();
13566
+ if (element.type === "StaticBlock") {
13567
+ statics.push({ element });
13514
13568
  continue;
13515
13569
  }
13516
- const entry = await readArrayElement(value, index, options);
13517
- if (entry === void 0) {
13518
- undefinedCount += 1;
13519
- continue;
13570
+ if (element.type === "MethodDefinition" && element.kind === "constructor") continue;
13571
+ let key;
13572
+ if (element.computed) {
13573
+ const result = await evaluateNode2(element.key, classContext);
13574
+ if (result.kind !== "normal") return result;
13575
+ key = await pattern.toPropertyKey(result.value);
13576
+ } else {
13577
+ key = element.key.type === "Identifier" ? element.key.name : String(element.key.value);
13520
13578
  }
13521
- definedValues.push(entry);
13522
- }
13523
- for (let index = 1; index < definedValues.length; index += 1) {
13524
- currentEntry = definedValues[index];
13525
- let cursor = index - 1;
13526
- while (cursor >= 0 && await compareEntries(definedValues[cursor], currentEntry, comparator, options, stack) > 0) {
13527
- definedValues[cursor + 1] = definedValues[cursor];
13528
- cursor -= 1;
13579
+ if (typeof key === "string") context.budget.allocateString(key);
13580
+ if (element.type === "PropertyDefinition") {
13581
+ (element.static ? statics : fields2).push({ element, key });
13582
+ } else {
13583
+ const home = element.static ? constructor : prototype;
13584
+ const method = createInterpretedClosure(element.value, classContext, evaluateNode2, home);
13585
+ const accessor = element.kind === "get" || element.kind === "set" ? element.kind : void 0;
13586
+ Object.defineProperty(materializeFunctionProperties(method), "name", {
13587
+ value: accessor === void 0 ? propertyFunctionName(key) : `${accessor} ${propertyFunctionName(key)}`
13588
+ });
13589
+ Object.defineProperty(
13590
+ element.static ? properties : prototype,
13591
+ key,
13592
+ accessor === void 0 ? { value: method, configurable: true, writable: true, enumerable: false } : { [accessor]: accessorAdapter(method, accessor), configurable: true, enumerable: false }
13593
+ );
13529
13594
  }
13530
- definedValues[cursor + 1] = currentEntry;
13531
13595
  }
13532
- currentEntry = void 0;
13533
- for (let index = 0; index < definedValues.length; index += 1) {
13534
- await writeArrayProperty(value, index, definedValues[index], options);
13535
- }
13536
- for (let index = 0; index < undefinedCount; index += 1) {
13537
- await writeArrayProperty(value, definedValues.length + index, void 0, options);
13538
- }
13539
- for (let index = definedValues.length + undefinedCount; index < length; index += 1) {
13540
- options.budget.visitNode();
13541
- deleteArrayElement(value, index, options);
13596
+ if (node.id !== void 0) scope.declare(node.id.name, "const", constructor);
13597
+ for (const element of statics) await initializeElement(element, constructor, constructor, classContext, evaluateNode2);
13598
+ classOrigins.get(constructor).initialized = true;
13599
+ if (node.type === "ClassDeclaration") {
13600
+ context.scope.declare(node.id.name, "let", constructor);
13601
+ return { kind: "normal", hasValue: false, value: void 0 };
13542
13602
  }
13603
+ return { kind: "normal", hasValue: true, value: constructor };
13543
13604
  } finally {
13544
- options.budget.setRetainedValues(definedValues, void 0);
13605
+ release();
13545
13606
  }
13546
13607
  }
13547
- async function compareEntries(left, right, comparator, options, stack) {
13548
- options.budget.visitNode();
13549
- if (comparator === void 0) {
13550
- const leftString = await sandboxString(left, options.budget, options.context);
13551
- const release = retainValues(options.budget, () => [leftString]);
13552
- try {
13553
- const rightString = await sandboxString(right, options.budget, options.context);
13554
- return leftString < rightString ? -1 : leftString > rightString ? 1 : 0;
13555
- } finally {
13556
- release();
13608
+ var classOrigins = /* @__PURE__ */ new WeakMap();
13609
+ function createClassConstructor(node, context, evaluateNode2, fields2) {
13610
+ const scope = context.scope;
13611
+ const classContext = { ...context, inferredName: void 0 };
13612
+ const constructorElement = node.body.body.find((element) => element.type === "MethodDefinition" && element.kind === "constructor");
13613
+ const derived = node.superClass !== void 0;
13614
+ const constructor = createSandboxClosure({
13615
+ guest: true,
13616
+ sandbox: true,
13617
+ name: node.id?.name ?? context.inferredName ?? "",
13618
+ length: constructorElement === void 0 ? 0 : getFunctionLength(constructorElement.value.params),
13619
+ sourceRange: functionSources.get(node),
13620
+ retainedValues: () => [...scope.retainedValues(), ...fields2.map((field) => field.key)],
13621
+ call: () => {
13622
+ throw new TypeError("Class constructor cannot be invoked without 'new'.");
13623
+ },
13624
+ construct: async (args, invocation) => {
13625
+ const prototype = materializeFunctionProperties(constructor).prototype;
13626
+ const newTarget = invocation?.newTarget ?? constructor;
13627
+ let thisValue;
13628
+ let thisScope;
13629
+ let initialized = !derived;
13630
+ const initializeFields = async (receiver) => {
13631
+ for (const field of fields2) {
13632
+ await initializeElement(field, receiver, prototype, classContext, evaluateNode2);
13633
+ }
13634
+ };
13635
+ const superCall = async (argumentsList) => {
13636
+ const superConstructor = getSandboxPrototype(constructor, context.budget);
13637
+ if (!isSandboxClosure(superConstructor) || superConstructor.construct === void 0)
13638
+ throw new TypeError("Super constructor is not a constructor.");
13639
+ const receiver = await invocation.invokeClosure(superConstructor, argumentsList, void 0, true, newTarget);
13640
+ if (initialized) throw new ReferenceError("Super constructor may only initialize this once.");
13641
+ initialized = true;
13642
+ thisValue = receiver;
13643
+ thisScope?.declare("this", "const", receiver);
13644
+ await initializeFields(receiver);
13645
+ return receiver;
13646
+ };
13647
+ if (!derived) {
13648
+ thisValue = {};
13649
+ const targetPrototype = await invocation.getProperty(newTarget, "prototype");
13650
+ if (typeof targetPrototype === "object" && targetPrototype !== null)
13651
+ setSandboxPrototype(thisValue, targetPrototype, context.budget);
13652
+ }
13653
+ if (constructorElement === void 0) {
13654
+ if (derived) return superCall(args);
13655
+ await initializeFields(thisValue);
13656
+ return thisValue;
13657
+ }
13658
+ const result = await executeClosure(constructorElement.value, args, thisValue, {
13659
+ ...classContext,
13660
+ compilation: invocation?.compilation ?? context.compilation,
13661
+ callStack: [...invocation?.stack ?? context.callStack],
13662
+ functionEnvironment: {
13663
+ newTarget,
13664
+ homeObject: prototype,
13665
+ construction: {
13666
+ derived,
13667
+ superCall,
13668
+ initialize: async (functionScope) => {
13669
+ thisScope = functionScope;
13670
+ if (!derived) await initializeFields(thisValue);
13671
+ }
13672
+ }
13673
+ }
13674
+ }, evaluateNode2);
13675
+ if (typeof result === "object" && result !== null) return result;
13676
+ if (derived && result !== void 0) throw new TypeError("Derived constructors may only return an object or undefined.");
13677
+ if (!initialized) throw new ReferenceError("Must call super constructor before returning from derived constructor.");
13678
+ return thisValue;
13557
13679
  }
13558
- }
13559
- const result = await sandboxNumber(
13560
- await options.callClosure(comparator, [left, right], stack),
13561
- options.budget,
13562
- options.context
13563
- );
13564
- return Number.isNaN(result) ? 0 : result;
13565
- }
13566
- async function callArrayCallback(callback, value, index, array2, options, stack, thisValue) {
13567
- return options.callClosure(
13568
- callback,
13569
- [value, index, arrayLikeSources.get(array2) ?? array2],
13570
- stack,
13571
- thisValue
13572
- );
13680
+ });
13681
+ classOrigins.set(constructor, { node, scope, fields: fields2, initialized: false });
13682
+ return constructor;
13573
13683
  }
13574
- function findNextDefinedIndex(value, startIndex, direction, length, budget) {
13575
- for (let index = startIndex; direction > 0 ? index < length : index >= 0; index += direction) {
13576
- budget.visitNode();
13577
- if (index in value) {
13578
- return index;
13579
- }
13684
+ async function initializeElement(definition, receiver, homeObject, context, evaluateNode2) {
13685
+ const scope = context.scope.child({}, { functionBoundary: true });
13686
+ scope.declare("this", "const", receiver);
13687
+ const element = definition.element;
13688
+ const initializer = element.type === "StaticBlock" ? element.body : element.value;
13689
+ let value;
13690
+ if (initializer !== void 0) {
13691
+ if (element.type === "StaticBlock") hoistVarDeclarations(element.body, scope);
13692
+ const result = await evaluateNode2(initializer, { ...context, scope, functionEnvironment: { homeObject }, inferredName: "key" in definition ? propertyFunctionName(definition.key) : void 0 });
13693
+ if (result.kind === "error") throw result.error;
13694
+ if (result.kind === "throw") throw result.value;
13695
+ value = result.hasValue ? result.value : void 0;
13580
13696
  }
13581
- return -1;
13582
- }
13583
- function budgetProducedValue(value, budget) {
13584
- if (typeof value === "object" && value !== null) value = arrayLikeSources.get(value) ?? value;
13585
- allocateProducedValue(value, budget, /* @__PURE__ */ new WeakSet());
13586
- return value;
13587
- }
13588
- function allocateProducedValue(value, budget, seen) {
13589
- if (typeof value === "string") {
13590
- budget.allocateString(value);
13591
- return;
13697
+ if ("key" in definition) {
13698
+ defineDataProperty(receiver, definition.key, { value, configurable: true, writable: true, enumerable: true }, context.budget);
13592
13699
  }
13593
- if (Array.isArray(value)) {
13594
- budget.allocateArrayLength(value.length);
13595
- if (seen.has(value)) {
13596
- return;
13597
- }
13598
- seen.add(value);
13599
- for (const entry of value) {
13600
- allocateProducedValue(entry, budget, seen);
13601
- }
13602
- return;
13700
+ }
13701
+
13702
+ // packages/safe-js/src/interp/resume-target.ts
13703
+ function containsResumeTarget(node, targetNodeIds) {
13704
+ if (targetNodeIds === void 0 ? node.type === "YieldExpression" : node.nodeId !== void 0 && targetNodeIds.has(node.nodeId)) {
13705
+ return true;
13603
13706
  }
13604
- if (isSandboxMap(value)) {
13605
- budget.allocateCollectionEntries(value.entries.size);
13606
- if (seen.has(value)) {
13607
- return;
13608
- }
13609
- seen.add(value);
13610
- for (const [key, entry] of value.entries) {
13611
- allocateProducedValue(key, budget, seen);
13612
- allocateProducedValue(entry, budget, seen);
13613
- }
13614
- return;
13707
+ if (node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression") {
13708
+ return false;
13615
13709
  }
13616
- if (isSandboxSet(value)) {
13617
- budget.allocateCollectionEntries(value.values.size);
13618
- if (seen.has(value)) {
13619
- return;
13710
+ for (const value of Object.values(node)) {
13711
+ if (Array.isArray(value)) {
13712
+ if (value.some((entry) => isParseResult(entry) && containsResumeTarget(entry, targetNodeIds))) {
13713
+ return true;
13714
+ }
13715
+ continue;
13620
13716
  }
13621
- seen.add(value);
13622
- for (const entry of value.values) {
13623
- allocateProducedValue(entry, budget, seen);
13717
+ if (isParseResult(value) && containsResumeTarget(value, targetNodeIds)) {
13718
+ return true;
13624
13719
  }
13625
- return;
13626
- }
13627
- if (typeof value !== "object" || value === null || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value)) {
13628
- return;
13629
- }
13630
- if (seen.has(value)) {
13631
- return;
13632
- }
13633
- seen.add(value);
13634
- for (const entry of Object.values(value)) {
13635
- allocateProducedValue(entry, budget, seen);
13636
13720
  }
13721
+ return false;
13637
13722
  }
13638
- function toIntegerOrInfinity(value) {
13639
- const number = Number(value);
13640
- if (Number.isNaN(number) || Object.is(number, 0) || Object.is(number, -0)) {
13641
- return 0;
13642
- }
13643
- if (!Number.isFinite(number)) {
13644
- return number;
13645
- }
13646
- return Math.trunc(number);
13723
+ function isParseResult(value) {
13724
+ return typeof value === "object" && value !== null && typeof value.type === "string" && Object.hasOwn(value, "span");
13647
13725
  }
13648
13726
 
13649
13727
  // packages/safe-js/src/interp/function-string.ts
@@ -16732,7 +16810,7 @@ async function evaluateMemberCallExpression(node, context) {
16732
16810
  property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
16733
16811
  };
16734
16812
  if (context.generatorYield !== void 0 && node.arguments.some((argument) => containsResumeTarget(argument.type === "SpreadElement" ? argument.argument : argument))) {
16735
- if (Array.isArray(member.object) && !hasExplicitSandboxPrototype(member.object) && typeof member.property !== "symbol" && isArrayMethodName(member.property) && !Object.hasOwn(member.object, member.property))
16813
+ if (Array.isArray(member.object) && typeof member.property !== "symbol" && isArrayMethodName(member.property) && isDefaultArrayMethod(member.object, member.property, context.budget))
16736
16814
  return evaluateArrayMethodCall(node, member.object, member.property, context);
16737
16815
  const receiver = member.superReceiver?.value ?? member.object;
16738
16816
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context, receiver), context, receiver);
@@ -16745,6 +16823,8 @@ async function evaluateMemberCallExpression(node, context) {
16745
16823
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
16746
16824
  if (Array.isArray(member.object) && hasExplicitSandboxPrototype(member.object))
16747
16825
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
16826
+ if (Array.isArray(member.object) && isArrayMethodName(member.property) && !isDefaultArrayMethod(member.object, member.property, context.budget))
16827
+ return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
16748
16828
  if ((typeof member.object === "string" || typeof member.object === "number" || typeof member.object === "bigint" || typeof member.object === "boolean" || typeof member.object === "symbol") && getBoxedPrototype(member.object, context.budget) !== void 0) {
16749
16829
  if (isDefaultBoxedMethod(member.object, member.property, context.budget)) {
16750
16830
  if (typeof member.object === "string" && isStringMethodName(member.property))
@@ -16788,6 +16868,8 @@ async function evaluateMemberCallExpression(node, context) {
16788
16868
  );
16789
16869
  }
16790
16870
  if (Array.isArray(member.object) && !Object.hasOwn(member.object, member.property)) {
16871
+ if (getSandboxPropertyDescriptor(member.object, member.property, context.budget) !== void 0)
16872
+ return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
16791
16873
  return evaluatePrimitiveMemberCall(
16792
16874
  node,
16793
16875
  "Array",
@@ -17359,6 +17441,7 @@ function getArrayMemberValue(target, property, context) {
17359
17441
  if (property === "raw" && templateRawArrays.has(target)) {
17360
17442
  return templateRawArrays.get(target);
17361
17443
  }
17444
+ if (getSandboxPrototype(target, context.budget) !== null) return void 0;
17362
17445
  return getArrayMember(target, property, createArrayMethodOptions(context));
17363
17446
  }
17364
17447
  function setSandboxProperty(target, property, value, budget, checkInherited = true, context) {
@@ -18011,7 +18094,7 @@ async function objectToPrimitive(value, budget, context, joining, hint, ordinary
18011
18094
  }
18012
18095
  }
18013
18096
  function conversionHook(value, name, budget, context) {
18014
- const implicitBuiltin = !hasExplicitSandboxPrototype(value) && (Array.isArray(value) || isFloat32Array(value) || sandboxErrorTypes.has(value) || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxCollectionIterator(value) || isSandboxRegExpIterator(value) || isSandboxPromise(value) || isSandboxRegex(value) && getSandboxPrototype(value, budget) === null || isSandboxGenerator(value) || isGuestHostObject(value));
18097
+ const implicitBuiltin = !hasExplicitSandboxPrototype(value) && (Array.isArray(value) && getSandboxPrototype(value, budget) === null || isFloat32Array(value) || sandboxErrorTypes.has(value) || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxCollectionIterator(value) || isSandboxRegExpIterator(value) || isSandboxPromise(value) || isSandboxRegex(value) && getSandboxPrototype(value, budget) === null || isSandboxGenerator(value) || isGuestHostObject(value));
18015
18098
  let current = value;
18016
18099
  let depth = 0;
18017
18100
  while (current !== null) {
@@ -18129,6 +18212,20 @@ function createObjectGlobal(methods, budget) {
18129
18212
  Object.defineProperty(properties, name, { value: method, writable: true, configurable: true });
18130
18213
  }
18131
18214
  const prototypeMethods = {
18215
+ toLocaleString: createSandboxClosure({
18216
+ guest: true,
18217
+ sandbox: true,
18218
+ name: "toLocaleString",
18219
+ length: 0,
18220
+ call: async (_args, context) => {
18221
+ const receiver = requireReceiver(context?.thisValue);
18222
+ const object = construct([receiver]);
18223
+ const descriptor = getSandboxPropertyDescriptor(object, "toString", budget);
18224
+ const method = context?.getProperty === void 0 ? descriptor === void 0 ? void 0 : await readPropertyDescriptor(descriptor, receiver, context) : await context.getProperty(receiver, "toString");
18225
+ if (!isSandboxClosure(method)) throw new TypeError("toString must be callable.");
18226
+ return invokeBuiltinClosure(method, [], budget, context, receiver);
18227
+ }
18228
+ }),
18132
18229
  toString: createSandboxClosure({
18133
18230
  sandbox: true,
18134
18231
  name: "toString",
@@ -40630,4 +40727,4 @@ export {
40630
40727
  FileSnapshotBackend,
40631
40728
  run
40632
40729
  };
40633
- //# sourceMappingURL=chunk-4MMZLA7N.js.map
40730
+ //# sourceMappingURL=chunk-SZZFUQKW.js.map