poe-code 14.0.60 → 14.0.62

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.
Files changed (41) hide show
  1. package/dist/index.js +313 -135
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-js/dist/chunks/{chunk-C7UCTQDN.js → chunk-F7TJSPDZ.js} +7 -3
  6. package/packages/safe-js/dist/chunks/chunk-F7TJSPDZ.js.map +7 -0
  7. package/packages/safe-js/dist/chunks/{chunk-MKJBQPBH.js → chunk-VKGWGZBH.js} +268 -126
  8. package/packages/safe-js/dist/chunks/chunk-VKGWGZBH.js.map +7 -0
  9. package/packages/safe-js/dist/cli.js +2 -2
  10. package/packages/safe-js/dist/core.js +1 -1
  11. package/packages/safe-js/dist/index.js +2 -2
  12. package/packages/safe-js/dist/interp/async.js +3 -0
  13. package/packages/safe-js/dist/interp/function-string.d.ts +2 -0
  14. package/packages/safe-js/dist/interp/function-string.js +21 -0
  15. package/packages/safe-js/dist/interp/globals/misc.js +11 -12
  16. package/packages/safe-js/dist/interp/globals/numeric-parsers.d.ts +5 -0
  17. package/packages/safe-js/dist/interp/globals/numeric-parsers.js +47 -0
  18. package/packages/safe-js/dist/interp/globals/object-array.js +2 -10
  19. package/packages/safe-js/dist/interp/interpreter.js +9 -14
  20. package/packages/safe-js/dist/interp/methods/function.d.ts +2 -0
  21. package/packages/safe-js/dist/interp/methods/function.js +10 -1
  22. package/packages/safe-js/dist/interp/methods/string.js +18 -0
  23. package/packages/safe-js/dist/interp/resources.d.ts +3 -0
  24. package/packages/safe-js/dist/interp/resources.js +11 -0
  25. package/packages/safe-js/dist/interp/string-coercion.js +16 -4
  26. package/packages/safe-js/dist/interp/values.d.ts +3 -0
  27. package/packages/safe-js/dist/interp/values.js +3 -0
  28. package/packages/safe-js/dist/migrate.js +1 -1
  29. package/packages/safe-js/dist/parse/function-source.d.ts +7 -0
  30. package/packages/safe-js/dist/parse/function-source.js +1 -0
  31. package/packages/safe-js/dist/parse/hash.d.ts +2 -2
  32. package/packages/safe-js/dist/parse/hash.js +23 -9
  33. package/packages/safe-js/dist/parse/parser.js +36 -23
  34. package/packages/safe-js/dist/restore.js +2 -1
  35. package/packages/safe-js/dist/run.js +16 -5
  36. package/packages/safe-js/dist/snapshot/dump-format.d.ts +1 -1
  37. package/packages/safe-js/dist/snapshot/dump-format.js +1 -1
  38. package/packages/safe-js/dist/snapshot/migration.js +2 -2
  39. package/packages/safe-js/dist/snapshot/restore.js +2 -0
  40. package/packages/safe-js/dist/chunks/chunk-C7UCTQDN.js.map +0 -7
  41. package/packages/safe-js/dist/chunks/chunk-MKJBQPBH.js.map +0 -7
@@ -1811,6 +1811,9 @@ function isAstNode(value) {
1811
1811
  return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string" && "span" in value && typeof value.span?.start.offset === "number" && typeof value.span?.end.offset === "number";
1812
1812
  }
1813
1813
 
1814
+ // packages/safe-js/src/parse/function-source.ts
1815
+ var functionSources = /* @__PURE__ */ new WeakMap();
1816
+
1814
1817
  // packages/safe-js/src/parse/format-error.ts
1815
1818
  var ParseError = class extends Error {
1816
1819
  constructor(filename, message, line, column, excerpt, caret, span) {
@@ -2459,7 +2462,11 @@ function parse(source, filename = "<input>", owner) {
2459
2462
  const compilation = new CompileScope(owner);
2460
2463
  try {
2461
2464
  const result = assignIds(
2462
- parseTokens(tokenize(source, { allowRegexLiterals: true, compilation }), compilation)
2465
+ new Parser(
2466
+ tokenize(source, { allowRegexLiterals: true, compilation }),
2467
+ source,
2468
+ compilation
2469
+ ).parseTopLevel()
2463
2470
  );
2464
2471
  const regexLiteral = findRegexLiteral(result);
2465
2472
  if (regexLiteral !== void 0) {
@@ -2485,7 +2492,11 @@ function parseModule(source, filename = "<input>", owner) {
2485
2492
  const compilation = new CompileScope(owner);
2486
2493
  try {
2487
2494
  return assignIds(
2488
- parseModuleTokens(tokenize(source, { allowRegexLiterals: true, compilation }), compilation)
2495
+ new Parser(
2496
+ tokenize(source, { allowRegexLiterals: true, compilation }),
2497
+ source,
2498
+ compilation
2499
+ ).parseModule()
2489
2500
  );
2490
2501
  } catch (error) {
2491
2502
  if (error instanceof DisallowedSyntaxError || error instanceof SandboxError) {
@@ -2503,7 +2514,11 @@ function parseExecutableModule(source, filename = "<input>", owner) {
2503
2514
  const compilation = new CompileScope(owner);
2504
2515
  try {
2505
2516
  const result = assignIds(
2506
- parseModuleTokens(tokenize(source, { allowRegexLiterals: true, compilation }), compilation)
2517
+ new Parser(
2518
+ tokenize(source, { allowRegexLiterals: true, compilation }),
2519
+ source,
2520
+ compilation
2521
+ ).parseModule()
2507
2522
  );
2508
2523
  throwIfImportMetaAssignment(result);
2509
2524
  return result;
@@ -2519,20 +2534,16 @@ function parseExecutableModule(source, filename = "<input>", owner) {
2519
2534
  compilation.dispose();
2520
2535
  }
2521
2536
  }
2522
- function parseTokens(tokens, compilation) {
2523
- return new Parser(tokens, compilation).parseTopLevel();
2524
- }
2525
- function parseModuleTokens(tokens, compilation) {
2526
- return new Parser(tokens, compilation).parseModule();
2527
- }
2528
2537
  var Parser = class {
2529
- constructor(tokens, compilation, functionContext = "normal") {
2538
+ constructor(tokens, source, compilation, functionContext = "normal") {
2530
2539
  this.tokens = tokens;
2540
+ this.source = source;
2531
2541
  this.compilation = compilation;
2532
2542
  this.functionContext = functionContext;
2533
2543
  this.functionScopes.add(this.scopes[0]);
2534
2544
  }
2535
2545
  tokens;
2546
+ source;
2536
2547
  compilation;
2537
2548
  functionContext;
2538
2549
  index = 0;
@@ -2543,6 +2554,14 @@ var Parser = class {
2543
2554
  scopes = [/* @__PURE__ */ new Map()];
2544
2555
  functionScopes = /* @__PURE__ */ new WeakSet();
2545
2556
  varNames = /* @__PURE__ */ new WeakMap();
2557
+ withFunctionSource(node) {
2558
+ functionSources.set(node, {
2559
+ text: this.source,
2560
+ start: node.span.start.offset,
2561
+ end: node.span.end.offset
2562
+ });
2563
+ return node;
2564
+ }
2546
2565
  parseTopLevel() {
2547
2566
  if (this.isExportToken(this.currentToken())) {
2548
2567
  throw new DisallowedSyntaxError("export", this.currentToken().start);
@@ -2684,14 +2703,14 @@ var Parser = class {
2684
2703
  });
2685
2704
  this.expectPunctuator("=>");
2686
2705
  const body = this.parseArrowFunctionBody(params);
2687
- return {
2706
+ return this.withFunctionSource({
2688
2707
  type: "ArrowFunctionExpression",
2689
2708
  async: isAsync,
2690
2709
  body,
2691
2710
  expression: body.type !== "BlockStatement",
2692
2711
  params,
2693
2712
  span: createSpan2(start, body.span.end)
2694
- };
2713
+ });
2695
2714
  }
2696
2715
  parseConditionalExpression() {
2697
2716
  if (this.conditionalExpressionDepth >= MAX_CONDITIONAL_EXPRESSION_DEPTH) {
@@ -3331,8 +3350,11 @@ var Parser = class {
3331
3350
  return parsedParams;
3332
3351
  });
3333
3352
  const generator = generatorToken !== void 0;
3334
- const body = this.withFunctionContext(generator ? "generator" : "normal", () => this.parseBlockStatement(params));
3335
- return {
3353
+ const body = this.withFunctionContext(
3354
+ generator ? "generator" : "normal",
3355
+ () => this.parseBlockStatement(params)
3356
+ );
3357
+ return this.withFunctionSource({
3336
3358
  type: "FunctionDeclaration",
3337
3359
  async: asyncToken !== void 0,
3338
3360
  body,
@@ -3340,7 +3362,7 @@ var Parser = class {
3340
3362
  id,
3341
3363
  params,
3342
3364
  span: createSpan2(asyncToken?.start ?? functionToken.start, body.span.end)
3343
- };
3365
+ });
3344
3366
  }
3345
3367
  parseVariableDeclarator(kind) {
3346
3368
  const id = this.parseBindingTarget();
@@ -4108,7 +4130,11 @@ var Parser = class {
4108
4130
  if (this.currentToken().type === "template") {
4109
4131
  const quasi = createTemplateLiteral(
4110
4132
  this.currentToken(),
4111
- { allowMalformedEscapes: true, functionContext: this.functionContext },
4133
+ {
4134
+ allowMalformedEscapes: true,
4135
+ functionContext: this.functionContext,
4136
+ source: this.source
4137
+ },
4112
4138
  this.compilation
4113
4139
  );
4114
4140
  this.index += 1;
@@ -4197,7 +4223,11 @@ var Parser = class {
4197
4223
  return {
4198
4224
  node: createTemplateLiteral(
4199
4225
  token,
4200
- { allowMalformedEscapes: false, functionContext: this.functionContext },
4226
+ {
4227
+ allowMalformedEscapes: false,
4228
+ functionContext: this.functionContext,
4229
+ source: this.source
4230
+ },
4201
4231
  this.compilation
4202
4232
  ),
4203
4233
  parenthesized: false
@@ -4282,7 +4312,8 @@ var Parser = class {
4282
4312
  break;
4283
4313
  }
4284
4314
  const optional = this.consumePunctuator("?.");
4285
- if (optional !== void 0) throw new DisallowedSyntaxError("new optional chain", optional.start);
4315
+ if (optional !== void 0)
4316
+ throw new DisallowedSyntaxError("new optional chain", optional.start);
4286
4317
  const args = this.consumePunctuator("(") === void 0 ? [] : this.parseArguments();
4287
4318
  const end = this.previousToken();
4288
4319
  return {
@@ -4315,8 +4346,11 @@ var Parser = class {
4315
4346
  return parsedParams;
4316
4347
  });
4317
4348
  const generator = generatorToken !== void 0;
4318
- const body = this.withFunctionContext(generator ? "generator" : "normal", () => this.parseBlockStatement(params));
4319
- return {
4349
+ const body = this.withFunctionContext(
4350
+ generator ? "generator" : "normal",
4351
+ () => this.parseBlockStatement(params)
4352
+ );
4353
+ return this.withFunctionSource({
4320
4354
  type: "FunctionExpression",
4321
4355
  async: asyncToken !== void 0,
4322
4356
  body,
@@ -4324,7 +4358,7 @@ var Parser = class {
4324
4358
  id,
4325
4359
  params,
4326
4360
  span: createSpan2(asyncToken?.start ?? functionToken.start, body.span.end)
4327
- };
4361
+ });
4328
4362
  }
4329
4363
  parseArrayExpression() {
4330
4364
  const start = this.expectPunctuator("[");
@@ -4560,7 +4594,7 @@ var Parser = class {
4560
4594
  return parsedParams;
4561
4595
  });
4562
4596
  const body = this.withFunctionContext("normal", () => this.parseBlockStatement(params));
4563
- return {
4597
+ return this.withFunctionSource({
4564
4598
  type: "FunctionExpression",
4565
4599
  async: asyncToken !== void 0,
4566
4600
  body,
@@ -4569,7 +4603,7 @@ var Parser = class {
4569
4603
  method: true,
4570
4604
  params,
4571
4605
  span: createSpan2(asyncToken?.start ?? methodStart, body.span.end)
4572
- };
4606
+ });
4573
4607
  }
4574
4608
  parseIdentifierName() {
4575
4609
  const token = this.currentToken();
@@ -5432,6 +5466,7 @@ function createTemplateLiteral(token, options, compilation) {
5432
5466
  raw.slice(expressionStart, expressionEnd),
5433
5467
  positionWithinRaw(token.start, raw, expressionStart),
5434
5468
  options.functionContext,
5469
+ options.source,
5435
5470
  compilation
5436
5471
  )
5437
5472
  );
@@ -5794,13 +5829,13 @@ function decodeHexEscape(value, start) {
5794
5829
  end: index + 2
5795
5830
  };
5796
5831
  }
5797
- function parseEmbeddedExpression(source, base, functionContext, compilation) {
5832
+ function parseEmbeddedExpression(source, base, functionContext, fullSource, compilation) {
5798
5833
  const tokens = tokenize(source, { allowRegexLiterals: true, compilation }).map((token) => ({
5799
5834
  ...token,
5800
5835
  start: rebasePosition(token.start, base),
5801
5836
  end: rebasePosition(token.end, base)
5802
5837
  }));
5803
- return new Parser(tokens, compilation, functionContext).parseExpressionOnly();
5838
+ return new Parser(tokens, fullSource, compilation, functionContext).parseExpressionOnly();
5804
5839
  }
5805
5840
  function findRegexLiteral(node) {
5806
5841
  if (node === null || node === void 0) {
@@ -7247,7 +7282,7 @@ function decodeFloat32Storage(value, resolve) {
7247
7282
 
7248
7283
  // packages/safe-js/src/snapshot/dump-format.ts
7249
7284
  var DUMP_FORMAT_VERSION = 1;
7250
- var EXECUTION_SEMANTICS = "jobs-v7";
7285
+ var EXECUTION_SEMANTICS = "jobs-v8";
7251
7286
  var SKIP_VALUE = /* @__PURE__ */ Symbol("SafeJS.skip-dump-value");
7252
7287
  function serializeSafeJSSnapshot(snapshot) {
7253
7288
  const replayError = Object.getOwnPropertyDescriptor(snapshot, "replayError");
@@ -8267,7 +8302,7 @@ function isCounter(value) {
8267
8302
  }
8268
8303
 
8269
8304
  // packages/safe-js/src/interp/cancel.ts
8270
- import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
8305
+ import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
8271
8306
 
8272
8307
  // packages/safe-js/src/interp/builtin-call.ts
8273
8308
  async function invokeBuiltinClosure(closure, args, budget, context, thisValue, construct = false) {
@@ -8627,6 +8662,71 @@ function toMatchArray(match, input) {
8627
8662
  return result;
8628
8663
  }
8629
8664
 
8665
+ // packages/safe-js/src/interp/resources.ts
8666
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
8667
+ var runResources = new AsyncLocalStorage3();
8668
+ function retainValues(budget, values) {
8669
+ const retained = {};
8670
+ budget.setRetainedValues(retained, values);
8671
+ const pending = runResources.getStore()?.referenceReleases;
8672
+ const release = () => {
8673
+ budget.setRetainedValues(retained, void 0);
8674
+ pending?.delete(release);
8675
+ };
8676
+ pending?.add(release);
8677
+ return release;
8678
+ }
8679
+ async function withRunResources(signal, execute) {
8680
+ const controller = new AbortController();
8681
+ const cancel = () => controller.abort(signal?.reason);
8682
+ const cleanups = /* @__PURE__ */ new Set();
8683
+ const resources = {
8684
+ signal: controller.signal,
8685
+ referenceReleases: /* @__PURE__ */ new Set(),
8686
+ add(close) {
8687
+ cleanups.add(close);
8688
+ }
8689
+ };
8690
+ signal?.addEventListener("abort", cancel, { once: true });
8691
+ if (signal?.aborted) cancel();
8692
+ let result;
8693
+ let failure;
8694
+ let errors = [];
8695
+ try {
8696
+ result = await runResources.run(resources, execute);
8697
+ } catch (error) {
8698
+ failure = { reason: error };
8699
+ } finally {
8700
+ signal?.removeEventListener("abort", cancel);
8701
+ controller.abort(new Error("SafeJS run finished."));
8702
+ for (const release of resources.referenceReleases) release();
8703
+ resources.referenceReleases.clear();
8704
+ const outcomes = await Promise.allSettled(
8705
+ [...cleanups].map((close) => Promise.resolve().then(close))
8706
+ );
8707
+ errors = outcomes.flatMap((outcome) => outcome.status === "rejected" ? [outcome.reason] : []);
8708
+ }
8709
+ if (failure !== void 0) throw failure.reason;
8710
+ if (errors.length > 0) throw new AggregateError(errors, "SafeJS resource cleanup failed.");
8711
+ return result;
8712
+ }
8713
+
8714
+ // packages/safe-js/src/interp/function-string.ts
8715
+ function functionString(value) {
8716
+ if (runResources.getStore()?.functionSourceText === false) return "[object Object]";
8717
+ const source = value.sourceRange;
8718
+ if (source !== void 0) return source.text.slice(source.start, source.end);
8719
+ let name = value.boundTarget === void 0 ? value.name?.split("#").at(-1) ?? "" : "";
8720
+ for (let index = 0; index < name.length; index++) {
8721
+ const code = name.charCodeAt(index);
8722
+ if (!(code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 36 || code === 95 || index > 0 && code >= 48 && code <= 57)) {
8723
+ name = "";
8724
+ break;
8725
+ }
8726
+ }
8727
+ return `function ${name}() { [native code] }`;
8728
+ }
8729
+
8630
8730
  // packages/safe-js/src/interp/string-coercion.ts
8631
8731
  var defaultStringHook = /* @__PURE__ */ Symbol("defaultStringHook");
8632
8732
  var defaultValueHook = /* @__PURE__ */ Symbol("defaultValueHook");
@@ -8694,6 +8794,7 @@ function conversionHook(value, name, budget) {
8694
8794
  return void 0;
8695
8795
  }
8696
8796
  async function defaultToString(value, budget, context, joining) {
8797
+ if (isSandboxClosure(value)) return budget.allocateString(functionString(value));
8697
8798
  if (isSandboxMap(value)) return "[object Map]";
8698
8799
  if (isSandboxSet(value)) return "[object Set]";
8699
8800
  if (isSandboxCollectionIterator(value)) return collectionIteratorState(value).collectionKind === "map" ? "[object Map Iterator]" : "[object Set Iterator]";
@@ -8713,9 +8814,10 @@ async function defaultToString(value, budget, context, joining) {
8713
8814
  }
8714
8815
  if (joining.has(value)) return "";
8715
8816
  joining.add(value);
8817
+ let text = "";
8818
+ const release = retainValues(budget, () => [text]);
8716
8819
  try {
8717
8820
  const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
8718
- let text = "";
8719
8821
  for (let index = 0; index < length; index++) {
8720
8822
  budget.visitNode();
8721
8823
  const element = ownDataValue(value, String(index));
@@ -8724,15 +8826,21 @@ async function defaultToString(value, budget, context, joining) {
8724
8826
  }
8725
8827
  return text;
8726
8828
  } finally {
8829
+ release();
8727
8830
  joining.delete(value);
8728
8831
  }
8729
8832
  }
8730
8833
  if (sandboxErrorTypes.has(value)) {
8731
8834
  const nameValue = ownDataValue(value, "name");
8732
8835
  const name = nameValue === void 0 ? "Error" : await sandboxString(nameValue, budget, context, joining);
8733
- const messageValue = ownDataValue(value, "message");
8734
- const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
8735
- return name === "" ? message : message === "" ? name : `${name}: ${message}`;
8836
+ const release = retainValues(budget, () => [name]);
8837
+ try {
8838
+ const messageValue = ownDataValue(value, "message");
8839
+ const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
8840
+ return name === "" ? message : message === "" ? name : `${name}: ${message}`;
8841
+ } finally {
8842
+ release();
8843
+ }
8736
8844
  }
8737
8845
  return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
8738
8846
  }
@@ -9342,8 +9450,8 @@ function syncIterator(iterator) {
9342
9450
  }
9343
9451
 
9344
9452
  // packages/safe-js/src/interp/jobs.ts
9345
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
9346
- var activeJob = new AsyncLocalStorage3();
9453
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
9454
+ var activeJob = new AsyncLocalStorage4();
9347
9455
  var SandboxJobQueue = class {
9348
9456
  running = false;
9349
9457
  pending = [];
@@ -10172,7 +10280,7 @@ function isPromiseLike(value) {
10172
10280
  }
10173
10281
 
10174
10282
  // packages/safe-js/src/interp/cancel.ts
10175
- var activeCancellation = new AsyncLocalStorage4();
10283
+ var activeCancellation = new AsyncLocalStorage5();
10176
10284
  var sandboxPromises = /* @__PURE__ */ new WeakSet();
10177
10285
  var cancelableOutcomes = /* @__PURE__ */ new WeakMap();
10178
10286
  function withCancellationSignal(signal, task) {
@@ -10371,6 +10479,9 @@ function createSandboxClosure(input) {
10371
10479
  enumerable: false,
10372
10480
  value: true
10373
10481
  });
10482
+ if (input.sourceRange !== void 0) {
10483
+ Object.defineProperty(closure, "sourceRange", { value: input.sourceRange });
10484
+ }
10374
10485
  if (input.sandbox === true) {
10375
10486
  Object.defineProperty(closure, "sandbox", { value: true });
10376
10487
  }
@@ -12218,19 +12329,19 @@ function normalize(value, seen) {
12218
12329
  var FNV_OFFSET_BASIS = 2166136261;
12219
12330
  var FNV_PRIME = 16777619;
12220
12331
  var IGNORED_KEYS = /* @__PURE__ */ new Set(["nodeId", "raw", "span"]);
12221
- function hashSource(source, owner) {
12332
+ function hashSource(source, owner, includeFunctionSource = true) {
12222
12333
  try {
12223
- return hashParsedAst(parse(source, "<input>", owner));
12334
+ return hashParsedAst(parse(source, "<input>", owner), includeFunctionSource);
12224
12335
  } catch (error) {
12225
12336
  if (error instanceof SandboxError) throw error;
12226
- return hashParsedAst(parseModule(source, "<input>", owner));
12337
+ return hashParsedAst(parseModule(source, "<input>", owner), includeFunctionSource);
12227
12338
  }
12228
12339
  }
12229
- function hashParsedAst(ast) {
12340
+ function hashParsedAst(ast, includeFunctionSource = true) {
12230
12341
  let hash = FNV_OFFSET_BASIS;
12231
12342
  visit(ast);
12232
12343
  return hash.toString(16).padStart(8, "0");
12233
- function visit(value, includeTemplateRaw = false) {
12344
+ function visit(value, includeTemplateRaw = false, enclosingSource) {
12234
12345
  if (value === null) {
12235
12346
  write("null");
12236
12347
  return;
@@ -12242,7 +12353,7 @@ function hashParsedAst(ast) {
12242
12353
  if (Array.isArray(value)) {
12243
12354
  write("[");
12244
12355
  for (const entry of value) {
12245
- visit(entry, includeTemplateRaw);
12356
+ visit(entry, includeTemplateRaw, enclosingSource);
12246
12357
  write(",");
12247
12358
  }
12248
12359
  write("]");
@@ -12260,12 +12371,23 @@ function hashParsedAst(ast) {
12260
12371
  return;
12261
12372
  case "object": {
12262
12373
  const record2 = value;
12374
+ const source = includeFunctionSource ? functionSources.get(value) : void 0;
12375
+ if (source !== void 0 && !(enclosingSource !== void 0 && source.text === enclosingSource.text && source.start >= enclosingSource.start && source.end <= enclosingSource.end)) {
12376
+ write("function-source:");
12377
+ write(String(source.end - source.start));
12378
+ write(":");
12379
+ write(source.text, source.start, source.end);
12380
+ }
12263
12381
  const keys = Object.keys(value).filter((key) => shouldHashKey(record2, key, includeTemplateRaw)).sort();
12264
12382
  write("{");
12265
12383
  for (const key of keys) {
12266
12384
  write(JSON.stringify(key));
12267
12385
  write(":");
12268
- visit(record2[key], shouldIncludeTemplateRaw(record2, key, includeTemplateRaw));
12386
+ visit(
12387
+ record2[key],
12388
+ shouldIncludeTemplateRaw(record2, key, includeTemplateRaw),
12389
+ source ?? enclosingSource
12390
+ );
12269
12391
  write(",");
12270
12392
  }
12271
12393
  write("}");
@@ -12275,8 +12397,8 @@ function hashParsedAst(ast) {
12275
12397
  throw new TypeError(`Unsupported AST value type: ${typeof value}`);
12276
12398
  }
12277
12399
  }
12278
- function write(chunk) {
12279
- for (let index = 0; index < chunk.length; index += 1) {
12400
+ function write(chunk, start = 0, end = chunk.length) {
12401
+ for (let index = start; index < end; index += 1) {
12280
12402
  hash ^= chunk.charCodeAt(index);
12281
12403
  hash = Math.imul(hash, FNV_PRIME) >>> 0;
12282
12404
  }
@@ -12303,11 +12425,11 @@ function shouldIncludeTemplateRaw(record2, key, includeTemplateRaw) {
12303
12425
 
12304
12426
  // packages/safe-js/src/snapshot/migration.ts
12305
12427
  function validateMigrationSemantics(value) {
12306
- if (!["jobs-v1", "jobs-v2", "jobs-v3", "jobs-v4", "jobs-v5", "jobs-v6", "jobs-v7"].includes(
12428
+ if (!["jobs-v1", "jobs-v2", "jobs-v3", "jobs-v4", "jobs-v5", "jobs-v6", "jobs-v7", "jobs-v8"].includes(
12307
12429
  value
12308
12430
  ))
12309
12431
  throw new TypeError(
12310
- "Migration requires a supported execution-semantics marker (jobs-v1 through jobs-v7)."
12432
+ "Migration requires a supported execution-semantics marker (jobs-v1 through jobs-v8)."
12311
12433
  );
12312
12434
  }
12313
12435
  function validateMigrationJournal(sourceHash, replay, hostCalls = [], owner) {
@@ -12416,14 +12538,18 @@ function restore(snapshot, options, owner) {
12416
12538
  assertSnapshotInactive(snapshot);
12417
12539
  validateDumpEnvelope(snapshot);
12418
12540
  validateSnapshotMigration(snapshot.migration, snapshot.sourceHash, owner);
12419
- if (snapshot.executionSemantics !== EXECUTION_SEMANTICS && snapshot.executionSemantics !== "jobs-v6" && (snapshot.executionSemantics !== void 0 || snapshot.promiseReplay !== void 0 || snapshot.replay !== void 0 || snapshot.initialInputs !== void 0)) {
12541
+ if (snapshot.executionSemantics !== EXECUTION_SEMANTICS && snapshot.executionSemantics !== "jobs-v6" && snapshot.executionSemantics !== "jobs-v7" && (snapshot.executionSemantics !== void 0 || snapshot.promiseReplay !== void 0 || snapshot.replay !== void 0 || snapshot.initialInputs !== void 0)) {
12420
12542
  throw new SnapshotValidationError(
12421
12543
  "unsupportedVersion",
12422
12544
  "$.executionSemantics",
12423
12545
  "incompatible execution semantics; resume with the SafeJS version that created this snapshot. Migration requires explicit reconciliation, not changing its version marker."
12424
12546
  );
12425
12547
  }
12426
- const currentSourceHash = hashSource(options.source, owner);
12548
+ const currentSourceHash = hashSource(
12549
+ options.source,
12550
+ owner,
12551
+ snapshot.executionSemantics !== "jobs-v6" && snapshot.executionSemantics !== "jobs-v7"
12552
+ );
12427
12553
  if (snapshot.sourceHash !== currentSourceHash) {
12428
12554
  throw new SnapshotMismatchError(snapshot.sourceHash, currentSourceHash);
12429
12555
  }
@@ -23890,44 +24016,6 @@ function hoistVarDeclarations(node, scope) {
23890
24016
  }
23891
24017
  }
23892
24018
 
23893
- // packages/safe-js/src/interp/resources.ts
23894
- import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
23895
- var runResources = new AsyncLocalStorage5();
23896
- async function withRunResources(signal, execute) {
23897
- const controller = new AbortController();
23898
- const cancel = () => controller.abort(signal?.reason);
23899
- const cleanups = /* @__PURE__ */ new Set();
23900
- const resources = {
23901
- signal: controller.signal,
23902
- referenceReleases: /* @__PURE__ */ new Set(),
23903
- add(close) {
23904
- cleanups.add(close);
23905
- }
23906
- };
23907
- signal?.addEventListener("abort", cancel, { once: true });
23908
- if (signal?.aborted) cancel();
23909
- let result;
23910
- let failure;
23911
- let errors = [];
23912
- try {
23913
- result = await runResources.run(resources, execute);
23914
- } catch (error) {
23915
- failure = { reason: error };
23916
- } finally {
23917
- signal?.removeEventListener("abort", cancel);
23918
- controller.abort(new Error("SafeJS run finished."));
23919
- for (const release of resources.referenceReleases) release();
23920
- resources.referenceReleases.clear();
23921
- const outcomes = await Promise.allSettled(
23922
- [...cleanups].map((close) => Promise.resolve().then(close))
23923
- );
23924
- errors = outcomes.flatMap((outcome) => outcome.status === "rejected" ? [outcome.reason] : []);
23925
- }
23926
- if (failure !== void 0) throw failure.reason;
23927
- if (errors.length > 0) throw new AggregateError(errors, "SafeJS resource cleanup failed.");
23928
- return result;
23929
- }
23930
-
23931
24019
  // packages/safe-js/src/interp/methods/array.ts
23932
24020
  var arrayLikeSources = /* @__PURE__ */ new WeakMap();
23933
24021
  var activeArrayCallbacks = /* @__PURE__ */ new WeakMap();
@@ -24706,7 +24794,7 @@ function toIntegerOrInfinity(value) {
24706
24794
  }
24707
24795
 
24708
24796
  // packages/safe-js/src/interp/methods/function.ts
24709
- var functionMethodNames = /* @__PURE__ */ new Set(["apply", "bind", "call"]);
24797
+ var functionMethodNames = /* @__PURE__ */ new Set(["apply", "bind", "call", "toString"]);
24710
24798
  function getFunctionMember(target, property, options) {
24711
24799
  if (isGuestClosure(target)) {
24712
24800
  const value = getGuestFunctionProperty(target, String(property));
@@ -24720,12 +24808,14 @@ function getFunctionMember(target, property, options) {
24720
24808
  if (property === "length") {
24721
24809
  return target.length;
24722
24810
  }
24811
+ if (property === "toString" && runResources.getStore()?.functionSourceText === false) return void 0;
24723
24812
  if (!isFunctionMethodName(property)) {
24724
24813
  return void 0;
24725
24814
  }
24726
24815
  return createSandboxClosure({
24727
24816
  sandbox: true,
24728
24817
  name: `Function#${property}`,
24818
+ ...property === "toString" ? { length: 0 } : {},
24729
24819
  call: (args, context) => callFunctionMethod(context?.thisValue, property, args, options, context?.stack ?? [])
24730
24820
  });
24731
24821
  }
@@ -24736,6 +24826,10 @@ function callFunctionMethod(target, methodName, args, options, stack) {
24736
24826
  if (!isSandboxClosure(target)) {
24737
24827
  throw new TypeError(`Function#${methodName} requires a callable receiver.`);
24738
24828
  }
24829
+ if (methodName === "toString") {
24830
+ const text = functionString(target);
24831
+ return options.budget?.allocateString(text) ?? text;
24832
+ }
24739
24833
  const thisValue = args[0];
24740
24834
  if (methodName === "bind") {
24741
24835
  const boundArgs = args.slice(1);
@@ -25074,6 +25168,9 @@ function isStringMethodName(property) {
25074
25168
  function validateStringMethodArguments(_methodName, _args) {
25075
25169
  }
25076
25170
  function callStringMethod(value, methodName, args, budget, callClosure = async (closure, closureArgs) => await closure.call(closureArgs), parent, context) {
25171
+ if (methodName === "concat" && args.some((argument) => argument !== null && typeof argument === "object")) {
25172
+ return callConcat(value, args, budget, context);
25173
+ }
25077
25174
  if (methodName === "isWellFormed") {
25078
25175
  for (let index = 0; index < value.length; index++) {
25079
25176
  const codeUnit = value.charCodeAt(index);
@@ -25229,6 +25326,19 @@ function callStringMethod(value, methodName, args, budget, callClosure = async (
25229
25326
  operation.release();
25230
25327
  }
25231
25328
  }
25329
+ async function callConcat(value, args, budget, context) {
25330
+ let result = budget.allocateString(value);
25331
+ const release = retainValues(budget, () => [result]);
25332
+ try {
25333
+ for (const argument of args) {
25334
+ const text = sandboxString(argument, budget, context);
25335
+ result = budget.allocateString(result + (typeof text === "string" ? text : await text));
25336
+ }
25337
+ return result;
25338
+ } finally {
25339
+ release();
25340
+ }
25341
+ }
25232
25342
  function callReplaceLikeMethod(value, methodName, args, budget, callClosure, context) {
25233
25343
  const search = args[0];
25234
25344
  const replacement = args[1];
@@ -26689,14 +26799,18 @@ function isObjectPrototypeSetterProperty(property, key) {
26689
26799
  }
26690
26800
  async function evaluateTemplateLiteral(node, context) {
26691
26801
  let value = context.budget.allocateString(node.quasis[0]?.value.cooked ?? "");
26692
- const release = retainValues(context.budget, () => [value]);
26802
+ let input = void 0;
26803
+ const release = retainValues(context.budget, () => [value, input]);
26693
26804
  try {
26694
26805
  for (let index = 0; index < node.expressions.length; index += 1) {
26695
26806
  const expression = await evaluateNode(node.expressions[index], context);
26696
26807
  if (expression.kind !== "normal") {
26697
26808
  return expression;
26698
26809
  }
26699
- const expressionText = context.budget.allocateString(String(expression.value));
26810
+ input = expression.value;
26811
+ const text = sandboxString(input, context.budget, createCoercionContext(context));
26812
+ const expressionText = typeof text === "string" ? text : await text;
26813
+ input = void 0;
26700
26814
  value = context.budget.allocateString(value + expressionText);
26701
26815
  const quasiText = context.budget.allocateString(node.quasis[index + 1]?.value.cooked ?? "");
26702
26816
  value = context.budget.allocateString(value + quasiText);
@@ -28143,17 +28257,6 @@ async function evaluateMemberAccess(node, context, consume) {
28143
28257
  release();
28144
28258
  }
28145
28259
  }
28146
- function retainValues(budget, values) {
28147
- const retained = {};
28148
- budget.setRetainedValues(retained, values);
28149
- const pending = runResources.getStore()?.referenceReleases;
28150
- const release = () => {
28151
- budget.setRetainedValues(retained, void 0);
28152
- pending?.delete(release);
28153
- };
28154
- pending?.add(release);
28155
- return release;
28156
- }
28157
28260
  async function evaluateMemberProperty(node, context) {
28158
28261
  const property = await evaluateNode(node, context);
28159
28262
  if (property.kind !== "normal") {
@@ -28911,6 +29014,7 @@ function createSetMethodOptions(context) {
28911
29014
  }
28912
29015
  function createFunctionMethodOptions(context) {
28913
29016
  return {
29017
+ budget: context.budget,
28914
29018
  callClosure: (closure, args, stack, thisValue, construct) => invokeSandboxClosure(closure, args, context, stack, void 0, thisValue, construct)
28915
29019
  };
28916
29020
  }
@@ -29148,6 +29252,7 @@ function createInterpretedClosure(node, context, evaluateNode2) {
29148
29252
  return isConstructResult(result) ? result : thisValue;
29149
29253
  } : void 0;
29150
29254
  const closure = createSandboxClosure({
29255
+ sourceRange: functionSources.get(node),
29151
29256
  guest: true,
29152
29257
  sandbox: true,
29153
29258
  length: getFunctionLength(node.params),
@@ -29210,6 +29315,7 @@ function executeAsyncFunction(execute, budget, signal) {
29210
29315
  }
29211
29316
  function createGeneratorClosure(node, context, evaluateNode2) {
29212
29317
  return createSandboxClosure({
29318
+ sourceRange: functionSources.get(node),
29213
29319
  guest: true,
29214
29320
  generator: true,
29215
29321
  sandbox: true,
@@ -30820,6 +30926,46 @@ function createRegexGlobals(options) {
30820
30926
  };
30821
30927
  }
30822
30928
 
30929
+ // packages/safe-js/src/interp/globals/numeric-parsers.ts
30930
+ function createNumericParsers(budget) {
30931
+ return {
30932
+ parseInt: createSandboxClosure({
30933
+ sandbox: true,
30934
+ name: "parseInt",
30935
+ call: ([value, radix], context) => {
30936
+ const parse2 = (text2) => {
30937
+ const release = retainValues(budget, () => [text2]);
30938
+ let convertedRadix;
30939
+ try {
30940
+ convertedRadix = sandboxNumber(radix, budget, context);
30941
+ } catch (error) {
30942
+ release();
30943
+ throw error;
30944
+ }
30945
+ if (typeof convertedRadix === "number") {
30946
+ try {
30947
+ return globalThis.parseInt(text2, convertedRadix);
30948
+ } finally {
30949
+ release();
30950
+ }
30951
+ }
30952
+ return convertedRadix.then((number) => globalThis.parseInt(text2, number)).finally(release);
30953
+ };
30954
+ const text = sandboxString(value, budget, context);
30955
+ return typeof text === "string" ? parse2(text) : text.then(parse2);
30956
+ }
30957
+ }),
30958
+ parseFloat: createSandboxClosure({
30959
+ sandbox: true,
30960
+ name: "parseFloat",
30961
+ call: ([value], context) => {
30962
+ const text = sandboxString(value, budget, context);
30963
+ return typeof text === "string" ? globalThis.parseFloat(text) : text.then(globalThis.parseFloat);
30964
+ }
30965
+ })
30966
+ };
30967
+ }
30968
+
30823
30969
  // packages/safe-js/src/interp/globals/misc.ts
30824
30970
  function createMiscGlobals(options) {
30825
30971
  return {
@@ -30828,24 +30974,21 @@ function createMiscGlobals(options) {
30828
30974
  call: ([value], context) => structuredCloneSandboxValue(value, options.budget, context?.compilation),
30829
30975
  name: "structuredClone"
30830
30976
  }),
30831
- parseInt: createSandboxClosure({
30832
- sandbox: true,
30833
- call: (args) => Reflect.apply(globalThis.parseInt, globalThis, [...args]),
30834
- name: "parseInt"
30835
- }),
30836
- parseFloat: createSandboxClosure({
30837
- sandbox: true,
30838
- call: (args) => Reflect.apply(globalThis.parseFloat, globalThis, [...args]),
30839
- name: "parseFloat"
30840
- }),
30977
+ ...createNumericParsers(options.budget),
30841
30978
  isNaN: createSandboxClosure({
30842
30979
  sandbox: true,
30843
- call: ([value]) => globalThis.isNaN(value),
30980
+ call: ([value], context) => {
30981
+ const number = sandboxNumber(value, options.budget, context);
30982
+ return typeof number === "number" ? Number.isNaN(number) : number.then(Number.isNaN);
30983
+ },
30844
30984
  name: "isNaN"
30845
30985
  }),
30846
30986
  isFinite: createSandboxClosure({
30847
30987
  sandbox: true,
30848
- call: ([value]) => globalThis.isFinite(value),
30988
+ call: ([value], context) => {
30989
+ const number = sandboxNumber(value, options.budget, context);
30990
+ return typeof number === "number" ? Number.isFinite(number) : number.then(Number.isFinite);
30991
+ },
30849
30992
  name: "isFinite"
30850
30993
  })
30851
30994
  };
@@ -31099,16 +31242,7 @@ function createObjectArrayGlobals(options) {
31099
31242
  call: ([value]) => typeof value === "number" && Number.isInteger(value),
31100
31243
  name: "isInteger"
31101
31244
  }),
31102
- parseInt: createSandboxClosure({
31103
- sandbox: true,
31104
- call: (args) => Reflect.apply(Number.parseInt, Number, [...args]),
31105
- name: "parseInt"
31106
- }),
31107
- parseFloat: createSandboxClosure({
31108
- sandbox: true,
31109
- call: (args) => Reflect.apply(Number.parseFloat, Number, [...args]),
31110
- name: "parseFloat"
31111
- }),
31245
+ ...createNumericParsers(options.budget),
31112
31246
  isSafeInteger: createSandboxClosure({
31113
31247
  sandbox: true,
31114
31248
  call: ([value]) => typeof value === "number" && Number.isSafeInteger(value),
@@ -32934,7 +33068,8 @@ function run(source, options = {}) {
32934
33068
  options.signal?.addEventListener("abort", captureCancellationSnapshot, { once: true });
32935
33069
  try {
32936
33070
  const restoredSnapshot = options.snapshot === void 0 ? void 0 : restore(options.snapshot, { source }, operation.owner);
32937
- const executionSemantics = restoredSnapshot?.executionSemantics === "jobs-v6" ? "jobs-v6" : EXECUTION_SEMANTICS;
33071
+ const executionSemantics = restoredSnapshot?.executionSemantics === "jobs-v6" || restoredSnapshot?.executionSemantics === "jobs-v7" ? restoredSnapshot.executionSemantics : EXECUTION_SEMANTICS;
33072
+ runResources.getStore().functionSourceText = executionSemantics === EXECUTION_SEMANTICS;
32938
33073
  const convertInitialInput = (convert) => executionSemantics === "jobs-v6" ? convert() : promiseReplayContext.exit(convert);
32939
33074
  if (restoredSnapshot !== void 0) {
32940
33075
  leaveSnapshotRun = enterSnapshotRun(restoredSnapshot);
@@ -32943,7 +33078,7 @@ function run(source, options = {}) {
32943
33078
  const filename = options.filename ?? "<input>";
32944
33079
  const module = parseExecutableModule(source, filename, operation.owner);
32945
33080
  promiseReplay.validateNodes(module);
32946
- const sourceHash = findRegexLiteral(module) === void 0 ? hashSource(source, operation.owner) : hashParsedAst(module);
33081
+ const sourceHash = findRegexLiteral(module) === void 0 ? hashSource(source, operation.owner, executionSemantics === EXECUTION_SEMANTICS) : hashParsedAst(module, executionSemantics === EXECUTION_SEMANTICS);
32947
33082
  const hostCalls = new HostCallJournal(
32948
33083
  sourceHash,
32949
33084
  readHostCallSnapshot(restoredSnapshot),
@@ -32970,7 +33105,14 @@ function run(source, options = {}) {
32970
33105
  lifecycle
32971
33106
  })
32972
33107
  );
32973
- const builtinBindings = createBuiltinBindings({ compileOwner: operation.owner, budget, hostCalls, sink: options.sink, random: random?.generator.next, clock: options.clock });
33108
+ const builtinBindings = createBuiltinBindings({
33109
+ compileOwner: operation.owner,
33110
+ budget,
33111
+ hostCalls,
33112
+ sink: options.sink,
33113
+ random: random?.generator.next,
33114
+ clock: options.clock
33115
+ });
32974
33116
  const importMeta = convertInitialInput(
32975
33117
  () => deepCopyToSandbox(options.importMeta ?? {})
32976
33118
  );
@@ -33445,6 +33587,7 @@ export {
33445
33587
  HostOperationResumePolicyError,
33446
33588
  registerPendingHostCallPolicy,
33447
33589
  HostCallResumabilityError,
33590
+ runResources,
33448
33591
  assertSnapshotInactive,
33449
33592
  isSandboxClosure,
33450
33593
  deepCopyToSandbox,
@@ -33461,7 +33604,6 @@ export {
33461
33604
  validateSnapshotMigration,
33462
33605
  restore,
33463
33606
  lint,
33464
- runResources,
33465
33607
  declareHostOperation,
33466
33608
  createSeededRandom,
33467
33609
  createReplayableRandom,
@@ -33473,4 +33615,4 @@ export {
33473
33615
  FileSnapshotBackend,
33474
33616
  run
33475
33617
  };
33476
- //# sourceMappingURL=chunk-MKJBQPBH.js.map
33618
+ //# sourceMappingURL=chunk-VKGWGZBH.js.map