poe-code 14.0.59 → 14.0.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,7 +22,7 @@ import {
22
22
  resolveFsConfig,
23
23
  splitFrontmatter,
24
24
  withBrokenPipeGuard
25
- } from "./chunks/chunk-YZGYOQK3.js";
25
+ } from "./chunks/chunk-VAYQP2VZ.js";
26
26
  import {
27
27
  Budget,
28
28
  SandboxError,
@@ -34,7 +34,7 @@ import {
34
34
  replaceErrorStack,
35
35
  restore,
36
36
  run
37
- } from "./chunks/chunk-D4YY44EF.js";
37
+ } from "./chunks/chunk-ZTGKRKQH.js";
38
38
  import "./chunks/chunk-UXMKEUH3.js";
39
39
  import "./chunks/chunk-5DYEOCT5.js";
40
40
  import "./chunks/chunk-4YIDX44G.js";
@@ -5,7 +5,7 @@ import {
5
5
  defineExtension,
6
6
  lint,
7
7
  run
8
- } from "./chunks/chunk-D4YY44EF.js";
8
+ } from "./chunks/chunk-ZTGKRKQH.js";
9
9
  import "./chunks/chunk-4YIDX44G.js";
10
10
  export {
11
11
  Budget,
@@ -26,7 +26,7 @@ import {
26
26
  runWithSpawnUsageAccumulator,
27
27
  splitFrontmatter,
28
28
  supportsSpawnMode
29
- } from "./chunks/chunk-YZGYOQK3.js";
29
+ } from "./chunks/chunk-VAYQP2VZ.js";
30
30
  import {
31
31
  Budget,
32
32
  FileSnapshotBackend,
@@ -50,7 +50,7 @@ import {
50
50
  registerPendingHostCallPolicy,
51
51
  restore,
52
52
  run
53
- } from "./chunks/chunk-D4YY44EF.js";
53
+ } from "./chunks/chunk-ZTGKRKQH.js";
54
54
  import "./chunks/chunk-UXMKEUH3.js";
55
55
  import "./chunks/chunk-5DYEOCT5.js";
56
56
  import "./chunks/chunk-4YIDX44G.js";
@@ -4,7 +4,8 @@ import { toPropertyKey } from "./property-key.js";
4
4
  import { assertPromiseExecutionAllowed } from "./promise-tracker.js";
5
5
  import { SandboxJobQueue, runAsyncPrefix, suspendJob } from "./jobs.js";
6
6
  import { withCancellationSignal } from "./cancel.js";
7
- import { runResources } from "./resources.js";
7
+ import { retainValues } from "./resources.js";
8
+ import { sandboxString } from "./string-coercion.js";
8
9
  import { attachErrorSpan, formatErrorStack, replaceErrorStack } from "../error/shape.js";
9
10
  import { evaluateArrowFunctionExpression, evaluateFunctionExpression, evaluateAwaitExpression, emitResumeBreakpoint, createInterpretedClosure, normalizeClosureResult } from "./async.js";
10
11
  import { HostCallResumabilityError } from "./host-call.js";
@@ -360,14 +361,18 @@ function isObjectPrototypeSetterProperty(property, key) {
360
361
  }
361
362
  async function evaluateTemplateLiteral(node, context) {
362
363
  let value = context.budget.allocateString(node.quasis[0]?.value.cooked ?? "");
363
- const release = retainValues(context.budget, () => [value]);
364
+ let input = undefined;
365
+ const release = retainValues(context.budget, () => [value, input]);
364
366
  try {
365
367
  for (let index = 0; index < node.expressions.length; index += 1) {
366
368
  const expression = await evaluateNode(node.expressions[index], context);
367
369
  if (expression.kind !== "normal") {
368
370
  return expression;
369
371
  }
370
- const expressionText = context.budget.allocateString(String(expression.value));
372
+ input = expression.value;
373
+ const text = sandboxString(input, context.budget, createCoercionContext(context));
374
+ const expressionText = typeof text === "string" ? text : await text;
375
+ input = undefined;
371
376
  value = context.budget.allocateString(value + expressionText);
372
377
  const quasiText = context.budget.allocateString(node.quasis[index + 1]?.value.cooked ?? "");
373
378
  value = context.budget.allocateString(value + quasiText);
@@ -1831,17 +1836,6 @@ async function evaluateMemberAccess(node, context, consume) {
1831
1836
  release();
1832
1837
  }
1833
1838
  }
1834
- function retainValues(budget, values) {
1835
- const retained = {};
1836
- budget.setRetainedValues(retained, values);
1837
- const pending = runResources.getStore()?.referenceReleases;
1838
- const release = () => {
1839
- budget.setRetainedValues(retained, undefined);
1840
- pending?.delete(release);
1841
- };
1842
- pending?.add(release);
1843
- return release;
1844
- }
1845
1839
  async function evaluateMemberProperty(node, context) {
1846
1840
  const property = await evaluateNode(node, context);
1847
1841
  if (property.kind !== "normal") {
@@ -2,6 +2,7 @@ import { invokeBuiltinClosure } from "../builtin-call.js";
2
2
  import { CompileScope } from "../regex/compile-guard.js";
3
3
  import { normalizeLastIndex } from "../regex/engine.js";
4
4
  import { sandboxNumber, sandboxString } from "../string-coercion.js";
5
+ import { retainValues } from "../resources.js";
5
6
  import { createSandboxClosure, createSandboxRegex, deepCopyFromSandbox, isSandboxClosure, isSandboxRegex } from "../values.js";
6
7
  import { executeRegex, toMatchArray } from "./regex.js";
7
8
  const SPLIT_STRING_MESSAGE = "String#split only supports string separator values.";
@@ -83,6 +84,9 @@ export function isStringMethodName(property) {
83
84
  }
84
85
  export function validateStringMethodArguments(_methodName, _args) { }
85
86
  export function callStringMethod(value, methodName, args, budget, callClosure = async (closure, closureArgs) => await closure.call(closureArgs), parent, context) {
87
+ if (methodName === "concat" && args.some(argument => argument !== null && typeof argument === "object")) {
88
+ return callConcat(value, args, budget, context);
89
+ }
86
90
  if (methodName === "isWellFormed") {
87
91
  for (let index = 0; index < value.length; index++) {
88
92
  const codeUnit = value.charCodeAt(index);
@@ -239,6 +243,20 @@ export function callStringMethod(value, methodName, args, budget, callClosure =
239
243
  operation.release();
240
244
  }
241
245
  }
246
+ async function callConcat(value, args, budget, context) {
247
+ let result = budget.allocateString(value);
248
+ const release = retainValues(budget, () => [result]);
249
+ try {
250
+ for (const argument of args) {
251
+ const text = sandboxString(argument, budget, context);
252
+ result = budget.allocateString(result + (typeof text === "string" ? text : await text));
253
+ }
254
+ return result;
255
+ }
256
+ finally {
257
+ release();
258
+ }
259
+ }
242
260
  function callReplaceLikeMethod(value, methodName, args, budget, callClosure, context) {
243
261
  const search = args[0];
244
262
  const replacement = args[1];
@@ -1,8 +1,10 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
+ import type { Budget } from "./budget.js";
2
3
  export type RunResources = {
3
4
  signal: AbortSignal;
4
5
  referenceReleases: Set<() => void>;
5
6
  add(close: () => Promise<void>): void;
6
7
  };
7
8
  export declare const runResources: AsyncLocalStorage<RunResources>;
9
+ export declare function retainValues(budget: Budget, values: () => Iterable<unknown>): () => void;
8
10
  export declare function withRunResources<Result>(signal: AbortSignal | undefined, execute: () => Promise<Result>): Promise<Result>;
@@ -1,5 +1,16 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
  export const runResources = new AsyncLocalStorage();
3
+ export function retainValues(budget, values) {
4
+ const retained = {};
5
+ budget.setRetainedValues(retained, values);
6
+ const pending = runResources.getStore()?.referenceReleases;
7
+ const release = () => {
8
+ budget.setRetainedValues(retained, undefined);
9
+ pending?.delete(release);
10
+ };
11
+ pending?.add(release);
12
+ return release;
13
+ }
3
14
  export async function withRunResources(signal, execute) {
4
15
  const controller = new AbortController();
5
16
  const cancel = () => controller.abort(signal?.reason);
@@ -7,6 +7,7 @@ import { isGuestHostObject } from "./host-capabilities.js";
7
7
  import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
8
8
  import { getGuestFunctionProperties, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure } from "./object-model.js";
9
9
  import { getRegexMember } from "./methods/regex.js";
10
+ import { retainValues } from "./resources.js";
10
11
  import { isSandboxClosure, isSandboxPromise, isSandboxMap, isSandboxSet, isSandboxRegex, isSandboxGenerator } from "./values.js";
11
12
  const defaultStringHook = Symbol("defaultStringHook");
12
13
  const defaultValueHook = Symbol("defaultValueHook");
@@ -118,9 +119,10 @@ async function defaultToString(value, budget, context, joining) {
118
119
  if (joining.has(value))
119
120
  return "";
120
121
  joining.add(value);
122
+ let text = "";
123
+ const release = retainValues(budget, () => [text]);
121
124
  try {
122
125
  const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
123
- let text = "";
124
126
  for (let index = 0; index < length; index++) {
125
127
  budget.visitNode();
126
128
  const element = ownDataValue(value, String(index));
@@ -132,15 +134,22 @@ async function defaultToString(value, budget, context, joining) {
132
134
  return text;
133
135
  }
134
136
  finally {
137
+ release();
135
138
  joining.delete(value);
136
139
  }
137
140
  }
138
141
  if (sandboxErrorTypes.has(value)) {
139
142
  const nameValue = ownDataValue(value, "name");
140
143
  const name = nameValue === undefined ? "Error" : await sandboxString(nameValue, budget, context, joining);
141
- const messageValue = ownDataValue(value, "message");
142
- const message = messageValue === undefined ? "" : await sandboxString(messageValue, budget, context, joining);
143
- return name === "" ? message : message === "" ? name : `${name}: ${message}`;
144
+ const release = retainValues(budget, () => [name]);
145
+ try {
146
+ const messageValue = ownDataValue(value, "message");
147
+ const message = messageValue === undefined ? "" : await sandboxString(messageValue, budget, context, joining);
148
+ return name === "" ? message : message === "" ? name : `${name}: ${message}`;
149
+ }
150
+ finally {
151
+ release();
152
+ }
144
153
  }
145
154
  return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
146
155
  }
@@ -107,24 +107,22 @@ function parseTokens(tokens, compilation) {
107
107
  function parseModuleTokens(tokens, compilation) {
108
108
  return new Parser(tokens, compilation).parseModule();
109
109
  }
110
- function parseExpressionTokens(tokens, compilation) {
111
- return new Parser(tokens, compilation).parseExpressionOnly();
112
- }
113
110
  class Parser {
114
111
  tokens;
115
112
  compilation;
113
+ functionContext;
116
114
  index = 0;
117
115
  breakableDepth = 0;
118
116
  conditionalExpressionDepth = 0;
119
117
  ifStatementDepth = 0;
120
118
  loopDepth = 0;
121
- generatorBody = false;
122
119
  scopes = [new Map()];
123
120
  functionScopes = new WeakSet();
124
121
  varNames = new WeakMap();
125
- constructor(tokens, compilation) {
122
+ constructor(tokens, compilation, functionContext = "normal") {
126
123
  this.tokens = tokens;
127
124
  this.compilation = compilation;
125
+ this.functionContext = functionContext;
128
126
  this.functionScopes.add(this.scopes[0]);
129
127
  }
130
128
  parseTopLevel() {
@@ -312,9 +310,9 @@ class Parser {
312
310
  }
313
311
  parseArrowFunctionBody(params) {
314
312
  if (this.currentToken().type === "punctuator" && this.currentToken().value === "{") {
315
- return this.withFunctionContext(false, () => this.parseBlockStatement(params));
313
+ return this.withFunctionContext("normal", () => this.parseBlockStatement(params));
316
314
  }
317
- return this.withFunctionContext(false, () => this.parseExpression().node);
315
+ return this.withFunctionContext("normal", () => this.parseExpression().node);
318
316
  }
319
317
  parseBlockStatement(params, catchParam) {
320
318
  const start = this.expectPunctuator("{");
@@ -921,7 +919,7 @@ class Parser {
921
919
  return parsedParams;
922
920
  });
923
921
  const generator = generatorToken !== undefined;
924
- const body = this.withFunctionContext(generator, () => this.parseBlockStatement(params));
922
+ const body = this.withFunctionContext(generator ? "generator" : "normal", () => this.parseBlockStatement(params));
925
923
  return {
926
924
  type: "FunctionDeclaration",
927
925
  async: asyncToken !== undefined,
@@ -952,30 +950,32 @@ class Parser {
952
950
  };
953
951
  }
954
952
  parseArrowParameters() {
955
- this.expectPunctuator("(");
956
- const params = [];
957
- if (this.consumePunctuator(")") !== undefined) {
958
- return params;
959
- }
960
- while (true) {
961
- const param = this.parseBindingElement();
962
- params.push(param);
963
- const comma = this.consumePunctuator(",");
964
- if (comma === undefined) {
965
- break;
953
+ return this.withFunctionContext("parameters", () => {
954
+ this.expectPunctuator("(");
955
+ const params = [];
956
+ if (this.consumePunctuator(")") !== undefined) {
957
+ return params;
966
958
  }
967
- if (param.type === "RestElement") {
959
+ while (true) {
960
+ const param = this.parseBindingElement();
961
+ params.push(param);
962
+ const comma = this.consumePunctuator(",");
963
+ if (comma === undefined) {
964
+ break;
965
+ }
966
+ if (param.type === "RestElement") {
967
+ if (this.currentToken().type === "punctuator" && this.currentToken().value === ")") {
968
+ throw unexpectedTokenError(comma);
969
+ }
970
+ throw new Error(`Rest element must be the last parameter at line ${comma.start.line}, column ${comma.start.column}.`);
971
+ }
968
972
  if (this.currentToken().type === "punctuator" && this.currentToken().value === ")") {
969
- throw unexpectedTokenError(comma);
973
+ break;
970
974
  }
971
- throw new Error(`Rest element must be the last parameter at line ${comma.start.line}, column ${comma.start.column}.`);
972
- }
973
- if (this.currentToken().type === "punctuator" && this.currentToken().value === ")") {
974
- break;
975
975
  }
976
- }
977
- this.expectPunctuator(")");
978
- return params;
976
+ this.expectPunctuator(")");
977
+ return params;
978
+ });
979
979
  }
980
980
  parseBindingElement() {
981
981
  if (this.consumePunctuator("...") !== undefined) {
@@ -1509,7 +1509,7 @@ class Parser {
1509
1509
  };
1510
1510
  }
1511
1511
  if (token.type === "keyword" && token.value === "yield") {
1512
- if (!this.generatorBody) {
1512
+ if (this.functionContext !== "generator") {
1513
1513
  throw new Error(`yield is only valid inside a generator body at line ${token.start.line}, column ${token.start.column}.`);
1514
1514
  }
1515
1515
  this.index += 1;
@@ -1539,9 +1539,12 @@ class Parser {
1539
1539
  };
1540
1540
  }
1541
1541
  if (token.type === "keyword" && token.value === "await") {
1542
- if (this.generatorBody) {
1542
+ if (this.functionContext === "generator") {
1543
1543
  throw new Error(`generators cannot await; use a regular async function at line ${token.start.line}, column ${token.start.column}.`);
1544
1544
  }
1545
+ if (this.functionContext === "parameters") {
1546
+ throw new Error(`await is not valid in function parameters at line ${token.start.line}, column ${token.start.column}.`);
1547
+ }
1545
1548
  this.index += 1;
1546
1549
  const argument = this.parseUnaryExpression();
1547
1550
  return {
@@ -1666,7 +1669,7 @@ class Parser {
1666
1669
  continue;
1667
1670
  }
1668
1671
  if (this.currentToken().type === "template") {
1669
- const quasi = createTemplateLiteral(this.currentToken(), { allowMalformedEscapes: true }, this.compilation);
1672
+ const quasi = createTemplateLiteral(this.currentToken(), { allowMalformedEscapes: true, functionContext: this.functionContext }, this.compilation);
1670
1673
  this.index += 1;
1671
1674
  expression = {
1672
1675
  node: {
@@ -1754,7 +1757,7 @@ class Parser {
1754
1757
  if (token.type === "template") {
1755
1758
  this.index += 1;
1756
1759
  return {
1757
- node: createTemplateLiteral(token, { allowMalformedEscapes: false }, this.compilation),
1760
+ node: createTemplateLiteral(token, { allowMalformedEscapes: false, functionContext: this.functionContext }, this.compilation),
1758
1761
  parenthesized: false
1759
1762
  };
1760
1763
  }
@@ -1871,7 +1874,7 @@ class Parser {
1871
1874
  return parsedParams;
1872
1875
  });
1873
1876
  const generator = generatorToken !== undefined;
1874
- const body = this.withFunctionContext(generator, () => this.parseBlockStatement(params));
1877
+ const body = this.withFunctionContext(generator ? "generator" : "normal", () => this.parseBlockStatement(params));
1875
1878
  return {
1876
1879
  type: "FunctionExpression",
1877
1880
  async: asyncToken !== undefined,
@@ -2135,7 +2138,7 @@ class Parser {
2135
2138
  }
2136
2139
  return parsedParams;
2137
2140
  });
2138
- const body = this.withFunctionContext(false, () => this.parseBlockStatement(params));
2141
+ const body = this.withFunctionContext("normal", () => this.parseBlockStatement(params));
2139
2142
  return {
2140
2143
  type: "FunctionExpression",
2141
2144
  async: asyncToken !== undefined,
@@ -2546,20 +2549,20 @@ class Parser {
2546
2549
  (nextToken.type === "punctuator" && (nextToken.value === ";" || nextToken.value === "}")) ||
2547
2550
  nextToken.type === "eof");
2548
2551
  }
2549
- withFunctionContext(generatorBody, callback) {
2552
+ withFunctionContext(functionContext, callback) {
2550
2553
  const previousBreakableDepth = this.breakableDepth;
2551
2554
  const previousLoopDepth = this.loopDepth;
2552
- const previousGeneratorBody = this.generatorBody;
2555
+ const previousFunctionContext = this.functionContext;
2553
2556
  this.breakableDepth = 0;
2554
2557
  this.loopDepth = 0;
2555
- this.generatorBody = generatorBody;
2558
+ this.functionContext = functionContext;
2556
2559
  try {
2557
2560
  return callback();
2558
2561
  }
2559
2562
  finally {
2560
2563
  this.breakableDepth = previousBreakableDepth;
2561
2564
  this.loopDepth = previousLoopDepth;
2562
- this.generatorBody = previousGeneratorBody;
2565
+ this.functionContext = previousFunctionContext;
2563
2566
  }
2564
2567
  }
2565
2568
  withLoopContext(callback) {
@@ -3014,7 +3017,7 @@ function createLiteralFromToken(token) {
3014
3017
  }
3015
3018
  return createKeywordLiteral(token);
3016
3019
  }
3017
- function createTemplateLiteral(token, options = { allowMalformedEscapes: false }, compilation) {
3020
+ function createTemplateLiteral(token, options, compilation) {
3018
3021
  const raw = token.value;
3019
3022
  const expressions = [];
3020
3023
  const quasis = [];
@@ -3030,7 +3033,7 @@ function createTemplateLiteral(token, options = { allowMalformedEscapes: false }
3030
3033
  quasis.push(createTemplateElement(token.start, raw, quasiStart, cursor, false, options));
3031
3034
  const expressionStart = cursor + 2;
3032
3035
  const expressionEnd = findTemplateExpressionEnd(raw, expressionStart);
3033
- expressions.push(parseEmbeddedExpression(raw.slice(expressionStart, expressionEnd), positionWithinRaw(token.start, raw, expressionStart), compilation));
3036
+ expressions.push(parseEmbeddedExpression(raw.slice(expressionStart, expressionEnd), positionWithinRaw(token.start, raw, expressionStart), options.functionContext, compilation));
3034
3037
  quasiStart = expressionEnd + 1;
3035
3038
  cursor = expressionEnd + 1;
3036
3039
  continue;
@@ -3391,13 +3394,13 @@ function decodeHexEscape(value, start) {
3391
3394
  end: index + 2
3392
3395
  };
3393
3396
  }
3394
- function parseEmbeddedExpression(source, base, compilation) {
3397
+ function parseEmbeddedExpression(source, base, functionContext, compilation) {
3395
3398
  const tokens = tokenize(source, { allowRegexLiterals: true, compilation }).map((token) => ({
3396
3399
  ...token,
3397
3400
  start: rebasePosition(token.start, base),
3398
3401
  end: rebasePosition(token.end, base)
3399
3402
  }));
3400
- return parseExpressionTokens(tokens, compilation);
3403
+ return new Parser(tokens, compilation, functionContext).parseExpressionOnly();
3401
3404
  }
3402
3405
  export function findRegexLiteral(node) {
3403
3406
  if (node === null || node === undefined) {