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.
- package/dist/index.js +2674 -1760
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-js/dist/chunks/{chunk-VYUHL33E.js → chunk-2J6W3YGB.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-6UY4Z7WY.js → chunk-YEZOXLY4.js} +6279 -5426
- package/packages/safe-js/dist/chunks/chunk-YEZOXLY4.js.map +7 -0
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.js +1 -1
- package/packages/safe-js/dist/graph-depth.js +10 -0
- package/packages/safe-js/dist/index.js +2 -2
- package/packages/safe-js/dist/interp/cancel.js +3 -0
- package/packages/safe-js/dist/interp/globals/misc.js +2 -1
- package/packages/safe-js/dist/interp/globals/object-array.js +9 -7
- package/packages/safe-js/dist/interp/globals/object.js +5 -2
- package/packages/safe-js/dist/interp/globals/regex.js +88 -7
- package/packages/safe-js/dist/interp/interpreter.js +21 -14
- package/packages/safe-js/dist/interp/iteration.js +6 -1
- package/packages/safe-js/dist/interp/methods/regex.d.ts +7 -3
- package/packages/safe-js/dist/interp/methods/regex.js +132 -23
- package/packages/safe-js/dist/interp/methods/regexp-iterator.d.ts +8 -0
- package/packages/safe-js/dist/interp/methods/regexp-iterator.js +49 -0
- package/packages/safe-js/dist/interp/methods/string.d.ts +2 -0
- package/packages/safe-js/dist/interp/methods/string.js +460 -127
- package/packages/safe-js/dist/interp/object-model.d.ts +2 -0
- package/packages/safe-js/dist/interp/object-model.js +45 -12
- package/packages/safe-js/dist/interp/regexp-iterator.d.ts +14 -0
- package/packages/safe-js/dist/interp/regexp-iterator.js +18 -0
- package/packages/safe-js/dist/interp/regexp-properties.d.ts +3 -0
- package/packages/safe-js/dist/interp/regexp-properties.js +7 -0
- package/packages/safe-js/dist/interp/string-coercion.js +11 -7
- package/packages/safe-js/dist/interp/values.d.ts +3 -1
- package/packages/safe-js/dist/interp/values.js +111 -2
- package/packages/safe-js/dist/snapshot/dump-format.js +51 -9
- package/packages/safe-js/dist/snapshot/regexp-properties.d.ts +18 -0
- package/packages/safe-js/dist/snapshot/regexp-properties.js +58 -0
- package/packages/safe-js/dist/snapshot/replay-data.d.ts +12 -3
- package/packages/safe-js/dist/snapshot/replay-data.js +35 -1
- package/packages/safe-js/dist/snapshot/replay-inputs.js +17 -0
- package/packages/safe-js/dist/snapshot/restore.js +19 -1
- package/packages/safe-js/dist/snapshot/serialize.d.ts +12 -3
- package/packages/safe-js/dist/snapshot/serialize.js +40 -17
- package/packages/safe-js/dist/snapshot/validation.js +25 -2
- package/packages/safe-js/dist/chunks/chunk-6UY4Z7WY.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-VYUHL33E.js.map → chunk-2J6W3YGB.js.map} +0 -0
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveFsConfig,
|
|
23
23
|
splitFrontmatter,
|
|
24
24
|
withBrokenPipeGuard
|
|
25
|
-
} from "./chunks/chunk-
|
|
25
|
+
} from "./chunks/chunk-2J6W3YGB.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-
|
|
37
|
+
} from "./chunks/chunk-YEZOXLY4.js";
|
|
38
38
|
import "./chunks/chunk-ZWJ5BJUI.js";
|
|
39
39
|
import "./chunks/chunk-3YTQEPZI.js";
|
|
40
40
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -2,8 +2,10 @@ import { replaceErrorStack } from "./error/shape.js";
|
|
|
2
2
|
import { SandboxError } from "./interp/budget.js";
|
|
3
3
|
import { getSandboxArgumentEntries, isSandboxArguments } from "./interp/arguments.js";
|
|
4
4
|
import { collectionIteratorState, isSandboxCollectionIterator } from "./interp/collection-iterator.js";
|
|
5
|
+
import { regexpIteratorState, isSandboxRegExpIterator } from "./interp/regexp-iterator.js";
|
|
5
6
|
import { isSandboxMap, isSandboxSet } from "./interp/collection-brands.js";
|
|
6
7
|
import { boxedDataProperties, isSandboxBox } from "./interp/boxed.js";
|
|
8
|
+
import { regexGuestProperties } from "./interp/regexp-properties.js";
|
|
7
9
|
export const MAX_DATA_DEPTH = 1_024;
|
|
8
10
|
export class SnapshotBudgetError extends Error {
|
|
9
11
|
code = "budgetExceeded";
|
|
@@ -64,6 +66,12 @@ function walkGraphDepth(root, rootPath, assertDepth) {
|
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
function graphEntries(value) {
|
|
69
|
+
const properties = regexGuestProperties.get(value);
|
|
70
|
+
if (properties !== undefined)
|
|
71
|
+
return Reflect.ownKeys(properties).flatMap(key => {
|
|
72
|
+
const descriptor = Object.getOwnPropertyDescriptor(properties, key);
|
|
73
|
+
return "value" in descriptor ? [[`.${String(key)}`, descriptor.value]] : [];
|
|
74
|
+
});
|
|
67
75
|
if (isSandboxBox(value))
|
|
68
76
|
return boxedDataProperties(value).map(([key, descriptor]) => [`.${key}`, descriptor.value]);
|
|
69
77
|
if (isSandboxArguments(value)) {
|
|
@@ -83,6 +91,8 @@ function graphEntries(value) {
|
|
|
83
91
|
const entries = [];
|
|
84
92
|
if (isSandboxCollectionIterator(value))
|
|
85
93
|
entries.push([".<collection>", collectionIteratorState(value).collection]);
|
|
94
|
+
if (isSandboxRegExpIterator(value))
|
|
95
|
+
entries.push([".<matcher>", regexpIteratorState(value).matcher]);
|
|
86
96
|
for (const key of Object.keys(value)) {
|
|
87
97
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
88
98
|
if (descriptor !== undefined && "value" in descriptor)
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
runWithSpawnUsageAccumulator,
|
|
27
27
|
splitFrontmatter,
|
|
28
28
|
supportsSpawnMode
|
|
29
|
-
} from "./chunks/chunk-
|
|
29
|
+
} from "./chunks/chunk-2J6W3YGB.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-
|
|
53
|
+
} from "./chunks/chunk-YEZOXLY4.js";
|
|
54
54
|
import "./chunks/chunk-ZWJ5BJUI.js";
|
|
55
55
|
import "./chunks/chunk-3YTQEPZI.js";
|
|
56
56
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
|
|
3
|
+
import { regexpIteratorState, isSandboxRegExpIterator } from "./regexp-iterator.js";
|
|
3
4
|
import { getSandboxPrototype } from "./object-model.js";
|
|
4
5
|
import { createSandboxPromise, isSandboxClosure, isSandboxMap, isSandboxPromise, isSandboxSet } from "./values.js";
|
|
5
6
|
import { assertPromiseExecutionAllowed, interruptOnFatalPromiseRejection, onFatalPromiseRejection, observeSandboxPromise, trackSandboxPromise } from "./promise-tracker.js";
|
|
@@ -100,6 +101,8 @@ function registerCancelablePromises(value, signal) {
|
|
|
100
101
|
else {
|
|
101
102
|
if (isSandboxCollectionIterator(current))
|
|
102
103
|
pending.push(collectionIteratorState(current).collection);
|
|
104
|
+
if (isSandboxRegExpIterator(current))
|
|
105
|
+
pending.push(regexpIteratorState(current).matcher);
|
|
103
106
|
for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(current))) {
|
|
104
107
|
if ("value" in descriptor)
|
|
105
108
|
pending.push(descriptor.value);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isSandboxCollectionIterator } from "../collection-iterator.js";
|
|
2
|
+
import { isSandboxRegExpIterator } from "../regexp-iterator.js";
|
|
2
3
|
import { assertSandboxGraphDepth } from "../../graph-depth.js";
|
|
3
4
|
import { CompileScope } from "../regex/compile-guard.js";
|
|
4
5
|
import { createNumericParsers } from "./numeric-parsers.js";
|
|
@@ -49,7 +50,7 @@ function structuredCloneSandboxValue(value, budget, parent) {
|
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
function assertStructuredCloneable(value, seen) {
|
|
52
|
-
if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value)) {
|
|
53
|
+
if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value) || isSandboxRegExpIterator(value)) {
|
|
53
54
|
throw new TypeError("structuredClone() cannot clone closures, promises, or collection iterators.");
|
|
54
55
|
}
|
|
55
56
|
if (typeof value !== "object" || value === null || seen.has(value)) {
|
|
@@ -17,7 +17,7 @@ import { toPropertyKey } from "../property-key.js";
|
|
|
17
17
|
import { createNumericParsers } from "./numeric-parsers.js";
|
|
18
18
|
import { createPrimitiveConstructor } from "./primitives.js";
|
|
19
19
|
import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
20
|
-
import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, measureSandboxData, ownEnumerableSandboxKeys as getOwnEnumerableKeys, ownSandboxSymbolKeys, ownEnumerableSandboxEntries as getDirectEntries } from "../values.js";
|
|
20
|
+
import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, getRegexProperties, isSandboxSet, measureSandboxData, ownEnumerableSandboxKeys as getOwnEnumerableKeys, ownSandboxSymbolKeys, ownEnumerableSandboxEntries as getDirectEntries } from "../values.js";
|
|
21
21
|
export function createObjectArrayGlobals(options) {
|
|
22
22
|
return {
|
|
23
23
|
Object: createObjectGlobal({
|
|
@@ -171,14 +171,14 @@ export function createObjectArrayGlobals(options) {
|
|
|
171
171
|
call: ([value]) => {
|
|
172
172
|
if (isGuestHostObject(value))
|
|
173
173
|
throw new TypeError("Live host objects cannot be made non-extensible.");
|
|
174
|
-
Object.preventExtensions(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
|
|
174
|
+
Object.preventExtensions(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value);
|
|
175
175
|
return value;
|
|
176
176
|
},
|
|
177
177
|
name: "preventExtensions"
|
|
178
178
|
}),
|
|
179
179
|
isExtensible: createSandboxClosure({
|
|
180
180
|
sandbox: true,
|
|
181
|
-
call: ([value]) => Object.isExtensible(isGuestClosure(value) ? materializeFunctionProperties(value) : value),
|
|
181
|
+
call: ([value]) => Object.isExtensible(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value),
|
|
182
182
|
name: "isExtensible"
|
|
183
183
|
}),
|
|
184
184
|
seal: createSandboxClosure({
|
|
@@ -186,14 +186,14 @@ export function createObjectArrayGlobals(options) {
|
|
|
186
186
|
call: ([value]) => {
|
|
187
187
|
if (isGuestHostObject(value))
|
|
188
188
|
throw new TypeError("Live host objects cannot be sealed.");
|
|
189
|
-
Object.seal(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
|
|
189
|
+
Object.seal(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value);
|
|
190
190
|
return value;
|
|
191
191
|
},
|
|
192
192
|
name: "seal"
|
|
193
193
|
}),
|
|
194
194
|
isSealed: createSandboxClosure({
|
|
195
195
|
sandbox: true,
|
|
196
|
-
call: ([value]) => Object.isSealed(isGuestClosure(value) ? materializeFunctionProperties(value) : value),
|
|
196
|
+
call: ([value]) => Object.isSealed(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value),
|
|
197
197
|
name: "isSealed"
|
|
198
198
|
}),
|
|
199
199
|
freeze: createSandboxClosure({
|
|
@@ -202,7 +202,7 @@ export function createObjectArrayGlobals(options) {
|
|
|
202
202
|
if (isGuestHostObject(value))
|
|
203
203
|
throw new TypeError("Live host objects cannot be frozen.");
|
|
204
204
|
if (typeof value === "object" && value !== null) {
|
|
205
|
-
Object.freeze(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
|
|
205
|
+
Object.freeze(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value);
|
|
206
206
|
}
|
|
207
207
|
return value;
|
|
208
208
|
},
|
|
@@ -210,7 +210,7 @@ export function createObjectArrayGlobals(options) {
|
|
|
210
210
|
}),
|
|
211
211
|
isFrozen: createSandboxClosure({
|
|
212
212
|
sandbox: true,
|
|
213
|
-
call: ([value]) => Object.isFrozen(isGuestClosure(value) ? materializeFunctionProperties(value) : value),
|
|
213
|
+
call: ([value]) => Object.isFrozen(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value),
|
|
214
214
|
name: "isFrozen"
|
|
215
215
|
}),
|
|
216
216
|
assign: createSandboxClosure({
|
|
@@ -425,6 +425,8 @@ function assignSandboxValues(target, sources, budget, context) {
|
|
|
425
425
|
})();
|
|
426
426
|
}
|
|
427
427
|
function objectProperties(value, mutable = false) {
|
|
428
|
+
if (isSandboxRegex(value))
|
|
429
|
+
return getRegexProperties(value);
|
|
428
430
|
if (isSandboxDate(value)) {
|
|
429
431
|
return value;
|
|
430
432
|
}
|
|
@@ -7,9 +7,10 @@ import { isSandboxErrorConstructorInstance } from "../exceptions.js";
|
|
|
7
7
|
import { isFloat32Array } from "../float32.js";
|
|
8
8
|
import { hasHostObjectMember, isGuestHostObject } from "../host-capabilities.js";
|
|
9
9
|
import { collectionIteratorState, isSandboxCollectionIterator } from "../collection-iterator.js";
|
|
10
|
+
import { isSandboxRegExpIterator } from "../regexp-iterator.js";
|
|
10
11
|
import { getSandboxPrototype, getSandboxPropertyDescriptor, hasExplicitSandboxPrototype, installObjectPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
11
12
|
import { toPropertyKey } from "../property-key.js";
|
|
12
|
-
import { createSandboxClosure, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "../values.js";
|
|
13
|
+
import { createSandboxClosure, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, getRegexProperties, isSandboxSet } from "../values.js";
|
|
13
14
|
import { measureSandboxData } from "../values.js";
|
|
14
15
|
export function createObjectGlobal(methods, budget) {
|
|
15
16
|
const construct = ([value]) => {
|
|
@@ -138,7 +139,7 @@ export function hasOwnSandboxProperty(value, key, enumerable) {
|
|
|
138
139
|
isSandboxGenerator(value))
|
|
139
140
|
return false;
|
|
140
141
|
else if (isSandboxRegex(value))
|
|
141
|
-
|
|
142
|
+
properties = getRegexProperties(value);
|
|
142
143
|
else
|
|
143
144
|
properties = Object(value);
|
|
144
145
|
const descriptor = Object.getOwnPropertyDescriptor(properties, key);
|
|
@@ -180,6 +181,8 @@ function typeTag(value, builtinOnly = false) {
|
|
|
180
181
|
return "Map";
|
|
181
182
|
if (isSandboxSet(value))
|
|
182
183
|
return "Set";
|
|
184
|
+
if (isSandboxRegExpIterator(value))
|
|
185
|
+
return "RegExp String Iterator";
|
|
183
186
|
if (isSandboxCollectionIterator(value))
|
|
184
187
|
return collectionIteratorState(value).collectionKind === "map" ? "Map Iterator" : "Set Iterator";
|
|
185
188
|
if (isSandboxPromise(value))
|
|
@@ -2,6 +2,11 @@ import { createSandboxClosure, createSandboxRegex, isSandboxRegex, reconcileComp
|
|
|
2
2
|
import { CompileScope } from "../regex/compile-guard.js";
|
|
3
3
|
import { SandboxError } from "../budget.js";
|
|
4
4
|
import { sandboxString } from "../string-coercion.js";
|
|
5
|
+
import { getSandboxPropertyDescriptor, installRegexPrototype, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
6
|
+
import { accessorAdapter, readPropertyDescriptor } from "../accessors.js";
|
|
7
|
+
import { callRegexMethod, getRegexMember, regexFlagProperties, regexSearch } from "../methods/regex.js";
|
|
8
|
+
import { regexMatch, regexReplace } from "../methods/string.js";
|
|
9
|
+
import { invokeBuiltinClosure } from "../builtin-call.js";
|
|
5
10
|
export function createRegexGlobals(options) {
|
|
6
11
|
const invoke = (construct) => async (args, context) => {
|
|
7
12
|
const selected = options.compileOwner ?? context?.compilation?.owner;
|
|
@@ -12,18 +17,51 @@ export function createRegexGlobals(options) {
|
|
|
12
17
|
const compilation = context?.compilation?.owner === operation.owner
|
|
13
18
|
? context.compilation : new CompileScope(operation.owner);
|
|
14
19
|
let source = "";
|
|
20
|
+
let retainedSource;
|
|
21
|
+
let retainedFlags;
|
|
22
|
+
let retainedPrototype;
|
|
15
23
|
const retained = {};
|
|
16
|
-
options.budget.setRetainedValues(retained, () => [...args, source]);
|
|
24
|
+
options.budget.setRetainedValues(retained, () => [...args, source, retainedSource, retainedFlags, retainedPrototype]);
|
|
17
25
|
try {
|
|
18
26
|
const pattern = args[0];
|
|
19
27
|
const flags = args[1];
|
|
20
|
-
|
|
28
|
+
const read = (key) => {
|
|
29
|
+
const descriptor = getSandboxPropertyDescriptor(pattern, key, options.budget);
|
|
30
|
+
if (context?.getProperty !== undefined)
|
|
31
|
+
return context.getProperty(pattern, key);
|
|
32
|
+
return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, pattern, context);
|
|
33
|
+
};
|
|
34
|
+
let regexLike = false;
|
|
35
|
+
if (pattern !== null && typeof pattern === "object") {
|
|
36
|
+
const match = await read(Symbol.match);
|
|
37
|
+
regexLike = match === undefined ? isSandboxRegex(pattern) : Boolean(match);
|
|
38
|
+
}
|
|
39
|
+
if (!construct && regexLike && flags === undefined && await read("constructor") === constructor)
|
|
21
40
|
return pattern;
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
let sourceValue = pattern;
|
|
42
|
+
let flagsValue = flags;
|
|
43
|
+
if (isSandboxRegex(pattern)) {
|
|
44
|
+
sourceValue = pattern.source;
|
|
45
|
+
if (flags === undefined)
|
|
46
|
+
flagsValue = pattern.flags;
|
|
47
|
+
}
|
|
48
|
+
else if (regexLike) {
|
|
49
|
+
sourceValue = retainedSource = await read("source");
|
|
50
|
+
if (flags === undefined)
|
|
51
|
+
flagsValue = retainedFlags = await read("flags");
|
|
52
|
+
}
|
|
53
|
+
if (construct && context?.newTarget !== undefined && context.newTarget !== constructor) {
|
|
54
|
+
retainedPrototype = context.getProperty !== undefined
|
|
55
|
+
? await context.getProperty(context.newTarget, "prototype")
|
|
56
|
+
: await readPropertyDescriptor(getSandboxPropertyDescriptor(context.newTarget, "prototype", options.budget) ?? { value: undefined }, context.newTarget, context);
|
|
57
|
+
}
|
|
24
58
|
source = sourceValue === undefined ? "" : await sandboxString(sourceValue, options.budget, context);
|
|
59
|
+
retainedSource = undefined;
|
|
25
60
|
const flagText = flagsValue === undefined ? "" : await sandboxString(flagsValue, options.budget, context);
|
|
61
|
+
retainedFlags = undefined;
|
|
26
62
|
const regex = createSandboxRegex(source, flagText, 0, compilation);
|
|
63
|
+
if (typeof retainedPrototype === "object" && retainedPrototype !== null)
|
|
64
|
+
setSandboxPrototype(regex, retainedPrototype, options.budget);
|
|
27
65
|
if (compilation !== context?.compilation) {
|
|
28
66
|
reconcileCompiledValues(options.budget, [regex], compilation);
|
|
29
67
|
}
|
|
@@ -36,7 +74,50 @@ export function createRegexGlobals(options) {
|
|
|
36
74
|
operation.release();
|
|
37
75
|
}
|
|
38
76
|
};
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
};
|
|
77
|
+
const constructor = createSandboxClosure({ guest: true, sandbox: true, name: "RegExp", length: 2, call: invoke(false), construct: invoke(true) });
|
|
78
|
+
const prototype = Object.create(null);
|
|
79
|
+
Object.defineProperty(materializeFunctionProperties(constructor), "prototype", { value: prototype, writable: false });
|
|
80
|
+
Object.defineProperty(prototype, "constructor", { value: constructor, writable: true, configurable: true });
|
|
81
|
+
Object.defineProperty(prototype, Symbol.search, {
|
|
82
|
+
value: createSandboxClosure({ guest: true, sandbox: true, name: "[Symbol.search]", length: 1,
|
|
83
|
+
call: (args, context) => regexSearch(context?.thisValue, args[0], options.budget, context) }),
|
|
84
|
+
writable: true, configurable: true
|
|
85
|
+
});
|
|
86
|
+
Object.defineProperty(prototype, Symbol.match, {
|
|
87
|
+
value: createSandboxClosure({ guest: true, sandbox: true, name: "[Symbol.match]", length: 1,
|
|
88
|
+
call: (args, context) => regexMatch(args[0], context?.thisValue, options.budget, context) }),
|
|
89
|
+
writable: true, configurable: true
|
|
90
|
+
});
|
|
91
|
+
Object.defineProperty(prototype, Symbol.replace, {
|
|
92
|
+
value: createSandboxClosure({ guest: true, sandbox: true, name: "[Symbol.replace]", length: 2,
|
|
93
|
+
call: (args, context) => regexReplace(args[0], context?.thisValue, args[1], options.budget, (closure, values) => invokeBuiltinClosure(closure, values, options.budget, context, undefined), context) }),
|
|
94
|
+
writable: true, configurable: true
|
|
95
|
+
});
|
|
96
|
+
for (const name of ["exec", "test", "toString"]) {
|
|
97
|
+
Object.defineProperty(prototype, name, {
|
|
98
|
+
value: createSandboxClosure({ sandbox: true, name, length: name === "toString" ? 0 : 1,
|
|
99
|
+
call: (args, context) => callRegexMethod(context?.thisValue, name, args, options.budget, context) }),
|
|
100
|
+
writable: true, configurable: true
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
for (const name of ["source", "flags", ...Object.keys(regexFlagProperties)]) {
|
|
104
|
+
const getter = createSandboxClosure({ sandbox: true, name: `get ${name}`, length: 0,
|
|
105
|
+
call: (_args, context) => {
|
|
106
|
+
const receiver = context?.thisValue;
|
|
107
|
+
if (name === "flags") {
|
|
108
|
+
if (receiver === null || typeof receiver !== "object")
|
|
109
|
+
throw new TypeError("RegExp flags requires an object receiver.");
|
|
110
|
+
return getRegexMember(receiver, name, options.budget, context);
|
|
111
|
+
}
|
|
112
|
+
if (receiver === prototype)
|
|
113
|
+
return name === "source" ? "(?:)" : undefined;
|
|
114
|
+
if (!isSandboxRegex(receiver))
|
|
115
|
+
throw new TypeError("RegExp accessor requires a regex receiver.");
|
|
116
|
+
return getRegexMember(receiver, name, options.budget, context);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
Object.defineProperty(prototype, name, { get: accessorAdapter(getter, "get"), configurable: true });
|
|
120
|
+
}
|
|
121
|
+
installRegexPrototype(options.budget, prototype, constructor);
|
|
122
|
+
return { RegExp: constructor };
|
|
42
123
|
}
|
|
@@ -26,7 +26,7 @@ import { getPromiseMember, isSandboxPromiseConstructor } from "./promise.js";
|
|
|
26
26
|
import { acquireSandboxIterator, closeIterator, readIteratorResult } from "./iteration.js";
|
|
27
27
|
import { assertCollectionMutable } from "./running-state.js";
|
|
28
28
|
import { getGeneratorMember } from "./methods/generator.js";
|
|
29
|
-
import { getRegexMember,
|
|
29
|
+
import { getRegexMember, setRegexMember } from "./methods/regex.js";
|
|
30
30
|
import { bindPattern } from "./patterns.js";
|
|
31
31
|
import { callStringMethod, getStringMember, isStringMethodName, validateStringMethodArguments } from "./methods/string.js";
|
|
32
32
|
import { callSetMethod, getSetMember, isSetMethodName } from "./methods/set.js";
|
|
@@ -35,11 +35,13 @@ import { hasOwnSandboxProperty } from "./globals/object.js";
|
|
|
35
35
|
import { isSandboxMapConstructor, isSandboxSetConstructor } from "./globals/collections.js";
|
|
36
36
|
import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
|
|
37
37
|
import { getCollectionIteratorMember } from "./methods/collection-iterator.js";
|
|
38
|
+
import { isSandboxRegExpIterator, regexpIteratorState } from "./regexp-iterator.js";
|
|
39
|
+
import { getRegExpIteratorMember } from "./methods/regexp-iterator.js";
|
|
38
40
|
import { getFloat32Member, isFloat32ArrayConstructor, setFloat32Member } from "./globals/float32array.js";
|
|
39
41
|
import { isFloat32Array } from "./float32.js";
|
|
40
42
|
import { dateString, dateTime, isSandboxDate } from "./date.js";
|
|
41
43
|
import { getDateMember, getDatePrototype, isDateConstructor } from "./globals/date.js";
|
|
42
|
-
import { createSandboxRegex, allocateProducedSandboxValue, ownEnumerableSandboxKeys, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, reconcileCompiledValues } from "./values.js";
|
|
44
|
+
import { createSandboxRegex, allocateProducedSandboxValue, ownEnumerableSandboxKeys, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, getRegexProperties, isSandboxSet, reconcileCompiledValues } from "./values.js";
|
|
43
45
|
import { Scope } from "./scope.js";
|
|
44
46
|
import { hoistVarDeclarations } from "./var-hoist.js";
|
|
45
47
|
const taggedTemplateRawArrays = new WeakMap();
|
|
@@ -857,6 +859,8 @@ function isRestorableBindingValue(value, seen = new WeakSet()) {
|
|
|
857
859
|
if (seen.has(value))
|
|
858
860
|
return true;
|
|
859
861
|
seen.add(value);
|
|
862
|
+
if (isSandboxRegExpIterator(value))
|
|
863
|
+
return isRestorableBindingValue(regexpIteratorState(value).matcher, seen);
|
|
860
864
|
if (isSandboxCollectionIterator(value)) {
|
|
861
865
|
return isRestorableBindingValue(collectionIteratorState(value).collection, seen);
|
|
862
866
|
}
|
|
@@ -1116,7 +1120,7 @@ async function evaluateForOfStatement(node, context) {
|
|
|
1116
1120
|
const restored = context.scope.consumeRestoredBinding(restoredIteration.values[0]);
|
|
1117
1121
|
if (restored.found && Array.isArray(restored.value)) {
|
|
1118
1122
|
restoredEntry = { done: false, value: restored.value[1] };
|
|
1119
|
-
if (Array.isArray(restored.value[0]) || isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0]) || isSandboxCollectionIterator(restored.value[0])) {
|
|
1123
|
+
if (Array.isArray(restored.value[0]) || isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0]) || isSandboxCollectionIterator(restored.value[0]) || isSandboxRegExpIterator(restored.value[0])) {
|
|
1120
1124
|
return evaluateForOfIterator(node, restored.value[0], context, restoredEntry);
|
|
1121
1125
|
}
|
|
1122
1126
|
}
|
|
@@ -1510,7 +1514,7 @@ function createLoopIterationContext(context, scope) {
|
|
|
1510
1514
|
snapshot.loopIterations = {};
|
|
1511
1515
|
for (const [nodeId, iteration] of context.activeLoopIterations) {
|
|
1512
1516
|
if (typeof iteration !== "number" &&
|
|
1513
|
-
(Array.isArray(iteration.values[0]) || isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]) || isSandboxCollectionIterator(iteration.values[0]))) {
|
|
1517
|
+
(Array.isArray(iteration.values[0]) || isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]) || isSandboxCollectionIterator(iteration.values[0]) || isSandboxRegExpIterator(iteration.values[0]))) {
|
|
1514
1518
|
const bindingName = `#for-of:${nodeId}`;
|
|
1515
1519
|
snapshot.bindings[bindingName] = iteration.values;
|
|
1516
1520
|
snapshot.loopIterations[nodeId] = { index: iteration.index, values: [bindingName] };
|
|
@@ -1772,7 +1776,7 @@ async function evaluateDeleteExpression(node, context) {
|
|
|
1772
1776
|
}
|
|
1773
1777
|
throw new TypeError("Cannot delete properties of null or undefined.");
|
|
1774
1778
|
}
|
|
1775
|
-
if (!isIndexableSandboxValue(member.object)) {
|
|
1779
|
+
if (!isIndexableSandboxValue(member.object) && !isSandboxRegex(member.object)) {
|
|
1776
1780
|
throw new TypeError("Unary operator 'delete' requires a sandbox object property.");
|
|
1777
1781
|
}
|
|
1778
1782
|
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
@@ -1852,6 +1856,8 @@ function getPropertyValue(target, property, context, receiver = target) {
|
|
|
1852
1856
|
const descriptor = getSandboxPropertyDescriptor(target, property, context.budget);
|
|
1853
1857
|
if (descriptor !== undefined)
|
|
1854
1858
|
return readPropertyDescriptor(descriptor, receiver, createCoercionContext(context), true);
|
|
1859
|
+
if (isSandboxRegExpIterator(target))
|
|
1860
|
+
return getRegExpIteratorMember(property, context.budget);
|
|
1855
1861
|
if (typeof target === "symbol") {
|
|
1856
1862
|
const prototype = getBoxedPrototype(target, context.budget);
|
|
1857
1863
|
return prototype === undefined ? undefined : getPropertyValue(prototype, property, context, receiver);
|
|
@@ -1892,7 +1898,8 @@ function getPropertyValue(target, property, context, receiver = target) {
|
|
|
1892
1898
|
if (isSandboxPromise(target))
|
|
1893
1899
|
return getPromiseMember(property, context.budget);
|
|
1894
1900
|
if (isSandboxRegex(target))
|
|
1895
|
-
return
|
|
1901
|
+
return hasExplicitSandboxPrototype(target) || getSandboxPrototype(target, context.budget) !== null
|
|
1902
|
+
? undefined : getRegexMember(target, property, context.budget, createCoercionContext(context));
|
|
1896
1903
|
if (!isIndexableSandboxValue(target)) {
|
|
1897
1904
|
throw new TypeError("Attempted to read a property from a non-object value.");
|
|
1898
1905
|
}
|
|
@@ -2132,8 +2139,8 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
2132
2139
|
if (isSandboxPromise(member.object)) {
|
|
2133
2140
|
return evaluateResolvedCallExpression(node, getPromiseMember(member.property, context.budget), context, member.object);
|
|
2134
2141
|
}
|
|
2135
|
-
if (isSandboxRegex(member.object)
|
|
2136
|
-
return evaluateResolvedCallExpression(node,
|
|
2142
|
+
if (isSandboxRegex(member.object)) {
|
|
2143
|
+
return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
|
|
2137
2144
|
}
|
|
2138
2145
|
if (!isIndexableSandboxValue(member.object)) {
|
|
2139
2146
|
throw new TypeError("Attempted to read a property from a non-object value.");
|
|
@@ -2381,9 +2388,9 @@ function hasSandboxProperty(value, key, context) {
|
|
|
2381
2388
|
return typeof key === "symbol" ? false : hasHostObjectMember(current, String(key));
|
|
2382
2389
|
if (hasOwnSandboxProperty(current, key, false))
|
|
2383
2390
|
return true;
|
|
2384
|
-
if (!((isGuestClosure(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) &&
|
|
2391
|
+
if (!isSandboxRegex(current) && !((isGuestClosure(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) &&
|
|
2385
2392
|
(Array.isArray(current) || !isPlainSandboxObject(current) ||
|
|
2386
|
-
isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current))) {
|
|
2393
|
+
isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isSandboxRegExpIterator(current))) {
|
|
2387
2394
|
return getPropertyValue(current, key, context) !== undefined;
|
|
2388
2395
|
}
|
|
2389
2396
|
current = getSandboxPrototype(current, context.budget);
|
|
@@ -2603,7 +2610,7 @@ function getMemberValue(target, property, context) {
|
|
|
2603
2610
|
return getClosureMemberValue(current, property, context);
|
|
2604
2611
|
if (Array.isArray(current))
|
|
2605
2612
|
return getArrayMemberValue(current, property, context);
|
|
2606
|
-
if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isFloat32Array(current)) {
|
|
2613
|
+
if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isSandboxRegExpIterator(current) || isFloat32Array(current)) {
|
|
2607
2614
|
return getPropertyValue(current, property, context);
|
|
2608
2615
|
}
|
|
2609
2616
|
if (Object.hasOwn(current, String(property)))
|
|
@@ -2646,9 +2653,7 @@ export function setSandboxProperty(target, property, value, budget, checkInherit
|
|
|
2646
2653
|
return;
|
|
2647
2654
|
}
|
|
2648
2655
|
if (isSandboxRegex(target)) {
|
|
2649
|
-
|
|
2650
|
-
throw new TypeError("RegExp symbol properties are not yet supported.");
|
|
2651
|
-
setRegexMember(target, property, value);
|
|
2656
|
+
setRegexMember(target, property, value, budget);
|
|
2652
2657
|
return;
|
|
2653
2658
|
}
|
|
2654
2659
|
if (!isIndexableSandboxValue(target)) {
|
|
@@ -2714,6 +2719,8 @@ function deleteSandboxProperty(target, property) {
|
|
|
2714
2719
|
return deleteHostObjectMember(target, String(property));
|
|
2715
2720
|
if (isGuestClosure(target))
|
|
2716
2721
|
target = materializeFunctionProperties(target);
|
|
2722
|
+
if (isSandboxRegex(target))
|
|
2723
|
+
target = getRegexProperties(target);
|
|
2717
2724
|
if (Array.isArray(target)) {
|
|
2718
2725
|
assertCollectionMutable(target);
|
|
2719
2726
|
}
|
|
@@ -4,6 +4,8 @@ import { isFloat32Array } from "./float32.js";
|
|
|
4
4
|
import { boxedValue, isSandboxBox } from "./boxed.js";
|
|
5
5
|
import { getHostObjectIterator, isGuestHostObject } from "./host-capabilities.js";
|
|
6
6
|
import { isSandboxCollectionIterator, nextCollectionIterator } from "./collection-iterator.js";
|
|
7
|
+
import { isSandboxRegExpIterator } from "./regexp-iterator.js";
|
|
8
|
+
import { nextRegExpIterator } from "./methods/regexp-iterator.js";
|
|
7
9
|
import { Budget, isFatalSandboxError } from "./budget.js";
|
|
8
10
|
import { sandboxString } from "./string-coercion.js";
|
|
9
11
|
import { awaitSandboxValue, awaitWithSignal } from "./cancel.js";
|
|
@@ -17,7 +19,8 @@ export async function acquireSandboxIterator(value, budget, context, asyncProtoc
|
|
|
17
19
|
return asyncProtocol
|
|
18
20
|
? getSandboxAsyncIterator(value, budget, context, signal)
|
|
19
21
|
: getSandboxIterator(value, budget, context);
|
|
20
|
-
if (getSandboxPropertyDescriptor(value, key, budget) === undefined
|
|
22
|
+
if (getSandboxPropertyDescriptor(value, key, budget) === undefined &&
|
|
23
|
+
!(isSandboxRegExpIterator(value) && !asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== undefined)) {
|
|
21
24
|
if (!asyncProtocol)
|
|
22
25
|
return getSandboxIterator(value, budget, context);
|
|
23
26
|
if (isSandboxGenerator(value) && value.async)
|
|
@@ -222,6 +225,8 @@ export function getSandboxIterator(value, budget, context) {
|
|
|
222
225
|
}
|
|
223
226
|
if (isSandboxCollectionIterator(value))
|
|
224
227
|
return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
|
|
228
|
+
if (isSandboxRegExpIterator(value))
|
|
229
|
+
return { next: () => nextRegExpIterator(value, budget), snapshotIndex: () => 0 };
|
|
225
230
|
if (isGuestHostObject(value))
|
|
226
231
|
return getHostObjectIterator(value);
|
|
227
232
|
if (isFloat32Array(value)) {
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { type SandboxCallContext, type SandboxRegex, type SandboxValue } from "../values.js";
|
|
2
2
|
import { type RegexMatch } from "../regex/engine.js";
|
|
3
3
|
import type { Budget } from "../budget.js";
|
|
4
|
-
export
|
|
4
|
+
export declare function regexSearch(target: SandboxValue, input: SandboxValue, budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
|
|
5
|
+
export type RegexMethodName = "exec" | "test" | "toString";
|
|
6
|
+
export declare const regexFlagProperties: Readonly<Record<string, string>>;
|
|
5
7
|
export declare function isRegexMethodName(property: string | number): property is RegexMethodName;
|
|
6
|
-
export declare function getRegexMember(target: SandboxRegex, property: string | number, budget: Budget): SandboxValue |
|
|
7
|
-
export declare function setRegexMember(target: SandboxRegex, property:
|
|
8
|
+
export declare function getRegexMember(target: SandboxRegex, property: string | number, budget: Budget, context?: SandboxCallContext): SandboxValue | Promise<SandboxValue>;
|
|
9
|
+
export declare function setRegexMember(target: SandboxRegex, property: PropertyKey, value: SandboxValue, budget?: Budget): void;
|
|
8
10
|
export declare function callRegexMethod(target: SandboxValue, methodName: RegexMethodName, args: readonly SandboxValue[], budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
|
|
11
|
+
export declare function regexExec(target: SandboxValue, input: string, budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
|
|
12
|
+
export declare function regexToString(target: SandboxValue, budget: Budget, context?: SandboxCallContext): Promise<string>;
|
|
9
13
|
export declare function executeRegex(target: SandboxRegex, input: string, lastIndex: number): RegexMatch | null;
|
|
10
14
|
export declare function toMatchArray(match: RegexMatch | null, input: string): SandboxValue;
|