@poe-platform/safe-js 0.1.89 → 0.1.91

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.
@@ -6997,26 +6997,8 @@ function getSandboxPrototype(value, budget) {
6997
6997
  if (prototypes.has(value)) return prototypes.get(value) ?? null;
6998
6998
  return budget !== void 0 && isPrototypeRecord(value) ? intrinsicPrototypes.get(budget) ?? null : null;
6999
6999
  }
7000
- function getSandboxDataProperty(value, key, budget) {
7001
- let current = value;
7002
- let depth = 0;
7003
- while (typeof current === "object" && current !== null) {
7004
- if (isGuestHostObject(current)) return getHostObjectMember(current, String(key));
7005
- if (isGuestClosure(current)) return getGuestFunctionProperty(current, String(key));
7006
- if (isSandboxClosure(current)) {
7007
- const properties = current.properties;
7008
- return properties !== void 0 && Object.hasOwn(properties, String(key)) ? properties[String(key)] : void 0;
7009
- }
7010
- if (isSandboxMap(current) || isSandboxSet(current) || isSandboxPromise(current) || isSandboxRegex(current) || isSandboxGenerator(current))
7011
- return void 0;
7012
- if (Object.hasOwn(current, String(key))) return current[String(key)];
7013
- current = getSandboxPrototype(current, budget);
7014
- if (current !== null) {
7015
- budget?.visitNode();
7016
- assertSandboxDataDepth(++depth);
7017
- }
7018
- }
7019
- return void 0;
7000
+ function hasExplicitSandboxPrototype(value) {
7001
+ return prototypes.has(value);
7020
7002
  }
7021
7003
  function setSandboxPrototype(value, prototype, budget) {
7022
7004
  if (budget !== void 0 && intrinsicPrototypes.get(budget) === value && prototype !== null) {
@@ -8178,179 +8160,500 @@ function isCounter(value) {
8178
8160
  // packages/safe-js/src/interp/cancel.ts
8179
8161
  import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
8180
8162
 
8181
- // packages/safe-js/src/interp/string-coercion.ts
8182
- function sandboxString(value, budget, context, joining = /* @__PURE__ */ new Set()) {
8183
- if (value === null || typeof value !== "object") {
8184
- if (typeof value === "function") throw new TypeError("Expected a sandbox value.");
8185
- return budget.allocateString(String(value));
8186
- }
8187
- return stringifyObject(value, budget, context, joining);
8163
+ // packages/safe-js/src/interp/regex/engine.ts
8164
+ function matchRegex(pattern, input, lastIndex = 0) {
8165
+ const startIndex = pattern.flags.global ? normalizeLastIndex(lastIndex) : 0;
8166
+ return matchRegexFrom(pattern, input, startIndex);
8188
8167
  }
8189
- async function stringifyObject(value, budget, context, joining) {
8190
- const leaveCall = budget.enterCall();
8191
- try {
8192
- budget.visitNode();
8193
- for (const name of ["toString", "valueOf"]) {
8194
- const descriptor = Object.getOwnPropertyDescriptor(value, name);
8195
- let result;
8196
- if (descriptor === void 0) {
8197
- if (name === "valueOf") continue;
8198
- result = await defaultToString(value, budget, context, joining);
8199
- } else {
8200
- const hook = ownDataValue(value, name);
8201
- if (!isSandboxClosure(hook)) continue;
8202
- if (context?.invokeClosure === void 0) {
8203
- throw new TypeError("String hooks require a sandbox call context.");
8204
- }
8205
- result = await context.invokeClosure(hook, [], value);
8206
- }
8207
- if (result === null || typeof result !== "object") {
8208
- return sandboxString(result, budget, context, joining);
8209
- }
8168
+ function matchRegexFrom(pattern, input, startIndex) {
8169
+ if (startIndex > input.length) {
8170
+ return null;
8171
+ }
8172
+ for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
8173
+ const context = { input, flags: pattern.flags, steps: 0 };
8174
+ charge(context);
8175
+ const initialState = {
8176
+ position: attempt,
8177
+ captures: new Array(pattern.captureCount)
8178
+ };
8179
+ const result = matchNode(pattern.body, initialState, context).next();
8180
+ if (!result.done) {
8181
+ return toRegexMatch(input, attempt, result.value);
8210
8182
  }
8211
- throw new TypeError("Cannot convert object to primitive value");
8212
- } finally {
8213
- leaveCall();
8214
8183
  }
8184
+ return null;
8215
8185
  }
8216
- async function defaultToString(value, budget, context, joining) {
8217
- if (isSandboxDate(value)) return budget.allocateString(dateString(value));
8218
- if (Array.isArray(value) || isFloat32Array(value)) {
8219
- if (Object.hasOwn(value, "join")) {
8220
- const join = ownDataValue(value, "join");
8221
- if (!isSandboxClosure(join))
8222
- return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
8223
- if (context?.invokeClosure === void 0) {
8224
- throw new TypeError("String hooks require a sandbox call context.");
8186
+ function* matchNode(node, state, context) {
8187
+ charge(context);
8188
+ switch (node.type) {
8189
+ case "empty":
8190
+ yield state;
8191
+ return;
8192
+ case "literal":
8193
+ if (charactersEqual(context.input[state.position], node.value, context.flags.ignoreCase)) {
8194
+ yield { ...state, position: state.position + 1 };
8225
8195
  }
8226
- return context.invokeClosure(join, [], value);
8196
+ return;
8197
+ case "dot":
8198
+ if (state.position < context.input.length && (context.flags.dotAll || !isLineTerminator(context.input[state.position]))) {
8199
+ yield { ...state, position: state.position + 1 };
8200
+ }
8201
+ return;
8202
+ case "anchor":
8203
+ if (matchesAnchor(node.kind, state.position, context)) {
8204
+ yield state;
8205
+ }
8206
+ return;
8207
+ case "wordBoundary": {
8208
+ const previousWord = state.position > 0 && isWordCharacter(context.input[state.position - 1]);
8209
+ const nextWord = state.position < context.input.length && isWordCharacter(context.input[state.position]);
8210
+ if (previousWord !== nextWord !== node.negated) {
8211
+ yield state;
8212
+ }
8213
+ return;
8227
8214
  }
8228
- if (joining.has(value)) return "";
8229
- joining.add(value);
8230
- try {
8231
- const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
8232
- let text = "";
8233
- for (let index = 0; index < length; index++) {
8234
- budget.visitNode();
8235
- const element = ownDataValue(value, String(index));
8236
- const part = element === null || element === void 0 ? "" : await sandboxString(element, budget, context, joining);
8237
- text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
8215
+ case "characterClass": {
8216
+ const character = context.input[state.position];
8217
+ if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context.flags.ignoreCase)) {
8218
+ yield { ...state, position: state.position + 1 };
8238
8219
  }
8239
- return text;
8240
- } finally {
8241
- joining.delete(value);
8220
+ return;
8242
8221
  }
8222
+ case "sequence":
8223
+ yield* matchSequence(node.elements, 0, state, context);
8224
+ return;
8225
+ case "alternation":
8226
+ for (const alternative of node.alternatives) {
8227
+ yield* matchNode(alternative, cloneState(state), context);
8228
+ }
8229
+ return;
8230
+ case "group":
8231
+ for (const result of matchNode(node.body, cloneState(state), context)) {
8232
+ if (!node.capturing || node.index === void 0) {
8233
+ yield result;
8234
+ continue;
8235
+ }
8236
+ const captures = result.captures.slice();
8237
+ captures[node.index - 1] = { start: state.position, end: result.position };
8238
+ yield { position: result.position, captures };
8239
+ }
8240
+ return;
8241
+ case "quantifier":
8242
+ yield* matchQuantifier(node, state, context, 0);
8243
8243
  }
8244
- if (sandboxErrorTypes.has(value)) {
8245
- const nameValue = ownDataValue(value, "name");
8246
- const name = nameValue === void 0 ? "Error" : await sandboxString(nameValue, budget, context, joining);
8247
- const messageValue = ownDataValue(value, "message");
8248
- const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
8249
- return name === "" ? message : message === "" ? name : `${name}: ${message}`;
8250
- }
8251
- return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
8252
8244
  }
8253
- function ownDataValue(value, name) {
8254
- const descriptor = Object.getOwnPropertyDescriptor(value, name);
8255
- if (descriptor !== void 0 && !Object.hasOwn(descriptor, "value")) {
8256
- throw new TypeError("String conversion requires sandbox data properties.");
8245
+ function* matchSequence(elements, index, state, context) {
8246
+ charge(context);
8247
+ if (index === elements.length) {
8248
+ yield state;
8249
+ return;
8250
+ }
8251
+ for (const result of matchNode(elements[index], state, context)) {
8252
+ yield* matchSequence(elements, index + 1, result, context);
8257
8253
  }
8258
- return descriptor?.value;
8259
8254
  }
8260
-
8261
- // packages/safe-js/src/interp/property-key.ts
8262
- async function toPropertyKey(value, budget, context) {
8263
- if (typeof value === "string") return value;
8264
- const invocation = context.invokeClosure === void 0 ? {
8265
- ...context,
8266
- invokeClosure: async (closure, args, thisValue) => {
8267
- const leaveCall = budget.enterCall();
8268
- try {
8269
- const result = closure.call(args, { ...invocation, thisValue });
8270
- if (isSandboxPromise(result)) {
8271
- await result.synchronousPrefix;
8272
- return result;
8255
+ function* matchQuantifier(node, state, context, count) {
8256
+ charge(context);
8257
+ const canRepeat = node.max === void 0 || count < node.max;
8258
+ if (!node.greedy && count >= node.min) {
8259
+ yield state;
8260
+ }
8261
+ if (canRepeat) {
8262
+ for (const result of matchNode(node.body, clearCaptures(node.body, state), context)) {
8263
+ if (result.position === state.position) {
8264
+ if (count >= node.min) {
8265
+ continue;
8273
8266
  }
8274
- return await result;
8275
- } finally {
8276
- leaveCall();
8277
- }
8278
- }
8279
- } : context;
8280
- if (typeof value === "object" && value !== null && !Array.isArray(value) && !isSandboxClosure(value) && !isSandboxMap(value) && !isSandboxSet(value) && !isSandboxPromise(value) && !isSandboxRegex(value) && !isSandboxDate(value) && !isFloat32Array(value) && !isSandboxGenerator(value) && !isGuestHostObject(value)) {
8281
- for (const name of ["toString", "valueOf"]) {
8282
- const method = getSandboxDataProperty(value, name, budget);
8283
- if (!isSandboxClosure(method)) continue;
8284
- const primitive = await invocation.invokeClosure(method, [], value);
8285
- if (primitive === null || typeof primitive !== "object") {
8286
- return budget.allocateString(String(primitive));
8267
+ if (count + 1 >= node.min) {
8268
+ yield result;
8269
+ } else {
8270
+ yield* matchQuantifier(node, result, context, count + 1);
8271
+ }
8272
+ continue;
8287
8273
  }
8274
+ yield* matchQuantifier(node, result, context, count + 1);
8288
8275
  }
8289
- throw new TypeError("Cannot convert object to primitive value.");
8290
8276
  }
8291
- return sandboxString(value, budget, invocation);
8292
- }
8293
-
8294
- // packages/safe-js/src/interp/exceptions.ts
8295
- var capturedExceptionBrand = /* @__PURE__ */ Symbol("CapturedException");
8296
- async function evaluateThrowStatement(node, context, evaluateNode2) {
8297
- const argument = await evaluateNode2(node.argument, context);
8298
- if (argument.kind !== "normal") {
8299
- return argument;
8277
+ if (node.greedy && count >= node.min) {
8278
+ yield state;
8300
8279
  }
8301
- return {
8302
- kind: "throw",
8303
- hasValue: true,
8304
- span: node.span,
8305
- stackFrames: context.callStack,
8306
- value: argument.value
8307
- };
8308
8280
  }
8309
- async function evaluateTryStatement(node, context, evaluateNode2) {
8310
- let fatalBudgetError;
8311
- let tryResult;
8312
- try {
8313
- tryResult = await evaluateBlockCompletion(node.block, context, evaluateNode2);
8314
- } catch (error) {
8315
- if (!isBudgetExceeded(error) || node.finalizer === void 0) {
8316
- throw error;
8317
- }
8318
- fatalBudgetError = error;
8319
- tryResult = {
8320
- kind: "throw",
8321
- hasValue: true,
8322
- value: void 0
8323
- };
8324
- }
8325
- const tryOrCatchResult = fatalBudgetError === void 0 && tryResult.kind === "throw" && node.handler !== void 0 ? await evaluateCatchClause(node.handler, tryResult.value, context, evaluateNode2) : tryResult;
8326
- if (node.finalizer === void 0 || tryOrCatchResult.kind === "error") {
8327
- return tryOrCatchResult;
8328
- }
8329
- const evaluateFinalizer = () => fatalBudgetError?.budget === "deadline" ? evaluateWithoutDeadlineChecks(
8330
- context,
8331
- () => evaluateBlockCompletion(node.finalizer, context, evaluateNode2)
8332
- ) : evaluateBlockCompletion(node.finalizer, context, evaluateNode2);
8333
- const finalizerResult = await (fatalBudgetError === void 0 ? evaluateFinalizer() : withFatalPromiseCleanup(evaluateFinalizer));
8334
- if (fatalBudgetError !== void 0) {
8335
- throw fatalBudgetError;
8336
- }
8337
- if (finalizerResult.kind === "normal") {
8338
- return tryOrCatchResult;
8281
+ function matchesAnchor(kind, position, context) {
8282
+ if (kind === "start") {
8283
+ return position === 0 || context.flags.multiline && position > 0 && isLineTerminator(context.input[position - 1]);
8339
8284
  }
8340
- return finalizerResult;
8341
- }
8342
- function createCapturedException(reason, stackFrames, sandbox = false) {
8343
- return {
8344
- reason,
8345
- sandbox,
8346
- stackFrames,
8347
- [capturedExceptionBrand]: true
8348
- };
8285
+ return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
8349
8286
  }
8350
- function isCapturedException(value) {
8351
- return typeof value === "object" && value !== null && capturedExceptionBrand in value;
8287
+ function matchesCharacterClass(character, items, negated, ignoreCase) {
8288
+ const matched = items.some((item) => matchesCharacterClassItem(character, item, ignoreCase));
8289
+ return negated ? !matched : matched;
8352
8290
  }
8353
- function coerceThrownValue(reason, budget, stackFrames, span, sandbox = false) {
8291
+ function matchesCharacterClassItem(character, item, ignoreCase) {
8292
+ if (item.type === "character") {
8293
+ return charactersEqual(character, item.value, ignoreCase);
8294
+ }
8295
+ if (item.type === "range") {
8296
+ const candidate = character.charCodeAt(0);
8297
+ const from = item.from.charCodeAt(0);
8298
+ const to = item.to.charCodeAt(0);
8299
+ if (candidate >= from && candidate <= to) {
8300
+ return true;
8301
+ }
8302
+ if (!ignoreCase) {
8303
+ return false;
8304
+ }
8305
+ const foldedCandidate = foldCharacter(character, true).charCodeAt(0);
8306
+ const foldedFrom = foldCharacter(item.from, true).charCodeAt(0);
8307
+ const foldedTo = foldCharacter(item.to, true).charCodeAt(0);
8308
+ return foldedCandidate >= foldedFrom && foldedCandidate <= foldedTo;
8309
+ }
8310
+ const matched = item.kind === "digit" ? isDigit(character) : item.kind === "word" ? isWordCharacter(character) : isSpaceCharacter(character);
8311
+ return item.negated ? !matched : matched;
8312
+ }
8313
+ function toRegexMatch(input, start, state) {
8314
+ return {
8315
+ index: start,
8316
+ text: input.slice(start, state.position),
8317
+ captures: state.captures.map(
8318
+ (capture) => capture === void 0 ? void 0 : input.slice(capture.start, capture.end)
8319
+ )
8320
+ };
8321
+ }
8322
+ function cloneState(state) {
8323
+ return { position: state.position, captures: state.captures.slice() };
8324
+ }
8325
+ function clearCaptures(node, state) {
8326
+ const captures = state.captures.slice();
8327
+ clearNodeCaptures(node, captures);
8328
+ return { position: state.position, captures };
8329
+ }
8330
+ function clearNodeCaptures(node, captures) {
8331
+ if (node.type === "group") {
8332
+ if (node.capturing && node.index !== void 0) {
8333
+ captures[node.index - 1] = void 0;
8334
+ }
8335
+ clearNodeCaptures(node.body, captures);
8336
+ return;
8337
+ }
8338
+ if (node.type === "sequence") {
8339
+ for (const element of node.elements) {
8340
+ clearNodeCaptures(element, captures);
8341
+ }
8342
+ return;
8343
+ }
8344
+ if (node.type === "alternation") {
8345
+ for (const alternative of node.alternatives) {
8346
+ clearNodeCaptures(alternative, captures);
8347
+ }
8348
+ return;
8349
+ }
8350
+ if (node.type === "quantifier") {
8351
+ clearNodeCaptures(node.body, captures);
8352
+ }
8353
+ }
8354
+ function charge(context) {
8355
+ context.steps += 1;
8356
+ allocateRegexSteps(context.steps);
8357
+ }
8358
+ function normalizeLastIndex(lastIndex) {
8359
+ if (!Number.isFinite(lastIndex) || lastIndex <= 0) {
8360
+ return 0;
8361
+ }
8362
+ return Math.floor(lastIndex);
8363
+ }
8364
+ function charactersEqual(left, right, ignoreCase) {
8365
+ return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
8366
+ }
8367
+ function foldCharacter(character, ignoreCase) {
8368
+ if (!ignoreCase) {
8369
+ return character;
8370
+ }
8371
+ const folded = character.toUpperCase();
8372
+ if (folded.length !== 1) {
8373
+ return character;
8374
+ }
8375
+ if (character.charCodeAt(0) >= 128 && folded.charCodeAt(0) < 128) {
8376
+ return character;
8377
+ }
8378
+ return folded;
8379
+ }
8380
+ function isDigit(character) {
8381
+ return character >= "0" && character <= "9";
8382
+ }
8383
+ function isWordCharacter(character) {
8384
+ return isDigit(character) || character >= "A" && character <= "Z" || character >= "a" && character <= "z" || character === "_";
8385
+ }
8386
+ function isSpaceCharacter(character) {
8387
+ return character === " " || character === "\f" || character === "\n" || character === "\r" || character === " " || character === "\v" || character === "\xA0" || character === "\u1680" || character >= "\u2000" && character <= "\u200A" || character === "\u2028" || character === "\u2029" || character === "\u202F" || character === "\u205F" || character === "\u3000" || character === "\uFEFF";
8388
+ }
8389
+ function isLineTerminator(character) {
8390
+ return character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029";
8391
+ }
8392
+
8393
+ // packages/safe-js/src/interp/methods/regex.ts
8394
+ var regexMethodNames = /* @__PURE__ */ new Set(["exec", "test"]);
8395
+ function isRegexMethodName(property) {
8396
+ return typeof property === "string" && regexMethodNames.has(property);
8397
+ }
8398
+ function getRegexMember(target, property, budget) {
8399
+ if (property === "source") return escapeRegexSource(target.source, budget);
8400
+ if (property === "flags") {
8401
+ const flags = [..."gims"].filter((flag) => target.flags.includes(flag)).join("");
8402
+ return budget === void 0 ? flags : budget.allocateString(flags);
8403
+ }
8404
+ if (property === "lastIndex") return target.lastIndex;
8405
+ if (!isRegexMethodName(property)) {
8406
+ return void 0;
8407
+ }
8408
+ return createSandboxClosure({
8409
+ sandbox: true,
8410
+ name: `RegExp#${property}`,
8411
+ call: (args) => callRegexMethod(target, property, args)
8412
+ });
8413
+ }
8414
+ function escapeRegexSource(source, budget) {
8415
+ let text = "";
8416
+ let escaped = false;
8417
+ let inClass = false;
8418
+ for (const character of source) {
8419
+ budget?.visitNode();
8420
+ if (character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029") {
8421
+ if (escaped) text = text.slice(0, -1);
8422
+ text += character === "\n" ? "\\n" : character === "\r" ? "\\r" : character === "\u2028" ? "\\u2028" : "\\u2029";
8423
+ escaped = false;
8424
+ } else {
8425
+ if (!escaped && character === "[") inClass = true;
8426
+ if (!escaped && character === "]") inClass = false;
8427
+ text += character === "/" && !escaped && !inClass ? "\\/" : character;
8428
+ escaped = character === "\\" && !escaped;
8429
+ }
8430
+ budget?.allocateString(text);
8431
+ }
8432
+ text = text === "" ? "(?:)" : text;
8433
+ return budget === void 0 ? text : budget.allocateString(text);
8434
+ }
8435
+ function setRegexMember(target, property, value) {
8436
+ if (property !== "lastIndex") {
8437
+ throw new TypeError(`RegExp#${String(property)} is not writable.`);
8438
+ }
8439
+ target.lastIndex = Number(value);
8440
+ }
8441
+ function callRegexMethod(target, methodName, args) {
8442
+ const match = executeRegex(target, String(args[0]));
8443
+ return methodName === "test" ? match !== null : toMatchArray(match, String(args[0]));
8444
+ }
8445
+ function executeRegex(target, input) {
8446
+ const pattern = getSandboxRegexPattern(target);
8447
+ const match = matchRegex(pattern, input, target.lastIndex);
8448
+ if (pattern.flags.global) {
8449
+ target.lastIndex = match === null ? 0 : match.index + match.text.length;
8450
+ }
8451
+ return match;
8452
+ }
8453
+ function toMatchArray(match, input) {
8454
+ if (match === null) {
8455
+ return null;
8456
+ }
8457
+ const result = [match.text, ...match.captures];
8458
+ Object.assign(result, { index: match.index, input, groups: void 0 });
8459
+ return result;
8460
+ }
8461
+
8462
+ // packages/safe-js/src/interp/string-coercion.ts
8463
+ var defaultStringHook = /* @__PURE__ */ Symbol("defaultStringHook");
8464
+ function sandboxString(value, budget, context, joining = /* @__PURE__ */ new Set()) {
8465
+ if (value === null || typeof value !== "object") {
8466
+ if (typeof value === "function") throw new TypeError("Expected a sandbox value.");
8467
+ return budget.allocateString(String(value));
8468
+ }
8469
+ const invocation = context?.invokeClosure !== void 0 ? context : {
8470
+ ...context,
8471
+ stack: context?.stack ?? [],
8472
+ thisValue: context?.thisValue,
8473
+ invokeClosure: async (closure, args, thisValue) => {
8474
+ const leaveCall = budget.enterCall();
8475
+ try {
8476
+ const result = closure.call(args, { ...invocation, thisValue });
8477
+ if (isSandboxPromise(result)) {
8478
+ await result.synchronousPrefix;
8479
+ return result;
8480
+ }
8481
+ return await result;
8482
+ } finally {
8483
+ leaveCall();
8484
+ }
8485
+ }
8486
+ };
8487
+ return stringifyObject(value, budget, invocation, joining);
8488
+ }
8489
+ async function stringifyObject(value, budget, context, joining) {
8490
+ const leaveCall = budget.enterCall();
8491
+ try {
8492
+ budget.visitNode();
8493
+ for (const name of ["toString", "valueOf"]) {
8494
+ const hook = conversionHook(value, name, budget);
8495
+ let result;
8496
+ if (hook === defaultStringHook) {
8497
+ result = await defaultToString(value, budget, context, joining);
8498
+ } else {
8499
+ if (!isSandboxClosure(hook)) continue;
8500
+ if (context?.invokeClosure === void 0) {
8501
+ throw new TypeError("String hooks require a sandbox call context.");
8502
+ }
8503
+ result = await context.invokeClosure(hook, [], value);
8504
+ }
8505
+ if (result === null || typeof result !== "object") {
8506
+ return sandboxString(result, budget, context, joining);
8507
+ }
8508
+ }
8509
+ throw new TypeError("Cannot convert object to primitive value");
8510
+ } finally {
8511
+ leaveCall();
8512
+ }
8513
+ }
8514
+ function conversionHook(value, name, budget) {
8515
+ const implicitBuiltin = !hasExplicitSandboxPrototype(value) && (Array.isArray(value) || isSandboxDate(value) || isFloat32Array(value) || sandboxErrorTypes.has(value) || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value) || isSandboxRegex(value) || isSandboxGenerator(value) || isGuestHostObject(value));
8516
+ let current = value;
8517
+ let depth = 0;
8518
+ while (current !== null) {
8519
+ const properties = isGuestClosure(current) ? getGuestFunctionProperties(current) : current;
8520
+ const descriptor = properties === void 0 ? void 0 : Object.getOwnPropertyDescriptor(properties, name);
8521
+ if (descriptor !== void 0) {
8522
+ if (!Object.hasOwn(descriptor, "value"))
8523
+ throw new TypeError("String conversion requires sandbox data properties.");
8524
+ return descriptor.value;
8525
+ }
8526
+ const parent = getSandboxPrototype(current, budget);
8527
+ if (current === value && (implicitBuiltin || parent === null && !hasExplicitSandboxPrototype(value))) {
8528
+ return name === "toString" ? defaultStringHook : void 0;
8529
+ }
8530
+ current = parent;
8531
+ if (current !== null) {
8532
+ budget.visitNode();
8533
+ assertSandboxDataDepth(++depth);
8534
+ }
8535
+ }
8536
+ return void 0;
8537
+ }
8538
+ async function defaultToString(value, budget, context, joining) {
8539
+ if (isSandboxMap(value)) return "[object Map]";
8540
+ if (isSandboxSet(value)) return "[object Set]";
8541
+ if (isSandboxGenerator(value)) return "[object Generator]";
8542
+ if (isSandboxRegex(value)) {
8543
+ return budget.allocateString(
8544
+ `/${getRegexMember(value, "source", budget)}/${getRegexMember(value, "flags", budget)}`
8545
+ );
8546
+ }
8547
+ if (isSandboxDate(value)) return budget.allocateString(dateString(value));
8548
+ if (Array.isArray(value) || isFloat32Array(value)) {
8549
+ if (Object.hasOwn(value, "join")) {
8550
+ const join = ownDataValue(value, "join");
8551
+ if (!isSandboxClosure(join))
8552
+ return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
8553
+ if (context?.invokeClosure === void 0) {
8554
+ throw new TypeError("String hooks require a sandbox call context.");
8555
+ }
8556
+ return context.invokeClosure(join, [], value);
8557
+ }
8558
+ if (joining.has(value)) return "";
8559
+ joining.add(value);
8560
+ try {
8561
+ const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
8562
+ let text = "";
8563
+ for (let index = 0; index < length; index++) {
8564
+ budget.visitNode();
8565
+ const element = ownDataValue(value, String(index));
8566
+ const part = element === null || element === void 0 ? "" : await sandboxString(element, budget, context, joining);
8567
+ text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
8568
+ }
8569
+ return text;
8570
+ } finally {
8571
+ joining.delete(value);
8572
+ }
8573
+ }
8574
+ if (sandboxErrorTypes.has(value)) {
8575
+ const nameValue = ownDataValue(value, "name");
8576
+ const name = nameValue === void 0 ? "Error" : await sandboxString(nameValue, budget, context, joining);
8577
+ const messageValue = ownDataValue(value, "message");
8578
+ const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
8579
+ return name === "" ? message : message === "" ? name : `${name}: ${message}`;
8580
+ }
8581
+ return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
8582
+ }
8583
+ function ownDataValue(value, name) {
8584
+ const descriptor = Object.getOwnPropertyDescriptor(value, name);
8585
+ if (descriptor !== void 0 && !Object.hasOwn(descriptor, "value")) {
8586
+ throw new TypeError("String conversion requires sandbox data properties.");
8587
+ }
8588
+ return descriptor?.value;
8589
+ }
8590
+
8591
+ // packages/safe-js/src/interp/property-key.ts
8592
+ async function toPropertyKey(value, budget, context) {
8593
+ if (typeof value === "string") return value;
8594
+ return sandboxString(value, budget, context);
8595
+ }
8596
+
8597
+ // packages/safe-js/src/interp/exceptions.ts
8598
+ var capturedExceptionBrand = /* @__PURE__ */ Symbol("CapturedException");
8599
+ async function evaluateThrowStatement(node, context, evaluateNode2) {
8600
+ const argument = await evaluateNode2(node.argument, context);
8601
+ if (argument.kind !== "normal") {
8602
+ return argument;
8603
+ }
8604
+ return {
8605
+ kind: "throw",
8606
+ hasValue: true,
8607
+ span: node.span,
8608
+ stackFrames: context.callStack,
8609
+ value: argument.value
8610
+ };
8611
+ }
8612
+ async function evaluateTryStatement(node, context, evaluateNode2) {
8613
+ let fatalBudgetError;
8614
+ let tryResult;
8615
+ try {
8616
+ tryResult = await evaluateBlockCompletion(node.block, context, evaluateNode2);
8617
+ } catch (error) {
8618
+ if (!isBudgetExceeded(error) || node.finalizer === void 0) {
8619
+ throw error;
8620
+ }
8621
+ fatalBudgetError = error;
8622
+ tryResult = {
8623
+ kind: "throw",
8624
+ hasValue: true,
8625
+ value: void 0
8626
+ };
8627
+ }
8628
+ const tryOrCatchResult = fatalBudgetError === void 0 && tryResult.kind === "throw" && node.handler !== void 0 ? await evaluateCatchClause(node.handler, tryResult.value, context, evaluateNode2) : tryResult;
8629
+ if (node.finalizer === void 0 || tryOrCatchResult.kind === "error") {
8630
+ return tryOrCatchResult;
8631
+ }
8632
+ const evaluateFinalizer = () => fatalBudgetError?.budget === "deadline" ? evaluateWithoutDeadlineChecks(
8633
+ context,
8634
+ () => evaluateBlockCompletion(node.finalizer, context, evaluateNode2)
8635
+ ) : evaluateBlockCompletion(node.finalizer, context, evaluateNode2);
8636
+ const finalizerResult = await (fatalBudgetError === void 0 ? evaluateFinalizer() : withFatalPromiseCleanup(evaluateFinalizer));
8637
+ if (fatalBudgetError !== void 0) {
8638
+ throw fatalBudgetError;
8639
+ }
8640
+ if (finalizerResult.kind === "normal") {
8641
+ return tryOrCatchResult;
8642
+ }
8643
+ return finalizerResult;
8644
+ }
8645
+ function createCapturedException(reason, stackFrames, sandbox = false) {
8646
+ return {
8647
+ reason,
8648
+ sandbox,
8649
+ stackFrames,
8650
+ [capturedExceptionBrand]: true
8651
+ };
8652
+ }
8653
+ function isCapturedException(value) {
8654
+ return typeof value === "object" && value !== null && capturedExceptionBrand in value;
8655
+ }
8656
+ function coerceThrownValue(reason, budget, stackFrames, span, sandbox = false) {
8354
8657
  if (reason instanceof HostCallResumabilityError) {
8355
8658
  throw reason;
8356
8659
  }
@@ -24185,399 +24488,127 @@ async function callMapMethod(target, methodName, args, options, stack = []) {
24185
24488
  target.entries.clear();
24186
24489
  updateKeyedCollectionCallbacks(target, "clear");
24187
24490
  return void 0;
24188
- case "forEach": {
24189
- const callback = args[0];
24190
- if (!isSandboxClosure(callback)) {
24191
- throw new TypeError("Map.prototype.forEach requires a callback function.");
24192
- }
24193
- const cursor = enterKeyedCollectionCallback(target, target.entries.keys(), options.budget);
24194
- try {
24195
- for (let entry = cursor.next(); !entry.done; entry = cursor.next()) {
24196
- const key = entry.value;
24197
- const value = target.entries.get(key);
24198
- await options.callClosure(callback, [value, key, target], stack, args[1]);
24199
- }
24200
- } finally {
24201
- cursor.leave();
24202
- }
24203
- return void 0;
24204
- }
24205
- case "keys":
24206
- return allocateProducedSandboxValue([...target.entries.keys()], options.budget);
24207
- case "values":
24208
- return allocateProducedSandboxValue([...target.entries.values()], options.budget);
24209
- case "entries":
24210
- return allocateProducedSandboxValue(
24211
- [...target.entries].map(([key, value]) => [key, value]),
24212
- options.budget
24213
- );
24214
- }
24215
- }
24216
-
24217
- // packages/safe-js/src/interp/methods/number.ts
24218
- var numberMethodNames = /* @__PURE__ */ new Set([
24219
- "toExponential",
24220
- "toFixed",
24221
- "toPrecision",
24222
- "toString"
24223
- ]);
24224
- function getNumberMember(value, property, budget) {
24225
- if (!isNumberMethodName(property)) {
24226
- return void 0;
24227
- }
24228
- return createSandboxClosure({
24229
- sandbox: true,
24230
- name: `Number#${property}`,
24231
- call: (args) => callNumberMethod(value, property, args, budget)
24232
- });
24233
- }
24234
- function isNumberMethodName(property) {
24235
- return typeof property === "string" && numberMethodNames.has(property);
24236
- }
24237
- function callNumberMethod(value, methodName, args, budget) {
24238
- return budget.allocateString(callNativeNumberMethod(value, methodName, args));
24239
- }
24240
- function callNativeNumberMethod(value, methodName, args) {
24241
- switch (methodName) {
24242
- case "toString":
24243
- return value.toString(asValidatedRadix(args[0]));
24244
- case "toExponential":
24245
- return args[0] === void 0 ? value.toExponential() : value.toExponential(asValidatedFractionDigits(args[0], methodName));
24246
- case "toFixed":
24247
- return value.toFixed(asValidatedFractionDigits(args[0], methodName));
24248
- case "toPrecision":
24249
- return args[0] === void 0 ? value.toPrecision() : value.toPrecision(asValidatedPrecision(args[0]));
24250
- }
24251
- }
24252
- function asValidatedRadix(value) {
24253
- if (value === void 0) {
24254
- return void 0;
24255
- }
24256
- const radix = toIntegerOrInfinity2(value);
24257
- if (radix < 2 || radix > 36) {
24258
- throw new RangeError("Number#toString radix must be between 2 and 36.");
24259
- }
24260
- return radix;
24261
- }
24262
- function asValidatedFractionDigits(value, methodName) {
24263
- const digits = toIntegerOrInfinity2(value);
24264
- if (digits < 0 || digits > 100) {
24265
- throw new RangeError(`Number#${methodName} digits must be between 0 and 100.`);
24266
- }
24267
- return digits;
24268
- }
24269
- function asValidatedPrecision(value) {
24270
- const precision = toIntegerOrInfinity2(value);
24271
- if (precision < 1 || precision > 100) {
24272
- throw new RangeError("Number#toPrecision precision must be between 1 and 100.");
24273
- }
24274
- return precision;
24275
- }
24276
- function toIntegerOrInfinity2(value) {
24277
- const number = Number(value);
24278
- if (Number.isNaN(number) || Object.is(number, 0) || Object.is(number, -0)) {
24279
- return 0;
24280
- }
24281
- if (!Number.isFinite(number)) {
24282
- return number;
24283
- }
24284
- return Math.trunc(number);
24285
- }
24286
-
24287
- // packages/safe-js/src/interp/methods/generator.ts
24288
- var generatorMethodNames = /* @__PURE__ */ new Set(["next", "return", "throw"]);
24289
- function getGeneratorMember(target, property, budget) {
24290
- if (typeof property !== "string" || !generatorMethodNames.has(property)) {
24291
- return void 0;
24292
- }
24293
- return createSandboxClosure({
24294
- sandbox: true,
24295
- name: property,
24296
- call: async ([value]) => {
24297
- const iterator = getSandboxIterator(target);
24298
- const result = await iterator[property](value);
24299
- return allocateProducedSandboxValue(
24300
- { value: result.value, done: result.done === true },
24301
- budget
24302
- );
24303
- }
24304
- });
24305
- }
24306
-
24307
- // packages/safe-js/src/interp/regex/engine.ts
24308
- function matchRegex(pattern, input, lastIndex = 0) {
24309
- const startIndex = pattern.flags.global ? normalizeLastIndex(lastIndex) : 0;
24310
- return matchRegexFrom(pattern, input, startIndex);
24311
- }
24312
- function matchRegexFrom(pattern, input, startIndex) {
24313
- if (startIndex > input.length) {
24314
- return null;
24315
- }
24316
- for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
24317
- const context = { input, flags: pattern.flags, steps: 0 };
24318
- charge(context);
24319
- const initialState = {
24320
- position: attempt,
24321
- captures: new Array(pattern.captureCount)
24322
- };
24323
- const result = matchNode(pattern.body, initialState, context).next();
24324
- if (!result.done) {
24325
- return toRegexMatch(input, attempt, result.value);
24326
- }
24327
- }
24328
- return null;
24329
- }
24330
- function* matchNode(node, state, context) {
24331
- charge(context);
24332
- switch (node.type) {
24333
- case "empty":
24334
- yield state;
24335
- return;
24336
- case "literal":
24337
- if (charactersEqual(context.input[state.position], node.value, context.flags.ignoreCase)) {
24338
- yield { ...state, position: state.position + 1 };
24339
- }
24340
- return;
24341
- case "dot":
24342
- if (state.position < context.input.length && (context.flags.dotAll || !isLineTerminator(context.input[state.position]))) {
24343
- yield { ...state, position: state.position + 1 };
24344
- }
24345
- return;
24346
- case "anchor":
24347
- if (matchesAnchor(node.kind, state.position, context)) {
24348
- yield state;
24349
- }
24350
- return;
24351
- case "wordBoundary": {
24352
- const previousWord = state.position > 0 && isWordCharacter(context.input[state.position - 1]);
24353
- const nextWord = state.position < context.input.length && isWordCharacter(context.input[state.position]);
24354
- if (previousWord !== nextWord !== node.negated) {
24355
- yield state;
24356
- }
24357
- return;
24358
- }
24359
- case "characterClass": {
24360
- const character = context.input[state.position];
24361
- if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context.flags.ignoreCase)) {
24362
- yield { ...state, position: state.position + 1 };
24363
- }
24364
- return;
24365
- }
24366
- case "sequence":
24367
- yield* matchSequence(node.elements, 0, state, context);
24368
- return;
24369
- case "alternation":
24370
- for (const alternative of node.alternatives) {
24371
- yield* matchNode(alternative, cloneState(state), context);
24372
- }
24373
- return;
24374
- case "group":
24375
- for (const result of matchNode(node.body, cloneState(state), context)) {
24376
- if (!node.capturing || node.index === void 0) {
24377
- yield result;
24378
- continue;
24379
- }
24380
- const captures = result.captures.slice();
24381
- captures[node.index - 1] = { start: state.position, end: result.position };
24382
- yield { position: result.position, captures };
24491
+ case "forEach": {
24492
+ const callback = args[0];
24493
+ if (!isSandboxClosure(callback)) {
24494
+ throw new TypeError("Map.prototype.forEach requires a callback function.");
24383
24495
  }
24384
- return;
24385
- case "quantifier":
24386
- yield* matchQuantifier(node, state, context, 0);
24387
- }
24388
- }
24389
- function* matchSequence(elements, index, state, context) {
24390
- charge(context);
24391
- if (index === elements.length) {
24392
- yield state;
24393
- return;
24394
- }
24395
- for (const result of matchNode(elements[index], state, context)) {
24396
- yield* matchSequence(elements, index + 1, result, context);
24397
- }
24398
- }
24399
- function* matchQuantifier(node, state, context, count) {
24400
- charge(context);
24401
- const canRepeat = node.max === void 0 || count < node.max;
24402
- if (!node.greedy && count >= node.min) {
24403
- yield state;
24404
- }
24405
- if (canRepeat) {
24406
- for (const result of matchNode(node.body, clearCaptures(node.body, state), context)) {
24407
- if (result.position === state.position) {
24408
- if (count >= node.min) {
24409
- continue;
24410
- }
24411
- if (count + 1 >= node.min) {
24412
- yield result;
24413
- } else {
24414
- yield* matchQuantifier(node, result, context, count + 1);
24496
+ const cursor = enterKeyedCollectionCallback(target, target.entries.keys(), options.budget);
24497
+ try {
24498
+ for (let entry = cursor.next(); !entry.done; entry = cursor.next()) {
24499
+ const key = entry.value;
24500
+ const value = target.entries.get(key);
24501
+ await options.callClosure(callback, [value, key, target], stack, args[1]);
24415
24502
  }
24416
- continue;
24503
+ } finally {
24504
+ cursor.leave();
24417
24505
  }
24418
- yield* matchQuantifier(node, result, context, count + 1);
24506
+ return void 0;
24419
24507
  }
24420
- }
24421
- if (node.greedy && count >= node.min) {
24422
- yield state;
24508
+ case "keys":
24509
+ return allocateProducedSandboxValue([...target.entries.keys()], options.budget);
24510
+ case "values":
24511
+ return allocateProducedSandboxValue([...target.entries.values()], options.budget);
24512
+ case "entries":
24513
+ return allocateProducedSandboxValue(
24514
+ [...target.entries].map(([key, value]) => [key, value]),
24515
+ options.budget
24516
+ );
24423
24517
  }
24424
24518
  }
24425
- function matchesAnchor(kind, position, context) {
24426
- if (kind === "start") {
24427
- return position === 0 || context.flags.multiline && position > 0 && isLineTerminator(context.input[position - 1]);
24519
+
24520
+ // packages/safe-js/src/interp/methods/number.ts
24521
+ var numberMethodNames = /* @__PURE__ */ new Set([
24522
+ "toExponential",
24523
+ "toFixed",
24524
+ "toPrecision",
24525
+ "toString"
24526
+ ]);
24527
+ function getNumberMember(property, budget) {
24528
+ if (!isNumberMethodName(property)) {
24529
+ return void 0;
24428
24530
  }
24429
- return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
24531
+ return createSandboxClosure({
24532
+ sandbox: true,
24533
+ name: `Number#${property}`,
24534
+ call: (args, context) => callNumberMethod(context?.thisValue, property, args, budget)
24535
+ });
24430
24536
  }
24431
- function matchesCharacterClass(character, items, negated, ignoreCase) {
24432
- const matched = items.some((item) => matchesCharacterClassItem(character, item, ignoreCase));
24433
- return negated ? !matched : matched;
24537
+ function isNumberMethodName(property) {
24538
+ return typeof property === "string" && numberMethodNames.has(property);
24434
24539
  }
24435
- function matchesCharacterClassItem(character, item, ignoreCase) {
24436
- if (item.type === "character") {
24437
- return charactersEqual(character, item.value, ignoreCase);
24438
- }
24439
- if (item.type === "range") {
24440
- const candidate = character.charCodeAt(0);
24441
- const from = item.from.charCodeAt(0);
24442
- const to = item.to.charCodeAt(0);
24443
- if (candidate >= from && candidate <= to) {
24444
- return true;
24445
- }
24446
- if (!ignoreCase) {
24447
- return false;
24448
- }
24449
- const foldedCandidate = foldCharacter(character, true).charCodeAt(0);
24450
- const foldedFrom = foldCharacter(item.from, true).charCodeAt(0);
24451
- const foldedTo = foldCharacter(item.to, true).charCodeAt(0);
24452
- return foldedCandidate >= foldedFrom && foldedCandidate <= foldedTo;
24540
+ function callNumberMethod(value, methodName, args, budget) {
24541
+ if (typeof value !== "number") {
24542
+ throw new TypeError(`Number#${methodName} requires a number receiver.`);
24453
24543
  }
24454
- const matched = item.kind === "digit" ? isDigit(character) : item.kind === "word" ? isWordCharacter(character) : isSpaceCharacter(character);
24455
- return item.negated ? !matched : matched;
24456
- }
24457
- function toRegexMatch(input, start, state) {
24458
- return {
24459
- index: start,
24460
- text: input.slice(start, state.position),
24461
- captures: state.captures.map(
24462
- (capture) => capture === void 0 ? void 0 : input.slice(capture.start, capture.end)
24463
- )
24464
- };
24465
- }
24466
- function cloneState(state) {
24467
- return { position: state.position, captures: state.captures.slice() };
24468
- }
24469
- function clearCaptures(node, state) {
24470
- const captures = state.captures.slice();
24471
- clearNodeCaptures(node, captures);
24472
- return { position: state.position, captures };
24544
+ return budget.allocateString(callNativeNumberMethod(value, methodName, args));
24473
24545
  }
24474
- function clearNodeCaptures(node, captures) {
24475
- if (node.type === "group") {
24476
- if (node.capturing && node.index !== void 0) {
24477
- captures[node.index - 1] = void 0;
24478
- }
24479
- clearNodeCaptures(node.body, captures);
24480
- return;
24481
- }
24482
- if (node.type === "sequence") {
24483
- for (const element of node.elements) {
24484
- clearNodeCaptures(element, captures);
24485
- }
24486
- return;
24546
+ function callNativeNumberMethod(value, methodName, args) {
24547
+ switch (methodName) {
24548
+ case "toString":
24549
+ return value.toString(asValidatedRadix(args[0]));
24550
+ case "toExponential":
24551
+ return args[0] === void 0 ? value.toExponential() : value.toExponential(asValidatedFractionDigits(args[0], methodName));
24552
+ case "toFixed":
24553
+ return value.toFixed(asValidatedFractionDigits(args[0], methodName));
24554
+ case "toPrecision":
24555
+ return args[0] === void 0 ? value.toPrecision() : value.toPrecision(asValidatedPrecision(args[0]));
24487
24556
  }
24488
- if (node.type === "alternation") {
24489
- for (const alternative of node.alternatives) {
24490
- clearNodeCaptures(alternative, captures);
24491
- }
24492
- return;
24557
+ }
24558
+ function asValidatedRadix(value) {
24559
+ if (value === void 0) {
24560
+ return void 0;
24493
24561
  }
24494
- if (node.type === "quantifier") {
24495
- clearNodeCaptures(node.body, captures);
24562
+ const radix = toIntegerOrInfinity2(value);
24563
+ if (radix < 2 || radix > 36) {
24564
+ throw new RangeError("Number#toString radix must be between 2 and 36.");
24496
24565
  }
24566
+ return radix;
24497
24567
  }
24498
- function charge(context) {
24499
- context.steps += 1;
24500
- allocateRegexSteps(context.steps);
24501
- }
24502
- function normalizeLastIndex(lastIndex) {
24503
- if (!Number.isFinite(lastIndex) || lastIndex <= 0) {
24504
- return 0;
24568
+ function asValidatedFractionDigits(value, methodName) {
24569
+ const digits = toIntegerOrInfinity2(value);
24570
+ if (digits < 0 || digits > 100) {
24571
+ throw new RangeError(`Number#${methodName} digits must be between 0 and 100.`);
24505
24572
  }
24506
- return Math.floor(lastIndex);
24507
- }
24508
- function charactersEqual(left, right, ignoreCase) {
24509
- return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
24573
+ return digits;
24510
24574
  }
24511
- function foldCharacter(character, ignoreCase) {
24512
- if (!ignoreCase) {
24513
- return character;
24575
+ function asValidatedPrecision(value) {
24576
+ const precision = toIntegerOrInfinity2(value);
24577
+ if (precision < 1 || precision > 100) {
24578
+ throw new RangeError("Number#toPrecision precision must be between 1 and 100.");
24514
24579
  }
24515
- const folded = character.toUpperCase();
24516
- if (folded.length !== 1) {
24517
- return character;
24580
+ return precision;
24581
+ }
24582
+ function toIntegerOrInfinity2(value) {
24583
+ const number = Number(value);
24584
+ if (Number.isNaN(number) || Object.is(number, 0) || Object.is(number, -0)) {
24585
+ return 0;
24518
24586
  }
24519
- if (character.charCodeAt(0) >= 128 && folded.charCodeAt(0) < 128) {
24520
- return character;
24587
+ if (!Number.isFinite(number)) {
24588
+ return number;
24521
24589
  }
24522
- return folded;
24523
- }
24524
- function isDigit(character) {
24525
- return character >= "0" && character <= "9";
24526
- }
24527
- function isWordCharacter(character) {
24528
- return isDigit(character) || character >= "A" && character <= "Z" || character >= "a" && character <= "z" || character === "_";
24529
- }
24530
- function isSpaceCharacter(character) {
24531
- return character === " " || character === "\f" || character === "\n" || character === "\r" || character === " " || character === "\v" || character === "\xA0" || character === "\u1680" || character >= "\u2000" && character <= "\u200A" || character === "\u2028" || character === "\u2029" || character === "\u202F" || character === "\u205F" || character === "\u3000" || character === "\uFEFF";
24532
- }
24533
- function isLineTerminator(character) {
24534
- return character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029";
24590
+ return Math.trunc(number);
24535
24591
  }
24536
24592
 
24537
- // packages/safe-js/src/interp/methods/regex.ts
24538
- var regexMethodNames = /* @__PURE__ */ new Set(["exec", "test"]);
24539
- function isRegexMethodName(property) {
24540
- return typeof property === "string" && regexMethodNames.has(property);
24541
- }
24542
- function getRegexMember(target, property) {
24543
- if (property === "source" || property === "flags" || property === "lastIndex") {
24544
- return target[property];
24545
- }
24546
- if (!isRegexMethodName(property)) {
24593
+ // packages/safe-js/src/interp/methods/generator.ts
24594
+ var generatorMethodNames = /* @__PURE__ */ new Set(["next", "return", "throw"]);
24595
+ function getGeneratorMember(target, property, budget) {
24596
+ if (typeof property !== "string" || !generatorMethodNames.has(property)) {
24547
24597
  return void 0;
24548
24598
  }
24549
24599
  return createSandboxClosure({
24550
24600
  sandbox: true,
24551
- name: `RegExp#${property}`,
24552
- call: (args) => callRegexMethod(target, property, args)
24601
+ name: property,
24602
+ call: async ([value]) => {
24603
+ const iterator = getSandboxIterator(target);
24604
+ const result = await iterator[property](value);
24605
+ return allocateProducedSandboxValue(
24606
+ { value: result.value, done: result.done === true },
24607
+ budget
24608
+ );
24609
+ }
24553
24610
  });
24554
24611
  }
24555
- function setRegexMember(target, property, value) {
24556
- if (property !== "lastIndex") {
24557
- throw new TypeError(`RegExp#${String(property)} is not writable.`);
24558
- }
24559
- target.lastIndex = Number(value);
24560
- }
24561
- function callRegexMethod(target, methodName, args) {
24562
- const match = executeRegex(target, String(args[0]));
24563
- return methodName === "test" ? match !== null : toMatchArray(match, String(args[0]));
24564
- }
24565
- function executeRegex(target, input) {
24566
- const pattern = getSandboxRegexPattern(target);
24567
- const match = matchRegex(pattern, input, target.lastIndex);
24568
- if (pattern.flags.global) {
24569
- target.lastIndex = match === null ? 0 : match.index + match.text.length;
24570
- }
24571
- return match;
24572
- }
24573
- function toMatchArray(match, input) {
24574
- if (match === null) {
24575
- return null;
24576
- }
24577
- const result = [match.text, ...match.captures];
24578
- Object.assign(result, { index: match.index, input, groups: void 0 });
24579
- return result;
24580
- }
24581
24612
 
24582
24613
  // packages/safe-js/src/interp/methods/string.ts
24583
24614
  var SPLIT_STRING_MESSAGE = "String#split only supports string separator values.";
@@ -27479,7 +27510,7 @@ async function evaluateMemberExpression(node, context) {
27479
27510
  function getPropertyValue(target, property, context) {
27480
27511
  if (isGuestHostObject(target)) return getHostObjectMember(target, String(property));
27481
27512
  if (typeof target === "string") return getStringMember(target, property, context.budget);
27482
- if (typeof target === "number") return getNumberMember(target, property, context.budget);
27513
+ if (typeof target === "number") return getNumberMember(property, context.budget);
27483
27514
  if (typeof target === "boolean") return void 0;
27484
27515
  if (isFloat32Array(target)) return getFloat32Member(target, property, context.budget);
27485
27516
  if (isSandboxDate(target)) return getDateMember(property, context.budget, context.compilation?.owner);
@@ -27488,7 +27519,7 @@ function getPropertyValue(target, property, context) {
27488
27519
  if (isSandboxGenerator(target)) return getGeneratorMember(target, property, context.budget);
27489
27520
  if (isSandboxClosure(target)) return getClosureMemberValue(target, property, context);
27490
27521
  if (isSandboxPromise(target)) return getPromiseMember(property, context.budget);
27491
- if (isSandboxRegex(target)) return getRegexMember(target, property);
27522
+ if (isSandboxRegex(target)) return getRegexMember(target, property, context.budget);
27492
27523
  if (!isIndexableSandboxValue(target)) {
27493
27524
  throw new TypeError("Attempted to read a property from a non-object value.");
27494
27525
  }
@@ -27686,7 +27717,7 @@ async function evaluateMemberCallExpression(node, context) {
27686
27717
  node,
27687
27718
  "Number",
27688
27719
  member.property,
27689
- getNumberMember(member.object, member.property, context.budget),
27720
+ getNumberMember(member.property, context.budget),
27690
27721
  context
27691
27722
  );
27692
27723
  }
@@ -27753,7 +27784,7 @@ async function evaluateMemberCallExpression(node, context) {
27753
27784
  if (isSandboxRegex(member.object) && isRegexMethodName(member.property)) {
27754
27785
  return evaluateResolvedCallExpression(
27755
27786
  node,
27756
- getRegexMember(member.object, member.property),
27787
+ getRegexMember(member.object, member.property, context.budget),
27757
27788
  context,
27758
27789
  member.object
27759
27790
  );
@@ -32866,4 +32897,4 @@ export {
32866
32897
  FileSnapshotBackend,
32867
32898
  run
32868
32899
  };
32869
- //# sourceMappingURL=chunk-M4M56OCI.js.map
32900
+ //# sourceMappingURL=chunk-JZXAWFPL.js.map