poe-code 14.0.74 → 14.0.75
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 +926 -84
- 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-2J6W3YGB.js → chunk-BAJI3K4B.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-YEZOXLY4.js → chunk-EOTY4PCT.js} +901 -84
- package/packages/safe-js/dist/chunks/chunk-EOTY4PCT.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/index.js +2 -2
- package/packages/safe-js/dist/interp/globals/regex.js +108 -2
- package/packages/safe-js/dist/interp/iteration.js +5 -2
- package/packages/safe-js/dist/interp/methods/regex-split.d.ts +3 -0
- package/packages/safe-js/dist/interp/methods/regex-split.js +102 -0
- package/packages/safe-js/dist/interp/methods/regex.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/regex.js +16 -5
- package/packages/safe-js/dist/interp/methods/regexp-iterator.d.ts +5 -1
- package/packages/safe-js/dist/interp/methods/regexp-iterator.js +59 -7
- package/packages/safe-js/dist/interp/methods/string.js +7 -7
- package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
- package/packages/safe-js/dist/interp/object-model.js +4 -1
- package/packages/safe-js/dist/interp/regex/compile-guard.js +26 -4
- package/packages/safe-js/dist/interp/regex/engine.d.ts +4 -0
- package/packages/safe-js/dist/interp/regex/engine.js +230 -30
- package/packages/safe-js/dist/interp/regex/parse.d.ts +42 -4
- package/packages/safe-js/dist/interp/regex/parse.js +429 -25
- package/packages/safe-js/dist/interp/regexp-iterator.d.ts +4 -2
- package/packages/safe-js/dist/interp/regexp-iterator.js +6 -1
- package/packages/safe-js/dist/interp/values.js +5 -3
- package/packages/safe-js/dist/snapshot/dump-format.js +10 -2
- package/packages/safe-js/dist/snapshot/replay-data.d.ts +3 -0
- package/packages/safe-js/dist/snapshot/replay-data.js +14 -4
- package/packages/safe-js/dist/snapshot/restore.js +8 -2
- package/packages/safe-js/dist/snapshot/serialize.d.ts +3 -0
- package/packages/safe-js/dist/snapshot/serialize.js +4 -1
- package/packages/safe-js/dist/snapshot/validation.js +8 -0
- package/packages/safe-js/dist/chunks/chunk-YEZOXLY4.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-2J6W3YGB.js.map → chunk-BAJI3K4B.js.map} +0 -0
|
@@ -711,7 +711,7 @@ var RegexCompileGuard = class {
|
|
|
711
711
|
this.work(flags.length);
|
|
712
712
|
}
|
|
713
713
|
retain(pattern, valueUnits = 0) {
|
|
714
|
-
const units =
|
|
714
|
+
const units = measurePattern(pattern);
|
|
715
715
|
if (this.ticket !== void 0) {
|
|
716
716
|
this.ticket.owner.budget.resizeCompileTicket(this.ticket, units + valueUnits);
|
|
717
717
|
}
|
|
@@ -728,7 +728,15 @@ var RegexCompileGuard = class {
|
|
|
728
728
|
}
|
|
729
729
|
};
|
|
730
730
|
function regexCompiledData(pattern) {
|
|
731
|
-
return compiledData.get(pattern) ?? { units:
|
|
731
|
+
return compiledData.get(pattern) ?? { units: measurePattern(pattern) };
|
|
732
|
+
}
|
|
733
|
+
function measurePattern(pattern) {
|
|
734
|
+
let units = 10 + pattern.source.length + measureNode(pattern.body);
|
|
735
|
+
if (pattern.groups !== void 0) {
|
|
736
|
+
units += 1;
|
|
737
|
+
for (const [name, indices] of Object.entries(pattern.groups)) units += name.length + 2 + indices.length;
|
|
738
|
+
}
|
|
739
|
+
return units;
|
|
732
740
|
}
|
|
733
741
|
function measureNode(node) {
|
|
734
742
|
switch (node.type) {
|
|
@@ -737,13 +745,18 @@ function measureNode(node) {
|
|
|
737
745
|
return 2;
|
|
738
746
|
case "literal":
|
|
739
747
|
return 3 + node.value.length;
|
|
748
|
+
case "namedBackreference":
|
|
749
|
+
return 3 + node.name.length;
|
|
740
750
|
case "anchor":
|
|
741
751
|
case "wordBoundary":
|
|
752
|
+
case "backreference":
|
|
742
753
|
return 3;
|
|
743
754
|
case "characterClass": {
|
|
744
755
|
let usage = 5 + node.items.length;
|
|
756
|
+
if (node.operation !== void 0) usage += 1 + node.operation.length;
|
|
757
|
+
if (node.strings !== void 0) usage += 1;
|
|
745
758
|
for (const item of node.items) {
|
|
746
|
-
usage += item.type === "character" ? 3 + item.value.length : item.type === "range" ? 4 + item.from.length + item.to.length : 4;
|
|
759
|
+
usage += item.type === "character" ? 3 + item.value.length : item.type === "range" ? 4 + item.from.length + item.to.length : item.type === "property" ? 4 + item.value.length + (item.strings === void 0 ? 0 : 1) : item.type === "set" ? 3 + measureNode({ type: "characterClass", ...item.value }) : item.type === "strings" ? 4 + item.values.reduce((total, value) => total + 1 + value.length, 0) : 4;
|
|
747
760
|
}
|
|
748
761
|
return usage;
|
|
749
762
|
}
|
|
@@ -755,7 +768,10 @@ function measureNode(node) {
|
|
|
755
768
|
return usage;
|
|
756
769
|
}
|
|
757
770
|
case "group":
|
|
758
|
-
return 5 + measureNode(node.body);
|
|
771
|
+
return 5 + measureNode(node.body) + (node.name === void 0 ? 0 : 1 + node.name.length) + (node.modifiers === void 0 ? 0 : 2 + Object.keys(node.modifiers).length);
|
|
772
|
+
case "lookahead":
|
|
773
|
+
case "lookbehind":
|
|
774
|
+
return 4 + measureNode(node.body);
|
|
759
775
|
case "quantifier":
|
|
760
776
|
return (Object.hasOwn(node, "max") ? 6 : 5) + measureNode(node.body);
|
|
761
777
|
}
|
|
@@ -2045,6 +2061,8 @@ function createIdentifier(token, name) {
|
|
|
2045
2061
|
}
|
|
2046
2062
|
|
|
2047
2063
|
// packages/safe-js/src/interp/regex/parse.ts
|
|
2064
|
+
var groupNameStart = /^[$_\p{ID_Start}]$/u;
|
|
2065
|
+
var groupNamePart = /^[$\u200c\u200d\p{ID_Continue}]$/u;
|
|
2048
2066
|
function parseRegex(source, flags = "", compilation, valueUnits = 0) {
|
|
2049
2067
|
const guard = new RegexCompileGuard(compilation);
|
|
2050
2068
|
try {
|
|
@@ -2052,10 +2070,11 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
|
|
|
2052
2070
|
guard.checkLength(flags.length, true);
|
|
2053
2071
|
guard.allocate(5 + valueUnits);
|
|
2054
2072
|
const parsedFlags = parseFlags(flags, guard);
|
|
2055
|
-
const parser = new RegexParser(source, guard);
|
|
2073
|
+
const parser = new RegexParser(source, guard, parsedFlags.unicode || parsedFlags.unicodeSets, parsedFlags.unicodeSets);
|
|
2056
2074
|
const body = parser.parse();
|
|
2057
2075
|
guard.allocate(5 + source.length);
|
|
2058
2076
|
const pattern = { source, flags: parsedFlags, captureCount: parser.captureCount, body };
|
|
2077
|
+
if (Object.keys(parser.namedGroups).length > 0) pattern.groups = parser.namedGroups;
|
|
2059
2078
|
guard.retain(pattern, valueUnits);
|
|
2060
2079
|
return pattern;
|
|
2061
2080
|
} finally {
|
|
@@ -2063,14 +2082,21 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
|
|
|
2063
2082
|
}
|
|
2064
2083
|
}
|
|
2065
2084
|
var RegexParser = class {
|
|
2066
|
-
constructor(source, guard) {
|
|
2085
|
+
constructor(source, guard, unicode, unicodeSets) {
|
|
2067
2086
|
this.source = source;
|
|
2068
2087
|
this.guard = guard;
|
|
2088
|
+
this.unicode = unicode;
|
|
2089
|
+
this.unicodeSets = unicodeSets;
|
|
2069
2090
|
}
|
|
2070
2091
|
source;
|
|
2071
2092
|
guard;
|
|
2093
|
+
unicode;
|
|
2094
|
+
unicodeSets;
|
|
2072
2095
|
captureCount = 0;
|
|
2073
2096
|
cursor = 0;
|
|
2097
|
+
totalCaptureCount;
|
|
2098
|
+
hasNamedCaptures = false;
|
|
2099
|
+
namedGroups = /* @__PURE__ */ Object.create(null);
|
|
2074
2100
|
get position() {
|
|
2075
2101
|
return this.cursor;
|
|
2076
2102
|
}
|
|
@@ -2086,6 +2112,7 @@ var RegexParser = class {
|
|
|
2086
2112
|
}
|
|
2087
2113
|
this.fail(`Unexpected character '${this.peek()}'`);
|
|
2088
2114
|
}
|
|
2115
|
+
if (this.unicode || Object.keys(this.namedGroups).length > 0) this.validateNamedGroups(body);
|
|
2089
2116
|
return body;
|
|
2090
2117
|
}
|
|
2091
2118
|
parseAlternation() {
|
|
@@ -2119,15 +2146,20 @@ var RegexParser = class {
|
|
|
2119
2146
|
parseQuantifiedAtom() {
|
|
2120
2147
|
const quantifierStart = this.position;
|
|
2121
2148
|
const current = this.peek();
|
|
2122
|
-
if (current === "*" || current === "+" || current === "?" || current === "{") {
|
|
2149
|
+
if (current === "*" || current === "+" || current === "?" || current === "{" && this.unicode) {
|
|
2123
2150
|
this.fail("Nothing to repeat", quantifierStart);
|
|
2124
2151
|
}
|
|
2152
|
+
if (current === "{") {
|
|
2153
|
+
const quantifier2 = this.parseQuantifier();
|
|
2154
|
+
this.position = quantifierStart;
|
|
2155
|
+
if (quantifier2 !== void 0) this.fail("Nothing to repeat", quantifierStart);
|
|
2156
|
+
}
|
|
2125
2157
|
const body = this.parseAtom();
|
|
2126
2158
|
const quantifier = this.parseQuantifier();
|
|
2127
2159
|
if (quantifier === void 0) {
|
|
2128
2160
|
return body;
|
|
2129
2161
|
}
|
|
2130
|
-
if (body.type === "anchor" || body.type === "wordBoundary") {
|
|
2162
|
+
if (body.type === "anchor" || body.type === "wordBoundary" || body.type === "lookbehind" || this.unicode && body.type === "lookahead") {
|
|
2131
2163
|
this.fail("Invalid quantifier target", quantifierStart);
|
|
2132
2164
|
}
|
|
2133
2165
|
const greedy = this.peek() !== "?";
|
|
@@ -2138,7 +2170,7 @@ var RegexParser = class {
|
|
|
2138
2170
|
return { type: "quantifier", body, ...quantifier, greedy };
|
|
2139
2171
|
}
|
|
2140
2172
|
parseAtom() {
|
|
2141
|
-
const character = this.
|
|
2173
|
+
const character = this.takeCharacter();
|
|
2142
2174
|
switch (character) {
|
|
2143
2175
|
case ".":
|
|
2144
2176
|
this.guard.allocate(2);
|
|
@@ -2156,12 +2188,17 @@ var RegexParser = class {
|
|
|
2156
2188
|
case "\\":
|
|
2157
2189
|
return this.parseEscape(false, this.position - 1);
|
|
2158
2190
|
default:
|
|
2191
|
+
if (this.unicode && (character === "]" || character === "}")) this.fail("Invalid Unicode pattern character");
|
|
2159
2192
|
this.guard.allocate(3 + character.length);
|
|
2160
2193
|
return { type: "literal", value: character };
|
|
2161
2194
|
}
|
|
2162
2195
|
}
|
|
2163
2196
|
parseGroup(start) {
|
|
2164
2197
|
let capturing = true;
|
|
2198
|
+
let name;
|
|
2199
|
+
let modifiers;
|
|
2200
|
+
let assertionNegated;
|
|
2201
|
+
let lookbehind = false;
|
|
2165
2202
|
if (this.peek() === "?") {
|
|
2166
2203
|
this.guard.allocate(Math.min(3, this.source.length - this.position));
|
|
2167
2204
|
this.guard.work(Math.min(3, this.source.length - this.position));
|
|
@@ -2170,17 +2207,33 @@ var RegexParser = class {
|
|
|
2170
2207
|
capturing = false;
|
|
2171
2208
|
this.position += 2;
|
|
2172
2209
|
} else if (extension.startsWith("?=") || extension.startsWith("?!")) {
|
|
2173
|
-
|
|
2210
|
+
capturing = false;
|
|
2211
|
+
assertionNegated = extension.startsWith("?!");
|
|
2212
|
+
this.position += 2;
|
|
2174
2213
|
} else if (extension.startsWith("?<=") || extension.startsWith("?<!")) {
|
|
2175
|
-
|
|
2214
|
+
capturing = false;
|
|
2215
|
+
assertionNegated = extension.startsWith("?<!");
|
|
2216
|
+
lookbehind = true;
|
|
2217
|
+
this.position += 3;
|
|
2176
2218
|
} else if (extension.startsWith("?<")) {
|
|
2177
|
-
this.
|
|
2219
|
+
this.position += 2;
|
|
2220
|
+
name = this.parseGroupName(start);
|
|
2221
|
+
} else if ("ims-".includes(extension[1] ?? "") && extension.length > 1) {
|
|
2222
|
+
capturing = false;
|
|
2223
|
+
this.position++;
|
|
2224
|
+
modifiers = this.parseModifiers(start);
|
|
2178
2225
|
} else {
|
|
2179
2226
|
this.fail("Unsupported group construct", start);
|
|
2180
2227
|
}
|
|
2181
2228
|
}
|
|
2182
2229
|
if (capturing) this.guard.allocate(1);
|
|
2183
2230
|
const index = capturing ? ++this.captureCount : void 0;
|
|
2231
|
+
if (name !== void 0) {
|
|
2232
|
+
this.guard.allocate(name.length + 2);
|
|
2233
|
+
const indices = this.namedGroups[name] ??= [];
|
|
2234
|
+
this.guard.array(indices.length + 1);
|
|
2235
|
+
indices.push(index);
|
|
2236
|
+
}
|
|
2184
2237
|
this.guard.enterGroup();
|
|
2185
2238
|
let body;
|
|
2186
2239
|
try {
|
|
@@ -2192,10 +2245,40 @@ var RegexParser = class {
|
|
|
2192
2245
|
this.fail("Unterminated group", start);
|
|
2193
2246
|
}
|
|
2194
2247
|
this.position += 1;
|
|
2248
|
+
if (assertionNegated !== void 0) {
|
|
2249
|
+
this.guard.allocate(4);
|
|
2250
|
+
return { type: lookbehind ? "lookbehind" : "lookahead", negated: assertionNegated, body };
|
|
2251
|
+
}
|
|
2195
2252
|
this.guard.allocate(5);
|
|
2196
|
-
return {
|
|
2253
|
+
return {
|
|
2254
|
+
type: "group",
|
|
2255
|
+
capturing,
|
|
2256
|
+
index,
|
|
2257
|
+
body,
|
|
2258
|
+
...name === void 0 ? {} : { name },
|
|
2259
|
+
...modifiers === void 0 ? {} : { modifiers }
|
|
2260
|
+
};
|
|
2261
|
+
}
|
|
2262
|
+
parseModifiers(start) {
|
|
2263
|
+
this.guard.allocate(2);
|
|
2264
|
+
const modifiers = {};
|
|
2265
|
+
let enabled = true;
|
|
2266
|
+
while (!this.atEnd() && this.peek() !== ":") {
|
|
2267
|
+
const flag = this.take();
|
|
2268
|
+
if (flag === "-" && enabled) {
|
|
2269
|
+
enabled = false;
|
|
2270
|
+
continue;
|
|
2271
|
+
}
|
|
2272
|
+
const name = flag === "i" ? "ignoreCase" : flag === "m" ? "multiline" : flag === "s" ? "dotAll" : void 0;
|
|
2273
|
+
if (name === void 0 || Object.hasOwn(modifiers, name)) this.fail("Invalid regex modifiers", start);
|
|
2274
|
+
this.guard.allocate(1);
|
|
2275
|
+
modifiers[name] = enabled;
|
|
2276
|
+
}
|
|
2277
|
+
if (this.take() !== ":" || Object.keys(modifiers).length === 0) this.fail("Invalid regex modifiers", start);
|
|
2278
|
+
return modifiers;
|
|
2197
2279
|
}
|
|
2198
2280
|
parseCharacterClass(start) {
|
|
2281
|
+
if (this.unicodeSets) return { type: "characterClass", ...this.parseUnicodeSet(start) };
|
|
2199
2282
|
const negated = this.peek() === "^";
|
|
2200
2283
|
if (negated) {
|
|
2201
2284
|
this.position += 1;
|
|
@@ -2215,9 +2298,13 @@ var RegexParser = class {
|
|
|
2215
2298
|
this.position += 1;
|
|
2216
2299
|
const right = this.parseClassItem(start);
|
|
2217
2300
|
if (left.type !== "character" || right.type !== "character") {
|
|
2218
|
-
this.fail("Character class ranges require literal endpoints", rangePosition);
|
|
2301
|
+
if (this.unicode) this.fail("Character class ranges require literal endpoints", rangePosition);
|
|
2302
|
+
this.guard.array(items.length + 3);
|
|
2303
|
+
this.guard.allocate(4);
|
|
2304
|
+
items.push(left, { type: "character", value: "-" }, right);
|
|
2305
|
+
continue;
|
|
2219
2306
|
}
|
|
2220
|
-
if (left.value.
|
|
2307
|
+
if (left.value.codePointAt(0) > right.value.codePointAt(0)) {
|
|
2221
2308
|
this.fail("Character class range is out of order", rangePosition);
|
|
2222
2309
|
}
|
|
2223
2310
|
this.guard.allocate(4 + left.value.length + right.value.length);
|
|
@@ -2246,26 +2333,193 @@ var RegexParser = class {
|
|
|
2246
2333
|
this.fail("Unsupported character class escape", escapeStart);
|
|
2247
2334
|
}
|
|
2248
2335
|
this.guard.allocate(4);
|
|
2249
|
-
return { type: "character", value: this.
|
|
2336
|
+
return { type: "character", value: this.takeCharacter() };
|
|
2337
|
+
}
|
|
2338
|
+
parseUnicodeSet(start) {
|
|
2339
|
+
this.guard.enterGroup();
|
|
2340
|
+
try {
|
|
2341
|
+
const negated = this.peek() === "^";
|
|
2342
|
+
if (negated) this.position++;
|
|
2343
|
+
this.guard.allocate(5);
|
|
2344
|
+
const items = [];
|
|
2345
|
+
let operation;
|
|
2346
|
+
while (!this.atEnd() && this.peek() !== "]") {
|
|
2347
|
+
this.guard.array(items.length + 1);
|
|
2348
|
+
let item = this.parseUnicodeSetItem(start);
|
|
2349
|
+
if (this.peek() === "-" && this.source[this.position + 1] !== "-") {
|
|
2350
|
+
this.position++;
|
|
2351
|
+
const right = this.parseUnicodeSetItem(start);
|
|
2352
|
+
if (item.type !== "character" || right.type !== "character") this.fail("Invalid set range", start);
|
|
2353
|
+
if (item.value.codePointAt(0) > right.value.codePointAt(0)) this.fail("Set range is out of order", start);
|
|
2354
|
+
this.guard.allocate(4 + item.value.length + right.value.length);
|
|
2355
|
+
item = { type: "range", from: item.value, to: right.value };
|
|
2356
|
+
}
|
|
2357
|
+
if (operation !== void 0 && item.type === "range") this.fail("Set operations require nested ranges", start);
|
|
2358
|
+
items.push(item);
|
|
2359
|
+
const operator = this.source.slice(this.position, this.position + 2);
|
|
2360
|
+
if (operator === "&&" || operator === "--") {
|
|
2361
|
+
const next = operator === "&&" ? "intersection" : "subtraction";
|
|
2362
|
+
if (operation === void 0 && (items.length !== 1 || item.type === "range") || operation !== void 0 && operation !== next) this.fail("Mixed set operations", start);
|
|
2363
|
+
if (operation === void 0) this.guard.allocate(1 + next.length);
|
|
2364
|
+
operation = next;
|
|
2365
|
+
this.position += 2;
|
|
2366
|
+
if (this.peek() === "]" || this.atEnd()) this.fail("Missing set operand", start);
|
|
2367
|
+
} else if (operation !== void 0 && this.peek() !== "]") this.fail("Missing set operator", start);
|
|
2368
|
+
}
|
|
2369
|
+
if (this.take() !== "]") this.fail("Unterminated character set", start);
|
|
2370
|
+
const mayContainStrings = (item) => {
|
|
2371
|
+
if (item.type === "set") return item.value.strings === true;
|
|
2372
|
+
if (item.type === "property") return item.strings === true;
|
|
2373
|
+
if (item.type === "strings") return item.values.some((value) => value.length !== ((value.codePointAt(0) ?? 0) > 65535 ? 2 : 1));
|
|
2374
|
+
return false;
|
|
2375
|
+
};
|
|
2376
|
+
const strings = operation === "intersection" ? items.every(mayContainStrings) : operation === "subtraction" ? mayContainStrings(items[0]) : items.some(mayContainStrings);
|
|
2377
|
+
if (negated && strings) this.fail("Cannot complement a set containing strings", start);
|
|
2378
|
+
if (strings) this.guard.allocate(1);
|
|
2379
|
+
return { negated, items, ...operation === void 0 ? {} : { operation }, ...strings ? { strings: true } : {} };
|
|
2380
|
+
} finally {
|
|
2381
|
+
this.guard.leaveGroup();
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
parseUnicodeSetItem(start) {
|
|
2385
|
+
if (this.peek() === "[") {
|
|
2386
|
+
this.position++;
|
|
2387
|
+
this.guard.allocate(3);
|
|
2388
|
+
return { type: "set", value: this.parseUnicodeSet(start) };
|
|
2389
|
+
}
|
|
2390
|
+
if (this.source.startsWith("\\q{", this.position)) {
|
|
2391
|
+
this.position += 3;
|
|
2392
|
+
this.guard.allocate(4);
|
|
2393
|
+
const values = [];
|
|
2394
|
+
let value2 = "";
|
|
2395
|
+
while (!this.atEnd()) {
|
|
2396
|
+
if (this.peek() === "|" || this.peek() === "}") {
|
|
2397
|
+
this.guard.array(values.length + 1);
|
|
2398
|
+
this.guard.allocate(1);
|
|
2399
|
+
values.push(value2);
|
|
2400
|
+
value2 = "";
|
|
2401
|
+
if (this.take() === "}") return { type: "strings", values };
|
|
2402
|
+
} else {
|
|
2403
|
+
const item = this.parseSetCharacter(start);
|
|
2404
|
+
this.guard.allocate(item.length);
|
|
2405
|
+
value2 += item;
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
this.fail("Unterminated class string", start);
|
|
2409
|
+
}
|
|
2410
|
+
if (this.peek() === "\\") return this.parseClassItem(start);
|
|
2411
|
+
const value = this.parseSetCharacter(start);
|
|
2412
|
+
this.guard.allocate(3 + value.length);
|
|
2413
|
+
return { type: "character", value };
|
|
2414
|
+
}
|
|
2415
|
+
parseSetCharacter(start) {
|
|
2416
|
+
if (this.peek() === "\\") {
|
|
2417
|
+
this.position++;
|
|
2418
|
+
const node = this.parseEscape(true, start);
|
|
2419
|
+
if (node.type !== "literal") this.fail("Class strings require literal characters", start);
|
|
2420
|
+
return node.value;
|
|
2421
|
+
}
|
|
2422
|
+
const character = this.takeCharacter();
|
|
2423
|
+
if (!character || "()[]{}/-|".includes(character) || "!#$%&*+,.:;<=>?@^`~".includes(character) && this.peek() === character)
|
|
2424
|
+
this.fail("Invalid character in Unicode set", start);
|
|
2425
|
+
return character;
|
|
2250
2426
|
}
|
|
2251
2427
|
parseEscape(inCharacterClass, start) {
|
|
2252
2428
|
if (this.atEnd()) {
|
|
2253
2429
|
this.fail("Trailing escape", start);
|
|
2254
2430
|
}
|
|
2255
2431
|
const escaped = this.take();
|
|
2256
|
-
if (escaped
|
|
2257
|
-
this.
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2432
|
+
if (escaped === "k") {
|
|
2433
|
+
this.totalCaptureCount ??= this.countAllCaptures();
|
|
2434
|
+
if (this.unicode || this.hasNamedCaptures) {
|
|
2435
|
+
if (inCharacterClass || this.take() !== "<") this.fail("Invalid named backreference", start);
|
|
2436
|
+
const name = this.parseGroupName(start);
|
|
2437
|
+
this.guard.allocate(3 + name.length);
|
|
2438
|
+
return { type: "namedBackreference", name };
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
if (isDecimalDigit2(escaped)) {
|
|
2442
|
+
if (!inCharacterClass && escaped !== "0") {
|
|
2443
|
+
let end = this.position;
|
|
2444
|
+
let index = Number(escaped);
|
|
2445
|
+
while (isDecimalDigit2(this.source[end] ?? "")) {
|
|
2446
|
+
this.guard.work(1);
|
|
2447
|
+
index = index * 10 + Number(this.source[end++]);
|
|
2448
|
+
}
|
|
2449
|
+
this.totalCaptureCount ??= this.countAllCaptures();
|
|
2450
|
+
if (index <= this.totalCaptureCount) {
|
|
2451
|
+
this.position = end;
|
|
2452
|
+
this.guard.allocate(3);
|
|
2453
|
+
return { type: "backreference", index };
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
if (this.unicode && (escaped !== "0" || isDecimalDigit2(this.peek())))
|
|
2457
|
+
this.fail("Invalid decimal escape", start);
|
|
2458
|
+
this.guard.allocate(4);
|
|
2459
|
+
if (escaped === "8" || escaped === "9") return { type: "literal", value: escaped };
|
|
2460
|
+
let code = Number(escaped);
|
|
2461
|
+
const maximum = escaped <= "3" ? 3 : 2;
|
|
2462
|
+
for (let digits = 1; digits < maximum && this.peek() >= "0" && this.peek() <= "7"; digits++) {
|
|
2463
|
+
code = code * 8 + Number(this.take());
|
|
2464
|
+
}
|
|
2465
|
+
return { type: "literal", value: String.fromCharCode(code) };
|
|
2466
|
+
}
|
|
2467
|
+
if (this.unicode && (escaped === "p" || escaped === "P")) {
|
|
2468
|
+
if (this.take() !== "{") this.fail("Invalid Unicode property escape", start);
|
|
2469
|
+
const begin = this.position;
|
|
2470
|
+
while (!this.atEnd() && this.peek() !== "}") {
|
|
2471
|
+
const character = this.take();
|
|
2472
|
+
if (!isDecimalDigit2(character) && !(character >= "a" && character <= "z") && !(character >= "A" && character <= "Z") && character !== "_" && character !== "=")
|
|
2473
|
+
this.fail("Invalid Unicode property escape", start);
|
|
2474
|
+
}
|
|
2475
|
+
this.guard.allocate(this.position - begin + 9);
|
|
2476
|
+
const value = this.source.slice(begin, this.position);
|
|
2477
|
+
if (this.take() !== "}") this.fail("Unterminated Unicode property escape", start);
|
|
2478
|
+
try {
|
|
2479
|
+
new RegExp(`\\${escaped}{${value}}`, this.unicodeSets ? "v" : "u");
|
|
2480
|
+
} catch {
|
|
2481
|
+
this.fail("Unknown Unicode property", start);
|
|
2482
|
+
}
|
|
2483
|
+
let strings = false;
|
|
2484
|
+
if (this.unicodeSets) {
|
|
2485
|
+
try {
|
|
2486
|
+
new RegExp(`\\p{${value}}`, "u");
|
|
2487
|
+
} catch {
|
|
2488
|
+
strings = true;
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
this.guard.array(1);
|
|
2492
|
+
return { type: "characterClass", negated: false, items: [{ type: "property", value, negated: escaped === "P", ...strings ? { strings: true } : {} }] };
|
|
2261
2493
|
}
|
|
2262
2494
|
if (escaped === "x") {
|
|
2263
2495
|
this.guard.allocate(4);
|
|
2264
|
-
return { type: "literal", value: this.parseHexEscape(2, "hexadecimal", start) };
|
|
2496
|
+
return { type: "literal", value: this.parseHexEscape(2, "hexadecimal", start, this.unicode ? void 0 : "x") };
|
|
2265
2497
|
}
|
|
2266
2498
|
if (escaped === "u") {
|
|
2267
2499
|
this.guard.allocate(4);
|
|
2268
|
-
|
|
2500
|
+
if (this.unicode && this.peek() === "{") {
|
|
2501
|
+
this.position++;
|
|
2502
|
+
const begin = this.position;
|
|
2503
|
+
while (!this.atEnd() && this.peek() !== "}") this.position++;
|
|
2504
|
+
this.guard.allocate(this.position - begin);
|
|
2505
|
+
const digits = this.source.slice(begin, this.position);
|
|
2506
|
+
const point = Number.parseInt(digits, 16);
|
|
2507
|
+
if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
|
|
2508
|
+
this.fail("Invalid Unicode escape", start);
|
|
2509
|
+
return { type: "literal", value: String.fromCodePoint(point) };
|
|
2510
|
+
}
|
|
2511
|
+
let value = this.parseHexEscape(4, "Unicode", start, this.unicode ? void 0 : "u");
|
|
2512
|
+
if (this.unicode && value.charCodeAt(0) >= 55296 && value.charCodeAt(0) <= 56319 && this.source.startsWith("\\u", this.position)) {
|
|
2513
|
+
const digits = this.source.slice(this.position + 2, this.position + 6);
|
|
2514
|
+
const point = Number.parseInt(digits, 16);
|
|
2515
|
+
this.guard.work(digits.length);
|
|
2516
|
+
this.guard.allocate(digits.length);
|
|
2517
|
+
if (digits.length === 4 && allHexDigits(digits) && point >= 56320 && point <= 57343) {
|
|
2518
|
+
value += String.fromCharCode(point);
|
|
2519
|
+
this.position += 6;
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
return { type: "literal", value };
|
|
2269
2523
|
}
|
|
2270
2524
|
this.guard.allocate(25);
|
|
2271
2525
|
const kinds = {
|
|
@@ -2296,20 +2550,101 @@ var RegexParser = class {
|
|
|
2296
2550
|
v: "\v",
|
|
2297
2551
|
"0": "\0"
|
|
2298
2552
|
};
|
|
2553
|
+
if (escaped === "c") {
|
|
2554
|
+
const letter = this.peek();
|
|
2555
|
+
this.guard.allocate(4);
|
|
2556
|
+
if (letter >= "a" && letter <= "z" || letter >= "A" && letter <= "Z" || !this.unicode && inCharacterClass && (isDecimalDigit2(letter) || letter === "_")) {
|
|
2557
|
+
this.position++;
|
|
2558
|
+
return { type: "literal", value: String.fromCharCode(letter.charCodeAt(0) % 32) };
|
|
2559
|
+
}
|
|
2560
|
+
if (this.unicode) this.fail("Invalid control escape", start);
|
|
2561
|
+
this.position--;
|
|
2562
|
+
return { type: "literal", value: "\\" };
|
|
2563
|
+
}
|
|
2564
|
+
if (this.unicode && controls[escaped] === void 0 && !"^$\\.*+?()[]{}|/".includes(escaped) && !(inCharacterClass && (escaped === "-" || this.unicodeSets && "!#$%&+,.:;<=>?@`~".includes(escaped))))
|
|
2565
|
+
this.fail("Invalid identity escape", start);
|
|
2299
2566
|
this.guard.allocate(4);
|
|
2300
2567
|
return { type: "literal", value: controls[escaped] ?? escaped };
|
|
2301
2568
|
}
|
|
2302
|
-
parseHexEscape(length, name, start) {
|
|
2569
|
+
parseHexEscape(length, name, start, identity) {
|
|
2303
2570
|
const end = this.position + length;
|
|
2304
2571
|
this.guard.allocate(Math.min(length, this.source.length - this.position));
|
|
2305
2572
|
this.guard.work(Math.min(length, this.source.length - this.position));
|
|
2306
2573
|
const digits = this.source.slice(this.position, end);
|
|
2307
2574
|
if (digits.length !== length || !allHexDigits(digits)) {
|
|
2575
|
+
if (identity !== void 0) return identity;
|
|
2308
2576
|
this.fail(`Invalid ${name} escape`, start);
|
|
2309
2577
|
}
|
|
2310
2578
|
this.position = end;
|
|
2311
2579
|
return String.fromCharCode(Number.parseInt(digits, 16));
|
|
2312
2580
|
}
|
|
2581
|
+
countAllCaptures() {
|
|
2582
|
+
let count = 0;
|
|
2583
|
+
let escaped = false;
|
|
2584
|
+
let characterClass = false;
|
|
2585
|
+
for (let index = 0; index < this.source.length; index++) {
|
|
2586
|
+
this.guard.work(1);
|
|
2587
|
+
const character = this.source[index];
|
|
2588
|
+
if (escaped) escaped = false;
|
|
2589
|
+
else if (character === "\\") escaped = true;
|
|
2590
|
+
else if (character === "[") characterClass = true;
|
|
2591
|
+
else if (character === "]") characterClass = false;
|
|
2592
|
+
else if (!characterClass && character === "(") {
|
|
2593
|
+
const named = this.source[index + 1] === "?" && this.source[index + 2] === "<" && this.source[index + 3] !== "=" && this.source[index + 3] !== "!";
|
|
2594
|
+
if (named) this.hasNamedCaptures = true;
|
|
2595
|
+
if (named || this.source[index + 1] !== "?") count++;
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
return count;
|
|
2599
|
+
}
|
|
2600
|
+
parseGroupName(start) {
|
|
2601
|
+
let name = "";
|
|
2602
|
+
while (!this.atEnd() && this.peek() !== ">") {
|
|
2603
|
+
let character = this.take();
|
|
2604
|
+
if (character === "\\") {
|
|
2605
|
+
if (this.take() !== "u") this.fail("Invalid group name escape", start);
|
|
2606
|
+
if (this.peek() === "{") {
|
|
2607
|
+
this.position++;
|
|
2608
|
+
const begin = this.position;
|
|
2609
|
+
while (!this.atEnd() && this.peek() !== "}") this.position++;
|
|
2610
|
+
this.guard.allocate(this.position - begin);
|
|
2611
|
+
const digits = this.source.slice(begin, this.position);
|
|
2612
|
+
const point = Number.parseInt(digits, 16);
|
|
2613
|
+
if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
|
|
2614
|
+
this.fail("Invalid group name escape", start);
|
|
2615
|
+
character = String.fromCodePoint(point);
|
|
2616
|
+
} else character = this.parseHexEscape(4, "Unicode", start);
|
|
2617
|
+
}
|
|
2618
|
+
this.guard.allocate(character.length);
|
|
2619
|
+
name += character;
|
|
2620
|
+
}
|
|
2621
|
+
if (this.take() !== ">" || name.length === 0) this.fail("Invalid group name", start);
|
|
2622
|
+
let first = true;
|
|
2623
|
+
for (const character of name) {
|
|
2624
|
+
this.guard.work(1);
|
|
2625
|
+
if (!(first ? groupNameStart : groupNamePart).test(character)) this.fail("Invalid group name", start);
|
|
2626
|
+
first = false;
|
|
2627
|
+
}
|
|
2628
|
+
return name;
|
|
2629
|
+
}
|
|
2630
|
+
validateNamedGroups(node) {
|
|
2631
|
+
this.guard.work(1);
|
|
2632
|
+
this.guard.allocate(1);
|
|
2633
|
+
const names = /* @__PURE__ */ new Set();
|
|
2634
|
+
if (node.type === "namedBackreference" && !Object.hasOwn(this.namedGroups, node.name))
|
|
2635
|
+
this.fail("Unknown named backreference");
|
|
2636
|
+
if (node.type === "group" && node.name !== void 0) names.add(node.name);
|
|
2637
|
+
const children = node.type === "sequence" ? node.elements : node.type === "alternation" ? node.alternatives : node.type === "group" || node.type === "quantifier" || node.type === "lookahead" || node.type === "lookbehind" ? [node.body] : [];
|
|
2638
|
+
for (const child of children) {
|
|
2639
|
+
for (const name of this.validateNamedGroups(child)) {
|
|
2640
|
+
this.guard.work(1);
|
|
2641
|
+
if (names.has(name) && node.type !== "alternation") this.fail("Duplicate capture group name");
|
|
2642
|
+
this.guard.allocate(1);
|
|
2643
|
+
names.add(name);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
return names;
|
|
2647
|
+
}
|
|
2313
2648
|
parseQuantifier() {
|
|
2314
2649
|
const character = this.peek();
|
|
2315
2650
|
if (character === "*") {
|
|
@@ -2339,18 +2674,29 @@ var RegexParser = class {
|
|
|
2339
2674
|
}
|
|
2340
2675
|
if (this.peek() === "}") {
|
|
2341
2676
|
this.position += 1;
|
|
2677
|
+
if (!Number.isSafeInteger(min)) this.fail("Quantifier is too large", start);
|
|
2342
2678
|
this.guard.allocate(3);
|
|
2343
2679
|
return { min, max: min };
|
|
2344
2680
|
}
|
|
2345
2681
|
if (this.peek() !== ",") {
|
|
2682
|
+
if (!this.unicode) {
|
|
2683
|
+
this.position = start;
|
|
2684
|
+
return void 0;
|
|
2685
|
+
}
|
|
2346
2686
|
this.fail("Invalid quantifier", start);
|
|
2347
2687
|
}
|
|
2348
2688
|
this.position += 1;
|
|
2349
2689
|
const max = this.parseDecimal();
|
|
2350
2690
|
if (this.peek() !== "}") {
|
|
2691
|
+
if (!this.unicode) {
|
|
2692
|
+
this.position = start;
|
|
2693
|
+
return void 0;
|
|
2694
|
+
}
|
|
2351
2695
|
this.fail("Unterminated quantifier", start);
|
|
2352
2696
|
}
|
|
2353
2697
|
this.position += 1;
|
|
2698
|
+
if (!Number.isSafeInteger(min) || max !== void 0 && !Number.isSafeInteger(max))
|
|
2699
|
+
this.fail("Quantifier is too large", start);
|
|
2354
2700
|
if (max !== void 0 && min > max) {
|
|
2355
2701
|
this.fail("Quantifier range is out of order", start);
|
|
2356
2702
|
}
|
|
@@ -2367,11 +2713,7 @@ var RegexParser = class {
|
|
|
2367
2713
|
}
|
|
2368
2714
|
this.guard.allocate(this.position - start);
|
|
2369
2715
|
this.guard.work(this.position - start);
|
|
2370
|
-
|
|
2371
|
-
if (!Number.isSafeInteger(value)) {
|
|
2372
|
-
this.fail("Quantifier is too large", start);
|
|
2373
|
-
}
|
|
2374
|
-
return value;
|
|
2716
|
+
return Number(this.source.slice(start, this.position));
|
|
2375
2717
|
}
|
|
2376
2718
|
peek() {
|
|
2377
2719
|
return this.source[this.position] ?? "";
|
|
@@ -2381,6 +2723,12 @@ var RegexParser = class {
|
|
|
2381
2723
|
this.position += 1;
|
|
2382
2724
|
return character;
|
|
2383
2725
|
}
|
|
2726
|
+
takeCharacter() {
|
|
2727
|
+
if (!this.unicode || this.atEnd()) return this.take();
|
|
2728
|
+
const character = String.fromCodePoint(this.source.codePointAt(this.position));
|
|
2729
|
+
this.position += character.length;
|
|
2730
|
+
return character;
|
|
2731
|
+
}
|
|
2384
2732
|
atEnd() {
|
|
2385
2733
|
return this.position >= this.source.length;
|
|
2386
2734
|
}
|
|
@@ -2391,16 +2739,24 @@ var RegexParser = class {
|
|
|
2391
2739
|
function parseFlags(flags, guard) {
|
|
2392
2740
|
guard.allocate(10);
|
|
2393
2741
|
const parsed = {
|
|
2742
|
+
hasIndices: false,
|
|
2394
2743
|
global: false,
|
|
2744
|
+
sticky: false,
|
|
2745
|
+
unicode: false,
|
|
2746
|
+
unicodeSets: false,
|
|
2395
2747
|
ignoreCase: false,
|
|
2396
2748
|
multiline: false,
|
|
2397
2749
|
dotAll: false
|
|
2398
2750
|
};
|
|
2399
2751
|
const names = {
|
|
2752
|
+
d: "hasIndices",
|
|
2400
2753
|
g: "global",
|
|
2401
2754
|
i: "ignoreCase",
|
|
2402
2755
|
m: "multiline",
|
|
2403
|
-
s: "dotAll"
|
|
2756
|
+
s: "dotAll",
|
|
2757
|
+
y: "sticky",
|
|
2758
|
+
u: "unicode",
|
|
2759
|
+
v: "unicodeSets"
|
|
2404
2760
|
};
|
|
2405
2761
|
for (let position = 0; position < flags.length; position += 1) {
|
|
2406
2762
|
guard.work(1);
|
|
@@ -2414,6 +2770,7 @@ function parseFlags(flags, guard) {
|
|
|
2414
2770
|
}
|
|
2415
2771
|
parsed[name] = true;
|
|
2416
2772
|
}
|
|
2773
|
+
if (parsed.unicode && parsed.unicodeSets) throw new SyntaxError("Unicode flags u and v cannot be combined");
|
|
2417
2774
|
return parsed;
|
|
2418
2775
|
}
|
|
2419
2776
|
function isDecimalDigit2(character) {
|
|
@@ -6723,9 +7080,13 @@ function isSandboxRegExpIterator(value) {
|
|
|
6723
7080
|
return typeof value === "object" && value !== null && states2.has(value);
|
|
6724
7081
|
}
|
|
6725
7082
|
function restoreSandboxRegExpIterator(state, target = /* @__PURE__ */ Object.create(null)) {
|
|
7083
|
+
if ((state.global !== void 0 || state.unicode !== void 0) && (typeof state.global !== "boolean" || typeof state.unicode !== "boolean"))
|
|
7084
|
+
throw new TypeError("Invalid RegExp iterator modes.");
|
|
7085
|
+
if (state.matcher !== void 0 && (state.matcher === null || typeof state.matcher !== "object"))
|
|
7086
|
+
throw new TypeError("Invalid RegExp iterator matcher.");
|
|
6726
7087
|
if (!state.exhausted && (state.matcher === void 0 || state.input === void 0))
|
|
6727
7088
|
throw new TypeError("A live RegExp iterator requires its matcher and input.");
|
|
6728
|
-
states2.set(target, state.exhausted ? { matcher: void 0, input: void 0, exhausted: true } : { ...state });
|
|
7089
|
+
states2.set(target, state.exhausted ? { ...state, matcher: void 0, input: void 0, exhausted: true } : { ...state });
|
|
6729
7090
|
return target;
|
|
6730
7091
|
}
|
|
6731
7092
|
function regexpIteratorState(value) {
|
|
@@ -7634,6 +7995,9 @@ function getSandboxPrototype(value, budget) {
|
|
|
7634
7995
|
function hasExplicitSandboxPrototype(value) {
|
|
7635
7996
|
return prototypes.has(value);
|
|
7636
7997
|
}
|
|
7998
|
+
function hasNullObjectPrototype(value) {
|
|
7999
|
+
return prototypes.get(value) === null && !Array.isArray(value) && !isSandboxClosure(value) && !isSandboxRegex(value);
|
|
8000
|
+
}
|
|
7637
8001
|
function getSandboxPropertyDescriptor(value, key, budget) {
|
|
7638
8002
|
const hostProperties = isSandboxClosure(value) ? value.properties : void 0;
|
|
7639
8003
|
if (isSandboxClosure(value) && !isGuestClosure(value))
|
|
@@ -7715,7 +8079,7 @@ function hasGuestObjectState(value) {
|
|
|
7715
8079
|
const intrinsicUnchanged = intrinsicConstructors.get(value);
|
|
7716
8080
|
if (intrinsicUnchanged !== void 0) return !intrinsicUnchanged();
|
|
7717
8081
|
if (isLiveCapability(value)) return true;
|
|
7718
|
-
if (functionProperties.has(value) || prototypes.has(value)) return true;
|
|
8082
|
+
if (functionProperties.has(value) || prototypes.has(value) && !hasNullObjectPrototype(value)) return true;
|
|
7719
8083
|
if (isSandboxBox(value) || isSandboxDate(value)) return false;
|
|
7720
8084
|
return descriptorObjects.has(value) && Object.values(Object.getOwnPropertyDescriptors(value)).some(
|
|
7721
8085
|
(descriptor) => !descriptor.enumerable || !descriptor.configurable || !descriptor.writable
|
|
@@ -7956,11 +8320,14 @@ function serializeHeapReference(value, path, state) {
|
|
|
7956
8320
|
if (isSandboxRegExpIterator(value)) {
|
|
7957
8321
|
const snapshot = regexpIteratorState(value);
|
|
7958
8322
|
const matcher = snapshot.matcher;
|
|
8323
|
+
const serializedMatcher = snapshot.global === void 0 && isSandboxRegex(matcher) ? { kind: "regex", source: matcher.source, flags: matcher.flags, lastIndex: Number(matcher.lastIndex) } : serializeDumpValue(matcher, `${path}.<matcher>`, state);
|
|
8324
|
+
if (serializedMatcher === SKIP_VALUE) throw new TypeError("Unsupported RegExp iterator matcher in public dump.");
|
|
7959
8325
|
const entries = /* @__PURE__ */ Object.create(null);
|
|
7960
8326
|
state.heap[String(id)] = {
|
|
7961
8327
|
kind: "regexp-iterator",
|
|
7962
8328
|
exhausted: snapshot.exhausted,
|
|
7963
|
-
matcher:
|
|
8329
|
+
matcher: serializedMatcher,
|
|
8330
|
+
...snapshot.global === void 0 ? {} : { global: snapshot.global, unicode: snapshot.unicode },
|
|
7964
8331
|
input: snapshot.input ?? { kind: "undefined" },
|
|
7965
8332
|
entries,
|
|
7966
8333
|
symbolEntries: serializeSymbolProperties(value, (entry) => {
|
|
@@ -8033,6 +8400,7 @@ function serializeHeapReference(value, path, state) {
|
|
|
8033
8400
|
});
|
|
8034
8401
|
state.heap[String(id)] = {
|
|
8035
8402
|
kind: "object",
|
|
8403
|
+
...hasNullObjectPrototype(value) ? { sandboxNullPrototype: true } : {},
|
|
8036
8404
|
entries: serializeObjectEntries(value, path, state),
|
|
8037
8405
|
...symbolEntries.length === 0 ? {} : { symbolEntries },
|
|
8038
8406
|
...errorType === void 0 ? {} : { errorType }
|
|
@@ -8066,7 +8434,7 @@ function indexHeapContainers(snapshot) {
|
|
|
8066
8434
|
const heapIds = /* @__PURE__ */ new Map();
|
|
8067
8435
|
let nextId = 1;
|
|
8068
8436
|
for (const [value, stat2] of stats.entries()) {
|
|
8069
|
-
if (stat2.count > 1 || stat2.cyclic || ownSerializableSymbolKeys(value).length > 0 || isSandboxBox(value) || isSandboxRegExpIterator(value) || isSandboxRegex(value) && hasCustomRegexProperties(value) || isSandboxDate(value) || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
|
|
8437
|
+
if (stat2.count > 1 || stat2.cyclic || hasNullObjectPrototype(value) || ownSerializableSymbolKeys(value).length > 0 || isSandboxBox(value) || isSandboxRegExpIterator(value) || isSandboxRegex(value) && hasCustomRegexProperties(value) || isSandboxDate(value) || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
|
|
8070
8438
|
heapIds.set(value, nextId);
|
|
8071
8439
|
nextId += 1;
|
|
8072
8440
|
}
|
|
@@ -8252,6 +8620,8 @@ function validateDumpHeap(root, state) {
|
|
|
8252
8620
|
continue;
|
|
8253
8621
|
}
|
|
8254
8622
|
if (entry.kind === "object") {
|
|
8623
|
+
if (Object.hasOwn(entry, "sandboxNullPrototype") && entry.sandboxNullPrototype !== true)
|
|
8624
|
+
fail("invalidValue", `${path}.sandboxNullPrototype`, "invalid object prototype");
|
|
8255
8625
|
requireRecord(entry.entries, `${path}.entries`);
|
|
8256
8626
|
continue;
|
|
8257
8627
|
}
|
|
@@ -8372,7 +8742,11 @@ function validateTaggedValue(record2, path, state) {
|
|
|
8372
8742
|
return;
|
|
8373
8743
|
case "array":
|
|
8374
8744
|
case "arguments":
|
|
8745
|
+
return;
|
|
8375
8746
|
case "object":
|
|
8747
|
+
if (Object.hasOwn(record2, "sandboxNullPrototype") && record2.sandboxNullPrototype !== true)
|
|
8748
|
+
fail("invalidValue", `${path}.sandboxNullPrototype`, "invalid object prototype");
|
|
8749
|
+
return;
|
|
8376
8750
|
case "map":
|
|
8377
8751
|
case "set":
|
|
8378
8752
|
case "collection-iterator":
|
|
@@ -8442,6 +8816,8 @@ function validateHeapValue(value, path, state, heap) {
|
|
|
8442
8816
|
}
|
|
8443
8817
|
if (record2.kind === "set") requireArray(record2.values, `${path}.values`, state);
|
|
8444
8818
|
if (record2.kind === "regexp-iterator") {
|
|
8819
|
+
if ((record2.global !== void 0 || record2.unicode !== void 0) && (typeof record2.global !== "boolean" || typeof record2.unicode !== "boolean"))
|
|
8820
|
+
fail("invalidValue", path, "invalid RegExp iterator modes");
|
|
8445
8821
|
if (typeof record2.exhausted !== "boolean") fail("invalidValue", `${path}.exhausted`, "invalid iterator exhaustion");
|
|
8446
8822
|
if (!Object.hasOwn(record2, "matcher") || !Object.hasOwn(record2, "input")) fail("invalidValue", path, "missing RegExp iterator state");
|
|
8447
8823
|
requireRecord(record2.entries, `${path}.entries`);
|
|
@@ -9290,15 +9666,17 @@ async function withRunResources(signal, execute) {
|
|
|
9290
9666
|
|
|
9291
9667
|
// packages/safe-js/src/interp/regex/engine.ts
|
|
9292
9668
|
function matchRegex(pattern, input, lastIndex = 0) {
|
|
9293
|
-
const startIndex = pattern.flags.global ? normalizeLastIndex(lastIndex) : 0;
|
|
9669
|
+
const startIndex = pattern.flags.global || pattern.flags.sticky ? normalizeLastIndex(lastIndex) : 0;
|
|
9294
9670
|
return matchRegexFrom(pattern, input, startIndex);
|
|
9295
9671
|
}
|
|
9296
9672
|
function matchRegexFrom(pattern, input, startIndex) {
|
|
9297
9673
|
if (startIndex > input.length) {
|
|
9298
9674
|
return null;
|
|
9299
9675
|
}
|
|
9300
|
-
|
|
9301
|
-
|
|
9676
|
+
const unicode = pattern.flags.unicode || pattern.flags.unicodeSets;
|
|
9677
|
+
if (unicode && startIndex > 0 && startIndex < input.length && input.charCodeAt(startIndex) >= 56320 && input.charCodeAt(startIndex) <= 57343 && input.charCodeAt(startIndex - 1) >= 55296 && input.charCodeAt(startIndex - 1) <= 56319) startIndex--;
|
|
9678
|
+
for (let attempt = startIndex; attempt <= input.length; attempt = advanceStringIndex(input, attempt, unicode)) {
|
|
9679
|
+
const context = { input, flags: pattern.flags, groups: pattern.groups, direction: 1, work: { steps: 0 } };
|
|
9302
9680
|
charge(context);
|
|
9303
9681
|
const initialState = {
|
|
9304
9682
|
position: attempt,
|
|
@@ -9306,25 +9684,59 @@ function matchRegexFrom(pattern, input, startIndex) {
|
|
|
9306
9684
|
};
|
|
9307
9685
|
const result = matchNode(pattern.body, initialState, context).next();
|
|
9308
9686
|
if (!result.done) {
|
|
9309
|
-
return toRegexMatch(input, attempt, result.value);
|
|
9687
|
+
return toRegexMatch(input, attempt, result.value, pattern.flags.hasIndices, pattern.groups);
|
|
9310
9688
|
}
|
|
9689
|
+
if (pattern.flags.sticky) break;
|
|
9311
9690
|
}
|
|
9312
9691
|
return null;
|
|
9313
9692
|
}
|
|
9314
9693
|
function* matchNode(node, state, context) {
|
|
9315
9694
|
charge(context);
|
|
9695
|
+
const unicode = context.flags.unicode || context.flags.unicodeSets;
|
|
9696
|
+
const character = readCharacter(context.input, state.position, context.direction, unicode);
|
|
9316
9697
|
switch (node.type) {
|
|
9317
9698
|
case "empty":
|
|
9318
9699
|
yield state;
|
|
9319
9700
|
return;
|
|
9320
9701
|
case "literal":
|
|
9321
|
-
if (charactersEqual(
|
|
9322
|
-
yield { ...state, position: state.position +
|
|
9702
|
+
if (charactersEqual(character, node.value, context.flags.ignoreCase, unicode)) {
|
|
9703
|
+
yield { ...state, position: state.position + context.direction * character.length };
|
|
9704
|
+
}
|
|
9705
|
+
return;
|
|
9706
|
+
case "backreference":
|
|
9707
|
+
case "namedBackreference": {
|
|
9708
|
+
let capture;
|
|
9709
|
+
if (node.type === "backreference") capture = state.captures[node.index - 1];
|
|
9710
|
+
else {
|
|
9711
|
+
for (const index of context.groups?.[node.name] ?? []) {
|
|
9712
|
+
charge(context);
|
|
9713
|
+
if (state.captures[index - 1] !== void 0) {
|
|
9714
|
+
capture = state.captures[index - 1];
|
|
9715
|
+
break;
|
|
9716
|
+
}
|
|
9717
|
+
}
|
|
9718
|
+
}
|
|
9719
|
+
if (capture === void 0) {
|
|
9720
|
+
yield state;
|
|
9721
|
+
return;
|
|
9722
|
+
}
|
|
9723
|
+
let position = state.position;
|
|
9724
|
+
let reference = context.direction === 1 ? capture.start : capture.end;
|
|
9725
|
+
const end = context.direction === 1 ? capture.end : capture.start;
|
|
9726
|
+
while (reference !== end) {
|
|
9727
|
+
charge(context);
|
|
9728
|
+
const expected = readCharacter(context.input, reference, context.direction, unicode);
|
|
9729
|
+
const actual = readCharacter(context.input, position, context.direction, unicode);
|
|
9730
|
+
if (!charactersEqual(actual, expected, context.flags.ignoreCase, unicode)) return;
|
|
9731
|
+
reference += context.direction * expected.length;
|
|
9732
|
+
position += context.direction * actual.length;
|
|
9323
9733
|
}
|
|
9734
|
+
yield { ...state, position };
|
|
9324
9735
|
return;
|
|
9736
|
+
}
|
|
9325
9737
|
case "dot":
|
|
9326
|
-
if (
|
|
9327
|
-
yield { ...state, position: state.position +
|
|
9738
|
+
if (character !== void 0 && (context.flags.dotAll || !isLineTerminator(character))) {
|
|
9739
|
+
yield { ...state, position: state.position + context.direction * character.length };
|
|
9328
9740
|
}
|
|
9329
9741
|
return;
|
|
9330
9742
|
case "anchor":
|
|
@@ -9333,17 +9745,24 @@ function* matchNode(node, state, context) {
|
|
|
9333
9745
|
}
|
|
9334
9746
|
return;
|
|
9335
9747
|
case "wordBoundary": {
|
|
9336
|
-
const previousWord = state.position > 0 &&
|
|
9337
|
-
const nextWord = state.position < context.input.length &&
|
|
9748
|
+
const previousWord = state.position > 0 && matchesCharacterClassItem(context.input[state.position - 1], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, unicode);
|
|
9749
|
+
const nextWord = state.position < context.input.length && matchesCharacterClassItem(context.input[state.position], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, unicode);
|
|
9338
9750
|
if (previousWord !== nextWord !== node.negated) {
|
|
9339
9751
|
yield state;
|
|
9340
9752
|
}
|
|
9341
9753
|
return;
|
|
9342
9754
|
}
|
|
9343
9755
|
case "characterClass": {
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9756
|
+
if (context.flags.unicodeSets) {
|
|
9757
|
+
const lengths = [...matchUnicodeSet(node, state.position, context)].sort((a, b) => b - a);
|
|
9758
|
+
for (const length of lengths) {
|
|
9759
|
+
charge(context);
|
|
9760
|
+
yield { ...state, position: state.position + context.direction * length };
|
|
9761
|
+
}
|
|
9762
|
+
return;
|
|
9763
|
+
}
|
|
9764
|
+
if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context)) {
|
|
9765
|
+
yield { ...state, position: state.position + context.direction * character.length };
|
|
9347
9766
|
}
|
|
9348
9767
|
return;
|
|
9349
9768
|
}
|
|
@@ -9355,14 +9774,30 @@ function* matchNode(node, state, context) {
|
|
|
9355
9774
|
yield* matchNode(alternative, cloneState(state), context);
|
|
9356
9775
|
}
|
|
9357
9776
|
return;
|
|
9777
|
+
case "lookahead":
|
|
9778
|
+
case "lookbehind": {
|
|
9779
|
+
const result = matchNode(node.body, cloneState(state), {
|
|
9780
|
+
...context,
|
|
9781
|
+
direction: node.type === "lookbehind" ? -1 : 1
|
|
9782
|
+
}).next();
|
|
9783
|
+
if (node.negated) {
|
|
9784
|
+
if (result.done) yield state;
|
|
9785
|
+
} else if (!result.done) {
|
|
9786
|
+
yield { position: state.position, captures: result.value.captures };
|
|
9787
|
+
}
|
|
9788
|
+
return;
|
|
9789
|
+
}
|
|
9358
9790
|
case "group":
|
|
9359
|
-
for (const result of matchNode(node.body, cloneState(state), context
|
|
9791
|
+
for (const result of matchNode(node.body, cloneState(state), node.modifiers === void 0 ? context : {
|
|
9792
|
+
...context,
|
|
9793
|
+
flags: { ...context.flags, ...node.modifiers }
|
|
9794
|
+
})) {
|
|
9360
9795
|
if (!node.capturing || node.index === void 0) {
|
|
9361
9796
|
yield result;
|
|
9362
9797
|
continue;
|
|
9363
9798
|
}
|
|
9364
9799
|
const captures = result.captures.slice();
|
|
9365
|
-
captures[node.index - 1] = { start: state.position, end: result.position };
|
|
9800
|
+
captures[node.index - 1] = { start: Math.min(state.position, result.position), end: Math.max(state.position, result.position) };
|
|
9366
9801
|
yield { position: result.position, captures };
|
|
9367
9802
|
}
|
|
9368
9803
|
return;
|
|
@@ -9376,7 +9811,8 @@ function* matchSequence(elements, index, state, context) {
|
|
|
9376
9811
|
yield state;
|
|
9377
9812
|
return;
|
|
9378
9813
|
}
|
|
9379
|
-
|
|
9814
|
+
const element = elements[context.direction === 1 ? index : elements.length - 1 - index];
|
|
9815
|
+
for (const result of matchNode(element, state, context)) {
|
|
9380
9816
|
yield* matchSequence(elements, index + 1, result, context);
|
|
9381
9817
|
}
|
|
9382
9818
|
}
|
|
@@ -9412,11 +9848,28 @@ function matchesAnchor(kind, position, context) {
|
|
|
9412
9848
|
}
|
|
9413
9849
|
return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
|
|
9414
9850
|
}
|
|
9415
|
-
function matchesCharacterClass(character, items, negated,
|
|
9416
|
-
const matched = items.some((item) =>
|
|
9851
|
+
function matchesCharacterClass(character, items, negated, context) {
|
|
9852
|
+
const matched = items.some((item) => {
|
|
9853
|
+
if (context.flags.unicode) charge(context);
|
|
9854
|
+
return matchesCharacterClassItem(character, item, context.flags.ignoreCase, context.flags.unicode);
|
|
9855
|
+
});
|
|
9417
9856
|
return negated ? !matched : matched;
|
|
9418
9857
|
}
|
|
9419
|
-
function matchesCharacterClassItem(character, item, ignoreCase) {
|
|
9858
|
+
function matchesCharacterClassItem(character, item, ignoreCase, unicode, unicodeSets = false) {
|
|
9859
|
+
if (item.type === "strings" || item.type === "set") return false;
|
|
9860
|
+
if (unicode) {
|
|
9861
|
+
const hex = (value) => `\\u{${value.codePointAt(0).toString(16)}}`;
|
|
9862
|
+
let atom;
|
|
9863
|
+
if (item.type === "character") atom = hex(item.value);
|
|
9864
|
+
else if (item.type === "range") atom = `[${hex(item.from)}-${hex(item.to)}]`;
|
|
9865
|
+
else if (item.type === "property") atom = `\\${item.negated ? "P" : "p"}{${item.value}}`;
|
|
9866
|
+
else {
|
|
9867
|
+
const kind = item.kind === "digit" ? "d" : item.kind === "word" ? "w" : "s";
|
|
9868
|
+
atom = `\\${item.negated ? kind.toUpperCase() : kind}`;
|
|
9869
|
+
}
|
|
9870
|
+
return new RegExp(`^(?:${atom})$`, (ignoreCase ? "i" : "") + (unicodeSets ? "v" : "u")).test(character);
|
|
9871
|
+
}
|
|
9872
|
+
if (item.type === "property") return false;
|
|
9420
9873
|
if (item.type === "character") {
|
|
9421
9874
|
return charactersEqual(character, item.value, ignoreCase);
|
|
9422
9875
|
}
|
|
@@ -9430,22 +9883,102 @@ function matchesCharacterClassItem(character, item, ignoreCase) {
|
|
|
9430
9883
|
if (!ignoreCase) {
|
|
9431
9884
|
return false;
|
|
9432
9885
|
}
|
|
9433
|
-
|
|
9434
|
-
const foldedFrom = foldCharacter(item.from, true).charCodeAt(0);
|
|
9435
|
-
const foldedTo = foldCharacter(item.to, true).charCodeAt(0);
|
|
9436
|
-
return foldedCandidate >= foldedFrom && foldedCandidate <= foldedTo;
|
|
9886
|
+
return new RegExp(`^[\\u${from.toString(16).padStart(4, "0")}-\\u${to.toString(16).padStart(4, "0")}]$`, "i").test(character);
|
|
9437
9887
|
}
|
|
9438
9888
|
const matched = item.kind === "digit" ? isDigit(character) : item.kind === "word" ? isWordCharacter(character) : isSpaceCharacter(character);
|
|
9439
9889
|
return item.negated ? !matched : matched;
|
|
9440
9890
|
}
|
|
9441
|
-
function
|
|
9442
|
-
|
|
9891
|
+
function matchUnicodeSet(set, position, context) {
|
|
9892
|
+
charge(context);
|
|
9893
|
+
let lengths = /* @__PURE__ */ new Set();
|
|
9894
|
+
for (let index = 0; index < set.items.length; index++) {
|
|
9895
|
+
const next = matchUnicodeSetItem(set.items[index], position, context);
|
|
9896
|
+
if (index === 0) lengths = next;
|
|
9897
|
+
else if (set.operation === void 0) {
|
|
9898
|
+
for (const length of next) {
|
|
9899
|
+
charge(context);
|
|
9900
|
+
lengths.add(length);
|
|
9901
|
+
}
|
|
9902
|
+
} else {
|
|
9903
|
+
for (const length of lengths) {
|
|
9904
|
+
charge(context);
|
|
9905
|
+
if (set.operation === "intersection" ? !next.has(length) : next.has(length)) lengths.delete(length);
|
|
9906
|
+
}
|
|
9907
|
+
}
|
|
9908
|
+
}
|
|
9909
|
+
if (set.negated) {
|
|
9910
|
+
const character = readCharacter(context.input, position, context.direction, true);
|
|
9911
|
+
return new Set(character !== void 0 && !lengths.has(character.length) ? [character.length] : []);
|
|
9912
|
+
}
|
|
9913
|
+
return lengths;
|
|
9914
|
+
}
|
|
9915
|
+
function matchUnicodeSetItem(item, position, context) {
|
|
9916
|
+
charge(context);
|
|
9917
|
+
if (item.type === "set") return matchUnicodeSet(item.value, position, context);
|
|
9918
|
+
const lengths = /* @__PURE__ */ new Set();
|
|
9919
|
+
if (item.type === "strings") {
|
|
9920
|
+
for (const value of item.values) {
|
|
9921
|
+
charge(context);
|
|
9922
|
+
let reference = context.direction === 1 ? 0 : value.length;
|
|
9923
|
+
let cursor = position;
|
|
9924
|
+
const end = context.direction === 1 ? value.length : 0;
|
|
9925
|
+
while (reference !== end) {
|
|
9926
|
+
charge(context);
|
|
9927
|
+
const expected = readCharacter(value, reference, context.direction, true);
|
|
9928
|
+
const actual = readCharacter(context.input, cursor, context.direction, true);
|
|
9929
|
+
if (!charactersEqual(actual, expected, context.flags.ignoreCase, true)) break;
|
|
9930
|
+
reference += context.direction * expected.length;
|
|
9931
|
+
cursor += context.direction * actual.length;
|
|
9932
|
+
}
|
|
9933
|
+
if (reference === end) lengths.add(Math.abs(cursor - position));
|
|
9934
|
+
}
|
|
9935
|
+
return lengths;
|
|
9936
|
+
}
|
|
9937
|
+
if (item.type === "property" && item.strings) {
|
|
9938
|
+
const atom = `\\p{${item.value}}`;
|
|
9939
|
+
const flags = (context.flags.ignoreCase ? "i" : "") + "v";
|
|
9940
|
+
const matcher = new RegExp(context.direction === 1 ? atom : `(?<=(${atom}))`, flags + "y");
|
|
9941
|
+
matcher.lastIndex = position;
|
|
9942
|
+
const match = matcher.exec(context.input);
|
|
9943
|
+
if (match === null) return lengths;
|
|
9944
|
+
const longest = context.direction === 1 ? match[0] : match[1];
|
|
9945
|
+
const member = new RegExp(`^(?:${atom})$`, flags);
|
|
9946
|
+
let consumed = 0;
|
|
9947
|
+
while (consumed < longest.length) {
|
|
9948
|
+
charge(context);
|
|
9949
|
+
const cursor = context.direction === 1 ? consumed : longest.length - consumed;
|
|
9950
|
+
consumed += readCharacter(longest, cursor, context.direction, true).length;
|
|
9951
|
+
const candidate = context.direction === 1 ? longest.slice(0, consumed) : longest.slice(longest.length - consumed);
|
|
9952
|
+
if (member.test(candidate)) lengths.add(consumed);
|
|
9953
|
+
}
|
|
9954
|
+
return lengths;
|
|
9955
|
+
}
|
|
9956
|
+
const character = readCharacter(context.input, position, context.direction, true);
|
|
9957
|
+
if (character !== void 0 && matchesCharacterClassItem(character, item, context.flags.ignoreCase, true, true))
|
|
9958
|
+
lengths.add(character.length);
|
|
9959
|
+
return lengths;
|
|
9960
|
+
}
|
|
9961
|
+
function toRegexMatch(input, start, state, hasIndices, groups) {
|
|
9962
|
+
const match = {
|
|
9443
9963
|
index: start,
|
|
9444
9964
|
text: input.slice(start, state.position),
|
|
9445
9965
|
captures: state.captures.map(
|
|
9446
9966
|
(capture) => capture === void 0 ? void 0 : input.slice(capture.start, capture.end)
|
|
9447
9967
|
)
|
|
9448
9968
|
};
|
|
9969
|
+
if (hasIndices) {
|
|
9970
|
+
match.indices = [[start, state.position], ...state.captures.map((capture) => capture === void 0 ? void 0 : [capture.start, capture.end])];
|
|
9971
|
+
}
|
|
9972
|
+
if (groups !== void 0) {
|
|
9973
|
+
match.groups = /* @__PURE__ */ Object.create(null);
|
|
9974
|
+
if (hasIndices) match.indicesGroups = /* @__PURE__ */ Object.create(null);
|
|
9975
|
+
for (const [name, indices] of Object.entries(groups)) {
|
|
9976
|
+
const index = indices.find((index2) => state.captures[index2 - 1] !== void 0);
|
|
9977
|
+
match.groups[name] = index === void 0 ? void 0 : match.captures[index - 1];
|
|
9978
|
+
if (match.indicesGroups !== void 0) match.indicesGroups[name] = index === void 0 ? void 0 : match.indices[index];
|
|
9979
|
+
}
|
|
9980
|
+
}
|
|
9981
|
+
return match;
|
|
9449
9982
|
}
|
|
9450
9983
|
function cloneState(state) {
|
|
9451
9984
|
return { position: state.position, captures: state.captures.slice() };
|
|
@@ -9475,13 +10008,13 @@ function clearNodeCaptures(node, captures) {
|
|
|
9475
10008
|
}
|
|
9476
10009
|
return;
|
|
9477
10010
|
}
|
|
9478
|
-
if (node.type === "quantifier") {
|
|
10011
|
+
if (node.type === "quantifier" || node.type === "lookahead" || node.type === "lookbehind") {
|
|
9479
10012
|
clearNodeCaptures(node.body, captures);
|
|
9480
10013
|
}
|
|
9481
10014
|
}
|
|
9482
10015
|
function charge(context) {
|
|
9483
|
-
context.steps += 1;
|
|
9484
|
-
allocateRegexSteps(context.steps);
|
|
10016
|
+
context.work.steps += 1;
|
|
10017
|
+
allocateRegexSteps(context.work.steps);
|
|
9485
10018
|
}
|
|
9486
10019
|
function normalizeLastIndex(lastIndex) {
|
|
9487
10020
|
if (Number.isNaN(lastIndex) || lastIndex <= 0) {
|
|
@@ -9489,9 +10022,20 @@ function normalizeLastIndex(lastIndex) {
|
|
|
9489
10022
|
}
|
|
9490
10023
|
return Math.min(Math.floor(lastIndex), Number.MAX_SAFE_INTEGER);
|
|
9491
10024
|
}
|
|
9492
|
-
function charactersEqual(left, right, ignoreCase) {
|
|
10025
|
+
function charactersEqual(left, right, ignoreCase, unicode = false) {
|
|
10026
|
+
if (unicode && ignoreCase && left !== void 0)
|
|
10027
|
+
return new RegExp(`^\\u{${right.codePointAt(0).toString(16)}}$`, "iu").test(left);
|
|
9493
10028
|
return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
|
|
9494
10029
|
}
|
|
10030
|
+
function advanceStringIndex(input, index, unicode) {
|
|
10031
|
+
return index + (unicode && (input.codePointAt(index) ?? 0) > 65535 ? 2 : 1);
|
|
10032
|
+
}
|
|
10033
|
+
function readCharacter(input, position, direction, unicode) {
|
|
10034
|
+
let index = direction === 1 ? position : position - 1;
|
|
10035
|
+
if (index < 0 || index >= input.length) return void 0;
|
|
10036
|
+
if (unicode && direction === -1 && index > 0 && input.charCodeAt(index) >= 56320 && input.charCodeAt(index) <= 57343 && input.charCodeAt(index - 1) >= 55296 && input.charCodeAt(index - 1) <= 56319) index--;
|
|
10037
|
+
return unicode ? String.fromCodePoint(input.codePointAt(index)) : input[index];
|
|
10038
|
+
}
|
|
9495
10039
|
function foldCharacter(character, ignoreCase) {
|
|
9496
10040
|
if (!ignoreCase) {
|
|
9497
10041
|
return character;
|
|
@@ -10067,7 +10611,7 @@ function callReplaceLikeMethod(value, methodName, args, budget, callClosure, use
|
|
|
10067
10611
|
);
|
|
10068
10612
|
}
|
|
10069
10613
|
async function replaceRegex(value, regex, replacement, budget, callClosure, context) {
|
|
10070
|
-
if (hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
|
|
10614
|
+
if (getSandboxRegexPattern(regex).groups !== void 0 || hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
|
|
10071
10615
|
return regexReplace(value, regex, replacement, budget, callClosure, context);
|
|
10072
10616
|
if (regex.flags.includes("g")) regex.lastIndex = 0;
|
|
10073
10617
|
const cursor = regex.lastIndex;
|
|
@@ -10117,7 +10661,7 @@ async function regexReplace(input, regex, replacementInput, budget, callClosure,
|
|
|
10117
10661
|
input = void 0;
|
|
10118
10662
|
replacement = isSandboxClosure(replacementInput) ? replacementInput : await sandboxString(replacementInput, budget, context);
|
|
10119
10663
|
replacementInput = void 0;
|
|
10120
|
-
if (isSandboxRegex(regex) && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
|
|
10664
|
+
if (isSandboxRegex(regex) && getSandboxRegexPattern(regex).groups === void 0 && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
|
|
10121
10665
|
release();
|
|
10122
10666
|
return await replaceRegex(value, regex, replacement, budget, callClosure, context);
|
|
10123
10667
|
}
|
|
@@ -10332,7 +10876,7 @@ function splitNormalized(value, separator, limit, budget, parent) {
|
|
|
10332
10876
|
while (result2.length < limit) {
|
|
10333
10877
|
const match = executeRegex(splitter, value, Number(splitter.lastIndex));
|
|
10334
10878
|
if (match === null) break;
|
|
10335
|
-
if (match.text.length === 0) splitter.lastIndex = match.index
|
|
10879
|
+
if (match.text.length === 0) splitter.lastIndex = advanceStringIndex(value, match.index, splitter.flags.includes("u") || splitter.flags.includes("v"));
|
|
10336
10880
|
endedWithZeroWidthMatch = match.text.length === 0 && match.index === value.length;
|
|
10337
10881
|
if (match.text.length === 0 && (match.index === copiedThrough || match.index === value.length))
|
|
10338
10882
|
continue;
|
|
@@ -10491,7 +11035,7 @@ function callMatchLikeMethod(value, methodName, args, compilation, lastIndex) {
|
|
|
10491
11035
|
return match?.index ?? -1;
|
|
10492
11036
|
}
|
|
10493
11037
|
if (methodName === "match" && !regex.flags.includes("g"))
|
|
10494
|
-
return toMatchArray(executeRegex(regex, value, lastIndex ?? Number(regex.lastIndex)), value);
|
|
11038
|
+
return toMatchArray(executeRegex(regex, value, lastIndex ?? Number(regex.lastIndex)), value, compilation.owner?.budget);
|
|
10495
11039
|
if (methodName === "match") regex.lastIndex = 0;
|
|
10496
11040
|
const matcher = methodName === "matchAll" ? createSandboxRegex(regex.source, regex.flags, normalizeLastIndex(lastIndex ?? Number(regex.lastIndex)), compilation) : regex;
|
|
10497
11041
|
if (methodName === "matchAll")
|
|
@@ -10507,7 +11051,7 @@ function collectRegexMatches(regex, value, all, budget, lastIndex = 0) {
|
|
|
10507
11051
|
budget?.allocateArrayLength(matches.length + 1);
|
|
10508
11052
|
matches.push(match);
|
|
10509
11053
|
lastIndex = match.index + match.text.length;
|
|
10510
|
-
if (all && match.text.length === 0) regex.lastIndex =
|
|
11054
|
+
if (all && match.text.length === 0) regex.lastIndex = lastIndex = advanceStringIndex(value, lastIndex, regex.flags.includes("u") || regex.flags.includes("v"));
|
|
10511
11055
|
} while (all);
|
|
10512
11056
|
return matches;
|
|
10513
11057
|
}
|
|
@@ -16656,7 +17200,7 @@ async function callRegexMethod(target, methodName, args, budget, context) {
|
|
|
16656
17200
|
cursor = target.lastIndex;
|
|
16657
17201
|
const lastIndex = await sandboxNumber(cursor, budget, context);
|
|
16658
17202
|
const match = executeRegex(target, input, lastIndex);
|
|
16659
|
-
return toMatchArray(match, input);
|
|
17203
|
+
return toMatchArray(match, input, budget);
|
|
16660
17204
|
} finally {
|
|
16661
17205
|
budget.setRetainedValues(retained, void 0);
|
|
16662
17206
|
}
|
|
@@ -16707,17 +17251,26 @@ async function regexToString(target, budget, context) {
|
|
|
16707
17251
|
function executeRegex(target, input, lastIndex) {
|
|
16708
17252
|
const pattern = getSandboxRegexPattern(target);
|
|
16709
17253
|
const match = matchRegex(pattern, input, lastIndex);
|
|
16710
|
-
if (pattern.flags.global) {
|
|
17254
|
+
if (pattern.flags.global || pattern.flags.sticky) {
|
|
16711
17255
|
target.lastIndex = match === null ? 0 : match.index + match.text.length;
|
|
16712
17256
|
}
|
|
16713
17257
|
return match;
|
|
16714
17258
|
}
|
|
16715
|
-
function toMatchArray(match, input) {
|
|
17259
|
+
function toMatchArray(match, input, budget) {
|
|
16716
17260
|
if (match === null) {
|
|
16717
17261
|
return null;
|
|
16718
17262
|
}
|
|
17263
|
+
budget?.allocateArrayLength(match.captures.length + 1);
|
|
16719
17264
|
const result = [match.text, ...match.captures];
|
|
16720
|
-
|
|
17265
|
+
if (match.groups !== void 0) setSandboxPrototype(match.groups, null, budget);
|
|
17266
|
+
if (match.indicesGroups !== void 0) setSandboxPrototype(match.indicesGroups, null, budget);
|
|
17267
|
+
Object.assign(result, { index: match.index, input, groups: match.groups });
|
|
17268
|
+
if (match.indices !== void 0) {
|
|
17269
|
+
budget?.allocateArrayLength(match.indices.length);
|
|
17270
|
+
budget?.allocateArrayLength(2);
|
|
17271
|
+
Object.assign(match.indices, { groups: match.indicesGroups });
|
|
17272
|
+
Object.assign(result, { indices: match.indices });
|
|
17273
|
+
}
|
|
16721
17274
|
return result;
|
|
16722
17275
|
}
|
|
16723
17276
|
|
|
@@ -16727,9 +17280,10 @@ function nextRegExpIterator(iterator, budget) {
|
|
|
16727
17280
|
budget?.visitNode();
|
|
16728
17281
|
if (state.exhausted) return { value: void 0, done: true };
|
|
16729
17282
|
const matcher = state.matcher;
|
|
17283
|
+
if (!isSandboxRegex(matcher)) throw new TypeError("Custom RegExp iterator execution requires a sandbox context.");
|
|
16730
17284
|
const input = state.input;
|
|
16731
17285
|
const match = executeRegex(matcher, input, Number(matcher.lastIndex));
|
|
16732
|
-
if (match === null || !matcher.flags.includes("g")) {
|
|
17286
|
+
if (match === null || !(state.global ?? matcher.flags.includes("g"))) {
|
|
16733
17287
|
state.exhausted = true;
|
|
16734
17288
|
state.matcher = void 0;
|
|
16735
17289
|
state.input = void 0;
|
|
@@ -16737,12 +17291,52 @@ function nextRegExpIterator(iterator, budget) {
|
|
|
16737
17291
|
if (match === null) return { value: void 0, done: true };
|
|
16738
17292
|
if (!state.exhausted && match.text.length === 0) {
|
|
16739
17293
|
const index = Number(matcher.lastIndex);
|
|
16740
|
-
const unicode = matcher.flags.includes("u") || matcher.flags.includes("v");
|
|
17294
|
+
const unicode = state.unicode ?? (matcher.flags.includes("u") || matcher.flags.includes("v"));
|
|
16741
17295
|
const codePoint = input.codePointAt(index);
|
|
16742
17296
|
matcher.lastIndex = index + (unicode && codePoint !== void 0 && codePoint > 65535 ? 2 : 1);
|
|
16743
17297
|
}
|
|
16744
|
-
|
|
16745
|
-
|
|
17298
|
+
return { value: toMatchArray(match, input, budget), done: false };
|
|
17299
|
+
}
|
|
17300
|
+
async function nextObservableRegExpIterator(iterator, budget, context) {
|
|
17301
|
+
const state = regexpIteratorState(iterator);
|
|
17302
|
+
if (state.exhausted) return { value: void 0, done: true };
|
|
17303
|
+
const matcher = state.matcher;
|
|
17304
|
+
if (isSandboxRegex(matcher) && !hasRegexPropertyOverride(matcher, ["exec"], budget) && (matcher.lastIndex === null || typeof matcher.lastIndex !== "object"))
|
|
17305
|
+
return nextRegExpIterator(iterator, budget);
|
|
17306
|
+
const input = state.input;
|
|
17307
|
+
let result;
|
|
17308
|
+
let field;
|
|
17309
|
+
const release = retainValues(budget, () => [iterator, matcher, input, result, field]);
|
|
17310
|
+
const read = (value, key) => {
|
|
17311
|
+
if (context.getProperty !== void 0) return context.getProperty(value, key);
|
|
17312
|
+
const descriptor = getSandboxPropertyDescriptor(value, key, budget);
|
|
17313
|
+
return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
|
|
17314
|
+
};
|
|
17315
|
+
try {
|
|
17316
|
+
budget.visitNode();
|
|
17317
|
+
result = await regexExec(matcher, input, budget, context);
|
|
17318
|
+
const global = state.global ?? (isSandboxRegex(matcher) && matcher.flags.includes("g"));
|
|
17319
|
+
if (result === null || !global) {
|
|
17320
|
+
state.exhausted = true;
|
|
17321
|
+
state.matcher = void 0;
|
|
17322
|
+
state.input = void 0;
|
|
17323
|
+
return result === null ? { value: void 0, done: true } : { value: result, done: false };
|
|
17324
|
+
}
|
|
17325
|
+
field = await read(result, "0");
|
|
17326
|
+
const text = await sandboxString(field, budget, context);
|
|
17327
|
+
field = void 0;
|
|
17328
|
+
if (text.length === 0) {
|
|
17329
|
+
field = await read(matcher, "lastIndex");
|
|
17330
|
+
const index = normalizeLastIndex(await sandboxNumber(field, budget, context));
|
|
17331
|
+
field = void 0;
|
|
17332
|
+
const unicode = state.unicode ?? (isSandboxRegex(matcher) && (matcher.flags.includes("u") || matcher.flags.includes("v")));
|
|
17333
|
+
const point = input.codePointAt(index);
|
|
17334
|
+
await setSandboxProperty(matcher, "lastIndex", index + (unicode && point !== void 0 && point > 65535 ? 2 : 1), budget, true, context);
|
|
17335
|
+
}
|
|
17336
|
+
return { value: result, done: false };
|
|
17337
|
+
} finally {
|
|
17338
|
+
release();
|
|
17339
|
+
}
|
|
16746
17340
|
}
|
|
16747
17341
|
function getRegExpIteratorMember(property, budget) {
|
|
16748
17342
|
if (property === Symbol.toStringTag) return "RegExp String Iterator";
|
|
@@ -16759,7 +17353,7 @@ function getRegExpIteratorMember(property, budget) {
|
|
|
16759
17353
|
const receiver = context?.thisValue;
|
|
16760
17354
|
if (!isSandboxRegExpIterator(receiver))
|
|
16761
17355
|
throw new TypeError("RegExp string iterator next requires a matching receiver.");
|
|
16762
|
-
return nextRegExpIterator(receiver, budget);
|
|
17356
|
+
return context === void 0 ? nextRegExpIterator(receiver, budget) : nextObservableRegExpIterator(receiver, budget, context);
|
|
16763
17357
|
}
|
|
16764
17358
|
});
|
|
16765
17359
|
}
|
|
@@ -16947,8 +17541,11 @@ function getSandboxIterator(value, budget, context) {
|
|
|
16947
17541
|
}
|
|
16948
17542
|
if (isSandboxCollectionIterator(value))
|
|
16949
17543
|
return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
|
|
16950
|
-
if (isSandboxRegExpIterator(value))
|
|
17544
|
+
if (isSandboxRegExpIterator(value)) {
|
|
17545
|
+
if (context !== void 0 && budget !== void 0)
|
|
17546
|
+
return { asynchronous: true, next: () => nextObservableRegExpIterator(value, budget, context), snapshotIndex: () => 0 };
|
|
16951
17547
|
return { next: () => nextRegExpIterator(value, budget), snapshotIndex: () => 0 };
|
|
17548
|
+
}
|
|
16952
17549
|
if (isGuestHostObject(value)) return getHostObjectIterator(value);
|
|
16953
17550
|
if (isFloat32Array(value)) {
|
|
16954
17551
|
return syncIterator(Float32Array.prototype.values.call(value));
|
|
@@ -17755,7 +18352,16 @@ function encodeReplayData(value, options = {}) {
|
|
|
17755
18352
|
}
|
|
17756
18353
|
let symbolIndex = 0;
|
|
17757
18354
|
const symbolEntries = serializeSymbolProperties(entry, (value2) => encode(value2, depth + 1, [...path, { symbol: Math.floor(symbolIndex++ / 2) }]));
|
|
17758
|
-
nodes[id] = {
|
|
18355
|
+
nodes[id] = {
|
|
18356
|
+
kind: "regexp-iterator",
|
|
18357
|
+
matcher: child(snapshot.matcher, "<matcher>"),
|
|
18358
|
+
input: child(snapshot.input, "<input>"),
|
|
18359
|
+
exhausted: snapshot.exhausted,
|
|
18360
|
+
properties,
|
|
18361
|
+
extensible: Object.isExtensible(entry),
|
|
18362
|
+
symbolEntries,
|
|
18363
|
+
...snapshot.global === void 0 ? {} : { global: snapshot.global, unicode: snapshot.unicode }
|
|
18364
|
+
};
|
|
17759
18365
|
} else if (isSandboxCollectionIterator(entry)) {
|
|
17760
18366
|
const snapshot = snapshotCollectionIterator(entry);
|
|
17761
18367
|
const properties = /* @__PURE__ */ Object.create(null);
|
|
@@ -17809,6 +18415,7 @@ function encodeReplayData(value, options = {}) {
|
|
|
17809
18415
|
nodes[id] = {
|
|
17810
18416
|
kind: Array.isArray(entry) ? "array" : "object",
|
|
17811
18417
|
nullPrototype: prototype === null,
|
|
18418
|
+
...hasNullObjectPrototype(entry) ? { sandboxNullPrototype: true } : {},
|
|
17812
18419
|
...errorType === void 0 ? {} : { errorType },
|
|
17813
18420
|
extensible: Object.isExtensible(entry),
|
|
17814
18421
|
properties,
|
|
@@ -17953,9 +18560,15 @@ function decodeReplayData(input, options = {}, parent) {
|
|
|
17953
18560
|
restored.set(id, result3);
|
|
17954
18561
|
const matcher = child(own(node, "matcher"));
|
|
17955
18562
|
const input2 = child(own(node, "input"));
|
|
17956
|
-
if (
|
|
18563
|
+
if ((node.global !== void 0 || node.unicode !== void 0) && (typeof node.global !== "boolean" || typeof node.unicode !== "boolean")) throw new TypeError("Invalid replay RegExp iterator modes.");
|
|
18564
|
+
if (matcher !== void 0 && (node.global === void 0 ? !isSandboxRegex(matcher) : matcher === null || typeof matcher !== "object")) throw new TypeError("Invalid replay RegExp iterator matcher.");
|
|
17957
18565
|
if (input2 !== void 0 && typeof input2 !== "string") throw new TypeError("Invalid replay RegExp iterator input.");
|
|
17958
|
-
restoreSandboxRegExpIterator({
|
|
18566
|
+
restoreSandboxRegExpIterator({
|
|
18567
|
+
matcher,
|
|
18568
|
+
input: input2,
|
|
18569
|
+
exhausted,
|
|
18570
|
+
...node.global === void 0 ? {} : { global: node.global, unicode: node.unicode }
|
|
18571
|
+
}, result3);
|
|
17959
18572
|
defineProperties(result3, record(own(node, "properties")), child, node.symbolEntries);
|
|
17960
18573
|
if (!node.extensible) Object.preventExtensions(result3);
|
|
17961
18574
|
return result3;
|
|
@@ -18025,6 +18638,10 @@ function decodeReplayData(input, options = {}, parent) {
|
|
|
18025
18638
|
throw new TypeError("Invalid replay object metadata.");
|
|
18026
18639
|
}
|
|
18027
18640
|
const result2 = kind === "array" ? [] : Object.create(node.nullPrototype ? null : Object.prototype);
|
|
18641
|
+
if (Object.hasOwn(node, "sandboxNullPrototype")) {
|
|
18642
|
+
if (kind !== "object" || node.sandboxNullPrototype !== true) throw new TypeError("Invalid replay object prototype.");
|
|
18643
|
+
setSandboxPrototype(result2, null);
|
|
18644
|
+
}
|
|
18028
18645
|
if (Object.hasOwn(node, "errorType")) {
|
|
18029
18646
|
sandboxErrorTypes.set(result2, node.errorType);
|
|
18030
18647
|
}
|
|
@@ -21472,7 +22089,7 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
|
|
|
21472
22089
|
const copy = restoreSandboxRegExpIterator({ matcher: void 0, input: void 0, exhausted: true });
|
|
21473
22090
|
state.seen.set(value, copy);
|
|
21474
22091
|
const matcher = copyToSandbox(snapshot.matcher, state, `${path}.<matcher>`, true, depth + 1);
|
|
21475
|
-
if (matcher !== void 0 && !isSandboxRegex(matcher)) throw new TypeError("Invalid RegExp iterator matcher.");
|
|
22092
|
+
if (matcher !== void 0 && (snapshot.global === void 0 ? !isSandboxRegex(matcher) : matcher === null || typeof matcher !== "object")) throw new TypeError("Invalid RegExp iterator matcher.");
|
|
21476
22093
|
restoreSandboxRegExpIterator({ ...snapshot, matcher }, copy);
|
|
21477
22094
|
for (const entry of getEnumerableObjectEntries(value, path)) {
|
|
21478
22095
|
defineOwnDataProperty(copy, entry.key, copyToSandbox(entry.value, state, joinPath2(path, entry.key), true, depth + 1));
|
|
@@ -21660,6 +22277,7 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
|
|
|
21660
22277
|
const copy = createPlainObject(
|
|
21661
22278
|
!cloneSandboxCollections || Object.getPrototypeOf(value) === null
|
|
21662
22279
|
);
|
|
22280
|
+
if (!state.structuredClone && hasNullObjectPrototype(value)) setSandboxPrototype(copy, null);
|
|
21663
22281
|
state.seen.set(value, copy);
|
|
21664
22282
|
const errorType = sandboxErrorTypes.get(value);
|
|
21665
22283
|
if (errorType !== void 0) sandboxErrorTypes.set(copy, errorType);
|
|
@@ -21871,7 +22489,7 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
|
|
|
21871
22489
|
if (existing !== void 0) {
|
|
21872
22490
|
return existing;
|
|
21873
22491
|
}
|
|
21874
|
-
const copy = createPlainObject(Object.getPrototypeOf(value) === null);
|
|
22492
|
+
const copy = createPlainObject(hasNullObjectPrototype(value) || Object.getPrototypeOf(value) === null);
|
|
21875
22493
|
state.seen.set(value, copy);
|
|
21876
22494
|
for (const entry of getEnumerableObjectEntries(value, path)) {
|
|
21877
22495
|
defineOwnDataProperty(
|
|
@@ -34388,6 +35006,90 @@ function defineDataProperty2(target, key, value) {
|
|
|
34388
35006
|
});
|
|
34389
35007
|
}
|
|
34390
35008
|
|
|
35009
|
+
// packages/safe-js/src/interp/methods/regex-split.ts
|
|
35010
|
+
async function regexSplit(target, input, limit, constructor, budget, context) {
|
|
35011
|
+
if (target === null || typeof target !== "object") throw new TypeError("RegExp split requires an object receiver.");
|
|
35012
|
+
let string;
|
|
35013
|
+
let species;
|
|
35014
|
+
let field;
|
|
35015
|
+
let flags;
|
|
35016
|
+
let matcher;
|
|
35017
|
+
let match;
|
|
35018
|
+
const result = [];
|
|
35019
|
+
const release = retainValues(budget, () => [target, input, limit, string, species, field, flags, matcher, match, result]);
|
|
35020
|
+
const read = (value, key) => {
|
|
35021
|
+
if (context?.getProperty !== void 0) return context.getProperty(value, key);
|
|
35022
|
+
const descriptor = getSandboxPropertyDescriptor(value, key, budget);
|
|
35023
|
+
return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
|
|
35024
|
+
};
|
|
35025
|
+
const append = (value) => {
|
|
35026
|
+
budget.allocateArrayLength(result.length + 1);
|
|
35027
|
+
result.push(value);
|
|
35028
|
+
};
|
|
35029
|
+
try {
|
|
35030
|
+
string = await sandboxString(input, budget, context);
|
|
35031
|
+
input = void 0;
|
|
35032
|
+
field = await read(target, "constructor");
|
|
35033
|
+
species = constructor;
|
|
35034
|
+
if (field !== void 0) {
|
|
35035
|
+
if (field === null || typeof field !== "object") throw new TypeError("Invalid RegExp species constructor.");
|
|
35036
|
+
species = await read(field, Symbol.species);
|
|
35037
|
+
if (species === null || species === void 0) species = constructor;
|
|
35038
|
+
}
|
|
35039
|
+
field = void 0;
|
|
35040
|
+
if (!isSandboxClosure(species) || species.construct === void 0) throw new TypeError("RegExp species must be a constructor.");
|
|
35041
|
+
field = await read(target, "flags");
|
|
35042
|
+
flags = await sandboxString(field, budget, context);
|
|
35043
|
+
field = void 0;
|
|
35044
|
+
const unicode = flags.includes("u") || flags.includes("v");
|
|
35045
|
+
if (!flags.includes("y")) flags = budget.allocateString(flags + "y");
|
|
35046
|
+
matcher = await invokeBuiltinClosure(species, [target, flags], budget, context, void 0, true);
|
|
35047
|
+
const maximum = limit === void 0 ? 2 ** 32 - 1 : await sandboxNumber(limit, budget, context) >>> 0;
|
|
35048
|
+
limit = void 0;
|
|
35049
|
+
if (maximum === 0) return result;
|
|
35050
|
+
if (string.length === 0) {
|
|
35051
|
+
match = await regexExec(matcher, string, budget, context);
|
|
35052
|
+
if (match === null) append(string);
|
|
35053
|
+
return result;
|
|
35054
|
+
}
|
|
35055
|
+
let end = 0;
|
|
35056
|
+
let index = 0;
|
|
35057
|
+
while (index < string.length) {
|
|
35058
|
+
budget.visitNode();
|
|
35059
|
+
match = void 0;
|
|
35060
|
+
await setSandboxProperty(matcher, "lastIndex", index, budget, true, context);
|
|
35061
|
+
match = await regexExec(matcher, string, budget, context);
|
|
35062
|
+
if (match !== null) {
|
|
35063
|
+
field = await read(matcher, "lastIndex");
|
|
35064
|
+
const next = Math.min(normalizeLastIndex(await sandboxNumber(field, budget, context)), string.length);
|
|
35065
|
+
field = void 0;
|
|
35066
|
+
if (next !== end) {
|
|
35067
|
+
append(budget.allocateString(string.slice(end, index)));
|
|
35068
|
+
if (result.length === maximum) return result;
|
|
35069
|
+
end = next;
|
|
35070
|
+
field = await read(match, "length");
|
|
35071
|
+
const length = normalizeLastIndex(await sandboxNumber(field, budget, context));
|
|
35072
|
+
field = void 0;
|
|
35073
|
+
for (let capture = 1; capture < length; capture++) {
|
|
35074
|
+
budget.visitNode();
|
|
35075
|
+
field = await read(match, String(capture));
|
|
35076
|
+
append(field);
|
|
35077
|
+
field = void 0;
|
|
35078
|
+
if (result.length === maximum) return result;
|
|
35079
|
+
}
|
|
35080
|
+
index = end;
|
|
35081
|
+
continue;
|
|
35082
|
+
}
|
|
35083
|
+
}
|
|
35084
|
+
index += unicode && (string.codePointAt(index) ?? 0) > 65535 ? 2 : 1;
|
|
35085
|
+
}
|
|
35086
|
+
append(budget.allocateString(string.slice(end)));
|
|
35087
|
+
return result;
|
|
35088
|
+
} finally {
|
|
35089
|
+
release();
|
|
35090
|
+
}
|
|
35091
|
+
}
|
|
35092
|
+
|
|
34391
35093
|
// packages/safe-js/src/interp/globals/regex.ts
|
|
34392
35094
|
function createRegexGlobals(options) {
|
|
34393
35095
|
const invoke = (construct) => async (args, context) => {
|
|
@@ -34452,7 +35154,55 @@ function createRegexGlobals(options) {
|
|
|
34452
35154
|
}
|
|
34453
35155
|
};
|
|
34454
35156
|
const constructor = createSandboxClosure({ guest: true, sandbox: true, name: "RegExp", length: 2, call: invoke(false), construct: invoke(true) });
|
|
35157
|
+
Object.defineProperty(materializeFunctionProperties(constructor), "escape", {
|
|
35158
|
+
value: createSandboxClosure({
|
|
35159
|
+
guest: true,
|
|
35160
|
+
sandbox: true,
|
|
35161
|
+
name: "escape",
|
|
35162
|
+
length: 1,
|
|
35163
|
+
call: (args) => {
|
|
35164
|
+
const input = args[0];
|
|
35165
|
+
if (typeof input !== "string") throw new TypeError("RegExp.escape requires a string.");
|
|
35166
|
+
const allocation = {};
|
|
35167
|
+
let escaped = "";
|
|
35168
|
+
try {
|
|
35169
|
+
for (const character of input) {
|
|
35170
|
+
options.budget.visitNode();
|
|
35171
|
+
const point = character.codePointAt(0);
|
|
35172
|
+
let part = character;
|
|
35173
|
+
if (escaped.length === 0 && (point >= 48 && point <= 57 || point >= 65 && point <= 90 || point >= 97 && point <= 122)) {
|
|
35174
|
+
part = `\\x${point.toString(16)}`;
|
|
35175
|
+
} else if ("^$\\.*+?()[]{}|/".includes(character)) {
|
|
35176
|
+
part = "\\" + character;
|
|
35177
|
+
} else {
|
|
35178
|
+
const control = "\f\n\r \v".indexOf(character);
|
|
35179
|
+
if (control !== -1) part = "\\" + "fnrtv"[control];
|
|
35180
|
+
else if (",-=<>#&!%:;@~'`\"".includes(character) || character.trim() === "" || point >= 55296 && point <= 57343) {
|
|
35181
|
+
part = point <= 255 ? `\\x${point.toString(16).padStart(2, "0")}` : `\\u${point.toString(16).padStart(4, "0")}`;
|
|
35182
|
+
}
|
|
35183
|
+
}
|
|
35184
|
+
options.budget.setRetainedDataUsage(allocation, escaped.length + part.length);
|
|
35185
|
+
escaped = options.budget.allocateString(escaped + part);
|
|
35186
|
+
}
|
|
35187
|
+
return escaped;
|
|
35188
|
+
} finally {
|
|
35189
|
+
options.budget.setRetainedDataUsage(allocation, 0);
|
|
35190
|
+
}
|
|
35191
|
+
}
|
|
35192
|
+
}),
|
|
35193
|
+
writable: true,
|
|
35194
|
+
configurable: true
|
|
35195
|
+
});
|
|
34455
35196
|
const prototype = /* @__PURE__ */ Object.create(null);
|
|
35197
|
+
Object.defineProperty(materializeFunctionProperties(constructor), Symbol.species, {
|
|
35198
|
+
get: accessorAdapter(createSandboxClosure({
|
|
35199
|
+
sandbox: true,
|
|
35200
|
+
name: "get [Symbol.species]",
|
|
35201
|
+
length: 0,
|
|
35202
|
+
call: (_args, context) => context?.thisValue
|
|
35203
|
+
}), "get"),
|
|
35204
|
+
configurable: true
|
|
35205
|
+
});
|
|
34456
35206
|
Object.defineProperty(materializeFunctionProperties(constructor), "prototype", { value: prototype, writable: false });
|
|
34457
35207
|
Object.defineProperty(prototype, "constructor", { value: constructor, writable: true, configurable: true });
|
|
34458
35208
|
Object.defineProperty(prototype, Symbol.search, {
|
|
@@ -34495,6 +35245,73 @@ function createRegexGlobals(options) {
|
|
|
34495
35245
|
writable: true,
|
|
34496
35246
|
configurable: true
|
|
34497
35247
|
});
|
|
35248
|
+
Object.defineProperty(prototype, Symbol.matchAll, {
|
|
35249
|
+
value: createSandboxClosure({
|
|
35250
|
+
guest: true,
|
|
35251
|
+
sandbox: true,
|
|
35252
|
+
name: "[Symbol.matchAll]",
|
|
35253
|
+
length: 1,
|
|
35254
|
+
call: async (args, context) => {
|
|
35255
|
+
const target = context?.thisValue;
|
|
35256
|
+
if (target === null || typeof target !== "object") throw new TypeError("RegExp matchAll requires an object receiver.");
|
|
35257
|
+
let input = args[0];
|
|
35258
|
+
let string;
|
|
35259
|
+
let species;
|
|
35260
|
+
let field;
|
|
35261
|
+
let flags;
|
|
35262
|
+
let matcher;
|
|
35263
|
+
const release = retainValues(options.budget, () => [target, input, string, species, field, flags, matcher]);
|
|
35264
|
+
const read = (value, key) => {
|
|
35265
|
+
if (context?.getProperty !== void 0) return context.getProperty(value, key);
|
|
35266
|
+
const descriptor = getSandboxPropertyDescriptor(value, key, options.budget);
|
|
35267
|
+
return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
|
|
35268
|
+
};
|
|
35269
|
+
try {
|
|
35270
|
+
string = await sandboxString(input, options.budget, context);
|
|
35271
|
+
input = void 0;
|
|
35272
|
+
field = await read(target, "constructor");
|
|
35273
|
+
species = constructor;
|
|
35274
|
+
if (field !== void 0) {
|
|
35275
|
+
if (field === null || typeof field !== "object") throw new TypeError("Invalid RegExp species constructor.");
|
|
35276
|
+
species = await read(field, Symbol.species);
|
|
35277
|
+
if (species === null || species === void 0) species = constructor;
|
|
35278
|
+
}
|
|
35279
|
+
field = void 0;
|
|
35280
|
+
if (!isSandboxClosure(species) || species.construct === void 0) throw new TypeError("RegExp species must be a constructor.");
|
|
35281
|
+
field = await read(target, "flags");
|
|
35282
|
+
flags = await sandboxString(field, options.budget, context);
|
|
35283
|
+
field = void 0;
|
|
35284
|
+
matcher = await invokeBuiltinClosure(species, [target, flags], options.budget, context, void 0, true);
|
|
35285
|
+
field = await read(target, "lastIndex");
|
|
35286
|
+
const cursor = normalizeLastIndex(await sandboxNumber(field, options.budget, context));
|
|
35287
|
+
field = void 0;
|
|
35288
|
+
await setSandboxProperty(matcher, "lastIndex", cursor, options.budget, true, context);
|
|
35289
|
+
return restoreSandboxRegExpIterator({
|
|
35290
|
+
matcher,
|
|
35291
|
+
input: string,
|
|
35292
|
+
exhausted: false,
|
|
35293
|
+
global: flags.includes("g"),
|
|
35294
|
+
unicode: flags.includes("u") || flags.includes("v")
|
|
35295
|
+
});
|
|
35296
|
+
} finally {
|
|
35297
|
+
release();
|
|
35298
|
+
}
|
|
35299
|
+
}
|
|
35300
|
+
}),
|
|
35301
|
+
writable: true,
|
|
35302
|
+
configurable: true
|
|
35303
|
+
});
|
|
35304
|
+
Object.defineProperty(prototype, Symbol.split, {
|
|
35305
|
+
value: createSandboxClosure({
|
|
35306
|
+
guest: true,
|
|
35307
|
+
sandbox: true,
|
|
35308
|
+
name: "[Symbol.split]",
|
|
35309
|
+
length: 2,
|
|
35310
|
+
call: (args, context) => regexSplit(context?.thisValue, args[0], args[1], constructor, options.budget, context)
|
|
35311
|
+
}),
|
|
35312
|
+
writable: true,
|
|
35313
|
+
configurable: true
|
|
35314
|
+
});
|
|
34498
35315
|
for (const name of ["exec", "test", "toString"]) {
|
|
34499
35316
|
Object.defineProperty(prototype, name, {
|
|
34500
35317
|
value: createSandboxClosure({
|
|
@@ -36839,4 +37656,4 @@ export {
|
|
|
36839
37656
|
FileSnapshotBackend,
|
|
36840
37657
|
run
|
|
36841
37658
|
};
|
|
36842
|
-
//# sourceMappingURL=chunk-
|
|
37659
|
+
//# sourceMappingURL=chunk-EOTY4PCT.js.map
|