poe-code 14.0.65 → 14.0.66

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 (42) hide show
  1. package/dist/index.js +1723 -797
  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-4VT2M7WL.js → chunk-MKTUVVEB.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-WBWD7ZCM.js → chunk-YKISHTWT.js} +1675 -772
  7. package/packages/safe-js/dist/chunks/chunk-YKISHTWT.js.map +7 -0
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.js +1 -1
  10. package/packages/safe-js/dist/index.js +2 -2
  11. package/packages/safe-js/dist/interp/accessors.d.ts +9 -0
  12. package/packages/safe-js/dist/interp/accessors.js +68 -0
  13. package/packages/safe-js/dist/interp/async.js +3 -3
  14. package/packages/safe-js/dist/interp/classes.js +10 -4
  15. package/packages/safe-js/dist/interp/exceptions.d.ts +1 -1
  16. package/packages/safe-js/dist/interp/exceptions.js +47 -8
  17. package/packages/safe-js/dist/interp/globals/collections.js +53 -16
  18. package/packages/safe-js/dist/interp/globals/console-json.js +41 -26
  19. package/packages/safe-js/dist/interp/globals/object-array.js +229 -68
  20. package/packages/safe-js/dist/interp/globals/object.js +6 -3
  21. package/packages/safe-js/dist/interp/globals/primitives.js +11 -5
  22. package/packages/safe-js/dist/interp/interpreter.d.ts +2 -2
  23. package/packages/safe-js/dist/interp/interpreter.js +83 -44
  24. package/packages/safe-js/dist/interp/iteration.js +13 -0
  25. package/packages/safe-js/dist/interp/methods/array.d.ts +1 -1
  26. package/packages/safe-js/dist/interp/methods/array.js +368 -109
  27. package/packages/safe-js/dist/interp/methods/function.js +56 -20
  28. package/packages/safe-js/dist/interp/methods/regex.js +1 -1
  29. package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
  30. package/packages/safe-js/dist/interp/object-model.js +48 -10
  31. package/packages/safe-js/dist/interp/patterns.d.ts +2 -2
  32. package/packages/safe-js/dist/interp/patterns.js +35 -16
  33. package/packages/safe-js/dist/interp/promise.d.ts +1 -1
  34. package/packages/safe-js/dist/interp/promise.js +103 -63
  35. package/packages/safe-js/dist/interp/string-coercion.d.ts +1 -0
  36. package/packages/safe-js/dist/interp/string-coercion.js +47 -37
  37. package/packages/safe-js/dist/interp/values.d.ts +2 -1
  38. package/packages/safe-js/dist/interp/values.js +26 -1
  39. package/packages/safe-js/dist/parse/parser.d.ts +1 -1
  40. package/packages/safe-js/dist/parse/parser.js +37 -8
  41. package/packages/safe-js/dist/chunks/chunk-WBWD7ZCM.js.map +0 -7
  42. /package/packages/safe-js/dist/chunks/{chunk-4VT2M7WL.js.map → chunk-MKTUVVEB.js.map} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { sandboxErrorTypes } from "../error/shape.js";
2
+ import { readPropertyDescriptor } from "./accessors.js";
2
3
  import { dateString, dateTime, isSandboxDate } from "./date.js";
3
4
  import { invokeBuiltinClosure } from "./builtin-call.js";
4
5
  import { float32Storage, isFloat32Array } from "./float32.js";
@@ -13,6 +14,7 @@ import { boxedValue, isSandboxBox } from "./boxed.js";
13
14
  import { isSandboxClosure, isSandboxPromise, isSandboxMap, isSandboxSet, isSandboxRegex, isSandboxGenerator } from "./values.js";
14
15
  const defaultStringHook = Symbol("defaultStringHook");
15
16
  const defaultValueHook = Symbol("defaultValueHook");
17
+ const joiningArrays = new WeakSet();
16
18
  export function sandboxNumber(value, budget, context) {
17
19
  if (value === null || typeof value !== "object") {
18
20
  if (typeof value === "function")
@@ -30,18 +32,44 @@ export function sandboxString(value, budget, context, joining = new Set()) {
30
32
  return objectToPrimitive(value, budget, context, joining, "string")
31
33
  .then(primitive => budget.allocateString(String(primitive)));
32
34
  }
35
+ export async function joinSandboxArray(value, length, separator, budget, context, joining = new Set()) {
36
+ if (joiningArrays.has(value))
37
+ return "";
38
+ joiningArrays.add(value);
39
+ let text = "";
40
+ const release = retainValues(budget, () => [value, text, separator]);
41
+ try {
42
+ for (let index = 0; index < length; index++) {
43
+ budget.visitNode();
44
+ const element = await readCoercionProperty(value, String(index), context);
45
+ const part = element === null || element === undefined
46
+ ? ""
47
+ : await sandboxString(element, budget, context, joining);
48
+ text = budget.allocateString(text + (index === 0 ? "" : separator) + part);
49
+ }
50
+ return text;
51
+ }
52
+ finally {
53
+ release();
54
+ joiningArrays.delete(value);
55
+ }
56
+ }
33
57
  async function objectToPrimitive(value, budget, context, joining, hint) {
34
58
  const leaveCall = budget.enterCall();
35
59
  try {
36
60
  budget.visitNode();
37
61
  for (const name of hint === "string" ? ["toString", "valueOf"] : ["valueOf", "toString"]) {
38
- const hook = conversionHook(value, name, budget);
62
+ const hook = await conversionHook(value, name, budget, context);
39
63
  let result;
40
64
  if (hook === defaultStringHook) {
41
65
  result = await defaultToString(value, budget, context, joining);
42
66
  }
43
67
  else if (hook === defaultValueHook) {
44
- result = isSandboxDate(value) ? dateTime(value) : isSandboxBox(value) ? boxedValue(value) : value;
68
+ result = isSandboxDate(value)
69
+ ? dateTime(value)
70
+ : isSandboxBox(value)
71
+ ? boxedValue(value)
72
+ : value;
45
73
  }
46
74
  else {
47
75
  if (!isSandboxClosure(hook))
@@ -60,7 +88,7 @@ async function objectToPrimitive(value, budget, context, joining, hint) {
60
88
  leaveCall();
61
89
  }
62
90
  }
63
- function conversionHook(value, name, budget) {
91
+ function conversionHook(value, name, budget, context) {
64
92
  const implicitBuiltin = !hasExplicitSandboxPrototype(value) &&
65
93
  (Array.isArray(value) ||
66
94
  isSandboxDate(value) ||
@@ -80,9 +108,7 @@ function conversionHook(value, name, budget) {
80
108
  const properties = isGuestClosure(current) ? getGuestFunctionProperties(current) : current;
81
109
  const descriptor = properties === undefined ? undefined : Object.getOwnPropertyDescriptor(properties, name);
82
110
  if (descriptor !== undefined) {
83
- if (!Object.hasOwn(descriptor, "value"))
84
- throw new TypeError("String conversion requires sandbox data properties.");
85
- return descriptor.value;
111
+ return readPropertyDescriptor(descriptor, value, context);
86
112
  }
87
113
  const parent = getSandboxPrototype(current, budget);
88
114
  if (current === value &&
@@ -107,7 +133,9 @@ async function defaultToString(value, budget, context, joining) {
107
133
  if (isSandboxSet(value))
108
134
  return "[object Set]";
109
135
  if (isSandboxCollectionIterator(value))
110
- return collectionIteratorState(value).collectionKind === "map" ? "[object Map Iterator]" : "[object Set Iterator]";
136
+ return collectionIteratorState(value).collectionKind === "map"
137
+ ? "[object Map Iterator]"
138
+ : "[object Set Iterator]";
111
139
  if (isSandboxGenerator(value))
112
140
  return "[object Generator]";
113
141
  if (isSandboxRegex(value)) {
@@ -117,40 +145,23 @@ async function defaultToString(value, budget, context, joining) {
117
145
  return budget.allocateString(dateString(value));
118
146
  if (Array.isArray(value) || isFloat32Array(value)) {
119
147
  if (Object.hasOwn(value, "join")) {
120
- const join = ownDataValue(value, "join");
148
+ const join = await readCoercionProperty(value, "join", context);
121
149
  if (!isSandboxClosure(join))
122
150
  return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
123
151
  return invokeBuiltinClosure(join, [], budget, context, value);
124
152
  }
125
- if (joining.has(value))
126
- return "";
127
- joining.add(value);
128
- let text = "";
129
- const release = retainValues(budget, () => [text]);
130
- try {
131
- const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
132
- for (let index = 0; index < length; index++) {
133
- budget.visitNode();
134
- const element = ownDataValue(value, String(index));
135
- const part = element === null || element === undefined
136
- ? ""
137
- : await sandboxString(element, budget, context, joining);
138
- text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
139
- }
140
- return text;
141
- }
142
- finally {
143
- release();
144
- joining.delete(value);
145
- }
153
+ const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
154
+ return joinSandboxArray(value, length, ",", budget, context, joining);
146
155
  }
147
156
  if (sandboxErrorTypes.has(value)) {
148
- const nameValue = ownDataValue(value, "name");
157
+ const nameValue = await readCoercionProperty(value, "name", context);
149
158
  const name = nameValue === undefined ? "Error" : await sandboxString(nameValue, budget, context, joining);
150
159
  const release = retainValues(budget, () => [name]);
151
160
  try {
152
- const messageValue = ownDataValue(value, "message");
153
- const message = messageValue === undefined ? "" : await sandboxString(messageValue, budget, context, joining);
161
+ const messageValue = await readCoercionProperty(value, "message", context);
162
+ const message = messageValue === undefined
163
+ ? ""
164
+ : await sandboxString(messageValue, budget, context, joining);
154
165
  return name === "" ? message : message === "" ? name : `${name}: ${message}`;
155
166
  }
156
167
  finally {
@@ -159,10 +170,9 @@ async function defaultToString(value, budget, context, joining) {
159
170
  }
160
171
  return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
161
172
  }
162
- function ownDataValue(value, name) {
173
+ function readCoercionProperty(value, name, context) {
174
+ if (context?.getProperty !== undefined)
175
+ return context.getProperty(value, name);
163
176
  const descriptor = Object.getOwnPropertyDescriptor(value, name);
164
- if (descriptor !== undefined && !Object.hasOwn(descriptor, "value")) {
165
- throw new TypeError("String conversion requires sandbox data properties.");
166
- }
167
- return descriptor?.value;
177
+ return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, value, context);
168
178
  }
@@ -54,7 +54,7 @@ export type SandboxCallContext = {
54
54
  };
55
55
  readonly stack: readonly string[];
56
56
  readonly thisValue: SandboxValue;
57
- readonly getProperty?: (value: SandboxValue, property: string | number) => SandboxValue;
57
+ readonly getProperty?: (value: SandboxValue, property: string | number) => SandboxValue | Promise<SandboxValue>;
58
58
  readonly reconcileData?: (value: SandboxValue) => void;
59
59
  readonly invokeClosure?: (closure: SandboxClosure, args: readonly SandboxValue[], thisValue: SandboxValue, construct?: boolean, newTarget?: SandboxClosure) => Promise<SandboxValue>;
60
60
  };
@@ -112,6 +112,7 @@ export declare function createSandboxClosure(input: {
112
112
  retainedValues?: () => Iterable<SandboxValue>;
113
113
  }): SandboxClosure;
114
114
  export declare function ownEnumerableSandboxEntries(value: SandboxValue, excludedKeys?: ReadonlySet<string>): Array<[string, SandboxValue]>;
115
+ export declare function ownEnumerableSandboxKeys(value: SandboxValue): string[];
115
116
  export declare function createSandboxPromise(promise: Promise<SandboxValue>, metadata?: {
116
117
  trackReplay?: boolean;
117
118
  synchronousPrefix?: Promise<void>;
@@ -1,4 +1,5 @@
1
1
  import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
2
+ import { retainedAccessorClosures } from "./accessors.js";
2
3
  import { isSandboxMap, isSandboxSet, sandboxMapBrand, sandboxSetBrand } from "./collection-brands.js";
3
4
  import { collectionIteratorState, isSandboxCollectionIterator, restoreSandboxCollectionIterator, snapshotCollectionIterator } from "./collection-iterator.js";
4
5
  import { copyNativeDate, exportDate, isSandboxDate } from "./date.js";
@@ -100,6 +101,17 @@ export function ownEnumerableSandboxEntries(value, excludedKeys) {
100
101
  entries = Object.entries(Object(value));
101
102
  return excludedKeys === undefined ? entries : entries.filter(([key]) => !excludedKeys.has(key));
102
103
  }
104
+ export function ownEnumerableSandboxKeys(value) {
105
+ if (isGuestHostObject(value))
106
+ return getHostObjectKeys(value);
107
+ if (value === null || value === undefined)
108
+ throw new TypeError("Cannot convert undefined or null to object.");
109
+ if (isGuestClosure(value))
110
+ return Object.keys(value.properties ?? {});
111
+ if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value) || isSandboxRegex(value))
112
+ return [];
113
+ return Object.keys(Object(value));
114
+ }
103
115
  export function createSandboxPromise(promise, metadata = {}) {
104
116
  const original = metadata.trackReplay === false
105
117
  ? promise
@@ -254,6 +266,9 @@ export function measureSandboxData(values, options = {}) {
254
266
  usage += key.length + 1;
255
267
  if ("value" in descriptor)
256
268
  visit(descriptor.value, depth + 1);
269
+ else
270
+ for (const closure of retainedAccessorClosures(descriptor))
271
+ visit(closure, depth + 1);
257
272
  }
258
273
  return;
259
274
  }
@@ -289,6 +304,9 @@ export function measureSandboxData(values, options = {}) {
289
304
  usage += key.length + 1;
290
305
  if ("value" in descriptor)
291
306
  visit(descriptor.value, depth + 1);
307
+ else
308
+ for (const closure of retainedAccessorClosures(descriptor))
309
+ visit(closure, depth + 1);
292
310
  }
293
311
  return;
294
312
  }
@@ -333,6 +351,9 @@ export function measureSandboxData(values, options = {}) {
333
351
  usage += key.length + 1;
334
352
  if ("value" in descriptor)
335
353
  visit(descriptor.value, depth + 1);
354
+ else
355
+ for (const closure of retainedAccessorClosures(descriptor))
356
+ visit(closure, depth + 1);
336
357
  }
337
358
  }
338
359
  else
@@ -386,7 +407,11 @@ export function measureSandboxData(values, options = {}) {
386
407
  if (!descriptor.enumerable && !hasManagedDescriptors(value))
387
408
  continue;
388
409
  usage += key.length;
389
- visit("value" in descriptor ? descriptor.value : undefined, depth + 1);
410
+ if ("value" in descriptor)
411
+ visit(descriptor.value, depth + 1);
412
+ else
413
+ for (const closure of retainedAccessorClosures(descriptor))
414
+ visit(closure, depth + 1);
390
415
  }
391
416
  };
392
417
  for (const value of values)
@@ -251,7 +251,7 @@ export type ClassElement = (BaseNode & {
251
251
  type: "MethodDefinition";
252
252
  computed: boolean;
253
253
  key: Expression;
254
- kind: "constructor" | "method";
254
+ kind: "constructor" | "method" | "get" | "set";
255
255
  static: boolean;
256
256
  value: FunctionExpression;
257
257
  }) | (BaseNode & {
@@ -980,7 +980,7 @@ class Parser {
980
980
  });
981
981
  });
982
982
  }
983
- parseFunctionParts(generator, lexicalContext) {
983
+ parseFunctionParts(generator, lexicalContext, accessor) {
984
984
  return this.withLexicalContext(lexicalContext, () => {
985
985
  const params = this.withScope(() => {
986
986
  const parsed = this.parseArrowParameters();
@@ -989,7 +989,27 @@ class Parser {
989
989
  this.declareBinding(identifier);
990
990
  return parsed;
991
991
  });
992
+ if (accessor === "get" && params.length !== 0)
993
+ throw new Error("A getter cannot have parameters.");
994
+ if (accessor === "set" && (params.length !== 1 || params[0]?.type === "RestElement"))
995
+ throw new Error("A setter must have exactly one non-rest parameter.");
996
+ const bodyTokenIndex = this.index;
992
997
  const body = this.withFunctionContext(generator ? "generator" : "normal", () => this.parseBlockStatement(params));
998
+ if (accessor === "set" && params[0]?.type !== "Identifier") {
999
+ let directiveTokenIndex = bodyTokenIndex + 1;
1000
+ for (const statement of body.body) {
1001
+ const token = this.tokens[directiveTokenIndex];
1002
+ if (statement.type !== "ExpressionStatement" ||
1003
+ statement.expression.type !== "StringLiteral" ||
1004
+ token?.type !== "string" ||
1005
+ statement.span.start.offset !== token.start.offset ||
1006
+ statement.span.end.offset !== token.end.offset)
1007
+ break;
1008
+ if (statement.expression.raw === '"use strict"' || statement.expression.raw === "'use strict'")
1009
+ throw new Error("A setter with a non-simple parameter cannot contain a use strict directive.");
1010
+ directiveTokenIndex += this.tokens[directiveTokenIndex + 1]?.value === ";" ? 2 : 1;
1011
+ }
1012
+ }
993
1013
  return { params, body };
994
1014
  });
995
1015
  }
@@ -1017,8 +1037,14 @@ class Parser {
1017
1037
  const generator = this.consumePunctuator("*") !== undefined;
1018
1038
  if (async && generator)
1019
1039
  throw new DisallowedSyntaxError("async generator", methodStart.start);
1020
- if ((this.currentToken().value === "get" || this.currentToken().value === "set") && this.isObjectMethodStart())
1021
- throw new DisallowedSyntaxError("class accessor", this.currentToken().start);
1040
+ let accessor;
1041
+ const modifier = this.currentToken();
1042
+ if ((modifier.value === "get" || modifier.value === "set") && this.isObjectMethodStart()) {
1043
+ if (async || generator || modifier.end.offset - modifier.start.offset !== modifier.value.length)
1044
+ throw unexpectedTokenError(modifier);
1045
+ accessor = modifier.value;
1046
+ this.index++;
1047
+ }
1022
1048
  const computed = this.consumePunctuator("[") !== undefined;
1023
1049
  const key = computed
1024
1050
  ? this.parseExpression({ allowSequence: true }).node
@@ -1035,19 +1061,19 @@ class Parser {
1035
1061
  throw new Error("A static class element cannot be named prototype.");
1036
1062
  if (this.currentToken().value === "(") {
1037
1063
  const constructor = !isStatic && name === "constructor";
1038
- if (constructor && (async || generator))
1039
- throw new Error("A class constructor cannot be async or a generator.");
1064
+ if (constructor && (async || generator || accessor !== undefined))
1065
+ throw new Error("A class constructor must be an ordinary method.");
1040
1066
  const { params, body } = this.parseFunctionParts(generator, {
1041
1067
  newTarget: true, superProperty: true, superCall: constructor && derived,
1042
1068
  arguments: true, return: true, await: async, strictAwait: true
1043
- });
1069
+ }, accessor);
1044
1070
  const value = this.withFunctionSource({
1045
1071
  type: "FunctionExpression", async, generator, method: true, params, body,
1046
1072
  span: createSpan(methodStart.start, body.span.end)
1047
1073
  });
1048
1074
  return {
1049
1075
  type: "MethodDefinition", key, computed, static: isStatic,
1050
- kind: constructor ? "constructor" : "method", value,
1076
+ kind: accessor ?? (constructor ? "constructor" : "method"), value,
1051
1077
  span: createSpan(start.start, value.span.end)
1052
1078
  };
1053
1079
  }
@@ -2285,7 +2311,10 @@ class Parser {
2285
2311
  this.peekToken(2).value === "(");
2286
2312
  }
2287
2313
  parseObjectMethod(asyncToken, methodStart) {
2288
- const { params, body } = this.parseFunctionParts(false, ordinaryFunctionContext);
2314
+ const { params, body } = this.parseFunctionParts(false, {
2315
+ ...ordinaryFunctionContext,
2316
+ superProperty: true
2317
+ });
2289
2318
  return this.withFunctionSource({
2290
2319
  type: "FunctionExpression",
2291
2320
  async: asyncToken !== undefined,