@poe-platform/safe-js 0.1.291 → 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)))
@@ -10446,62 +10460,6 @@ function createNumericParsers(budget) {
10446
10460
  };
10447
10461
  }
10448
10462
 
10449
- // packages/safe-js/src/interp/methods/number.ts
10450
- var numberMethodNames = /* @__PURE__ */ new Set([
10451
- "toExponential",
10452
- "toFixed",
10453
- "toPrecision",
10454
- "toString"
10455
- ]);
10456
- function getNumberMember(property, budget) {
10457
- if (!isNumberMethodName(property)) {
10458
- return void 0;
10459
- }
10460
- return createSandboxClosure({
10461
- sandbox: true,
10462
- name: `Number#${property}`,
10463
- call: (args, context) => callNumberMethod(context?.thisValue, property, args, budget, context)
10464
- });
10465
- }
10466
- function isNumberMethodName(property) {
10467
- return typeof property === "string" && numberMethodNames.has(property);
10468
- }
10469
- function callNumberMethod(value, methodName, args, budget, context) {
10470
- if (isSandboxBox(value)) value = boxedValue(value);
10471
- if (typeof value !== "number") {
10472
- throw new TypeError(`Number#${methodName} requires a number receiver.`);
10473
- }
10474
- const argument = args[0];
10475
- if (argument !== null && typeof argument === "object") {
10476
- return formatObjectArgument(value, methodName, argument, budget, context);
10477
- }
10478
- return formatNumber(value, methodName, argument === void 0 ? void 0 : +argument, budget);
10479
- }
10480
- async function formatObjectArgument(value, methodName, argument, budget, context) {
10481
- const retainedArgument = {};
10482
- budget.setRetainedValues(retainedArgument, () => [argument]);
10483
- try {
10484
- const number = await sandboxNumber(argument, budget, context);
10485
- return formatNumber(value, methodName, number, budget);
10486
- } finally {
10487
- budget.setRetainedValues(retainedArgument, void 0);
10488
- }
10489
- }
10490
- function formatNumber(value, methodName, argument, budget) {
10491
- let result;
10492
- try {
10493
- result = value[methodName](argument);
10494
- } catch (error) {
10495
- if (!(error instanceof RangeError)) throw error;
10496
- const detail = methodName === "toString" ? "radix must be between 2 and 36." : methodName === "toPrecision" ? "precision must be between 1 and 100." : "digits must be between 0 and 100.";
10497
- throw new RangeError(`Number#${methodName} ${detail}`);
10498
- }
10499
- return budget.allocateString(result);
10500
- }
10501
-
10502
- // packages/safe-js/src/interp/methods/string.ts
10503
- import { types as types5 } from "node:util";
10504
-
10505
10463
  // packages/safe-js/src/interp/intl-options.ts
10506
10464
  var canonicalLocales = Intl.getCanonicalLocales;
10507
10465
  function readIntlProperty(value, key, budget, context) {
@@ -10557,6 +10515,162 @@ async function convertIntlOption(value, key, type, budget, context, invalid) {
10557
10515
  throw new RangeError(`Invalid ${key} option.`);
10558
10516
  }
10559
10517
 
10518
+ // packages/safe-js/src/interp/number-locale.ts
10519
+ var NativeNumberFormat = Intl.NumberFormat;
10520
+ var roundingIncrements = [1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1e3, 2e3, 2500, 5e3];
10521
+ async function formatNumberLocale(value, args, budget, context) {
10522
+ let locales = [];
10523
+ const options = /* @__PURE__ */ Object.create(null);
10524
+ const digits = /* @__PURE__ */ Object.create(null);
10525
+ const release = retainValues(budget, () => [value, locales, options, digits]);
10526
+ const allocation = {};
10527
+ try {
10528
+ locales = await canonicalizeGuestLocales(args[0], budget, context);
10529
+ const input = intlOptionsObject(args[1], budget);
10530
+ const readString = async (key, type) => {
10531
+ const raw = await readIntlProperty(input, key, budget, context);
10532
+ if (raw === void 0) return void 0;
10533
+ const text = type === void 0 ? await sandboxString(raw, budget, context) : await convertIntlOption(raw, key, type, budget, context);
10534
+ if (type === void 0) budget.visitNode(text.length);
10535
+ options[key] = text;
10536
+ return text;
10537
+ };
10538
+ const numberOption = async (raw, key, minimum, maximum, fallback) => {
10539
+ if (raw === void 0) return fallback;
10540
+ const number = await sandboxNumber(raw, budget, context);
10541
+ if (!Number.isFinite(number) || number < minimum || number > maximum)
10542
+ throw new RangeError(`Invalid ${key} option.`);
10543
+ return Math.floor(number);
10544
+ };
10545
+ await readString("localeMatcher", ["lookup", "best fit"]);
10546
+ await readString("numberingSystem", "unicodeType");
10547
+ const style = await readString("style", ["decimal", "percent", "currency", "unit"]) ?? "decimal";
10548
+ const currency = await readString("currency");
10549
+ if (currency === void 0) {
10550
+ if (style === "currency") throw new TypeError("Currency formatting requires a currency.");
10551
+ } else if (currency.length !== 3 || ![...currency].every((char) => char >= "A" && char <= "Z" || char >= "a" && char <= "z"))
10552
+ throw new RangeError("Invalid currency code.");
10553
+ await readString("currencyDisplay", ["code", "symbol", "narrowSymbol", "name"]);
10554
+ await readString("currencySign", ["standard", "accounting"]);
10555
+ const unit = await readString("unit");
10556
+ if (unit === void 0) {
10557
+ if (style === "unit") throw new TypeError("Unit formatting requires a unit.");
10558
+ } else new NativeNumberFormat("en", { style: "unit", unit });
10559
+ await readString("unitDisplay", ["short", "narrow", "long"]);
10560
+ const notation = await readString("notation", ["standard", "scientific", "engineering", "compact"]) ?? "standard";
10561
+ let minimumDefault = 0;
10562
+ let maximumDefault = style === "percent" ? 0 : 3;
10563
+ if (style === "currency" && notation === "standard") {
10564
+ const currencyDefaults = new NativeNumberFormat("en", { style: "currency", currency }).resolvedOptions();
10565
+ minimumDefault = currencyDefaults.minimumFractionDigits;
10566
+ maximumDefault = currencyDefaults.maximumFractionDigits;
10567
+ }
10568
+ options.minimumIntegerDigits = await numberOption(await readIntlProperty(input, "minimumIntegerDigits", budget, context), "minimumIntegerDigits", 1, 21, 1);
10569
+ for (const key of ["minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits"])
10570
+ digits[key] = await readIntlProperty(input, key, budget, context);
10571
+ const increment = await numberOption(await readIntlProperty(input, "roundingIncrement", budget, context), "roundingIncrement", 1, 5e3, 1);
10572
+ if (!roundingIncrements.includes(increment)) throw new RangeError("Invalid roundingIncrement option.");
10573
+ options.roundingIncrement = increment;
10574
+ await readString("roundingMode", ["ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven"]);
10575
+ const priority = await readString("roundingPriority", ["auto", "morePrecision", "lessPrecision"]) ?? "auto";
10576
+ await readString("trailingZeroDisplay", ["auto", "stripIfInteger"]);
10577
+ if (increment !== 1) maximumDefault = minimumDefault;
10578
+ const hasSignificant = digits.minimumSignificantDigits !== void 0 || digits.maximumSignificantDigits !== void 0;
10579
+ const hasFraction = digits.minimumFractionDigits !== void 0 || digits.maximumFractionDigits !== void 0;
10580
+ const needSignificant = priority !== "auto" || hasSignificant;
10581
+ const needFraction = priority !== "auto" || !(hasSignificant || !hasFraction && notation === "compact");
10582
+ if (needSignificant) {
10583
+ const minimum = await numberOption(digits.minimumSignificantDigits, "minimumSignificantDigits", 1, 21, 1);
10584
+ options.minimumSignificantDigits = minimum;
10585
+ options.maximumSignificantDigits = await numberOption(digits.maximumSignificantDigits, "maximumSignificantDigits", minimum, 21, 21);
10586
+ }
10587
+ if (needFraction) {
10588
+ let minimum = await numberOption(digits.minimumFractionDigits, "minimumFractionDigits", 0, 100);
10589
+ let maximum = await numberOption(digits.maximumFractionDigits, "maximumFractionDigits", 0, 100);
10590
+ if (minimum === void 0 && maximum === void 0) {
10591
+ minimum = minimumDefault;
10592
+ maximum = maximumDefault;
10593
+ } else if (minimum === void 0) minimum = Math.min(minimumDefault, maximum);
10594
+ else if (maximum === void 0) maximum = Math.max(maximumDefault, minimum);
10595
+ if (minimum > maximum) throw new RangeError("minimumFractionDigits exceeds maximumFractionDigits.");
10596
+ options.minimumFractionDigits = minimum;
10597
+ options.maximumFractionDigits = maximum;
10598
+ }
10599
+ new NativeNumberFormat(locales, options);
10600
+ await readString("compactDisplay", ["short", "long"]);
10601
+ const grouping = await readIntlProperty(input, "useGrouping", budget, context);
10602
+ if (grouping !== void 0) options.useGrouping = grouping === true ? true : !grouping ? false : await convertIntlOption(grouping, "useGrouping", ["min2", "auto", "always", "true", "false"], budget, context);
10603
+ await readString("signDisplay", ["auto", "never", "always", "exceptZero", "negative"]);
10604
+ const size = typeof value === "bigint" ? value.toString(16).length * 4 : 64;
10605
+ budget.visitNode(size);
10606
+ budget.setRetainedDataUsage(allocation, size);
10607
+ const formatter = new NativeNumberFormat(locales, options);
10608
+ return budget.allocateString(formatter.format(value));
10609
+ } finally {
10610
+ budget.setRetainedDataUsage(allocation, 0);
10611
+ release();
10612
+ }
10613
+ }
10614
+
10615
+ // packages/safe-js/src/interp/methods/number.ts
10616
+ var numberMethodNames = /* @__PURE__ */ new Set([
10617
+ "toExponential",
10618
+ "toFixed",
10619
+ "toPrecision",
10620
+ "toString",
10621
+ "toLocaleString"
10622
+ ]);
10623
+ function getNumberMember(property, budget) {
10624
+ if (!isNumberMethodName(property)) {
10625
+ return void 0;
10626
+ }
10627
+ return createSandboxClosure({
10628
+ sandbox: true,
10629
+ name: `Number#${property}`,
10630
+ ...property === "toLocaleString" ? { guest: true, name: property, length: 0 } : {},
10631
+ call: (args, context) => callNumberMethod(context?.thisValue, property, args, budget, context)
10632
+ });
10633
+ }
10634
+ function isNumberMethodName(property) {
10635
+ return typeof property === "string" && numberMethodNames.has(property);
10636
+ }
10637
+ function callNumberMethod(value, methodName, args, budget, context) {
10638
+ if (isSandboxBox(value)) value = boxedValue(value);
10639
+ if (typeof value !== "number") {
10640
+ throw new TypeError(`Number#${methodName} requires a number receiver.`);
10641
+ }
10642
+ if (methodName === "toLocaleString") return formatNumberLocale(value, args, budget, context);
10643
+ const argument = args[0];
10644
+ if (argument !== null && typeof argument === "object") {
10645
+ return formatObjectArgument(value, methodName, argument, budget, context);
10646
+ }
10647
+ return formatNumber(value, methodName, argument === void 0 ? void 0 : +argument, budget);
10648
+ }
10649
+ async function formatObjectArgument(value, methodName, argument, budget, context) {
10650
+ const retainedArgument = {};
10651
+ budget.setRetainedValues(retainedArgument, () => [argument]);
10652
+ try {
10653
+ const number = await sandboxNumber(argument, budget, context);
10654
+ return formatNumber(value, methodName, number, budget);
10655
+ } finally {
10656
+ budget.setRetainedValues(retainedArgument, void 0);
10657
+ }
10658
+ }
10659
+ function formatNumber(value, methodName, argument, budget) {
10660
+ let result;
10661
+ try {
10662
+ result = value[methodName](argument);
10663
+ } catch (error) {
10664
+ if (!(error instanceof RangeError)) throw error;
10665
+ const detail = methodName === "toString" ? "radix must be between 2 and 36." : methodName === "toPrecision" ? "precision must be between 1 and 100." : "digits must be between 0 and 100.";
10666
+ throw new RangeError(`Number#${methodName} ${detail}`);
10667
+ }
10668
+ return budget.allocateString(result);
10669
+ }
10670
+
10671
+ // packages/safe-js/src/interp/methods/string.ts
10672
+ import { types as types5 } from "node:util";
10673
+
10560
10674
  // packages/safe-js/src/interp/methods/string-locale.ts
10561
10675
  var collatorOptions = [
10562
10676
  ["usage", ["sort", "search"]],
@@ -11490,2060 +11604,2124 @@ function createPrimitiveConstructor(options, budget) {
11490
11604
  return constructor;
11491
11605
  }
11492
11606
 
11493
- // packages/safe-js/src/interp/globals/object-array.ts
11494
- function createObjectArrayGlobals(options) {
11495
- return {
11496
- Object: createObjectGlobal(
11497
- {
11498
- keys: createSandboxClosure({
11499
- sandbox: true,
11500
- call: ([value]) => budgetSandboxValue(ownEnumerableSandboxKeys(value), options.budget),
11501
- name: "keys"
11502
- }),
11503
- values: createSandboxClosure({
11504
- sandbox: true,
11505
- call: ([value], context) => context === void 0 ? allocateProducedSandboxValue(
11506
- ownEnumerableSandboxEntries(value).map(([, entry]) => entry),
11507
- options.budget
11508
- ) : getOwnEnumerableEntries(value, options.budget, context).then(
11509
- (entries) => allocateProducedSandboxValue(
11510
- entries.map(([, entry]) => entry),
11511
- options.budget
11512
- )
11513
- ),
11514
- name: "values"
11515
- }),
11516
- entries: createSandboxClosure({
11517
- sandbox: true,
11518
- call: ([value], context) => context === void 0 ? allocateProducedSandboxValue(ownEnumerableSandboxEntries(value), options.budget) : getOwnEnumerableEntries(value, options.budget, context).then(
11519
- (entries) => allocateProducedSandboxValue(entries, options.budget)
11520
- ),
11521
- name: "entries"
11522
- }),
11523
- hasOwn: createSandboxClosure({
11524
- sandbox: true,
11525
- call: ([value, key], context) => {
11526
- if (value === null || value === void 0)
11527
- throw new TypeError("Cannot convert undefined or null to object.");
11528
- const name = toPropertyKey(key, options.budget, context);
11529
- return typeof name === "string" || typeof name === "symbol" ? hasOwnSandboxProperty(value, name, false) : name.then((property) => hasOwnSandboxProperty(value, property, false));
11530
- },
11531
- name: "hasOwn"
11532
- }),
11533
- getOwnPropertyDescriptor: createSandboxClosure({
11534
- sandbox: true,
11535
- call: async ([value, key], context) => {
11536
- const descriptor = Object.getOwnPropertyDescriptor(
11537
- reflectionProperties(value),
11538
- await toPropertyKey(key, options.budget, context)
11539
- );
11540
- if (descriptor === void 0) return void 0;
11541
- return allocateProducedSandboxValue(
11542
- exposePropertyDescriptor(descriptor),
11543
- options.budget
11544
- );
11545
- },
11546
- name: "getOwnPropertyDescriptor"
11547
- }),
11548
- getOwnPropertyDescriptors: createSandboxClosure({
11549
- sandbox: true,
11550
- call: ([value]) => {
11551
- const descriptors2 = /* @__PURE__ */ Object.create(null);
11552
- const properties = reflectionProperties(value);
11553
- for (const key of [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(value)])
11554
- defineOwnDataProperty(descriptors2, key, exposePropertyDescriptor(Object.getOwnPropertyDescriptor(properties, key)));
11555
- return allocateProducedSandboxValue(descriptors2, options.budget);
11556
- },
11557
- name: "getOwnPropertyDescriptors"
11558
- }),
11559
- getOwnPropertyNames: createSandboxClosure({
11560
- sandbox: true,
11561
- call: ([value]) => budgetSandboxValue(Object.getOwnPropertyNames(reflectionProperties(value)), options.budget),
11562
- name: "getOwnPropertyNames"
11563
- }),
11564
- getOwnPropertySymbols: createSandboxClosure({
11565
- sandbox: true,
11566
- call: ([value]) => allocateProducedSandboxValue(ownSandboxSymbolKeys(value), options.budget),
11567
- name: "getOwnPropertySymbols"
11568
- }),
11569
- defineProperty: createSandboxClosure({
11570
- sandbox: true,
11571
- call: async ([value, key, descriptor], context) => {
11572
- objectProperties(value, true);
11573
- const property = await toPropertyKey(key, options.budget, context);
11574
- defineDataProperty(
11575
- value,
11576
- property,
11577
- await propertyDescriptor(descriptor, options.budget, context),
11578
- options.budget
11579
- );
11580
- return value;
11581
- },
11582
- name: "defineProperty"
11583
- }),
11584
- defineProperties: createSandboxClosure({
11585
- sandbox: true,
11586
- call: async ([value, descriptors2], context) => {
11587
- await definePropertiesFromObject(value, descriptors2, options.budget, context);
11588
- return value;
11589
- },
11590
- name: "defineProperties"
11591
- }),
11592
- getPrototypeOf: createSandboxClosure({
11593
- sandbox: true,
11594
- call: ([value]) => {
11595
- if (isSandboxMap(value) || isSandboxSet(value))
11596
- return getSandboxPrototype(value, options.budget);
11597
- if (value !== null && value !== void 0 && typeof value !== "object")
11598
- value = createSandboxBox(value);
11599
- objectProperties(value);
11600
- return getSandboxPrototype(value, options.budget);
11601
- },
11602
- name: "getPrototypeOf"
11603
- }),
11604
- setPrototypeOf: createSandboxClosure({
11605
- sandbox: true,
11606
- call: ([value, prototype]) => {
11607
- if (value === null || value === void 0)
11608
- throw new TypeError("Cannot set the prototype of null or undefined.");
11609
- if (prototype !== null && typeof prototype !== "object")
11610
- throw new TypeError("Prototype must be an object or null.");
11611
- if (typeof value !== "object") return value;
11612
- objectProperties(value, true);
11613
- if (prototype !== null) objectProperties(prototype);
11614
- setSandboxPrototype(value, prototype, options.budget);
11615
- return value;
11616
- },
11617
- name: "setPrototypeOf"
11618
- }),
11619
- create: createSandboxClosure({
11620
- sandbox: true,
11621
- call: async ([prototype, descriptors2], context) => {
11622
- if (prototype !== null) objectProperties(prototype);
11623
- const value = /* @__PURE__ */ Object.create(null);
11624
- setSandboxPrototype(value, prototype, options.budget);
11625
- if (descriptors2 !== void 0) {
11626
- await definePropertiesFromObject(value, descriptors2, options.budget, context);
11627
- }
11628
- return allocateProducedSandboxValue(value, options.budget);
11629
- },
11630
- name: "create"
11631
- }),
11632
- is: createSandboxClosure({
11633
- sandbox: true,
11634
- call: ([left, right]) => Reflect.apply(Object.is, Object, [left, right]),
11635
- name: "is"
11636
- }),
11637
- fromEntries: createSandboxClosure({
11638
- sandbox: true,
11639
- call: ([value], context) => {
11640
- if (context !== void 0) return acquireSandboxIterator(value, options.budget, context).then((iterator2) => {
11641
- if (iterator2 === void 0) throw new TypeError("Object.fromEntries requires an iterable.");
11642
- return objectFromSandboxEntries(value, iterator2, options.budget, context);
11643
- });
11644
- const iterator = getSandboxIterator(value, options.budget, context);
11645
- if (iterator === void 0) {
11646
- throw new TypeError("Object.fromEntries requires an iterable.");
11647
- }
11648
- if (context === void 0 && !iterator.generator && !iterator.asynchronous) {
11649
- return allocateProducedSandboxValue(
11650
- Object.setPrototypeOf(
11651
- Reflect.apply(Object.fromEntries, Object, [
11652
- { [Symbol.iterator]: () => iterator }
11653
- ]),
11654
- null
11655
- ),
11656
- options.budget
11657
- );
11658
- }
11659
- return objectFromSandboxEntries(value, iterator, options.budget, context);
11660
- },
11661
- name: "fromEntries"
11662
- }),
11663
- preventExtensions: createSandboxClosure({
11664
- sandbox: true,
11665
- call: ([value]) => {
11666
- if (isGuestHostObject(value))
11667
- throw new TypeError("Live host objects cannot be made non-extensible.");
11668
- Object.preventExtensions(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
11669
- return value;
11670
- },
11671
- name: "preventExtensions"
11672
- }),
11673
- isExtensible: createSandboxClosure({
11674
- sandbox: true,
11675
- call: ([value]) => Object.isExtensible(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
11676
- name: "isExtensible"
11677
- }),
11678
- seal: createSandboxClosure({
11679
- sandbox: true,
11680
- call: ([value]) => {
11681
- if (isGuestHostObject(value))
11682
- throw new TypeError("Live host objects cannot be sealed.");
11683
- Object.seal(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
11684
- return value;
11685
- },
11686
- name: "seal"
11687
- }),
11688
- isSealed: createSandboxClosure({
11689
- sandbox: true,
11690
- call: ([value]) => Object.isSealed(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
11691
- name: "isSealed"
11692
- }),
11693
- freeze: createSandboxClosure({
11694
- sandbox: true,
11695
- call: ([value]) => {
11696
- if (isGuestHostObject(value))
11697
- throw new TypeError("Live host objects cannot be frozen.");
11698
- if (typeof value === "object" && value !== null) {
11699
- Object.freeze(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
11700
- }
11701
- return value;
11702
- },
11703
- name: "freeze"
11704
- }),
11705
- isFrozen: createSandboxClosure({
11706
- sandbox: true,
11707
- call: ([value]) => Object.isFrozen(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
11708
- name: "isFrozen"
11709
- }),
11710
- assign: createSandboxClosure({
11711
- sandbox: true,
11712
- call: ([target, ...sources], context) => assignSandboxValues(target, sources, options.budget, context),
11713
- name: "assign"
11714
- })
11715
- },
11716
- options.budget
11717
- ),
11718
- 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({
11719
11660
  sandbox: true,
11720
- call: (args) => createArrayFromConstructorArgs(args, options.budget),
11721
- construct: (args) => createArrayFromConstructorArgs(args, options.budget),
11722
- name: "Array",
11723
- properties: {
11724
- isArray: createSandboxClosure({
11725
- sandbox: true,
11726
- call: ([value]) => Array.isArray(value),
11727
- name: "isArray"
11728
- }),
11729
- from: createSandboxClosure({
11730
- sandbox: true,
11731
- call: (args, context) => arrayFromSandboxValues(args, options.budget, context),
11732
- name: "from"
11733
- }),
11734
- of: createSandboxClosure({
11735
- sandbox: true,
11736
- call: (args) => budgetSandboxValue(Reflect.apply(Array.of, Array, [...args]), options.budget),
11737
- name: "of"
11738
- })
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);
11739
11702
  }
11740
- }),
11741
- String: createPrimitiveConstructor(
11742
- {
11743
- call: (args, context) => typeof args[0] === "symbol" ? options.budget.allocateString(String(args[0])) : sandboxString(args.length === 0 ? "" : args[0], options.budget, context),
11744
- name: "String",
11745
- properties: {
11746
- raw: createSandboxClosure({
11747
- sandbox: true,
11748
- call: (args, context) => stringRaw(args, options.budget, context),
11749
- name: "raw"
11750
- }),
11751
- fromCharCode: createSandboxClosure({
11752
- sandbox: true,
11753
- call: (args, context) => stringFromCodes(args, String.fromCharCode, options.budget, context),
11754
- name: "fromCharCode"
11755
- }),
11756
- fromCodePoint: createSandboxClosure({
11757
- sandbox: true,
11758
- call: (args, context) => stringFromCodes(args, String.fromCodePoint, options.budget, context),
11759
- name: "fromCodePoint"
11760
- })
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();
11761
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);
11762
11733
  },
11763
- options.budget
11764
- ),
11765
- Number: createPrimitiveConstructor(
11766
- {
11767
- call: (args, context) => sandboxNumber(args.length === 0 ? 0 : args[0], options.budget, context, true),
11768
- name: "Number",
11769
- properties: {
11770
- isFinite: createSandboxClosure({
11771
- guest: true,
11772
- sandbox: true,
11773
- call: ([value]) => typeof value === "number" && Number.isFinite(value),
11774
- name: "isFinite"
11775
- }),
11776
- isNaN: createSandboxClosure({
11777
- guest: true,
11778
- sandbox: true,
11779
- call: ([value]) => typeof value === "number" && Number.isNaN(value),
11780
- name: "isNaN"
11781
- }),
11782
- isInteger: createSandboxClosure({
11783
- guest: true,
11784
- sandbox: true,
11785
- call: ([value]) => typeof value === "number" && Number.isInteger(value),
11786
- name: "isInteger"
11787
- }),
11788
- ...createNumericParsers(options.budget),
11789
- isSafeInteger: createSandboxClosure({
11790
- guest: true,
11791
- sandbox: true,
11792
- call: ([value]) => typeof value === "number" && Number.isSafeInteger(value),
11793
- name: "isSafeInteger"
11794
- }),
11795
- MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER,
11796
- MIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER,
11797
- EPSILON: Number.EPSILON,
11798
- MAX_VALUE: Number.MAX_VALUE,
11799
- MIN_VALUE: Number.MIN_VALUE,
11800
- NaN: Number.NaN,
11801
- NEGATIVE_INFINITY: Number.NEGATIVE_INFINITY,
11802
- 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;
11803
11741
  }
11742
+ return false;
11804
11743
  },
11805
- options.budget
11806
- ),
11807
- Boolean: createPrimitiveConstructor(
11808
- {
11809
- call: ([value]) => Boolean(value),
11810
- 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;
11811
11751
  },
11812
- options.budget
11813
- )
11814
- };
11815
- }
11816
- async function objectFromSandboxEntries(items, iterator, budget, context) {
11817
- const object = /* @__PURE__ */ Object.create(null);
11818
- let entry;
11819
- let key;
11820
- let value;
11821
- let failure;
11822
- const retained = {};
11823
- budget.setRetainedValues(retained, () => [
11824
- items,
11825
- iterator.retainedValue,
11826
- object,
11827
- entry,
11828
- key,
11829
- value,
11830
- failure
11831
- ]);
11832
- const checkData = createDataCheckpoint(budget, context);
11833
- const closeOnThrow = async (error) => {
11834
- failure = isCapturedException(error) ? error.reason : error;
11835
- try {
11836
- await closeIterator(iterator, true);
11837
- } catch (closeError) {
11838
- if (!isFatalSandboxError(error) && isFatalSandboxError(closeError)) throw closeError;
11839
- }
11840
- throw error;
11841
- };
11842
- try {
11843
- checkData(object, 0, true);
11844
- while (true) {
11845
- try {
11846
- budget.visitNode();
11847
- } catch (error) {
11848
- await closeOnThrow(error);
11849
- }
11850
- const result = await iterator.next();
11851
- if (typeof result !== "object" || result === null) {
11852
- throw new TypeError("Iterator result must be an object.");
11853
- }
11854
- if ((await readIteratorResult(iterator, result, "done")).value) break;
11855
- entry = (await readIteratorResult(iterator, result, "value")).value;
11856
- try {
11857
- if (typeof entry !== "object" || entry === null) {
11858
- throw new TypeError("Object.fromEntries requires entry objects.");
11859
- }
11860
- key = context?.getProperty !== void 0 ? await context.getProperty(entry, 0) : getSandboxDataProperty(entry, 0, budget);
11861
- value = context?.getProperty !== void 0 ? await context.getProperty(entry, 1) : getSandboxDataProperty(entry, 1, budget);
11862
- const property = await toPropertyKey(key, budget, context);
11863
- const growth = (typeof property === "symbol" ? property.description?.length ?? 0 : property.length) + 1 + (budget.limits.dataSize === void 0 ? 0 : measureSandboxData([value]));
11864
- budget.visitNode();
11865
- defineOwnDataProperty(object, property, value);
11866
- entry = key = value = void 0;
11867
- checkData(object, growth);
11868
- } catch (error) {
11869
- await closeOnThrow(error);
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);
11870
11757
  }
11871
11758
  }
11872
- checkData(object, 0, true);
11873
- return allocateProducedSandboxValue(object, budget);
11874
- } finally {
11875
- budget.setRetainedValues(retained, void 0);
11876
- }
11759
+ );
11760
+ arrayLikeSources.set(view, receiver);
11761
+ return view;
11877
11762
  }
11878
- function assignSandboxValues(target, sources, budget, context) {
11879
- if (target === null || target === void 0) {
11880
- throw new TypeError("Object.assign(target, ...sources) requires a non-null target.");
11881
- }
11882
- if (typeof target !== "object") {
11883
- target = createSandboxBox(target);
11884
- budget.chargeDataUsage(measureSandboxData([target]));
11885
- }
11886
- if (!isGuestHostObject(target)) objectProperties(target, true);
11887
- if (context === void 0) {
11888
- for (const source of sources) {
11889
- if (source === null || source === void 0) continue;
11890
- const properties = isGuestHostObject(source) ? void 0 : reflectionProperties(source);
11891
- const keys = properties === void 0 ? ownEnumerableSandboxKeys(source, true) : [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(source)];
11892
- for (const key of keys) {
11893
- if (!hasOwnSandboxProperty(source, key, true)) continue;
11894
- const value = properties === void 0 ? getSandboxDataProperty(source, key, budget) : Reflect.get(properties, key, source);
11895
- setSandboxProperty(target, key, value, budget);
11896
- }
11897
- }
11898
- return target;
11899
- }
11900
- return (async () => {
11901
- const release = retainValues(budget, () => [target, ...sources]);
11902
- try {
11903
- for (const source of sources) {
11904
- if (source === null || source === void 0) continue;
11905
- const properties = isGuestHostObject(source) ? void 0 : reflectionProperties(source);
11906
- const keys = properties === void 0 ? ownEnumerableSandboxKeys(source, true) : [...Object.getOwnPropertyNames(properties), ...ownSandboxSymbolKeys(source)];
11907
- for (const key of keys) {
11908
- if (!hasOwnSandboxProperty(source, key, true)) continue;
11909
- 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));
11910
- await setSandboxProperty(target, key, value, budget, true, context);
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]);
11772
+ try {
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);
11911
11784
  }
11785
+ return text;
11786
+ } finally {
11787
+ release();
11788
+ localeArrays.delete(receiver);
11912
11789
  }
11913
- return target;
11914
- } finally {
11915
- release();
11916
- }
11917
- })();
11918
- }
11919
- function reflectionProperties(value) {
11920
- if (value !== null && value !== void 0 && typeof value !== "object")
11921
- value = createSandboxBox(value);
11922
- return objectProperties(value);
11923
- }
11924
- function objectProperties(value, mutable = false) {
11925
- if (isSandboxPromise(value)) return getPromiseProperties(value);
11926
- if (isSandboxMap(value) || isSandboxSet(value)) return getCollectionProperties(value);
11927
- if (isSandboxRegex(value)) return getRegexProperties(value);
11928
- if (isSandboxDate(value)) {
11929
- return value;
11930
- }
11931
- if (isGuestHostObject(value))
11932
- throw new TypeError("Live host object descriptors are not supported.");
11933
- if (isGuestClosure(value)) return materializeFunctionProperties(value);
11934
- if (isSandboxClosure(value)) {
11935
- if (mutable) throw new TypeError("Host function properties are read only.");
11936
- return value.properties ?? /* @__PURE__ */ Object.create(null);
11937
- }
11938
- if (!isAssignableSandboxTarget(value))
11939
- throw new TypeError("Expected a sandbox object or function.");
11940
- return value;
11941
- }
11942
- function exposePropertyDescriptor(descriptor) {
11943
- return "value" in descriptor ? descriptor : {
11944
- get: accessorClosure(descriptor.get),
11945
- set: accessorClosure(descriptor.set),
11946
- enumerable: descriptor.enumerable,
11947
- configurable: descriptor.configurable
11948
- };
11949
- }
11950
- async function propertyDescriptor(input, budget, context) {
11951
- objectProperties(input);
11952
- const descriptor = {};
11953
- const release = retainValues(budget, () => [
11954
- input,
11955
- descriptor.value,
11956
- ...retainedAccessorClosures(descriptor)
11957
- ]);
11958
- try {
11959
- for (const field of [
11960
- "enumerable",
11961
- "configurable",
11962
- "value",
11963
- "writable",
11964
- "get",
11965
- "set"
11966
- ]) {
11967
- if (getSandboxPropertyDescriptor(input, field, budget) === void 0 && !hasOwnSandboxProperty(input, field, false))
11968
- continue;
11969
- const value = await (context?.getProperty !== void 0 ? context.getProperty(input, field) : getSandboxDataProperty(input, field, budget));
11970
- if (field === "get" || field === "set") {
11971
- if (value !== void 0 && !isSandboxClosure(value))
11972
- throw new TypeError("Accessor must be a function or undefined.");
11973
- descriptor[field] = value === void 0 ? void 0 : accessorAdapter(value, field);
11974
- } else if (field === "value") {
11975
- descriptor.value = value;
11976
- } else {
11977
- descriptor[field] = Boolean(value);
11978
- }
11979
- }
11980
- if (("get" in descriptor || "set" in descriptor) && ("value" in descriptor || "writable" in descriptor))
11981
- throw new TypeError("A property cannot be both a data property and an accessor.");
11982
- return descriptor;
11983
- } finally {
11984
- release();
11985
- }
11986
- }
11987
- async function definePropertiesFromObject(target, descriptors2, budget, context) {
11988
- objectProperties(target, true);
11989
- const properties = [];
11990
- const release = retainValues(budget, () => [
11991
- target,
11992
- descriptors2,
11993
- properties,
11994
- ...properties.flatMap(([, descriptor]) => retainedAccessorClosures(descriptor))
11995
- ]);
11996
- try {
11997
- for (const key of ownEnumerableSandboxKeys(descriptors2, true)) {
11998
- if (!hasOwnSandboxProperty(descriptors2, key, true)) continue;
11999
- const descriptor = await (context?.getProperty !== void 0 ? context.getProperty(descriptors2, key) : getSandboxDataProperty(descriptors2, key, budget));
12000
- properties.push([key, await propertyDescriptor(descriptor, budget, context)]);
12001
11790
  }
12002
- for (const [key, descriptor] of properties) defineDataProperty(target, key, descriptor, budget);
12003
- } finally {
12004
- release();
12005
- }
12006
- }
12007
- function defineDataProperty(target, key, descriptor, budget) {
12008
- budget.visitNode();
12009
- if (isFloat32Array(target))
12010
- throw new TypeError("Typed array property descriptors are not supported.");
12011
- const properties = objectProperties(target, true);
12012
- if (Array.isArray(properties)) {
12013
- if (key === "length" && "value" in descriptor)
12014
- budget.allocateArrayLength(Number(descriptor.value));
12015
- else if (typeof key !== "symbol") {
12016
- const index = Number(key);
12017
- if (Number.isInteger(index) && index >= 0 && index < 4294967295 && String(index) === key) {
12018
- budget.allocateArrayLength(index + 1);
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;
12019
11910
  }
11911
+ return methodName === "includes" ? false : -1;
12020
11912
  }
12021
- }
12022
- Object.defineProperty(properties, key, descriptor);
12023
- markDescriptorObject(properties);
12024
- }
12025
- function isAssignableSandboxTarget(value) {
12026
- return typeof value === "object" && value !== null && !isSandboxClosure(value) && !isSandboxGenerator(value) && !isSandboxMap(value) && !isSandboxSet(value) && !isSandboxPromise(value) && !isSandboxRegex(value);
12027
- }
12028
- async function arrayFromSandboxValues(args, budget, context) {
12029
- const [items, mapFn, thisValue] = args;
12030
- if (mapFn !== void 0 && !isSandboxClosure(mapFn)) {
12031
- throw new TypeError("Array.from mapping callback must be a function.");
12032
- }
12033
- if (items === null || items === void 0) {
12034
- throw new TypeError("Array.from requires a non-null input.");
12035
- }
12036
- const read = (property) => context?.getProperty !== void 0 ? context.getProperty(items, property) : getSandboxDataProperty(items, property, budget);
12037
- const iterator = context === void 0 ? getSandboxIterator(items, budget) : await acquireSandboxIterator(items, budget, context);
12038
- const constructor = context?.thisValue;
12039
- let result;
12040
- let currentValue;
12041
- let failure;
12042
- const retained = {};
12043
- budget.setRetainedValues(retained, () => [
12044
- items,
12045
- iterator?.retainedValue,
12046
- mapFn,
12047
- constructor,
12048
- result,
12049
- currentValue,
12050
- failure
12051
- ]);
12052
- const checkData = createDataCheckpoint(budget, context);
12053
- const closeOnThrow = async (error) => {
12054
- failure = isCapturedException(error) ? error.reason : error;
12055
- try {
12056
- if (iterator !== void 0) await closeIterator(iterator, true);
12057
- } catch (closeError) {
12058
- if (!isFatalSandboxError(error) && isFatalSandboxError(closeError)) throw closeError;
12059
- }
12060
- throw error;
12061
- };
12062
- try {
12063
- let length = 0;
12064
- if (iterator === void 0) {
12065
- const number = await sandboxNumber(await read("length"), budget, context);
12066
- length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
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
+ );
12067
11923
  }
12068
- result = isSandboxClosure(constructor) && constructor.construct !== void 0 ? await invokeBuiltinClosure(
12069
- constructor,
12070
- iterator === void 0 ? [length] : [],
12071
- budget,
12072
- context,
12073
- void 0,
12074
- true
12075
- ) : createArrayFromConstructorArgs([length], budget);
12076
- checkData(result, 0, true);
12077
- let index = 0;
12078
- while (iterator !== void 0 || index < length) {
12079
- try {
12080
- budget.visitNode();
12081
- if (iterator !== void 0 && index >= Number.MAX_SAFE_INTEGER)
12082
- throw new TypeError("Array.from input is too long.");
12083
- } catch (error) {
12084
- await closeOnThrow(error);
12085
- }
12086
- if (iterator !== void 0) {
12087
- const next = await iterator.next();
12088
- if (typeof next !== "object" || next === null)
12089
- throw new TypeError("Iterator result must be an object.");
12090
- if ((await readIteratorResult(iterator, next, "done")).value) break;
12091
- currentValue = (await readIteratorResult(iterator, next, "value")).value;
12092
- } else {
12093
- currentValue = await read(index);
12094
- }
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]);
12095
11936
  try {
12096
- if (Array.isArray(result)) budget.allocateArrayLength(index + 1);
12097
- if (mapFn !== void 0)
12098
- currentValue = await invokeBuiltinClosure(
12099
- mapFn,
12100
- [currentValue, index],
12101
- budget,
12102
- context,
12103
- thisValue
12104
- );
12105
- const key = String(index);
12106
- const growth = key.length + 1 + (Array.isArray(result) ? Math.max(0, index + 1 - result.length) : 0) + (budget.limits.dataSize === void 0 ? 0 : measureSandboxData([currentValue]));
12107
- budget.visitNode();
12108
- defineOwnDataProperty(objectProperties(result, true), key, currentValue);
12109
- currentValue = void 0;
12110
- checkData(result, growth, isSandboxClosure(result));
12111
- } catch (error) {
12112
- await closeOnThrow(error);
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);
11941
+ }
11942
+ return budgetProducedValue(result, options.budget);
11943
+ } finally {
11944
+ release();
12113
11945
  }
12114
- index += 1;
12115
11946
  }
12116
- setSandboxProperty(result, "length", index, budget);
12117
- checkData(result, 0, true);
12118
- return allocateProducedSandboxValue(result, budget);
12119
- } finally {
12120
- budget.setRetainedValues(retained, void 0);
12121
- }
12122
- }
12123
- function createArrayFromConstructorArgs(args, budget) {
12124
- if (args.length !== 1) {
12125
- return budgetSandboxValue(Reflect.apply(Array, Array, [...args]), budget);
12126
- }
12127
- const [lengthOrValue] = args;
12128
- if (typeof lengthOrValue !== "number") {
12129
- return budgetSandboxValue([lengthOrValue], budget);
12130
- }
12131
- if (!Number.isInteger(lengthOrValue) || lengthOrValue < 0 || lengthOrValue > 4294967295) {
12132
- throw new RangeError("Invalid array length.");
12133
- }
12134
- budget.allocateArrayLength(lengthOrValue);
12135
- const release = budget.provisionDataUsage(lengthOrValue + 1);
12136
- try {
12137
- return new Array(lengthOrValue);
12138
- } finally {
12139
- release();
12140
- }
12141
- }
12142
- async function getOwnEnumerableEntries(value, budget, context) {
12143
- const entries = [];
12144
- const release = retainValues(budget, () => [value, entries]);
12145
- try {
12146
- for (const key of ownEnumerableSandboxKeys(value)) {
12147
- if (!hasOwnSandboxProperty(value, key, true)) continue;
12148
- entries.push([
12149
- key,
12150
- await (context?.getProperty !== void 0 ? context.getProperty(value, key) : getSandboxDataProperty(value, key, budget))
12151
- ]);
12152
- }
12153
- return entries;
12154
- } finally {
12155
- release();
12156
- }
12157
- }
12158
- function budgetSandboxValue(value, budget) {
12159
- const sandboxValue = deepCopyToSandbox(value);
12160
- return allocateProducedSandboxValue(sandboxValue, budget);
12161
- }
12162
- function stringFromCodes(args, convert, budget, context) {
12163
- let result = "";
12164
- let index = 0;
12165
- const release = retainValues(budget, () => [...args, result]);
12166
- try {
12167
- const output = advance();
12168
- if (typeof output !== "string") return output.finally(release);
12169
- release();
12170
- return output;
12171
- } catch (error) {
12172
- release();
12173
- throw error;
12174
- }
12175
- function advance() {
12176
- while (index < args.length) {
12177
- budget.visitNode();
12178
- const number = sandboxNumber(args[index++], budget, context);
12179
- if (number instanceof Promise) return number.then((value) => {
12180
- result = budget.allocateString(result + convert(value));
12181
- return advance();
12182
- });
12183
- result = budget.allocateString(result + convert(number));
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);
11977
+ }
12184
11978
  }
12185
- return result;
12186
- }
12187
- }
12188
- function stringRaw(args, budget, context) {
12189
- const [template, ...substitutions] = args;
12190
- if (context?.getProperty !== void 0)
12191
- return (async () => {
12192
- if (template === null || template === void 0)
12193
- throw new TypeError("String.raw requires a template object.");
12194
- const raw2 = await context.getProperty(template, "raw");
12195
- if (raw2 === null || raw2 === void 0)
12196
- throw new TypeError("String.raw requires raw strings.");
12197
- const number = await sandboxNumber(
12198
- await context.getProperty(raw2, "length"),
12199
- budget,
12200
- context
11979
+ case "splice": {
11980
+ const length = value.length;
11981
+ const start = toIntegerOrInfinity(
11982
+ await sandboxNumber(args[0], options.budget, options.context)
12201
11983
  );
12202
- const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
12203
- let result2 = "";
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);
12204
12000
  const retained = {};
12205
- budget.setRetainedValues(retained, () => [raw2, result2]);
12001
+ options.budget.setRetainedValues(retained, () => [removed]);
12206
12002
  try {
12207
- for (let index = 0; index < length; index++) {
12208
- budget.visitNode();
12209
- result2 = budget.allocateString(
12210
- result2 + await sandboxString(await context.getProperty(raw2, index), budget, context)
12211
- );
12212
- if (index + 1 < length && index < substitutions.length)
12213
- result2 = budget.allocateString(
12214
- result2 + await sandboxString(substitutions[index], budget, context)
12215
- );
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);
12216
12007
  }
12217
- return result2;
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);
12218
12020
  } finally {
12219
- budget.setRetainedValues(retained, void 0);
12021
+ options.budget.setRetainedValues(retained, void 0);
12220
12022
  }
12221
- })();
12222
- const raw = getTemplateRawParts(template);
12223
- let result = "";
12224
- for (let index = 0; index < raw.length; index += 1) {
12225
- result += String(raw[index]);
12226
- if (index < raw.length - 1 && index < substitutions.length) {
12227
- result += String(substitutions[index]);
12023
+ budgetProducedValue(removed, options.budget);
12024
+ budgetProducedValue(value, options.budget);
12025
+ return removed;
12228
12026
  }
12229
- }
12230
- return budget.allocateString(result);
12231
- }
12232
- function getTemplateRawParts(template) {
12233
- const raw = typeof template === "object" && template !== null ? template.raw : void 0;
12234
- if (typeof template !== "object" || template === null || isSandboxClosure(template) || isSandboxPromise(template) || !Array.isArray(raw)) {
12235
- throw new TypeError("String.raw requires a raw strings array.");
12236
- }
12237
- return raw;
12238
- }
12239
-
12240
- // packages/safe-js/src/interp/classes.ts
12241
- async function evaluateClass(node, context, evaluateNode2, callContext) {
12242
- const scope = context.scope.child();
12243
- if (node.id !== void 0) scope.predeclare(node.id.name, "const");
12244
- const classContext = { ...context, scope, inferredName: void 0 };
12245
- let parent;
12246
- let prototypeParent;
12247
- const fields2 = [];
12248
- const statics = [];
12249
- let constructor;
12250
- const release = retainValues(context.budget, () => [parent, prototypeParent, constructor, ...fields2.map((field) => field.key), ...statics.flatMap((field) => "key" in field ? [field.key] : [])]);
12251
- try {
12252
- if (node.superClass !== void 0) {
12253
- const result = await evaluateNode2(node.superClass, classContext);
12254
- if (result.kind !== "normal") return result;
12255
- parent = result.value;
12256
- if (parent !== null && (!isSandboxClosure(parent) || parent.construct === void 0))
12257
- throw new TypeError("Class extends value is not a constructor or null.");
12258
- prototypeParent = parent === null ? null : await callContext.getProperty(parent, "prototype");
12259
- if (prototypeParent !== null && typeof prototypeParent !== "object")
12260
- throw new TypeError("Class extends value has an invalid prototype.");
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;
12261
12039
  }
12262
- const derived = node.superClass !== void 0;
12263
- constructor = createClassConstructor(node, { ...classContext, inferredName: context.inferredName }, evaluateNode2, fields2);
12264
- const properties = materializeFunctionProperties(constructor);
12265
- const prototype = properties.prototype;
12266
- Object.defineProperty(properties, "prototype", { writable: false });
12267
- if (derived) setSandboxPrototype(prototype, prototypeParent, context.budget);
12268
- if (isSandboxClosure(parent)) setSandboxPrototype(constructor, parent, context.budget);
12269
- const pattern = createPatternContext(classContext, scope, evaluateNode2);
12270
- for (const element of node.body.body) {
12271
- context.budget.visitNode();
12272
- if (element.type === "StaticBlock") {
12273
- statics.push({ element });
12274
- continue;
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;
12275
12057
  }
12276
- if (element.type === "MethodDefinition" && element.kind === "constructor") continue;
12277
- let key;
12278
- if (element.computed) {
12279
- const result = await evaluateNode2(element.key, classContext);
12280
- if (result.kind !== "normal") return result;
12281
- key = await pattern.toPropertyKey(result.value);
12282
- } else {
12283
- key = element.key.type === "Identifier" ? element.key.name : String(element.key.value);
12284
- }
12285
- if (typeof key === "string") context.budget.allocateString(key);
12286
- if (element.type === "PropertyDefinition") {
12287
- (element.static ? statics : fields2).push({ element, key });
12288
- } else {
12289
- const home = element.static ? constructor : prototype;
12290
- const method = createInterpretedClosure(element.value, classContext, evaluateNode2, home);
12291
- const accessor = element.kind === "get" || element.kind === "set" ? element.kind : void 0;
12292
- Object.defineProperty(materializeFunctionProperties(method), "name", {
12293
- value: accessor === void 0 ? propertyFunctionName(key) : `${accessor} ${propertyFunctionName(key)}`
12294
- });
12295
- Object.defineProperty(
12296
- element.static ? properties : prototype,
12297
- key,
12298
- accessor === void 0 ? { value: method, configurable: true, writable: true, enumerable: false } : { [accessor]: accessorAdapter(method, accessor), configurable: true, enumerable: false }
12299
- );
12058
+ while (count-- > 0) {
12059
+ await moveArrayElement(value, from, to, options);
12060
+ from += direction;
12061
+ to += direction;
12300
12062
  }
12063
+ budgetProducedValue(value, options.budget);
12064
+ return value;
12301
12065
  }
12302
- if (node.id !== void 0) scope.declare(node.id.name, "const", constructor);
12303
- for (const element of statics) await initializeElement(element, constructor, constructor, classContext, evaluateNode2);
12304
- classOrigins.get(constructor).initialized = true;
12305
- if (node.type === "ClassDeclaration") {
12306
- context.scope.declare(node.id.name, "let", constructor);
12307
- return { kind: "normal", hasValue: false, value: void 0 };
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);
12308
12073
  }
12309
- return { kind: "normal", hasValue: true, value: constructor };
12310
- } finally {
12311
- release();
12312
- }
12313
- }
12314
- var classOrigins = /* @__PURE__ */ new WeakMap();
12315
- function createClassConstructor(node, context, evaluateNode2, fields2) {
12316
- const scope = context.scope;
12317
- const classContext = { ...context, inferredName: void 0 };
12318
- const constructorElement = node.body.body.find((element) => element.type === "MethodDefinition" && element.kind === "constructor");
12319
- const derived = node.superClass !== void 0;
12320
- const constructor = createSandboxClosure({
12321
- guest: true,
12322
- sandbox: true,
12323
- name: node.id?.name ?? context.inferredName ?? "",
12324
- length: constructorElement === void 0 ? 0 : getFunctionLength(constructorElement.value.params),
12325
- sourceRange: functionSources.get(node),
12326
- retainedValues: () => [...scope.retainedValues(), ...fields2.map((field) => field.key)],
12327
- call: () => {
12328
- throw new TypeError("Class constructor cannot be invoked without 'new'.");
12329
- },
12330
- construct: async (args, invocation) => {
12331
- const prototype = materializeFunctionProperties(constructor).prototype;
12332
- const newTarget = invocation?.newTarget ?? constructor;
12333
- let thisValue;
12334
- let thisScope;
12335
- let initialized = !derived;
12336
- const initializeFields = async (receiver) => {
12337
- for (const field of fields2) {
12338
- await initializeElement(field, receiver, prototype, classContext, evaluateNode2);
12074
+ case "sort":
12075
+ await sortArray(
12076
+ value,
12077
+ args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
12078
+ options,
12079
+ stack
12080
+ );
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]);
12088
+ try {
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
+ }
12339
12107
  }
12340
- };
12341
- const superCall = async (argumentsList) => {
12342
- const superConstructor = getSandboxPrototype(constructor, context.budget);
12343
- if (!isSandboxClosure(superConstructor) || superConstructor.construct === void 0)
12344
- throw new TypeError("Super constructor is not a constructor.");
12345
- const receiver = await invocation.invokeClosure(superConstructor, argumentsList, void 0, true, newTarget);
12346
- if (initialized) throw new ReferenceError("Super constructor may only initialize this once.");
12347
- initialized = true;
12348
- thisValue = receiver;
12349
- thisScope?.declare("this", "const", receiver);
12350
- await initializeFields(receiver);
12351
- return receiver;
12352
- };
12353
- if (!derived) {
12354
- thisValue = {};
12355
- const targetPrototype = await invocation.getProperty(newTarget, "prototype");
12356
- if (typeof targetPrototype === "object" && targetPrototype !== null)
12357
- setSandboxPrototype(thisValue, targetPrototype, context.budget);
12358
- }
12359
- if (constructorElement === void 0) {
12360
- if (derived) return superCall(args);
12361
- await initializeFields(thisValue);
12362
- return thisValue;
12108
+ budgetProducedValue(value, options.budget);
12109
+ return value;
12110
+ } finally {
12111
+ release();
12363
12112
  }
12364
- const result = await executeClosure(constructorElement.value, args, thisValue, {
12365
- ...classContext,
12366
- compilation: invocation?.compilation ?? context.compilation,
12367
- callStack: [...invocation?.stack ?? context.callStack],
12368
- functionEnvironment: {
12369
- newTarget,
12370
- homeObject: prototype,
12371
- construction: {
12372
- derived,
12373
- superCall,
12374
- initialize: async (functionScope) => {
12375
- thisScope = functionScope;
12376
- if (!derived) await initializeFields(thisValue);
12377
- }
12378
- }
12113
+ }
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);
12379
12123
  }
12380
- }, evaluateNode2);
12381
- if (typeof result === "object" && result !== null) return result;
12382
- if (derived && result !== void 0) throw new TypeError("Derived constructors may only return an object or undefined.");
12383
- if (!initialized) throw new ReferenceError("Must call super constructor before returning from derived constructor.");
12384
- return thisValue;
12124
+ await sortArray(
12125
+ result,
12126
+ args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
12127
+ options,
12128
+ stack
12129
+ );
12130
+ return budgetProducedValue(result, options.budget);
12131
+ } finally {
12132
+ release();
12133
+ }
12385
12134
  }
12386
- });
12387
- classOrigins.set(constructor, { node, scope, fields: fields2, initialized: false });
12388
- return constructor;
12389
- }
12390
- async function initializeElement(definition, receiver, homeObject, context, evaluateNode2) {
12391
- const scope = context.scope.child({}, { functionBoundary: true });
12392
- scope.declare("this", "const", receiver);
12393
- const element = definition.element;
12394
- const initializer = element.type === "StaticBlock" ? element.body : element.value;
12395
- let value;
12396
- if (initializer !== void 0) {
12397
- if (element.type === "StaticBlock") hoistVarDeclarations(element.body, scope);
12398
- const result = await evaluateNode2(initializer, { ...context, scope, functionEnvironment: { homeObject }, inferredName: "key" in definition ? propertyFunctionName(definition.key) : void 0 });
12399
- if (result.kind === "error") throw result.error;
12400
- if (result.kind === "throw") throw result.value;
12401
- value = result.hasValue ? result.value : void 0;
12402
- }
12403
- if ("key" in definition) {
12404
- defineDataProperty(receiver, definition.key, { value, configurable: true, writable: true, enumerable: true }, context.budget);
12405
- }
12406
- }
12407
-
12408
- // packages/safe-js/src/interp/resume-target.ts
12409
- function containsResumeTarget(node, targetNodeIds) {
12410
- if (targetNodeIds === void 0 ? node.type === "YieldExpression" : node.nodeId !== void 0 && targetNodeIds.has(node.nodeId)) {
12411
- return true;
12412
- }
12413
- if (node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression") {
12414
- return false;
12415
- }
12416
- for (const value of Object.values(node)) {
12417
- if (Array.isArray(value)) {
12418
- if (value.some((entry) => isParseResult(entry) && containsResumeTarget(entry, targetNodeIds))) {
12419
- return true;
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();
12420
12148
  }
12421
- continue;
12422
12149
  }
12423
- if (isParseResult(value) && containsResumeTarget(value, targetNodeIds)) {
12424
- return true;
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);
12176
+ }
12177
+ return budgetProducedValue(result, options.budget);
12178
+ } finally {
12179
+ release();
12180
+ }
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");
12190
+ }
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);
12198
+ }
12199
+ return budgetProducedValue(result, options.budget);
12200
+ } finally {
12201
+ release();
12202
+ }
12203
+ }
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;
12425
12234
  }
12426
12235
  }
12427
- return false;
12428
- }
12429
- function isParseResult(value) {
12430
- return typeof value === "object" && value !== null && typeof value.type === "string" && Object.hasOwn(value, "span");
12431
- }
12432
-
12433
- // packages/safe-js/src/interp/methods/array.ts
12434
- var arrayLikeSources = /* @__PURE__ */ new WeakMap();
12435
- var activeArrayCallbacks = /* @__PURE__ */ new WeakMap();
12436
- var arrayMethodNames = /* @__PURE__ */ new Set([
12437
- "map",
12438
- "filter",
12439
- "find",
12440
- "findIndex",
12441
- "findLast",
12442
- "findLastIndex",
12443
- "some",
12444
- "every",
12445
- "reduce",
12446
- "reduceRight",
12447
- "forEach",
12448
- "flatMap",
12449
- "flat",
12450
- "includes",
12451
- "indexOf",
12452
- "lastIndexOf",
12453
- "join",
12454
- "slice",
12455
- "concat",
12456
- "splice",
12457
- "fill",
12458
- "copyWithin",
12459
- "at",
12460
- "sort",
12461
- "reverse",
12462
- "toSorted",
12463
- "toReversed",
12464
- "toSpliced",
12465
- "with",
12466
- "push",
12467
- "pop",
12468
- "shift",
12469
- "unshift"
12470
- ]);
12471
- function getArrayMember(value, property, options) {
12472
- const index = getArrayIndex(property);
12473
- if (index !== void 0) {
12474
- return Object.hasOwn(value, index) ? value[index] : void 0;
12475
- }
12476
- if (property === "length") {
12477
- return value.length;
12236
+ }
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);
12478
12243
  }
12479
- if (Object.hasOwn(value, property)) {
12480
- return value[String(property)];
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);
12481
12255
  }
12482
- if (isArrayMethodName(property)) {
12483
- return createSandboxClosure({
12484
- sandbox: true,
12485
- name: `Array#${property}`,
12486
- call: (args, context) => callArrayMethod(
12487
- context?.thisValue,
12488
- property,
12489
- args,
12490
- { ...options, context },
12491
- context?.stack ?? []
12492
- )
12493
- });
12256
+ for (let index = 0; index < values.length; index += 1) {
12257
+ await writeArrayProperty(target, index, values[index], options);
12494
12258
  }
12495
- return void 0;
12259
+ await writeArrayProperty(target, "length", length, options);
12260
+ return length;
12496
12261
  }
12497
- function getArrayIndex(property) {
12498
- const index = typeof property === "number" ? property : Number(property);
12499
- if (!Number.isSafeInteger(index) || index < 0 || index >= 2 ** 32 - 1 || String(index) !== String(property)) {
12500
- return void 0;
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.`);
12501
12271
  }
12502
- return index;
12272
+ return value;
12503
12273
  }
12504
- function isArrayMethodName(property) {
12505
- return typeof property === "string" && arrayMethodNames.has(property);
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);
12506
12277
  }
12507
- async function callArrayMethod(receiver, methodName, args, options, stack = []) {
12508
- if (receiver === null || receiver === void 0)
12509
- throw new TypeError("Array method requires a receiver.");
12510
- if (typeof receiver !== "object") {
12511
- receiver = createSandboxBox(receiver);
12512
- options.budget.chargeDataUsage(measureSandboxData([receiver]));
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);
12513
12284
  }
12514
- const retainedReceiver = {};
12515
- options.budget.setRetainedValues(retainedReceiver, () => [receiver]);
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]);
12516
12306
  try {
12517
- const value = Array.isArray(receiver) || methodName === "concat" ? receiver : await arrayLikeView(receiver, options);
12518
- if (isMutatingArrayMethod(methodName)) {
12519
- assertCollectionMutable(receiver);
12307
+ for (let index = 0; index < length; index += 1) {
12308
+ options.budget.visitNode();
12309
+ if (!(index in value)) {
12310
+ continue;
12311
+ }
12312
+ result[index] = await callArrayCallback(
12313
+ callback,
12314
+ await readArrayElement(value, index, options),
12315
+ index,
12316
+ value,
12317
+ options,
12318
+ stack,
12319
+ thisValue
12320
+ );
12520
12321
  }
12521
- if (isCallbackArrayMethod(methodName)) {
12522
- let callbackState = activeArrayCallbacks.get(receiver);
12523
- if (callbackState === void 0) {
12524
- callbackState = { depth: 0, leave: enterRunningState(receiver) };
12525
- activeArrayCallbacks.set(receiver, callbackState);
12322
+ return result;
12323
+ } finally {
12324
+ options.budget.setRetainedValues(result, void 0);
12325
+ }
12326
+ }
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;
12526
12336
  }
12527
- callbackState.depth += 1;
12528
- try {
12529
- const result2 = await callArrayMethodUnlocked(value, methodName, args, options, stack);
12530
- return result2 === value ? receiver : result2;
12531
- } finally {
12532
- callbackState.depth -= 1;
12533
- if (callbackState.depth === 0) {
12534
- activeArrayCallbacks.delete(receiver);
12535
- callbackState.leave();
12536
- }
12337
+ const entry = await readArrayElement(value, index, options);
12338
+ if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
12339
+ result.push(entry);
12537
12340
  }
12538
12341
  }
12539
- const result = await callArrayMethodUnlocked(value, methodName, args, options, stack);
12540
- return result === value ? receiver : result;
12342
+ return result;
12541
12343
  } finally {
12542
- options.budget.setRetainedValues(retainedReceiver, void 0);
12344
+ options.budget.setRetainedValues(result, void 0);
12543
12345
  }
12544
12346
  }
12545
- async function arrayLikeView(receiver, options) {
12546
- const rawLength = options.context?.getProperty !== void 0 ? await options.context.getProperty(receiver, "length") : getSandboxDataProperty(receiver, "length", options.budget);
12547
- const number = await sandboxNumber(rawLength, options.budget, options.context);
12548
- const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
12549
- const view = new Proxy(
12550
- /* @__PURE__ */ Object.create(null),
12551
- {
12552
- get: (_target, key) => {
12553
- options.budget.visitNode();
12554
- if (key === "length") return length;
12555
- if (typeof key !== "string") return void 0;
12556
- return options.context?.getProperty !== void 0 ? options.context.getProperty(receiver, key) : getSandboxDataProperty(receiver, key, options.budget);
12557
- },
12558
- has: (_target, key) => {
12559
- options.budget.visitNode();
12560
- if (typeof key === "string" && options.hasProperty !== void 0)
12561
- return options.hasProperty(receiver, key);
12562
- for (let current = receiver; current !== null; current = getSandboxPrototype(current, options.budget)) {
12563
- options.budget.visitNode();
12564
- if (Object.hasOwn(current, key)) return true;
12565
- }
12566
- return false;
12567
- },
12568
- set: (_target, key, entry) => {
12569
- options.budget.visitNode();
12570
- if (typeof key !== "string") throw new TypeError("Array indices must be string keys.");
12571
- if (options.setProperty !== void 0) options.setProperty(receiver, key, entry);
12572
- else if (!Reflect.set(receiver, key, entry))
12573
- throw new TypeError(`Cannot assign property '${key}'.`);
12574
- return true;
12575
- },
12576
- deleteProperty: (_target, key) => {
12577
- options.budget.visitNode();
12578
- if (typeof key === "string" && options.deleteProperty !== void 0)
12579
- return options.deleteProperty(receiver, key);
12580
- return Reflect.deleteProperty(receiver, key);
12581
- }
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
+ }
12355
+ }
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
+ }
12366
+ }
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
+ }
12377
+ }
12378
+ return void 0;
12379
+ }
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
+ }
12388
+ }
12389
+ return -1;
12390
+ }
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;
12411
+ }
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;
12582
12429
  }
12430
+ }
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
12583
12450
  );
12584
- arrayLikeSources.set(view, receiver);
12585
- return view;
12586
12451
  }
12587
- async function callArrayMethodUnlocked(value, methodName, args, options, stack) {
12588
- switch (methodName) {
12589
- case "map":
12590
- return budgetProducedValue(
12591
- await mapArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
12592
- options.budget
12593
- );
12594
- case "filter":
12595
- return budgetProducedValue(
12596
- await filterArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
12597
- options.budget
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]);
12475
+ try {
12476
+ for (let index = startIndex; index < length; index += 1) {
12477
+ options.budget.visitNode();
12478
+ if (!(index in value)) {
12479
+ continue;
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
12598
12490
  );
12599
- case "find":
12600
- return budgetProducedValue(
12601
- await findInArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]),
12602
- options.budget
12491
+ }
12492
+ return current;
12493
+ } finally {
12494
+ options.budget.setRetainedValues(retainedAccumulator, void 0);
12495
+ }
12496
+ }
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;
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
12603
12516
  );
12604
- case "findIndex":
12605
- return await findIndexInArray(
12517
+ }
12518
+ return current;
12519
+ } finally {
12520
+ options.budget.setRetainedValues(retainedAccumulator, void 0);
12521
+ }
12522
+ }
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,
12606
12555
  value,
12607
- getRequiredCallback(methodName, args[0]),
12608
12556
  options,
12609
12557
  stack,
12610
- args[1]
12558
+ thisValue
12611
12559
  );
12612
- case "findLast":
12613
- return budgetProducedValue(
12614
- await findLastInArray(
12615
- value,
12616
- getRequiredCallback(methodName, args[0]),
12617
- options,
12618
- stack,
12619
- args[1]
12620
- ),
12621
- options.budget
12622
- );
12623
- case "findLastIndex":
12624
- return await findLastIndexInArray(
12625
- value,
12626
- getRequiredCallback(methodName, args[0]),
12627
- options,
12628
- stack,
12629
- args[1]
12630
- );
12631
- case "some":
12632
- return await someInArray(
12633
- value,
12634
- getRequiredCallback(methodName, args[0]),
12635
- options,
12636
- stack,
12637
- args[1]
12638
- );
12639
- case "every":
12640
- return await everyInArray(
12641
- value,
12642
- getRequiredCallback(methodName, args[0]),
12643
- options,
12644
- stack,
12645
- args[1]
12646
- );
12647
- case "reduce":
12648
- return budgetProducedValue(
12649
- await reduceArray(
12650
- value,
12651
- getRequiredCallback(methodName, args[0]),
12652
- args.length > 1,
12653
- args[1],
12654
- options,
12655
- stack
12656
- ),
12657
- options.budget
12658
- );
12659
- case "reduceRight":
12660
- return budgetProducedValue(
12661
- await reduceRightArray(
12662
- value,
12663
- getRequiredCallback(methodName, args[0]),
12664
- args.length > 1,
12665
- args[1],
12666
- options,
12667
- stack
12668
- ),
12669
- options.budget
12670
- );
12671
- case "forEach":
12672
- await forEachArray(value, getRequiredCallback(methodName, args[0]), options, stack, args[1]);
12673
- return void 0;
12674
- case "flatMap":
12675
- return budgetProducedValue(
12676
- await flatMapArray(
12677
- value,
12678
- getRequiredCallback(methodName, args[0]),
12679
- options,
12680
- stack,
12681
- args[1]
12682
- ),
12683
- options.budget
12684
- );
12685
- case "flat":
12686
- return budgetProducedValue(
12687
- await flattenArray(
12688
- value,
12689
- args[0] === void 0 ? 1 : toIntegerOrInfinity(await sandboxNumber(args[0], options.budget, options.context)),
12690
- options
12691
- ),
12692
- options.budget
12693
- );
12694
- case "includes":
12695
- case "indexOf":
12696
- case "lastIndexOf": {
12697
- const length = value.length;
12698
- if (length === 0) return methodName === "includes" ? false : -1;
12699
- const reverse = methodName === "lastIndexOf";
12700
- const start = reverse && args.length < 2 ? length - 1 : toIntegerOrInfinity(await sandboxNumber(args[1], options.budget, options.context));
12701
- let index = reverse ? Math.min(start < 0 ? length + start : start, length - 1) : start < 0 ? Math.max(length + start, 0) : start;
12702
- for (; index >= 0 && index < length; index += reverse ? -1 : 1) {
12703
- options.budget.visitNode();
12704
- if (methodName !== "includes" && !(index in value)) continue;
12705
- const entry = await readArrayElement(value, index, options);
12706
- if (entry === args[0] || methodName === "includes" && Number.isNaN(entry) && Number.isNaN(args[0]))
12707
- return methodName === "includes" ? true : index;
12708
- }
12709
- return methodName === "includes" ? false : -1;
12710
- }
12711
- case "join": {
12712
- const length = value.length;
12713
- const separator = args[0] === void 0 ? "," : await sandboxString(args[0], options.budget, options.context);
12714
- return joinSandboxArray(
12715
- arrayLikeSources.get(value) ?? value,
12716
- length,
12717
- separator,
12718
- options.budget,
12719
- options.context
12720
- );
12721
- }
12722
- case "slice": {
12723
- const length = value.length;
12724
- const start = toIntegerOrInfinity(
12725
- await sandboxNumber(args[0], options.budget, options.context)
12726
- );
12727
- const end = args[1] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[1], options.budget, options.context));
12728
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12729
- const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12730
- const count = Math.max(final - first, 0);
12731
- options.budget.allocateArrayLength(count);
12732
- const result = new Array(count);
12733
- const release = retainValues(options.budget, () => [result]);
12734
- try {
12735
- for (let index = 0; index < count; index += 1) {
12560
+ if (Array.isArray(mapped)) {
12561
+ for (let mappedIndex = 0; mappedIndex < mapped.length; mappedIndex += 1) {
12736
12562
  options.budget.visitNode();
12737
- if (first + index in value)
12738
- result[index] = await readArrayElement(value, first + index, options);
12739
- }
12740
- return budgetProducedValue(result, options.budget);
12741
- } finally {
12742
- release();
12743
- }
12744
- }
12745
- case "concat": {
12746
- const result = [];
12747
- const retained = {};
12748
- options.budget.setRetainedValues(retained, () => [result]);
12749
- try {
12750
- for (const entry of [value, ...args]) {
12751
- let spread = false;
12752
- if (entry !== null && (typeof entry === "object" || typeof entry === "function")) {
12753
- const flag = options.context?.getProperty !== void 0 ? await options.context.getProperty(entry, Symbol.isConcatSpreadable) : getSandboxDataProperty(entry, Symbol.isConcatSpreadable, options.budget);
12754
- spread = flag === void 0 ? Array.isArray(entry) : Boolean(flag);
12755
- }
12756
- if (!spread) {
12757
- options.budget.allocateArrayLength(result.length + 1);
12758
- result.push(entry);
12563
+ if (!(mappedIndex in mapped)) {
12759
12564
  continue;
12760
12565
  }
12761
- const start = result.length;
12762
- const source = await arrayLikeView(entry, options);
12763
- const length = source.length;
12764
- options.budget.allocateArrayLength(start + length);
12765
- result.length += length;
12766
- for (let index = 0; index < length; index++) {
12767
- options.budget.visitNode();
12768
- if (index in source)
12769
- result[start + index] = await readArrayElement(source, index, options);
12770
- }
12566
+ result.push(await readArrayElement(mapped, mappedIndex, options));
12567
+ options.budget.allocateArrayLength(result.length);
12771
12568
  }
12772
- return budgetProducedValue(result, options.budget);
12773
- } finally {
12774
- options.budget.setRetainedValues(retained, void 0);
12569
+ continue;
12775
12570
  }
12571
+ result.push(mapped);
12572
+ options.budget.allocateArrayLength(result.length);
12776
12573
  }
12777
- case "splice": {
12778
- const length = value.length;
12779
- const start = toIntegerOrInfinity(
12780
- await sandboxNumber(args[0], options.budget, options.context)
12781
- );
12782
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12783
- const inserted = Math.max(args.length - 2, 0);
12784
- const deleted = args.length === 0 ? 0 : args.length === 1 ? length - first : Math.min(
12785
- Math.max(
12786
- toIntegerOrInfinity(
12787
- await sandboxNumber(args[1], options.budget, options.context)
12788
- ),
12789
- 0
12790
- ),
12791
- length - first
12792
- );
12793
- const nextLength = length + inserted - deleted;
12794
- if (nextLength > Number.MAX_SAFE_INTEGER)
12795
- throw new TypeError("Array-like length exceeds the safe integer limit.");
12796
- options.budget.allocateArrayLength(deleted);
12797
- const removed = new Array(deleted);
12798
- const retained = {};
12799
- options.budget.setRetainedValues(retained, () => [removed]);
12800
- try {
12801
- for (let index = 0; index < deleted; index++) {
12802
- options.budget.visitNode();
12803
- if (first + index in value)
12804
- removed[index] = await readArrayElement(value, first + index, options);
12805
- }
12806
- if (inserted < deleted) {
12807
- for (let index = first; index < length - deleted; index++)
12808
- await moveArrayElement(value, index + deleted, index + inserted, options);
12809
- for (let index = length; index > nextLength; index--)
12810
- deleteArrayElement(value, index - 1, options);
12811
- } else if (inserted > deleted) {
12812
- for (let index = length - deleted; index > first; index--)
12813
- await moveArrayElement(value, index + deleted - 1, index + inserted - 1, options);
12814
- }
12815
- for (let index = 0; index < inserted; index++)
12816
- await writeArrayProperty(value, first + index, args[index + 2], options);
12817
- await writeArrayProperty(value, "length", nextLength, options);
12818
- } finally {
12819
- options.budget.setRetainedValues(retained, void 0);
12820
- }
12821
- budgetProducedValue(removed, options.budget);
12822
- budgetProducedValue(value, options.budget);
12823
- return removed;
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;
12824
12596
  }
12825
- case "fill": {
12826
- const length = value.length;
12827
- const start = toIntegerOrInfinity(
12828
- await sandboxNumber(args[1], options.budget, options.context)
12829
- );
12830
- const end = args[2] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[2], options.budget, options.context));
12831
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12832
- const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12833
- for (let index = first; index < final; index++)
12834
- await writeArrayProperty(value, index, args[0], options);
12835
- budgetProducedValue(value, options.budget);
12836
- return value;
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;
12837
12601
  }
12838
- case "copyWithin": {
12839
- const length = value.length;
12840
- const target = toIntegerOrInfinity(
12841
- await sandboxNumber(args[0], options.budget, options.context)
12842
- );
12843
- const start = toIntegerOrInfinity(
12844
- await sandboxNumber(args[1], options.budget, options.context)
12845
- );
12846
- const end = args[2] === void 0 ? length : toIntegerOrInfinity(await sandboxNumber(args[2], options.budget, options.context));
12847
- let to = target < 0 ? Math.max(length + target, 0) : Math.min(target, length);
12848
- let from = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12849
- const final = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
12850
- let count = Math.min(final - from, length - to);
12851
- const direction = from < to && to < from + count ? -1 : 1;
12852
- if (direction < 0) {
12853
- from += count - 1;
12854
- to += count - 1;
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;
12855
12617
  }
12856
- while (count-- > 0) {
12857
- await moveArrayElement(value, from, to, options);
12858
- from += direction;
12859
- to += direction;
12618
+ const entry = await readArrayElement(value, index, options);
12619
+ if (entry === void 0) {
12620
+ undefinedCount += 1;
12621
+ continue;
12860
12622
  }
12861
- budgetProducedValue(value, options.budget);
12862
- return value;
12863
- }
12864
- case "at": {
12865
- const length = value.length;
12866
- const index = toIntegerOrInfinity(
12867
- await sandboxNumber(args[0], options.budget, options.context)
12868
- );
12869
- const actual = index < 0 ? length + index : index;
12870
- return actual < 0 || actual >= length ? void 0 : budgetProducedValue(await readArrayElement(value, actual, options), options.budget);
12623
+ definedValues.push(entry);
12871
12624
  }
12872
- case "sort":
12873
- await sortArray(
12874
- value,
12875
- args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
12876
- options,
12877
- stack
12878
- );
12879
- budgetProducedValue(value, options.budget);
12880
- return value;
12881
- case "reverse": {
12882
- const length = value.length;
12883
- let lowerValue;
12884
- let upperValue;
12885
- const release = retainValues(options.budget, () => [lowerValue, upperValue]);
12886
- try {
12887
- for (let lower = 0; lower < Math.floor(length / 2); lower++) {
12888
- options.budget.visitNode();
12889
- lowerValue = upperValue = void 0;
12890
- const upper = length - lower - 1;
12891
- const lowerExists = lower in value;
12892
- lowerValue = lowerExists ? await readArrayElement(value, lower, options) : void 0;
12893
- const upperExists = upper in value;
12894
- upperValue = upperExists ? await readArrayElement(value, upper, options) : void 0;
12895
- if (lowerExists && upperExists) {
12896
- await writeArrayProperty(value, lower, upperValue, options);
12897
- await writeArrayProperty(value, upper, lowerValue, options);
12898
- } else if (!lowerExists && upperExists) {
12899
- await writeArrayProperty(value, lower, upperValue, options);
12900
- deleteArrayElement(value, upper, options);
12901
- } else if (lowerExists) {
12902
- deleteArrayElement(value, lower, options);
12903
- await writeArrayProperty(value, upper, lowerValue, options);
12904
- }
12905
- }
12906
- budgetProducedValue(value, options.budget);
12907
- return value;
12908
- } finally {
12909
- release();
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;
12910
12631
  }
12632
+ definedValues[cursor + 1] = currentEntry;
12911
12633
  }
12912
- case "toSorted": {
12913
- const length = value.length;
12914
- options.budget.allocateArrayLength(length);
12915
- const result = new Array(length);
12916
- const release = retainValues(options.budget, () => [result]);
12917
- try {
12918
- for (let index = 0; index < length; index += 1) {
12919
- options.budget.visitNode();
12920
- result[index] = await readArrayElement(value, index, options);
12921
- }
12922
- await sortArray(
12923
- result,
12924
- args[0] === void 0 ? void 0 : getRequiredCallback(methodName, args[0]),
12925
- options,
12926
- stack
12927
- );
12928
- return budgetProducedValue(result, options.budget);
12929
- } finally {
12930
- release();
12931
- }
12634
+ currentEntry = void 0;
12635
+ for (let index = 0; index < definedValues.length; index += 1) {
12636
+ await writeArrayProperty(value, index, definedValues[index], options);
12932
12637
  }
12933
- case "toReversed": {
12934
- const length = value.length;
12935
- options.budget.allocateArrayLength(length);
12936
- const result = new Array(length);
12937
- const release = retainValues(options.budget, () => [result]);
12938
- try {
12939
- for (let index = 0; index < length; index += 1) {
12940
- options.budget.visitNode();
12941
- result[index] = await readArrayElement(value, length - index - 1, options);
12942
- }
12943
- return budgetProducedValue(result, options.budget);
12944
- } finally {
12945
- release();
12946
- }
12638
+ for (let index = 0; index < undefinedCount; index += 1) {
12639
+ await writeArrayProperty(value, definedValues.length + index, void 0, options);
12947
12640
  }
12948
- case "toSpliced": {
12949
- const length = value.length;
12950
- const start = toIntegerOrInfinity(
12951
- await sandboxNumber(args[0], options.budget, options.context)
12952
- );
12953
- const first = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
12954
- const inserted = Math.max(args.length - 2, 0);
12955
- const deleted = args.length === 0 ? 0 : args.length === 1 ? length - first : Math.min(
12956
- Math.max(
12957
- toIntegerOrInfinity(
12958
- await sandboxNumber(args[1], options.budget, options.context)
12959
- ),
12960
- 0
12961
- ),
12962
- length - first
12963
- );
12964
- const resultLength = length + inserted - deleted;
12965
- if (resultLength > Number.MAX_SAFE_INTEGER)
12966
- throw new TypeError("Array-like length exceeds the safe integer limit.");
12967
- options.budget.allocateArrayLength(resultLength);
12968
- const result = new Array(resultLength);
12969
- const release = retainValues(options.budget, () => [result]);
12970
- try {
12971
- for (let index = 0; index < resultLength; index += 1) {
12972
- options.budget.visitNode();
12973
- result[index] = index < first ? await readArrayElement(value, index, options) : index < first + inserted ? args[index - first + 2] : await readArrayElement(value, index - inserted + deleted, options);
12974
- }
12975
- return budgetProducedValue(result, options.budget);
12976
- } finally {
12977
- release();
12978
- }
12641
+ for (let index = definedValues.length + undefinedCount; index < length; index += 1) {
12642
+ options.budget.visitNode();
12643
+ deleteArrayElement(value, index, options);
12644
+ }
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();
12659
+ }
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;
12681
+ }
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;
12699
+ }
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
+ )
12771
+ ),
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
+ })
12997
+ }
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);
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;
12979
13133
  }
12980
- case "with": {
12981
- const length = value.length;
12982
- const index = toIntegerOrInfinity(
12983
- options.context === void 0 ? args[0] : await sandboxNumber(args[0], options.budget, options.context)
12984
- );
12985
- const actualIndex = index < 0 ? length + index : index;
12986
- if (actualIndex < 0 || actualIndex >= length) {
12987
- throw new RangeError("Invalid index");
12988
- }
12989
- options.budget.allocateArrayLength(length);
12990
- const result = [];
12991
- const release = retainValues(options.budget, () => [result]);
13134
+ throw error;
13135
+ };
13136
+ try {
13137
+ checkData(object, 0, true);
13138
+ while (true) {
12992
13139
  try {
12993
- for (let position = 0; position < length; position += 1) {
12994
- options.budget.visitNode();
12995
- result[position] = position === actualIndex ? args[1] : await readArrayElement(value, position, options);
12996
- }
12997
- return budgetProducedValue(result, options.budget);
12998
- } finally {
12999
- release();
13140
+ budget.visitNode();
13141
+ } catch (error) {
13142
+ await closeOnThrow(error);
13000
13143
  }
13001
- }
13002
- case "push": {
13003
- const nextLength = await appendArrayValues(value, args, options);
13004
- budgetProducedValue(value, options.budget);
13005
- return nextLength;
13006
- }
13007
- case "pop":
13008
- case "shift": {
13009
- const length = value.length;
13010
- if (length === 0) {
13011
- await writeArrayProperty(value, "length", 0, options);
13012
- 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.");
13013
13147
  }
13014
- const result = await readArrayElement(value, methodName === "pop" ? length - 1 : 0, options);
13015
- const retained = {};
13016
- options.budget.setRetainedValues(retained, () => [result]);
13148
+ if ((await readIteratorResult(iterator, result, "done")).value) break;
13149
+ entry = (await readIteratorResult(iterator, result, "value")).value;
13017
13150
  try {
13018
- if (methodName === "shift")
13019
- for (let index = 1; index < length; index++)
13020
- await moveArrayElement(value, index, index - 1, options);
13021
- deleteArrayElement(value, length - 1, options);
13022
- await writeArrayProperty(value, "length", length - 1, options);
13023
- return budgetProducedValue(result, options.budget);
13024
- } finally {
13025
- 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);
13026
13164
  }
13027
13165
  }
13028
- case "unshift": {
13029
- const nextLength = await prependArrayValues(value, args, options);
13030
- budgetProducedValue(value, options.budget);
13031
- return nextLength;
13032
- }
13166
+ checkData(object, 0, true);
13167
+ return allocateProducedSandboxValue(object, budget);
13168
+ } finally {
13169
+ budget.setRetainedValues(retained, void 0);
13033
13170
  }
13034
13171
  }
13035
- async function appendArrayValues(target, values, options) {
13036
- let length = target.length;
13037
- if (length + values.length > Number.MAX_SAFE_INTEGER)
13038
- throw new TypeError("Array-like length exceeds the safe integer limit.");
13039
- for (const value of values) {
13040
- 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.");
13041
13175
  }
13042
- await writeArrayProperty(target, "length", length, options);
13043
- return length;
13044
- }
13045
- async function prependArrayValues(target, values, options) {
13046
- const originalLength = target.length;
13047
- const length = originalLength + values.length;
13048
- if (length > Number.MAX_SAFE_INTEGER)
13049
- throw new TypeError("Array-like length exceeds the safe integer limit.");
13050
- for (let index = values.length === 0 ? -1 : originalLength - 1; index >= 0; index -= 1) {
13051
- const targetIndex = index + values.length;
13052
- await moveArrayElement(target, index, targetIndex, options);
13176
+ if (typeof target !== "object") {
13177
+ target = createSandboxBox(target);
13178
+ budget.chargeDataUsage(measureSandboxData([target]));
13053
13179
  }
13054
- for (let index = 0; index < values.length; index += 1) {
13055
- 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;
13056
13193
  }
13057
- await writeArrayProperty(target, "length", length, options);
13058
- return length;
13059
- }
13060
- function isCallbackArrayMethod(methodName) {
13061
- 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
+ })();
13062
13212
  }
13063
- function isMutatingArrayMethod(methodName) {
13064
- 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);
13065
13217
  }
13066
- function getRequiredCallback(methodName, value) {
13067
- if (!isSandboxClosure(value)) {
13068
- 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;
13069
13224
  }
13070
- return value;
13071
- }
13072
- function readArrayElement(value, index, options) {
13073
- const receiver = arrayLikeSources.get(value) ?? value;
13074
- return options.context?.getProperty !== void 0 ? options.context.getProperty(receiver, index) : getSandboxDataProperty(receiver, index, options.budget);
13075
- }
13076
- function writeArrayProperty(value, key, entry, options) {
13077
- options.budget.visitNode();
13078
- const receiver = arrayLikeSources.get(value) ?? value;
13079
- if (Array.isArray(receiver)) {
13080
- if (key === "length") options.budget.allocateArrayLength(Number(entry));
13081
- 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);
13082
13231
  }
13083
- if (options.setProperty !== void 0) return options.setProperty(receiver, String(key), entry);
13084
- if (!Reflect.set(receiver, key, entry))
13085
- throw new TypeError(`Cannot assign to read only property '${key}'.`);
13086
- }
13087
- function deleteArrayElement(value, index, options) {
13088
- options.budget.visitNode();
13089
- const receiver = arrayLikeSources.get(value) ?? value;
13090
- const deleted = options.deleteProperty === void 0 ? Reflect.deleteProperty(receiver, String(index)) : options.deleteProperty(receiver, String(index));
13091
- if (!deleted) throw new TypeError(`Cannot delete property '${index}'.`);
13092
- }
13093
- async function moveArrayElement(value, from, to, options) {
13094
- options.budget.visitNode();
13095
- if (from in value)
13096
- await writeArrayProperty(value, to, await readArrayElement(value, from, options), options);
13097
- else deleteArrayElement(value, to, options);
13232
+ if (!isAssignableSandboxTarget(value))
13233
+ throw new TypeError("Expected a sandbox object or function.");
13234
+ return value;
13098
13235
  }
13099
- async function mapArray(value, callback, options, stack, thisValue) {
13100
- const length = value.length;
13101
- options.budget.allocateArrayLength(length);
13102
- const result = new Array(length);
13103
- options.budget.setRetainedValues(result, () => [result]);
13104
- try {
13105
- for (let index = 0; index < length; index += 1) {
13106
- options.budget.visitNode();
13107
- if (!(index in value)) {
13108
- continue;
13109
- }
13110
- result[index] = await callArrayCallback(
13111
- callback,
13112
- await readArrayElement(value, index, options),
13113
- index,
13114
- value,
13115
- options,
13116
- stack,
13117
- thisValue
13118
- );
13119
- }
13120
- return result;
13121
- } finally {
13122
- options.budget.setRetainedValues(result, void 0);
13123
- }
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
+ };
13124
13243
  }
13125
- async function filterArray(value, callback, options, stack, thisValue) {
13126
- const length = value.length;
13127
- const result = [];
13128
- 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
+ ]);
13129
13252
  try {
13130
- for (let index = 0; index < length; index += 1) {
13131
- options.budget.visitNode();
13132
- 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))
13133
13262
  continue;
13134
- }
13135
- const entry = await readArrayElement(value, index, options);
13136
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13137
- result.push(entry);
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);
13138
13272
  }
13139
13273
  }
13140
- 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;
13141
13277
  } finally {
13142
- options.budget.setRetainedValues(result, void 0);
13278
+ release();
13143
13279
  }
13144
13280
  }
13145
- async function findInArray(value, callback, options, stack, thisValue) {
13146
- const length = value.length;
13147
- for (let index = 0; index < length; index += 1) {
13148
- options.budget.visitNode();
13149
- const entry = await readArrayElement(value, index, options);
13150
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13151
- return entry;
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
+ ]);
13290
+ try {
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)]);
13152
13295
  }
13296
+ for (const [key, descriptor] of properties) defineDataProperty(target, key, descriptor, budget);
13297
+ } finally {
13298
+ release();
13153
13299
  }
13154
- return void 0;
13155
13300
  }
13156
- async function findIndexInArray(value, callback, options, stack, thisValue) {
13157
- const length = value.length;
13158
- for (let index = 0; index < length; index += 1) {
13159
- options.budget.visitNode();
13160
- const entry = await readArrayElement(value, index, options);
13161
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13162
- 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
+ }
13163
13314
  }
13164
13315
  }
13165
- return -1;
13316
+ Object.defineProperty(properties, key, descriptor);
13317
+ markDescriptorObject(properties);
13166
13318
  }
13167
- async function findLastInArray(value, callback, options, stack, thisValue) {
13168
- const length = value.length;
13169
- for (let index = length - 1; index >= 0; index -= 1) {
13170
- options.budget.visitNode();
13171
- const entry = await readArrayElement(value, index, options);
13172
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13173
- return entry;
13174
- }
13175
- }
13176
- 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);
13177
13321
  }
13178
- async function findLastIndexInArray(value, callback, options, stack, thisValue) {
13179
- const length = value.length;
13180
- for (let index = length - 1; index >= 0; index -= 1) {
13181
- options.budget.visitNode();
13182
- const entry = await readArrayElement(value, index, options);
13183
- if (await callArrayCallback(callback, entry, index, value, options, stack, thisValue)) {
13184
- return index;
13185
- }
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.");
13186
13326
  }
13187
- return -1;
13188
- }
13189
- async function someInArray(value, callback, options, stack, thisValue) {
13190
- const length = value.length;
13191
- for (let index = 0; index < length; index += 1) {
13192
- options.budget.visitNode();
13193
- if (!(index in value)) {
13194
- continue;
13195
- }
13196
- if (await callArrayCallback(
13197
- callback,
13198
- await readArrayElement(value, index, options),
13199
- index,
13200
- value,
13201
- options,
13202
- stack,
13203
- thisValue
13204
- )) {
13205
- return true;
13206
- }
13327
+ if (items === null || items === void 0) {
13328
+ throw new TypeError("Array.from requires a non-null input.");
13207
13329
  }
13208
- return false;
13209
- }
13210
- async function everyInArray(value, callback, options, stack, thisValue) {
13211
- const length = value.length;
13212
- for (let index = 0; index < length; index += 1) {
13213
- options.budget.visitNode();
13214
- if (!(index in value)) {
13215
- continue;
13216
- }
13217
- if (!await callArrayCallback(
13218
- callback,
13219
- await readArrayElement(value, index, options),
13220
- index,
13221
- value,
13222
- options,
13223
- stack,
13224
- thisValue
13225
- )) {
13226
- 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;
13227
13353
  }
13228
- }
13229
- return true;
13230
- }
13231
- async function reduceArray(value, callback, hasInitialValue, initialValue, options, stack) {
13232
- const length = value.length;
13233
- if (hasInitialValue) {
13234
- return reduceFromLeft(value, callback, initialValue, 0, length, options, stack);
13235
- }
13236
- const start = findNextDefinedIndex(value, 0, 1, length, options.budget);
13237
- if (start < 0) {
13238
- throw new TypeError("Reduce of empty array with no initial value.");
13239
- }
13240
- return reduceFromLeft(
13241
- value,
13242
- callback,
13243
- await readArrayElement(value, start, options),
13244
- start + 1,
13245
- length,
13246
- options,
13247
- stack
13248
- );
13249
- }
13250
- async function reduceRightArray(value, callback, hasInitialValue, initialValue, options, stack) {
13251
- const length = value.length;
13252
- if (hasInitialValue) {
13253
- return reduceFromRight(value, callback, initialValue, length - 1, length, options, stack);
13254
- }
13255
- const start = findNextDefinedIndex(value, length - 1, -1, length, options.budget);
13256
- if (start < 0) {
13257
- throw new TypeError("Reduce of empty array with no initial value.");
13258
- }
13259
- return reduceFromRight(
13260
- value,
13261
- callback,
13262
- await readArrayElement(value, start, options),
13263
- start - 1,
13264
- length,
13265
- options,
13266
- stack
13267
- );
13268
- }
13269
- async function reduceFromLeft(value, callback, accumulator, startIndex, length, options, stack) {
13270
- let current = accumulator;
13271
- const retainedAccumulator = {};
13272
- options.budget.setRetainedValues(retainedAccumulator, () => [current]);
13354
+ throw error;
13355
+ };
13273
13356
  try {
13274
- for (let index = startIndex; index < length; index += 1) {
13275
- options.budget.visitNode();
13276
- if (!(index in value)) {
13277
- 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);
13278
13379
  }
13279
- current = await options.callClosure(
13280
- callback,
13281
- [
13282
- current,
13283
- await readArrayElement(value, index, options),
13284
- index,
13285
- arrayLikeSources.get(value) ?? value
13286
- ],
13287
- stack
13288
- );
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;
13289
13409
  }
13290
- return current;
13410
+ setSandboxProperty(result, "length", index, budget);
13411
+ checkData(result, 0, true);
13412
+ return allocateProducedSandboxValue(result, budget);
13291
13413
  } finally {
13292
- options.budget.setRetainedValues(retainedAccumulator, void 0);
13414
+ budget.setRetainedValues(retained, void 0);
13293
13415
  }
13294
13416
  }
13295
- async function reduceFromRight(value, callback, accumulator, startIndex, length, options, stack) {
13296
- let current = accumulator;
13297
- const retainedAccumulator = {};
13298
- 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);
13299
13430
  try {
13300
- for (let index = Math.min(startIndex, length - 1); index >= 0; index -= 1) {
13301
- options.budget.visitNode();
13302
- if (!(index in value)) {
13303
- continue;
13304
- }
13305
- current = await options.callClosure(
13306
- callback,
13307
- [
13308
- current,
13309
- await readArrayElement(value, index, options),
13310
- index,
13311
- arrayLikeSources.get(value) ?? value
13312
- ],
13313
- stack
13314
- );
13315
- }
13316
- return current;
13431
+ return new Array(lengthOrValue);
13317
13432
  } finally {
13318
- options.budget.setRetainedValues(retainedAccumulator, void 0);
13319
- }
13320
- }
13321
- async function forEachArray(value, callback, options, stack, thisValue) {
13322
- const length = value.length;
13323
- for (let index = 0; index < length; index += 1) {
13324
- options.budget.visitNode();
13325
- if (!(index in value)) {
13326
- continue;
13327
- }
13328
- await callArrayCallback(
13329
- callback,
13330
- await readArrayElement(value, index, options),
13331
- index,
13332
- value,
13333
- options,
13334
- stack,
13335
- thisValue
13336
- );
13433
+ release();
13337
13434
  }
13338
13435
  }
13339
- async function flatMapArray(value, callback, options, stack, thisValue) {
13340
- const length = value.length;
13341
- const result = [];
13342
- options.budget.setRetainedValues(result, () => [result]);
13436
+ async function getOwnEnumerableEntries(value, budget, context) {
13437
+ const entries = [];
13438
+ const release = retainValues(budget, () => [value, entries]);
13343
13439
  try {
13344
- for (let index = 0; index < length; index += 1) {
13345
- options.budget.visitNode();
13346
- if (!(index in value)) {
13347
- continue;
13348
- }
13349
- const mapped = await callArrayCallback(
13350
- callback,
13351
- await readArrayElement(value, index, options),
13352
- index,
13353
- value,
13354
- options,
13355
- stack,
13356
- thisValue
13357
- );
13358
- if (Array.isArray(mapped)) {
13359
- for (let mappedIndex = 0; mappedIndex < mapped.length; mappedIndex += 1) {
13360
- options.budget.visitNode();
13361
- if (!(mappedIndex in mapped)) {
13362
- continue;
13363
- }
13364
- result.push(await readArrayElement(mapped, mappedIndex, options));
13365
- options.budget.allocateArrayLength(result.length);
13366
- }
13367
- continue;
13368
- }
13369
- result.push(mapped);
13370
- 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
+ ]);
13371
13446
  }
13372
- return result;
13447
+ return entries;
13373
13448
  } finally {
13374
- options.budget.setRetainedValues(result, void 0);
13449
+ release();
13375
13450
  }
13376
13451
  }
13377
- async function flattenArray(value, depth, options) {
13378
- const result = [];
13379
- const retained = {};
13380
- 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]);
13381
13460
  try {
13382
- 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
+ }
13383
13479
  return result;
13384
- } finally {
13385
- options.budget.setRetainedValues(retained, void 0);
13386
13480
  }
13387
13481
  }
13388
- async function appendFlattenedEntries(value, depth, result, options) {
13389
- const length = value.length;
13390
- for (let index = 0; index < length; index += 1) {
13391
- options.budget.visitNode();
13392
- if (!(index in value)) {
13393
- continue;
13394
- }
13395
- const entry = await readArrayElement(value, index, options);
13396
- if (depth > 0 && Array.isArray(entry)) {
13397
- await appendFlattenedEntries(entry, depth - 1, result, options);
13398
- 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]);
13399
13522
  }
13400
- result.push(entry);
13401
- options.budget.allocateArrayLength(result.length);
13402
13523
  }
13524
+ return budget.allocateString(result);
13403
13525
  }
13404
- async function sortArray(value, comparator, options, stack) {
13405
- const length = value.length;
13406
- const definedValues = [];
13407
- let undefinedCount = 0;
13408
- let currentEntry;
13409
- 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] : [])]);
13410
13545
  try {
13411
- for (let index = 0; index < length; index += 1) {
13412
- options.budget.visitNode();
13413
- 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 });
13414
13568
  continue;
13415
13569
  }
13416
- const entry = await readArrayElement(value, index, options);
13417
- if (entry === void 0) {
13418
- undefinedCount += 1;
13419
- 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);
13420
13578
  }
13421
- definedValues.push(entry);
13422
- }
13423
- for (let index = 1; index < definedValues.length; index += 1) {
13424
- currentEntry = definedValues[index];
13425
- let cursor = index - 1;
13426
- while (cursor >= 0 && await compareEntries(definedValues[cursor], currentEntry, comparator, options, stack) > 0) {
13427
- definedValues[cursor + 1] = definedValues[cursor];
13428
- 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
+ );
13429
13594
  }
13430
- definedValues[cursor + 1] = currentEntry;
13431
13595
  }
13432
- currentEntry = void 0;
13433
- for (let index = 0; index < definedValues.length; index += 1) {
13434
- await writeArrayProperty(value, index, definedValues[index], options);
13435
- }
13436
- for (let index = 0; index < undefinedCount; index += 1) {
13437
- await writeArrayProperty(value, definedValues.length + index, void 0, options);
13438
- }
13439
- for (let index = definedValues.length + undefinedCount; index < length; index += 1) {
13440
- options.budget.visitNode();
13441
- 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 };
13442
13602
  }
13603
+ return { kind: "normal", hasValue: true, value: constructor };
13443
13604
  } finally {
13444
- options.budget.setRetainedValues(definedValues, void 0);
13605
+ release();
13445
13606
  }
13446
13607
  }
13447
- async function compareEntries(left, right, comparator, options, stack) {
13448
- options.budget.visitNode();
13449
- if (comparator === void 0) {
13450
- const leftString = await sandboxString(left, options.budget, options.context);
13451
- const release = retainValues(options.budget, () => [leftString]);
13452
- try {
13453
- const rightString = await sandboxString(right, options.budget, options.context);
13454
- return leftString < rightString ? -1 : leftString > rightString ? 1 : 0;
13455
- } finally {
13456
- 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;
13457
13679
  }
13458
- }
13459
- const result = await sandboxNumber(
13460
- await options.callClosure(comparator, [left, right], stack),
13461
- options.budget,
13462
- options.context
13463
- );
13464
- return Number.isNaN(result) ? 0 : result;
13465
- }
13466
- async function callArrayCallback(callback, value, index, array2, options, stack, thisValue) {
13467
- return options.callClosure(
13468
- callback,
13469
- [value, index, arrayLikeSources.get(array2) ?? array2],
13470
- stack,
13471
- thisValue
13472
- );
13680
+ });
13681
+ classOrigins.set(constructor, { node, scope, fields: fields2, initialized: false });
13682
+ return constructor;
13473
13683
  }
13474
- function findNextDefinedIndex(value, startIndex, direction, length, budget) {
13475
- for (let index = startIndex; direction > 0 ? index < length : index >= 0; index += direction) {
13476
- budget.visitNode();
13477
- if (index in value) {
13478
- return index;
13479
- }
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;
13480
13696
  }
13481
- return -1;
13482
- }
13483
- function budgetProducedValue(value, budget) {
13484
- if (typeof value === "object" && value !== null) value = arrayLikeSources.get(value) ?? value;
13485
- allocateProducedValue(value, budget, /* @__PURE__ */ new WeakSet());
13486
- return value;
13487
- }
13488
- function allocateProducedValue(value, budget, seen) {
13489
- if (typeof value === "string") {
13490
- budget.allocateString(value);
13491
- return;
13697
+ if ("key" in definition) {
13698
+ defineDataProperty(receiver, definition.key, { value, configurable: true, writable: true, enumerable: true }, context.budget);
13492
13699
  }
13493
- if (Array.isArray(value)) {
13494
- budget.allocateArrayLength(value.length);
13495
- if (seen.has(value)) {
13496
- return;
13497
- }
13498
- seen.add(value);
13499
- for (const entry of value) {
13500
- allocateProducedValue(entry, budget, seen);
13501
- }
13502
- 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;
13503
13706
  }
13504
- if (isSandboxMap(value)) {
13505
- budget.allocateCollectionEntries(value.entries.size);
13506
- if (seen.has(value)) {
13507
- return;
13508
- }
13509
- seen.add(value);
13510
- for (const [key, entry] of value.entries) {
13511
- allocateProducedValue(key, budget, seen);
13512
- allocateProducedValue(entry, budget, seen);
13513
- }
13514
- return;
13707
+ if (node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression") {
13708
+ return false;
13515
13709
  }
13516
- if (isSandboxSet(value)) {
13517
- budget.allocateCollectionEntries(value.values.size);
13518
- if (seen.has(value)) {
13519
- 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;
13520
13716
  }
13521
- seen.add(value);
13522
- for (const entry of value.values) {
13523
- allocateProducedValue(entry, budget, seen);
13717
+ if (isParseResult(value) && containsResumeTarget(value, targetNodeIds)) {
13718
+ return true;
13524
13719
  }
13525
- return;
13526
- }
13527
- if (typeof value !== "object" || value === null || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value)) {
13528
- return;
13529
- }
13530
- if (seen.has(value)) {
13531
- return;
13532
- }
13533
- seen.add(value);
13534
- for (const entry of Object.values(value)) {
13535
- allocateProducedValue(entry, budget, seen);
13536
13720
  }
13721
+ return false;
13537
13722
  }
13538
- function toIntegerOrInfinity(value) {
13539
- const number = Number(value);
13540
- if (Number.isNaN(number) || Object.is(number, 0) || Object.is(number, -0)) {
13541
- return 0;
13542
- }
13543
- if (!Number.isFinite(number)) {
13544
- return number;
13545
- }
13546
- return Math.trunc(number);
13723
+ function isParseResult(value) {
13724
+ return typeof value === "object" && value !== null && typeof value.type === "string" && Object.hasOwn(value, "span");
13547
13725
  }
13548
13726
 
13549
13727
  // packages/safe-js/src/interp/function-string.ts
@@ -16632,7 +16810,7 @@ async function evaluateMemberCallExpression(node, context) {
16632
16810
  property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
16633
16811
  };
16634
16812
  if (context.generatorYield !== void 0 && node.arguments.some((argument) => containsResumeTarget(argument.type === "SpreadElement" ? argument.argument : argument))) {
16635
- 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))
16636
16814
  return evaluateArrayMethodCall(node, member.object, member.property, context);
16637
16815
  const receiver = member.superReceiver?.value ?? member.object;
16638
16816
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context, receiver), context, receiver);
@@ -16645,6 +16823,8 @@ async function evaluateMemberCallExpression(node, context) {
16645
16823
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
16646
16824
  if (Array.isArray(member.object) && hasExplicitSandboxPrototype(member.object))
16647
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);
16648
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) {
16649
16829
  if (isDefaultBoxedMethod(member.object, member.property, context.budget)) {
16650
16830
  if (typeof member.object === "string" && isStringMethodName(member.property))
@@ -16688,6 +16868,8 @@ async function evaluateMemberCallExpression(node, context) {
16688
16868
  );
16689
16869
  }
16690
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);
16691
16873
  return evaluatePrimitiveMemberCall(
16692
16874
  node,
16693
16875
  "Array",
@@ -17259,6 +17441,7 @@ function getArrayMemberValue(target, property, context) {
17259
17441
  if (property === "raw" && templateRawArrays.has(target)) {
17260
17442
  return templateRawArrays.get(target);
17261
17443
  }
17444
+ if (getSandboxPrototype(target, context.budget) !== null) return void 0;
17262
17445
  return getArrayMember(target, property, createArrayMethodOptions(context));
17263
17446
  }
17264
17447
  function setSandboxProperty(target, property, value, budget, checkInherited = true, context) {
@@ -17911,7 +18094,7 @@ async function objectToPrimitive(value, budget, context, joining, hint, ordinary
17911
18094
  }
17912
18095
  }
17913
18096
  function conversionHook(value, name, budget, context) {
17914
- 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));
17915
18098
  let current = value;
17916
18099
  let depth = 0;
17917
18100
  while (current !== null) {
@@ -18029,6 +18212,20 @@ function createObjectGlobal(methods, budget) {
18029
18212
  Object.defineProperty(properties, name, { value: method, writable: true, configurable: true });
18030
18213
  }
18031
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
+ }),
18032
18229
  toString: createSandboxClosure({
18033
18230
  sandbox: true,
18034
18231
  name: "toString",
@@ -23642,6 +23839,17 @@ function createBigIntGlobal(budget) {
23642
23839
  writable: true,
23643
23840
  configurable: true
23644
23841
  },
23842
+ toLocaleString: {
23843
+ value: createSandboxClosure({
23844
+ guest: true,
23845
+ sandbox: true,
23846
+ name: "toLocaleString",
23847
+ length: 0,
23848
+ call: (args, context) => formatNumberLocale(primitiveReceiver(context?.thisValue, "bigint"), args, budget, context)
23849
+ }),
23850
+ writable: true,
23851
+ configurable: true
23852
+ },
23645
23853
  [Symbol.toStringTag]: { value: "BigInt", configurable: true }
23646
23854
  });
23647
23855
  const properties = materializeFunctionProperties(constructor);
@@ -40519,4 +40727,4 @@ export {
40519
40727
  FileSnapshotBackend,
40520
40728
  run
40521
40729
  };
40522
- //# sourceMappingURL=chunk-ZOLHW4OV.js.map
40730
+ //# sourceMappingURL=chunk-SZZFUQKW.js.map