poe-code 14.0.72 → 14.0.74

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 (45) hide show
  1. package/dist/index.js +2674 -1760
  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-VYUHL33E.js → chunk-2J6W3YGB.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-6UY4Z7WY.js → chunk-YEZOXLY4.js} +6279 -5426
  7. package/packages/safe-js/dist/chunks/chunk-YEZOXLY4.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/graph-depth.js +10 -0
  11. package/packages/safe-js/dist/index.js +2 -2
  12. package/packages/safe-js/dist/interp/cancel.js +3 -0
  13. package/packages/safe-js/dist/interp/globals/misc.js +2 -1
  14. package/packages/safe-js/dist/interp/globals/object-array.js +9 -7
  15. package/packages/safe-js/dist/interp/globals/object.js +5 -2
  16. package/packages/safe-js/dist/interp/globals/regex.js +88 -7
  17. package/packages/safe-js/dist/interp/interpreter.js +21 -14
  18. package/packages/safe-js/dist/interp/iteration.js +6 -1
  19. package/packages/safe-js/dist/interp/methods/regex.d.ts +7 -3
  20. package/packages/safe-js/dist/interp/methods/regex.js +132 -23
  21. package/packages/safe-js/dist/interp/methods/regexp-iterator.d.ts +8 -0
  22. package/packages/safe-js/dist/interp/methods/regexp-iterator.js +49 -0
  23. package/packages/safe-js/dist/interp/methods/string.d.ts +2 -0
  24. package/packages/safe-js/dist/interp/methods/string.js +460 -127
  25. package/packages/safe-js/dist/interp/object-model.d.ts +2 -0
  26. package/packages/safe-js/dist/interp/object-model.js +45 -12
  27. package/packages/safe-js/dist/interp/regexp-iterator.d.ts +14 -0
  28. package/packages/safe-js/dist/interp/regexp-iterator.js +18 -0
  29. package/packages/safe-js/dist/interp/regexp-properties.d.ts +3 -0
  30. package/packages/safe-js/dist/interp/regexp-properties.js +7 -0
  31. package/packages/safe-js/dist/interp/string-coercion.js +11 -7
  32. package/packages/safe-js/dist/interp/values.d.ts +3 -1
  33. package/packages/safe-js/dist/interp/values.js +111 -2
  34. package/packages/safe-js/dist/snapshot/dump-format.js +51 -9
  35. package/packages/safe-js/dist/snapshot/regexp-properties.d.ts +18 -0
  36. package/packages/safe-js/dist/snapshot/regexp-properties.js +58 -0
  37. package/packages/safe-js/dist/snapshot/replay-data.d.ts +12 -3
  38. package/packages/safe-js/dist/snapshot/replay-data.js +35 -1
  39. package/packages/safe-js/dist/snapshot/replay-inputs.js +17 -0
  40. package/packages/safe-js/dist/snapshot/restore.js +19 -1
  41. package/packages/safe-js/dist/snapshot/serialize.d.ts +12 -3
  42. package/packages/safe-js/dist/snapshot/serialize.js +40 -17
  43. package/packages/safe-js/dist/snapshot/validation.js +25 -2
  44. package/packages/safe-js/dist/chunks/chunk-6UY4Z7WY.js.map +0 -7
  45. /package/packages/safe-js/dist/chunks/{chunk-VYUHL33E.js.map → chunk-2J6W3YGB.js.map} +0 -0
@@ -1,22 +1,84 @@
1
- import { createSandboxClosure, getSandboxRegexPattern, isSandboxClosure, isSandboxRegex } from "../values.js";
1
+ import { createSandboxClosure, getSandboxRegexPattern, getRegexProperties, isSandboxClosure, isSandboxRegex } from "../values.js";
2
2
  import { matchRegex } from "../regex/engine.js";
3
3
  import { invokeBuiltinClosure } from "../builtin-call.js";
4
- import { getSandboxDataProperty } from "../object-model.js";
4
+ import { getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype } from "../object-model.js";
5
+ import { readPropertyDescriptor } from "../accessors.js";
6
+ import { retainValues } from "../resources.js";
5
7
  import { sandboxNumber, sandboxString } from "../string-coercion.js";
6
- const regexMethodNames = new Set(["exec", "test"]);
7
- const regexFlagProperties = {
8
+ import { setSandboxProperty } from "../interpreter.js";
9
+ export async function regexSearch(target, input, budget, context) {
10
+ if (target === null || typeof target !== "object")
11
+ throw new TypeError("RegExp search requires an object receiver.");
12
+ let string;
13
+ let previous;
14
+ let result;
15
+ const release = retainValues(budget, () => [target, input, string, previous, result]);
16
+ const read = (value, key) => {
17
+ if (context?.getProperty !== undefined)
18
+ return context.getProperty(value, key);
19
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
20
+ return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, value, context);
21
+ };
22
+ try {
23
+ string = await sandboxString(input, budget, context);
24
+ input = undefined;
25
+ previous = await read(target, "lastIndex");
26
+ if (!Object.is(previous, 0))
27
+ await setSandboxProperty(target, "lastIndex", 0, budget, true, context);
28
+ result = await regexExec(target, string, budget, context);
29
+ if (!Object.is(await read(target, "lastIndex"), previous))
30
+ await setSandboxProperty(target, "lastIndex", previous, budget, true, context);
31
+ return result === null ? -1 : await read(result, "index");
32
+ }
33
+ finally {
34
+ release();
35
+ }
36
+ }
37
+ const regexMethodNames = new Set(["exec", "test", "toString"]);
38
+ export const regexFlagProperties = {
8
39
  hasIndices: "d", global: "g", ignoreCase: "i", multiline: "m",
9
40
  dotAll: "s", unicode: "u", unicodeSets: "v", sticky: "y"
10
41
  };
11
42
  export function isRegexMethodName(property) {
12
43
  return typeof property === "string" && regexMethodNames.has(property);
13
44
  }
14
- export function getRegexMember(target, property, budget) {
45
+ export function getRegexMember(target, property, budget, context) {
15
46
  if (property === "source")
16
47
  return escapeRegexSource(target.source, budget);
17
48
  if (property === "flags") {
18
- const flags = [..."gims"].filter((flag) => target.flags.includes(flag)).join("");
19
- return budget === undefined ? flags : budget.allocateString(flags);
49
+ let flags = "";
50
+ const entries = Object.entries(regexFlagProperties);
51
+ const release = retainValues(budget, () => [target, flags]);
52
+ const read = (index) => {
53
+ if (index === entries.length)
54
+ return budget.allocateString(flags);
55
+ budget.visitNode();
56
+ const [key, flag] = entries[index];
57
+ const descriptor = context?.getProperty === undefined
58
+ ? getSandboxPropertyDescriptor(target, key, budget) : undefined;
59
+ const value = context?.getProperty !== undefined
60
+ ? context.getProperty(target, key)
61
+ : descriptor !== undefined
62
+ ? readPropertyDescriptor(descriptor, target, context)
63
+ : target.flags.includes(flag);
64
+ const append = (value) => {
65
+ if (value)
66
+ flags += flag;
67
+ return read(index + 1);
68
+ };
69
+ return value instanceof Promise ? value.then(append) : append(value);
70
+ };
71
+ try {
72
+ const result = read(0);
73
+ if (result instanceof Promise)
74
+ return result.finally(release);
75
+ release();
76
+ return result;
77
+ }
78
+ catch (error) {
79
+ release();
80
+ throw error;
81
+ }
20
82
  }
21
83
  if (property === "lastIndex")
22
84
  return target.lastIndex;
@@ -27,7 +89,7 @@ export function getRegexMember(target, property, budget) {
27
89
  }
28
90
  return createSandboxClosure({
29
91
  sandbox: true,
30
- name: `RegExp#${property}`,
92
+ name: property === "toString" ? "toString" : `RegExp#${property}`,
31
93
  call: (args, context) => callRegexMethod(context?.thisValue, property, args, budget, context)
32
94
  });
33
95
  }
@@ -66,13 +128,18 @@ function escapeRegexSource(source, budget) {
66
128
  text = text === "" ? "(?:)" : text;
67
129
  return budget === undefined ? text : budget.allocateString(text);
68
130
  }
69
- export function setRegexMember(target, property, value) {
70
- if (property !== "lastIndex") {
131
+ export function setRegexMember(target, property, value, budget) {
132
+ const properties = getRegexProperties(target);
133
+ if (!hasExplicitSandboxPrototype(target) && getSandboxPrototype(target, budget) === null && !Object.hasOwn(properties, property) &&
134
+ (property === "source" || property === "flags" || Object.hasOwn(regexFlagProperties, property))) {
71
135
  throw new TypeError(`RegExp#${String(property)} is not writable.`);
72
136
  }
73
- target.lastIndex = value;
137
+ if (!Reflect.set(properties, property, value))
138
+ throw new TypeError(`RegExp#${String(property)} is not writable.`);
74
139
  }
75
140
  export async function callRegexMethod(target, methodName, args, budget, context) {
141
+ if (methodName === "toString")
142
+ return regexToString(target, budget, context);
76
143
  if (target === null || typeof target !== "object" || (methodName === "exec" && !isSandboxRegex(target))) {
77
144
  throw new TypeError(`RegExp#${methodName} requires ${methodName === "exec" ? "a regex" : "an object"} receiver.`);
78
145
  }
@@ -83,29 +150,71 @@ export async function callRegexMethod(target, methodName, args, budget, context)
83
150
  try {
84
151
  const input = await sandboxString(args[0], budget, context);
85
152
  if (methodName === "test") {
86
- const exec = context?.getProperty === undefined
87
- ? getSandboxDataProperty(target, "exec", budget) : await context.getProperty(target, "exec");
88
- if (isSandboxClosure(exec)) {
89
- const result = await invokeBuiltinClosure(exec, [input], budget, context, target);
90
- if (result !== null && typeof result !== "object") {
91
- throw new TypeError("RegExp#test exec must return an object or null.");
92
- }
93
- return result !== null;
94
- }
153
+ budget.setRetainedValues(retained, undefined);
154
+ return await regexExec(target, input, budget, context) !== null;
95
155
  }
96
- if (!isSandboxRegex(target))
97
- throw new TypeError("RegExp execution requires a regex receiver.");
98
156
  if (typeof args[0] !== "string")
99
157
  convertedInput = input;
158
+ if (!isSandboxRegex(target))
159
+ throw new TypeError("RegExp execution requires a regex receiver.");
100
160
  cursor = target.lastIndex;
101
161
  const lastIndex = await sandboxNumber(cursor, budget, context);
102
162
  const match = executeRegex(target, input, lastIndex);
103
- return methodName === "test" ? match !== null : toMatchArray(match, input);
163
+ return toMatchArray(match, input);
104
164
  }
105
165
  finally {
106
166
  budget.setRetainedValues(retained, undefined);
107
167
  }
108
168
  }
169
+ export async function regexExec(target, input, budget, context) {
170
+ let exec;
171
+ const release = retainValues(budget, () => [target, input, exec]);
172
+ try {
173
+ const descriptor = context?.getProperty === undefined
174
+ ? getSandboxPropertyDescriptor(target, "exec", budget) : undefined;
175
+ exec = await (context?.getProperty !== undefined ? context.getProperty(target, "exec")
176
+ : descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, target, context));
177
+ if (isSandboxClosure(exec)) {
178
+ const result = await invokeBuiltinClosure(exec, [input], budget, context, target);
179
+ if (result !== null && typeof result !== "object")
180
+ throw new TypeError("RegExp exec must return an object or null.");
181
+ return result;
182
+ }
183
+ return await callRegexMethod(target, "exec", [input], budget, context);
184
+ }
185
+ finally {
186
+ release();
187
+ }
188
+ }
189
+ export async function regexToString(target, budget, context) {
190
+ if (target === null || typeof target !== "object")
191
+ throw new TypeError("RegExp#toString requires an object receiver.");
192
+ const read = (key) => {
193
+ if (context?.getProperty !== undefined)
194
+ return context.getProperty(target, key);
195
+ const descriptor = getSandboxPropertyDescriptor(target, key, budget);
196
+ if (descriptor !== undefined)
197
+ return readPropertyDescriptor(descriptor, target, context);
198
+ return isSandboxRegex(target) ? getRegexMember(target, key, budget, context) : undefined;
199
+ };
200
+ let sourceValue;
201
+ let flagsValue;
202
+ let source;
203
+ let flags;
204
+ const release = retainValues(budget, () => [target, sourceValue, flagsValue, source, flags]);
205
+ try {
206
+ sourceValue = await read("source");
207
+ source = await sandboxString(sourceValue, budget, context);
208
+ sourceValue = undefined;
209
+ flagsValue = await read("flags");
210
+ flags = await sandboxString(flagsValue, budget, context);
211
+ flagsValue = undefined;
212
+ return budget.allocateString(`/${source}/${flags}`);
213
+ }
214
+ finally {
215
+ release();
216
+ }
217
+ }
109
218
  export function executeRegex(target, input, lastIndex) {
110
219
  const pattern = getSandboxRegexPattern(target);
111
220
  const match = matchRegex(pattern, input, lastIndex);
@@ -0,0 +1,8 @@
1
+ import type { Budget } from "../budget.js";
2
+ import { type SandboxRegExpIterator } from "../regexp-iterator.js";
3
+ import { type SandboxValue } from "../values.js";
4
+ export declare function nextRegExpIterator(iterator: SandboxRegExpIterator, budget?: Budget): {
5
+ value: SandboxValue;
6
+ done: boolean;
7
+ };
8
+ export declare function getRegExpIteratorMember(property: PropertyKey, budget: Budget): SandboxValue;
@@ -0,0 +1,49 @@
1
+ import { isSandboxRegExpIterator, regexpIteratorState } from "../regexp-iterator.js";
2
+ import { createSandboxClosure } from "../values.js";
3
+ import { executeRegex, toMatchArray } from "./regex.js";
4
+ export function nextRegExpIterator(iterator, budget) {
5
+ const state = regexpIteratorState(iterator);
6
+ budget?.visitNode();
7
+ if (state.exhausted)
8
+ return { value: undefined, done: true };
9
+ const matcher = state.matcher;
10
+ const input = state.input;
11
+ const match = executeRegex(matcher, input, Number(matcher.lastIndex));
12
+ if (match === null || !matcher.flags.includes("g")) {
13
+ state.exhausted = true;
14
+ state.matcher = undefined;
15
+ state.input = undefined;
16
+ }
17
+ if (match === null)
18
+ return { value: undefined, done: true };
19
+ if (!state.exhausted && match.text.length === 0) {
20
+ const index = Number(matcher.lastIndex);
21
+ const unicode = matcher.flags.includes("u") || matcher.flags.includes("v");
22
+ const codePoint = input.codePointAt(index);
23
+ matcher.lastIndex = index + (unicode && codePoint !== undefined && codePoint > 0xffff ? 2 : 1);
24
+ }
25
+ budget?.allocateArrayLength(match.captures.length + 1);
26
+ return { value: toMatchArray(match, input), done: false };
27
+ }
28
+ export function getRegExpIteratorMember(property, budget) {
29
+ if (property === Symbol.toStringTag)
30
+ return "RegExp String Iterator";
31
+ if (property === Symbol.iterator)
32
+ return createSandboxClosure({
33
+ sandbox: true,
34
+ name: "[Symbol.iterator]",
35
+ call: (_args, context) => context?.thisValue
36
+ });
37
+ if (property !== "next")
38
+ return undefined;
39
+ return createSandboxClosure({
40
+ sandbox: true,
41
+ name: "next",
42
+ call: (_args, context) => {
43
+ const receiver = context?.thisValue;
44
+ if (!isSandboxRegExpIterator(receiver))
45
+ throw new TypeError("RegExp string iterator next requires a matching receiver.");
46
+ return nextRegExpIterator(receiver, budget);
47
+ }
48
+ });
49
+ }
@@ -9,4 +9,6 @@ export declare function getStringIndex(property: string | number): number | unde
9
9
  export declare function isStringMethodName(property: string | number): property is StringMethodName;
10
10
  export declare function validateStringMethodArguments(_methodName: StringMethodName, _args: readonly Expression[]): void;
11
11
  export declare function callStringMethod(value: SandboxValue, methodName: StringMethodName, args: readonly SandboxValue[], budget: Budget, callClosure?: (closure: SandboxClosure, args: readonly SandboxValue[]) => Promise<SandboxValue>, parent?: CompileScope, context?: SandboxCallContext): SandboxValue | Promise<SandboxValue>;
12
+ export declare function regexReplace(input: SandboxValue, regex: SandboxValue, replacementInput: SandboxValue, budget: Budget, callClosure: (closure: SandboxClosure, args: readonly SandboxValue[]) => Promise<SandboxValue>, context?: SandboxCallContext): Promise<string>;
13
+ export declare function regexMatch(input: SandboxValue, regex: SandboxValue, budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
12
14
  export {};