vinext 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/README.md +13 -10
  2. package/dist/build/client-build-config.d.ts +64 -3
  3. package/dist/build/client-build-config.js +131 -4
  4. package/dist/build/client-reference-groups.d.ts +163 -0
  5. package/dist/build/client-reference-groups.js +534 -0
  6. package/dist/build/module-dependency-cache.d.ts +31 -0
  7. package/dist/build/module-dependency-cache.js +51 -1
  8. package/dist/build/next-client-runtime-manifests.d.ts +10 -1
  9. package/dist/build/next-client-runtime-manifests.js +19 -4
  10. package/dist/build/nitro-public-files.d.ts +24 -0
  11. package/dist/build/nitro-public-files.js +60 -0
  12. package/dist/build/output-root-externals.d.ts +21 -0
  13. package/dist/build/output-root-externals.js +40 -0
  14. package/dist/build/pages-client-assets-module.js +1 -1
  15. package/dist/build/prerender-paths.js +6 -3
  16. package/dist/build/prerender.js +1 -1
  17. package/dist/build/server-actions-encryption-key.d.ts +23 -0
  18. package/dist/build/server-actions-encryption-key.js +101 -0
  19. package/dist/build/ssr-manifest.d.ts +3 -0
  20. package/dist/build/ssr-manifest.js +10 -1
  21. package/dist/check.js +5 -6
  22. package/dist/cli-dev-config.js +3 -3
  23. package/dist/cli.js +1 -1
  24. package/dist/client/client-rewrite-params.d.ts +9 -0
  25. package/dist/client/client-rewrite-params.js +20 -0
  26. package/dist/client/dev-error-overlay.js +2 -1
  27. package/dist/client/navigation-runtime.d.ts +25 -2
  28. package/dist/client/navigation-runtime.js +42 -11
  29. package/dist/client/vinext-next-data.d.ts +0 -1
  30. package/dist/config/config-matchers.d.ts +15 -40
  31. package/dist/config/config-matchers.js +195 -262
  32. package/dist/config/config-source.d.ts +34 -0
  33. package/dist/config/config-source.js +141 -0
  34. package/dist/config/header-params.d.ts +29 -0
  35. package/dist/config/header-params.js +106 -0
  36. package/dist/config/next-config.d.ts +7 -5
  37. package/dist/config/next-config.js +120 -7
  38. package/dist/entries/app-browser-entry.d.ts +14 -1
  39. package/dist/entries/app-browser-entry.js +26 -36
  40. package/dist/entries/app-rsc-entry.d.ts +2 -0
  41. package/dist/entries/app-rsc-entry.js +92 -57
  42. package/dist/entries/app-rsc-manifest.d.ts +10 -0
  43. package/dist/entries/app-rsc-manifest.js +20 -1
  44. package/dist/entries/app-ssr-entry.d.ts +4 -1
  45. package/dist/entries/app-ssr-entry.js +9 -2
  46. package/dist/entries/pages-client-entry.d.ts +1 -0
  47. package/dist/entries/pages-client-entry.js +6 -6
  48. package/dist/entries/pages-server-entry.js +17 -14
  49. package/dist/index.d.ts +11 -0
  50. package/dist/index.js +350 -175
  51. package/dist/init.d.ts +1 -1
  52. package/dist/init.js +103 -6
  53. package/dist/plugins/ast-utils.d.ts +53 -2
  54. package/dist/plugins/ast-utils.js +90 -2
  55. package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
  56. package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
  57. package/dist/plugins/commonjs-esm-facade.js +2 -2
  58. package/dist/plugins/css-module-imports.js +13 -20
  59. package/dist/plugins/dynamic-preload-metadata.js +2 -3
  60. package/dist/plugins/extensionless-dynamic-import.js +2 -3
  61. package/dist/plugins/fonts.d.ts +1 -1
  62. package/dist/plugins/fonts.js +3 -3
  63. package/dist/plugins/ignore-dynamic-requests.js +2 -3
  64. package/dist/plugins/import-meta-url.js +3 -4
  65. package/dist/plugins/instrumentation-client.js +3 -2
  66. package/dist/plugins/middleware-export-validation.js +2 -3
  67. package/dist/plugins/og-harfbuzz.js +2 -3
  68. package/dist/plugins/optimize-imports.d.ts +25 -2
  69. package/dist/plugins/optimize-imports.js +109 -24
  70. package/dist/plugins/pages-node-externals.js +2 -3
  71. package/dist/plugins/remove-console.js +2 -18
  72. package/dist/plugins/require-condition-resolution.js +3 -3
  73. package/dist/plugins/require-context.js +2 -3
  74. package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
  75. package/dist/plugins/rsc-client-reference-loaders.js +336 -18
  76. package/dist/plugins/strip-server-exports.js +3 -4
  77. package/dist/plugins/styled-jsx.js +2 -3
  78. package/dist/plugins/use-cache-callable.d.ts +26 -2
  79. package/dist/plugins/use-cache-callable.js +101 -36
  80. package/dist/plugins/worker-image-imports.d.ts +1 -0
  81. package/dist/plugins/worker-image-imports.js +31 -34
  82. package/dist/plugins/worker-use-server.js +38 -14
  83. package/dist/routing/app-route-graph.d.ts +1 -1
  84. package/dist/routing/browser-route-manifest.d.ts +43 -0
  85. package/dist/routing/browser-route-manifest.js +195 -0
  86. package/dist/routing/hashed-route-patterns.d.ts +4 -0
  87. package/dist/routing/hashed-route-patterns.js +22 -0
  88. package/dist/routing/optimistic-route-trie.d.ts +27 -0
  89. package/dist/routing/optimistic-route-trie.js +102 -0
  90. package/dist/routing/route-validation.d.ts +6 -1
  91. package/dist/routing/route-validation.js +26 -10
  92. package/dist/server/api-handler.js +1 -1
  93. package/dist/server/app-action-forwarding.d.ts +8 -0
  94. package/dist/server/app-action-forwarding.js +17 -3
  95. package/dist/server/app-browser-entry.js +149 -62
  96. package/dist/server/app-browser-error.d.ts +3 -1
  97. package/dist/server/app-browser-error.js +7 -2
  98. package/dist/server/app-browser-interception-context.d.ts +2 -2
  99. package/dist/server/app-browser-interception-context.js +1 -1
  100. package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
  101. package/dist/server/app-browser-mpa-navigation.js +6 -5
  102. package/dist/server/app-browser-navigation-controller.d.ts +17 -6
  103. package/dist/server/app-browser-navigation-controller.js +88 -26
  104. package/dist/server/app-browser-prefetch-response.js +2 -2
  105. package/dist/server/app-browser-state.d.ts +2 -2
  106. package/dist/server/app-browser-state.js +1 -1
  107. package/dist/server/app-browser-supplemental-refresh.js +1 -1
  108. package/dist/server/app-browser-visible-commit.d.ts +4 -4
  109. package/dist/server/app-client-reference-preloader.d.ts +23 -0
  110. package/dist/server/app-client-reference-preloader.js +30 -7
  111. package/dist/server/app-fallback-renderer.js +2 -1
  112. package/dist/server/app-middleware.d.ts +6 -0
  113. package/dist/server/app-middleware.js +8 -10
  114. package/dist/server/app-optimistic-routing.d.ts +8 -10
  115. package/dist/server/app-optimistic-routing.js +4 -95
  116. package/dist/server/app-page-boundary-render.js +8 -1
  117. package/dist/server/app-page-cache-render.js +1 -0
  118. package/dist/server/app-page-dispatch.js +3 -1
  119. package/dist/server/app-page-render.js +4 -2
  120. package/dist/server/app-page-rsc-render-status.d.ts +1 -0
  121. package/dist/server/app-page-rsc-render-status.js +1 -0
  122. package/dist/server/app-page-search-params-observation.d.ts +1 -4
  123. package/dist/server/app-page-search-params-observation.js +8 -10
  124. package/dist/server/app-page-stream.d.ts +7 -0
  125. package/dist/server/app-page-stream.js +1 -0
  126. package/dist/server/app-pages-bridge.d.ts +2 -1
  127. package/dist/server/app-pages-bridge.js +12 -8
  128. package/dist/server/app-prerender-endpoints.js +1 -1
  129. package/dist/server/app-prerender-static-params.js +3 -2
  130. package/dist/server/app-render-abort-error.d.ts +19 -0
  131. package/dist/server/app-render-abort-error.js +31 -1
  132. package/dist/server/app-render-dependency.js +42 -2
  133. package/dist/server/app-request-stage-independent-entry.js +7 -7
  134. package/dist/server/app-response-stage-entry.js +5 -5
  135. package/dist/server/app-route-handler-dispatch.js +3 -1
  136. package/dist/server/app-route-handler-execution.d.ts +2 -0
  137. package/dist/server/app-route-handler-execution.js +9 -2
  138. package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
  139. package/dist/server/app-route-handler-middleware-context.js +3 -3
  140. package/dist/server/app-route-handler-response.d.ts +2 -1
  141. package/dist/server/app-route-handler-response.js +2 -2
  142. package/dist/server/app-route-handler-runtime.d.ts +2 -0
  143. package/dist/server/app-route-handler-runtime.js +21 -4
  144. package/dist/server/app-route-module-loader.js +7 -6
  145. package/dist/server/app-route-tree.d.ts +20 -0
  146. package/dist/server/app-route-tree.js +18 -0
  147. package/dist/server/app-router-entry.js +7 -7
  148. package/dist/server/app-rsc-cache-busting.d.ts +16 -0
  149. package/dist/server/app-rsc-cache-busting.js +29 -12
  150. package/dist/server/app-rsc-combined-handler.js +8 -1
  151. package/dist/server/app-rsc-errors.d.ts +7 -0
  152. package/dist/server/app-rsc-errors.js +9 -2
  153. package/dist/server/app-rsc-handler.d.ts +4 -1
  154. package/dist/server/app-rsc-handler.js +151 -135
  155. package/dist/server/app-rsc-request-normalization.js +3 -3
  156. package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
  157. package/dist/server/app-rsc-response-finalizer.js +4 -1
  158. package/dist/server/app-rsc-response-stage.js +5 -3
  159. package/dist/server/app-rsc-route-matching.d.ts +1 -0
  160. package/dist/server/app-rsc-route-matching.js +1 -1
  161. package/dist/server/app-server-action-execution.d.ts +23 -6
  162. package/dist/server/app-server-action-execution.js +51 -57
  163. package/dist/server/app-ssr-entry.d.ts +6 -0
  164. package/dist/server/app-ssr-entry.js +21 -11
  165. package/dist/server/app-ssr-stream.d.ts +7 -0
  166. package/dist/server/app-ssr-stream.js +13 -1
  167. package/dist/server/app-visited-response-cache.js +2 -2
  168. package/dist/server/config-headers.js +13 -4
  169. package/dist/server/defer-until-stream-consumed.d.ts +2 -1
  170. package/dist/server/defer-until-stream-consumed.js +3 -1
  171. package/dist/server/dev-server.js +1 -1
  172. package/dist/server/image-optimization.js +1 -0
  173. package/dist/server/isolate-shared-promise.d.ts +10 -0
  174. package/dist/server/isolate-shared-promise.js +33 -0
  175. package/dist/server/isr-cache.js +3 -2
  176. package/dist/server/metadata-route-response.js +2 -2
  177. package/dist/server/middleware-matcher-pattern.d.ts +0 -1
  178. package/dist/server/middleware-matcher-pattern.js +11 -140
  179. package/dist/server/middleware-matcher.js +5 -6
  180. package/dist/server/middleware-response-headers.d.ts +31 -0
  181. package/dist/server/middleware-response-headers.js +57 -1
  182. package/dist/server/middleware-runtime.js +30 -17
  183. package/dist/server/navigation-planner.d.ts +2 -2
  184. package/dist/server/navigation-planner.js +1 -1
  185. package/dist/server/nitro-public-files-plugin.d.ts +38 -0
  186. package/dist/server/nitro-public-files-plugin.js +106 -0
  187. package/dist/server/nitro-public-files.d.ts +21 -0
  188. package/dist/server/nitro-public-files.js +39 -0
  189. package/dist/server/open-redirect.d.ts +11 -4
  190. package/dist/server/open-redirect.js +11 -4
  191. package/dist/server/pages-api-route.js +2 -2
  192. package/dist/server/pages-asset-tags.d.ts +5 -0
  193. package/dist/server/pages-asset-tags.js +9 -2
  194. package/dist/server/pages-client-assets.d.ts +4 -1
  195. package/dist/server/pages-data-route.js +2 -1
  196. package/dist/server/pages-i18n.d.ts +18 -0
  197. package/dist/server/pages-i18n.js +18 -2
  198. package/dist/server/pages-node-compat.d.ts +5 -3
  199. package/dist/server/pages-node-compat.js +35 -16
  200. package/dist/server/pages-page-data.js +1 -1
  201. package/dist/server/pages-page-handler.js +1 -1
  202. package/dist/server/pages-page-response.js +1 -1
  203. package/dist/server/pages-request-pipeline.d.ts +6 -1
  204. package/dist/server/pages-request-pipeline.js +35 -39
  205. package/dist/server/pages-request-stage-entry.js +20 -10
  206. package/dist/server/pages-response-stage-entry.js +1 -1
  207. package/dist/server/pages-revalidate.js +3 -2
  208. package/dist/server/pages-router-entry.js +2 -2
  209. package/dist/server/prod-server.d.ts +2 -2
  210. package/dist/server/prod-server.js +74 -36
  211. package/dist/server/proxy-trust.d.ts +6 -0
  212. package/dist/server/proxy-trust.js +12 -6
  213. package/dist/server/request-pipeline.d.ts +5 -0
  214. package/dist/server/request-pipeline.js +12 -1
  215. package/dist/server/rsc-stream-hints.d.ts +1 -1
  216. package/dist/server/rsc-stream-hints.js +21 -3
  217. package/dist/server/server-reference-loader.js +10 -1
  218. package/dist/server/static-file-cache.js +15 -3
  219. package/dist/server/worker-image-optimization.js +19 -6
  220. package/dist/server/worker-utils.js +1 -1
  221. package/dist/shims/cache-handler.js +3 -2
  222. package/dist/shims/cache-request-state.d.ts +40 -3
  223. package/dist/shims/cache-request-state.js +70 -5
  224. package/dist/shims/cache-runtime.js +47 -19
  225. package/dist/shims/cache.d.ts +2 -2
  226. package/dist/shims/cache.js +17 -8
  227. package/dist/shims/cdn-purge-routes.d.ts +24 -0
  228. package/dist/shims/cdn-purge-routes.js +77 -0
  229. package/dist/shims/dynamic.js +17 -4
  230. package/dist/shims/form.js +8 -3
  231. package/dist/shims/head.js +1 -1
  232. package/dist/shims/headers.js +2 -2
  233. package/dist/shims/image-props.d.ts +93 -0
  234. package/dist/shims/image-props.js +323 -0
  235. package/dist/shims/image.d.ts +4 -18
  236. package/dist/shims/image.js +4 -319
  237. package/dist/shims/internal/headers-state.d.ts +7 -0
  238. package/dist/shims/internal/headers-state.js +14 -2
  239. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
  240. package/dist/shims/internal/hybrid-client-route-owner-direct.js +32 -15
  241. package/dist/shims/internal/hybrid-client-route-owner.js +9 -8
  242. package/dist/shims/link-prefetch.js +5 -4
  243. package/dist/shims/link.js +7 -5
  244. package/dist/shims/navigation.d.ts +1 -1
  245. package/dist/shims/navigation.js +21 -10
  246. package/dist/shims/og.js +35 -10
  247. package/dist/shims/request-context.d.ts +13 -0
  248. package/dist/shims/router.js +28 -52
  249. package/dist/shims/server.d.ts +42 -8
  250. package/dist/shims/server.js +99 -15
  251. package/dist/shims/thenable-params.d.ts +6 -1
  252. package/dist/shims/thenable-params.js +11 -2
  253. package/dist/shims/unified-request-context.d.ts +5 -0
  254. package/dist/shims/unified-request-context.js +2 -0
  255. package/dist/shims/url-utils.d.ts +7 -0
  256. package/dist/shims/url-utils.js +12 -3
  257. package/dist/utils/asset-prefix.d.ts +7 -0
  258. package/dist/utils/asset-prefix.js +10 -1
  259. package/dist/utils/client-build-manifest.js +12 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +1 -0
  261. package/dist/utils/client-runtime-metadata.js +15 -2
  262. package/dist/utils/domain-locale.js +1 -1
  263. package/dist/utils/lazy-chunks.d.ts +4 -0
  264. package/dist/utils/manifest-paths.d.ts +14 -0
  265. package/dist/utils/manifest-paths.js +22 -1
  266. package/dist/utils/path-to-regexp.d.ts +21 -0
  267. package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
  268. package/dist/utils/plugin-react-version.d.ts +15 -0
  269. package/dist/utils/plugin-react-version.js +64 -0
  270. package/dist/utils/plugin-rsc-version.d.ts +2 -0
  271. package/dist/utils/plugin-rsc-version.js +28 -2
  272. package/dist/utils/public-routes.d.ts +2 -0
  273. package/dist/utils/public-routes.js +18 -7
  274. package/dist/utils/react-version.d.ts +7 -0
  275. package/dist/utils/react-version.js +39 -16
  276. package/package.json +6 -6
  277. package/dist/build/nitro-route-rules.d.ts +0 -47
  278. package/dist/build/nitro-route-rules.js +0 -79
  279. package/dist/plugins/cache-flight-codec.d.ts +0 -19
  280. package/dist/plugins/cache-flight-codec.js +0 -68
  281. package/dist/server/middleware-path-to-regexp.d.ts +0 -13
  282. package/dist/utils/regex-safety.d.ts +0 -17
  283. package/dist/utils/regex-safety.js +0 -789
@@ -1,789 +0,0 @@
1
- //#region src/utils/regex-safety.ts
2
- const MAX_NODES = 16384;
3
- const MAX_NESTING_DEPTH = 256;
4
- const MAX_PATTERN_LENGTH = 65536;
5
- const MAX_WORDS = 4096;
6
- const MAX_WORD_SYMBOLS = 32768;
7
- const MAX_OPAQUE_COMPARISONS = 4096;
8
- const MAX_SEQUENCE_EXPANSIONS = 256;
9
- const MAX_SAFE_OVERLAPPING_VARIABLE_BOUNDARIES = 1;
10
- function canonicalizeIgnoreCase(character) {
11
- const upper = character.toUpperCase();
12
- if (upper.length !== 1) return character;
13
- if (character.charCodeAt(0) >= 128 && upper.charCodeAt(0) < 128) return character;
14
- return upper;
15
- }
16
- function literalSymbol(character, ignoreCase) {
17
- return {
18
- kind: "literal",
19
- key: ignoreCase ? canonicalizeIgnoreCase(character) : character,
20
- value: character
21
- };
22
- }
23
- function createClassSymbol(values, nonAscii) {
24
- return {
25
- kind: "class",
26
- key: `class:${nonAscii}:${[...values].sort().join("")}`,
27
- values,
28
- nonAscii
29
- };
30
- }
31
- function shorthandClassSymbol(shorthand, ignoreCase) {
32
- if (!"dDwWsS".includes(shorthand)) return null;
33
- const regexp = new RegExp(`\\${shorthand}`);
34
- const values = /* @__PURE__ */ new Set();
35
- for (let code = 0; code <= 127; code++) {
36
- const character = String.fromCharCode(code);
37
- if (regexp.test(character)) values.add(ignoreCase ? canonicalizeIgnoreCase(character) : character);
38
- }
39
- return createClassSymbol(values, shorthand === "d" || shorthand === "w" ? "none" : shorthand === "s" ? "whitespace" : shorthand === "S" ? "non-whitespace" : "all");
40
- }
41
- function unionNonAscii(left, right) {
42
- if (left === "none") return right;
43
- if (right === "none" || left === right) return left;
44
- return "all";
45
- }
46
- function simpleClassSymbol(raw, ignoreCase) {
47
- const end = raw.length - 1;
48
- if (raw[0] !== "[" || raw[end] !== "]" || raw[1] === "^") return null;
49
- const values = /* @__PURE__ */ new Set();
50
- let nonAscii = "none";
51
- const add = (character) => {
52
- if (character.charCodeAt(0) > 127) return false;
53
- values.add(ignoreCase ? canonicalizeIgnoreCase(character) : character);
54
- return true;
55
- };
56
- const addClass = (symbol) => {
57
- if (symbol.kind !== "class") return false;
58
- for (const value of symbol.values) values.add(value);
59
- nonAscii = unionNonAscii(nonAscii, symbol.nonAscii);
60
- return true;
61
- };
62
- for (let index = 1; index < end; index++) {
63
- const start = raw[index];
64
- if (start === "\\") {
65
- const escaped = raw[++index];
66
- if (escaped === void 0) return null;
67
- const shorthand = shorthandClassSymbol(escaped, ignoreCase);
68
- if (shorthand) {
69
- if (!addClass(shorthand)) return null;
70
- } else if ("\\-]".includes(escaped)) {
71
- if (!add(escaped)) return null;
72
- } else return null;
73
- continue;
74
- }
75
- if (index + 2 < end && raw[index + 1] === "-") {
76
- const rangeEnd = raw[index + 2];
77
- if (rangeEnd === "\\") return null;
78
- const startCode = start.charCodeAt(0);
79
- const endCode = rangeEnd.charCodeAt(0);
80
- if (startCode > endCode || endCode > 127) return null;
81
- for (let code = startCode; code <= endCode; code++) if (!add(String.fromCharCode(code))) return null;
82
- index += 2;
83
- } else if (!add(start)) return null;
84
- }
85
- if (values.size === 0 && nonAscii === "none") return null;
86
- return createClassSymbol(values, nonAscii);
87
- }
88
- var RegexParser = class {
89
- pattern;
90
- ignoreCase;
91
- namedGroups;
92
- index = 0;
93
- nodes = 0;
94
- depth = 0;
95
- exceededBudget = false;
96
- constructor(pattern, ignoreCase, namedGroups) {
97
- this.pattern = pattern;
98
- this.ignoreCase = ignoreCase;
99
- this.namedGroups = namedGroups;
100
- }
101
- parse() {
102
- return this.parseAlternation();
103
- }
104
- node(node) {
105
- this.nodes++;
106
- if (this.nodes > MAX_NODES) this.exceededBudget = true;
107
- return node;
108
- }
109
- parseAlternation() {
110
- const branches = [this.parseSequence()];
111
- while (this.pattern[this.index] === "|") {
112
- this.index++;
113
- branches.push(this.parseSequence());
114
- }
115
- return branches.length === 1 ? branches[0] : this.node({
116
- kind: "alternation",
117
- branches
118
- });
119
- }
120
- parseSequence() {
121
- const children = [];
122
- while (this.index < this.pattern.length) {
123
- const character = this.pattern[this.index];
124
- if (character === "|" || character === ")") break;
125
- const term = this.parseTerm();
126
- if (term.kind === "sequence") children.push(...term.children);
127
- else children.push(term);
128
- }
129
- return children.length === 1 ? children[0] : this.node({
130
- kind: "sequence",
131
- children
132
- });
133
- }
134
- parseTerm() {
135
- const atom = this.parseAtom();
136
- const quantifier = this.parseQuantifier();
137
- if (!quantifier) return atom;
138
- if (this.pattern[this.index] === "?") this.index++;
139
- if (quantifier.min === 1 && quantifier.max === 1) return atom;
140
- return this.node({
141
- kind: "repeat",
142
- child: atom,
143
- ...quantifier
144
- });
145
- }
146
- parseAtom() {
147
- const character = this.pattern[this.index++];
148
- if (character === "(") return this.parseGroup();
149
- if (character === "[") return this.parseClass();
150
- if (character === "\\") return this.parseEscape();
151
- if (character === "^" || character === "$") return this.node({
152
- kind: "assertion",
153
- child: this.node({
154
- kind: "sequence",
155
- children: []
156
- })
157
- });
158
- if (character === ".") return this.node({
159
- kind: "atom",
160
- symbol: {
161
- kind: "opaque",
162
- key: "opaque:.",
163
- pattern: ".",
164
- ignoreCase: this.ignoreCase
165
- },
166
- fixedWidth: true
167
- });
168
- return this.node({
169
- kind: "atom",
170
- symbol: literalSymbol(character, this.ignoreCase),
171
- fixedWidth: true
172
- });
173
- }
174
- parseGroup() {
175
- this.depth++;
176
- if (this.depth > MAX_NESTING_DEPTH) {
177
- this.exceededBudget = true;
178
- this.skipGroup();
179
- this.depth--;
180
- return this.node({
181
- kind: "atom",
182
- symbol: null,
183
- fixedWidth: false
184
- });
185
- }
186
- let assertion = false;
187
- if (this.pattern[this.index] === "?") {
188
- const marker = this.pattern[this.index + 1];
189
- if (marker === ":") this.index += 2;
190
- else if (marker === "=" || marker === "!") {
191
- assertion = true;
192
- this.index += 2;
193
- } else if (marker === "<" && (this.pattern[this.index + 2] === "=" || this.pattern[this.index + 2] === "!")) {
194
- assertion = true;
195
- this.index += 3;
196
- } else if (marker === "<") {
197
- const nameEnd = this.pattern.indexOf(">", this.index + 2);
198
- this.index = nameEnd === -1 ? this.pattern.length : nameEnd + 1;
199
- } else {
200
- while (this.index < this.pattern.length && this.pattern[this.index] !== ")") this.index++;
201
- if (this.pattern[this.index] === ")") this.index++;
202
- this.depth--;
203
- return this.node({
204
- kind: "atom",
205
- symbol: null,
206
- fixedWidth: false
207
- });
208
- }
209
- }
210
- const child = this.parseAlternation();
211
- if (this.pattern[this.index] === ")") this.index++;
212
- this.depth--;
213
- return assertion ? this.node({
214
- kind: "assertion",
215
- child
216
- }) : child;
217
- }
218
- skipGroup() {
219
- let depth = 1;
220
- let inClass = false;
221
- while (this.index < this.pattern.length && depth > 0) {
222
- const character = this.pattern[this.index++];
223
- if (character === "\\") {
224
- this.index++;
225
- continue;
226
- }
227
- if (character === "[") inClass = true;
228
- else if (character === "]") inClass = false;
229
- else if (!inClass && character === "(") depth++;
230
- else if (!inClass && character === ")") depth--;
231
- }
232
- }
233
- parseClass() {
234
- const start = this.index - 1;
235
- while (this.index < this.pattern.length) {
236
- const character = this.pattern[this.index++];
237
- if (character === "\\") this.index++;
238
- else if (character === "]") break;
239
- }
240
- const raw = this.pattern.slice(start, this.index);
241
- return this.node({
242
- kind: "atom",
243
- symbol: simpleClassSymbol(raw, this.ignoreCase) ?? {
244
- kind: "opaque",
245
- key: `opaque:${raw}`,
246
- pattern: raw,
247
- ignoreCase: this.ignoreCase
248
- },
249
- fixedWidth: true
250
- });
251
- }
252
- parseEscape() {
253
- const escaped = this.pattern[this.index++];
254
- if (escaped === void 0) return this.node({
255
- kind: "atom",
256
- symbol: null,
257
- fixedWidth: false
258
- });
259
- if (escaped === "b" || escaped === "B") return this.node({
260
- kind: "assertion",
261
- child: this.node({
262
- kind: "sequence",
263
- children: []
264
- })
265
- });
266
- const shorthand = shorthandClassSymbol(escaped, this.ignoreCase);
267
- if (shorthand) return this.node({
268
- kind: "atom",
269
- symbol: shorthand,
270
- fixedWidth: true
271
- });
272
- if (escaped === "k" && this.namedGroups && this.pattern[this.index] === "<") {
273
- const nameEnd = this.pattern.indexOf(">", this.index);
274
- this.index = nameEnd === -1 ? this.pattern.length : nameEnd + 1;
275
- return this.node({
276
- kind: "atom",
277
- symbol: null,
278
- fixedWidth: false
279
- });
280
- }
281
- if (/\d/.test(escaped)) return this.node({
282
- kind: "atom",
283
- symbol: null,
284
- fixedWidth: false
285
- });
286
- let literal = null;
287
- if (escaped === "x" && /^[\da-fA-F]{2}/.test(this.pattern.slice(this.index, this.index + 2))) {
288
- literal = String.fromCharCode(Number.parseInt(this.pattern.slice(this.index, this.index + 2), 16));
289
- this.index += 2;
290
- } else if (escaped === "u" && /^[\da-fA-F]{4}/.test(this.pattern.slice(this.index, this.index + 4))) {
291
- literal = String.fromCharCode(Number.parseInt(this.pattern.slice(this.index, this.index + 4), 16));
292
- this.index += 4;
293
- } else if (escaped === "c") {
294
- const letter = this.pattern[this.index];
295
- if (letter !== void 0 && /[A-Za-z]/.test(letter)) {
296
- literal = String.fromCharCode(letter.charCodeAt(0) % 32);
297
- this.index++;
298
- } else {
299
- literal = "\\";
300
- this.index--;
301
- }
302
- } else if ("nrtvf0".includes(escaped)) literal = {
303
- n: "\n",
304
- r: "\r",
305
- t: " ",
306
- v: "\v",
307
- f: "\f",
308
- 0: "\0"
309
- }[escaped];
310
- else if (!/[A-Za-z]/.test(escaped)) literal = escaped;
311
- if (literal !== null) return this.node({
312
- kind: "atom",
313
- symbol: literalSymbol(literal, this.ignoreCase),
314
- fixedWidth: true
315
- });
316
- const raw = `\\${escaped}`;
317
- return this.node({
318
- kind: "atom",
319
- symbol: {
320
- kind: "opaque",
321
- key: `opaque:${raw}`,
322
- pattern: raw,
323
- ignoreCase: this.ignoreCase
324
- },
325
- fixedWidth: true
326
- });
327
- }
328
- parseQuantifier() {
329
- const character = this.pattern[this.index];
330
- if (character === "*") {
331
- this.index++;
332
- return {
333
- min: 0,
334
- max: Infinity
335
- };
336
- }
337
- if (character === "+") {
338
- this.index++;
339
- return {
340
- min: 1,
341
- max: Infinity
342
- };
343
- }
344
- if (character === "?") {
345
- this.index++;
346
- return {
347
- min: 0,
348
- max: 1
349
- };
350
- }
351
- if (character !== "{") return null;
352
- const start = this.index;
353
- let cursor = start + 1;
354
- while (/\d/.test(this.pattern[cursor] ?? "")) cursor++;
355
- if (cursor === start + 1) return null;
356
- const min = Number(this.pattern.slice(start + 1, cursor));
357
- if (this.pattern[cursor] === "}") {
358
- this.index = cursor + 1;
359
- return {
360
- min,
361
- max: min
362
- };
363
- }
364
- if (this.pattern[cursor] !== ",") return null;
365
- cursor++;
366
- const maxStart = cursor;
367
- while (/\d/.test(this.pattern[cursor] ?? "")) cursor++;
368
- if (this.pattern[cursor] !== "}") return null;
369
- const max = cursor === maxStart ? Infinity : Number(this.pattern.slice(maxStart, cursor));
370
- this.index = cursor + 1;
371
- return {
372
- min,
373
- max
374
- };
375
- }
376
- };
377
- function exactWidth(node) {
378
- switch (node.kind) {
379
- case "atom": return node.fixedWidth ? 1 : null;
380
- case "assertion": return 0;
381
- case "sequence": {
382
- let width = 0;
383
- for (const child of node.children) {
384
- const childWidth = exactWidth(child);
385
- if (childWidth === null) return null;
386
- width += childWidth;
387
- }
388
- return width;
389
- }
390
- case "alternation": {
391
- let width;
392
- for (const branch of node.branches) {
393
- const branchWidth = exactWidth(branch);
394
- if (branchWidth === null) return null;
395
- if (width === void 0) width = branchWidth;
396
- else if (width !== branchWidth) return null;
397
- }
398
- return width ?? 0;
399
- }
400
- case "repeat": {
401
- if (node.min !== node.max || !Number.isFinite(node.max)) return null;
402
- const childWidth = exactWidth(node.child);
403
- return childWidth === null ? null : childWidth * node.min;
404
- }
405
- }
406
- }
407
- function containsConsumingRepetition(node) {
408
- switch (node.kind) {
409
- case "atom": return false;
410
- case "assertion": return false;
411
- case "sequence": return node.children.some(containsConsumingRepetition);
412
- case "alternation": return node.branches.some(containsConsumingRepetition);
413
- case "repeat": return node.min !== 1 || node.max !== 1 || containsConsumingRepetition(node.child);
414
- }
415
- }
416
- function containsConsumingAlternation(node) {
417
- switch (node.kind) {
418
- case "atom": return false;
419
- case "assertion": return false;
420
- case "sequence": return node.children.some(containsConsumingAlternation);
421
- case "alternation": return true;
422
- case "repeat": return containsConsumingAlternation(node.child);
423
- }
424
- }
425
- function fixedWords(node, budget) {
426
- if (budget.exceeded) return null;
427
- switch (node.kind) {
428
- case "atom": return node.symbol ? [[node.symbol]] : null;
429
- case "assertion": return [[]];
430
- case "sequence": {
431
- let words = [[]];
432
- for (const child of node.children) {
433
- const childWords = fixedWords(child, budget);
434
- if (!childWords) return null;
435
- const next = [];
436
- for (const prefix of words) for (const suffix of childWords) {
437
- if (++budget.words > MAX_WORDS) {
438
- budget.exceeded = true;
439
- return null;
440
- }
441
- const word = [...prefix, ...suffix];
442
- budget.symbols += word.length;
443
- if (budget.symbols > MAX_WORD_SYMBOLS) {
444
- budget.exceeded = true;
445
- return null;
446
- }
447
- next.push(word);
448
- }
449
- words = next;
450
- }
451
- return words;
452
- }
453
- case "alternation": {
454
- const words = [];
455
- for (const branch of node.branches) {
456
- const branchWords = fixedWords(branch, budget);
457
- if (!branchWords) return null;
458
- words.push(...branchWords);
459
- if ((budget.words += branchWords.length) > MAX_WORDS) {
460
- budget.exceeded = true;
461
- return null;
462
- }
463
- }
464
- return words;
465
- }
466
- case "repeat": {
467
- if (!Number.isFinite(node.max) || node.min > node.max) return null;
468
- let words = [[]];
469
- const childWords = fixedWords(node.child, budget);
470
- if (!childWords) return null;
471
- const repeated = node.min === 0 ? [[]] : [];
472
- for (let count = 1; count <= node.max; count++) {
473
- const next = [];
474
- for (const prefix of words) for (const suffix of childWords) {
475
- if (++budget.words > MAX_WORDS) {
476
- budget.exceeded = true;
477
- return null;
478
- }
479
- const word = [...prefix, ...suffix];
480
- budget.symbols += word.length;
481
- if (budget.symbols > MAX_WORD_SYMBOLS) {
482
- budget.exceeded = true;
483
- return null;
484
- }
485
- next.push(word);
486
- }
487
- words = next;
488
- if (count >= node.min) repeated.push(...words);
489
- }
490
- return repeated;
491
- }
492
- }
493
- }
494
- function createTrieNode() {
495
- return {
496
- terminal: false,
497
- edges: /* @__PURE__ */ new Map(),
498
- complexEdges: []
499
- };
500
- }
501
- function opaqueMatchesLiteral(opaque, literal) {
502
- if (opaque.kind !== "opaque" || literal.kind !== "literal") return false;
503
- try {
504
- return new RegExp(`^(?:${opaque.pattern})$`, opaque.ignoreCase ? "i" : "").test(literal.value);
505
- } catch {
506
- return true;
507
- }
508
- }
509
- function classMatchesLiteral(characterClass, literal) {
510
- if (characterClass.kind !== "class" || literal.kind !== "literal") return false;
511
- if (literal.value.charCodeAt(0) <= 127) return characterClass.values.has(literal.key);
512
- if (characterClass.nonAscii === "all") return true;
513
- return /\s/.test(literal.value) ? characterClass.nonAscii === "whitespace" : characterClass.nonAscii === "non-whitespace";
514
- }
515
- function nonAsciiDomainsOverlap(left, right) {
516
- if (left === "none" || right === "none") return false;
517
- if (left === "all" || right === "all") return true;
518
- return left === right;
519
- }
520
- function symbolsMayOverlap(left, right) {
521
- if (left.kind === "literal" && right.kind === "literal") return left.key === right.key;
522
- if (left.kind === "class" && right.kind === "literal") return classMatchesLiteral(left, right);
523
- if (left.kind === "literal" && right.kind === "class") return classMatchesLiteral(right, left);
524
- if (left.kind === "class" && right.kind === "class") {
525
- const [smaller, larger] = left.values.size <= right.values.size ? [left.values, right.values] : [right.values, left.values];
526
- for (const value of smaller) if (larger.has(value)) return true;
527
- return nonAsciiDomainsOverlap(left.nonAscii, right.nonAscii);
528
- }
529
- if (left.kind === "opaque" && right.kind === "literal") return opaqueMatchesLiteral(left, right);
530
- if (left.kind === "literal" && right.kind === "opaque") return opaqueMatchesLiteral(right, left);
531
- return true;
532
- }
533
- function wordMayCollide(node, word, index, comparisons, branched) {
534
- if (node.terminal) return true;
535
- if (index === word.length) return node.edges.size > 0;
536
- if (branched && ++comparisons.count > MAX_OPAQUE_COMPARISONS) return true;
537
- const symbol = word[index];
538
- const exact = node.edges.get(symbol.key);
539
- if (exact && wordMayCollide(exact.node, word, index + 1, comparisons, branched)) return true;
540
- const candidates = symbol.kind === "literal" ? node.complexEdges : node.edges.values();
541
- for (const candidate of candidates) {
542
- if (candidate === exact) continue;
543
- if (++comparisons.count > MAX_OPAQUE_COMPARISONS) return true;
544
- if (symbolsMayOverlap(candidate.symbol, symbol) && wordMayCollide(candidate.node, word, index + 1, comparisons, true)) return true;
545
- }
546
- return false;
547
- }
548
- function insertPrefixFreeWord(root, word, comparisons) {
549
- if (wordMayCollide(root, word, 0, comparisons, false)) return false;
550
- let node = root;
551
- for (const symbol of word) {
552
- let edge = node.edges.get(symbol.key);
553
- if (!edge) {
554
- edge = {
555
- symbol,
556
- node: createTrieNode()
557
- };
558
- node.edges.set(symbol.key, edge);
559
- if (symbol.kind !== "literal") node.complexEdges.push(edge);
560
- }
561
- node = edge.node;
562
- }
563
- node.terminal = true;
564
- return true;
565
- }
566
- function hasPrefixFreeFiniteLanguage(node) {
567
- const budget = {
568
- words: 0,
569
- symbols: 0,
570
- exceeded: false
571
- };
572
- const words = fixedWords(node, budget);
573
- if (!words) return {
574
- safe: false,
575
- budgetExceeded: budget.exceeded,
576
- wordCount: 0
577
- };
578
- const root = createTrieNode();
579
- const comparisons = { count: 0 };
580
- for (const word of words) if (!insertPrefixFreeWord(root, word, comparisons)) return {
581
- safe: false,
582
- budgetExceeded: comparisons.count > MAX_OPAQUE_COMPARISONS,
583
- wordCount: words.length
584
- };
585
- return {
586
- safe: true,
587
- budgetExceeded: false,
588
- wordCount: words.length
589
- };
590
- }
591
- function ambiguousExpansionFactor(node) {
592
- switch (node.kind) {
593
- case "atom":
594
- case "assertion": return 1;
595
- case "alternation": {
596
- const result = hasPrefixFreeFiniteLanguage(node);
597
- if (result.safe) return 1;
598
- if (result.budgetExceeded || result.wordCount === 0) return 257;
599
- return result.wordCount;
600
- }
601
- case "sequence": {
602
- let factor = 1;
603
- for (const child of node.children) {
604
- factor *= ambiguousExpansionFactor(child);
605
- if (factor > MAX_SEQUENCE_EXPANSIONS) return factor;
606
- }
607
- return factor;
608
- }
609
- case "repeat": {
610
- if (node.min !== node.max || !Number.isFinite(node.max)) return 1;
611
- const childFactor = ambiguousExpansionFactor(node.child);
612
- if (childFactor === 1) return 1;
613
- let factor = 1;
614
- for (let count = 0; count < node.max; count++) {
615
- factor *= childFactor;
616
- if (factor > MAX_SEQUENCE_EXPANSIONS) return factor;
617
- }
618
- return factor;
619
- }
620
- }
621
- }
622
- function isNullable(node) {
623
- switch (node.kind) {
624
- case "atom": return !node.fixedWidth;
625
- case "assertion": return true;
626
- case "sequence": return node.children.every(isNullable);
627
- case "alternation": return node.branches.some(isNullable);
628
- case "repeat": return node.min === 0 || isNullable(node.child);
629
- }
630
- }
631
- function firstSymbols(node) {
632
- switch (node.kind) {
633
- case "atom": return node.symbol ? [node.symbol] : null;
634
- case "assertion": return [];
635
- case "repeat": return firstSymbols(node.child);
636
- case "alternation": {
637
- const symbols = [];
638
- for (const branch of node.branches) {
639
- const branchSymbols = firstSymbols(branch);
640
- if (!branchSymbols) return null;
641
- symbols.push(...branchSymbols);
642
- }
643
- return symbols;
644
- }
645
- case "sequence": {
646
- const symbols = [];
647
- for (const child of node.children) {
648
- const childSymbols = firstSymbols(child);
649
- if (!childSymbols) return null;
650
- symbols.push(...childSymbols);
651
- if (!isNullable(child)) break;
652
- }
653
- return symbols;
654
- }
655
- }
656
- }
657
- function lastSymbols(node) {
658
- switch (node.kind) {
659
- case "atom": return node.symbol ? [node.symbol] : null;
660
- case "assertion": return [];
661
- case "repeat": return lastSymbols(node.child);
662
- case "alternation": {
663
- const symbols = [];
664
- for (const branch of node.branches) {
665
- const branchSymbols = lastSymbols(branch);
666
- if (!branchSymbols) return null;
667
- symbols.push(...branchSymbols);
668
- }
669
- return symbols;
670
- }
671
- case "sequence": {
672
- const symbols = [];
673
- for (let index = node.children.length - 1; index >= 0; index--) {
674
- const child = node.children[index];
675
- const childSymbols = lastSymbols(child);
676
- if (!childSymbols) return null;
677
- symbols.push(...childSymbols);
678
- if (!isNullable(child)) break;
679
- }
680
- return symbols;
681
- }
682
- }
683
- }
684
- function boundariesMayOverlap(left, right, comparisons) {
685
- if (!left || !right) return true;
686
- for (const leftSymbol of left) for (const rightSymbol of right) {
687
- if (++comparisons.count > MAX_OPAQUE_COMPARISONS) return true;
688
- if (symbolsMayOverlap(leftSymbol, rightSymbol)) return true;
689
- }
690
- return false;
691
- }
692
- function findSequenceIssue(node) {
693
- if (ambiguousExpansionFactor(node) > MAX_SEQUENCE_EXPANSIONS) return "ambiguous sequence expansion";
694
- let pendingRepetitionEnds = [];
695
- const comparisons = { count: 0 };
696
- let overlappingBoundaryCount = 0;
697
- for (const child of node.children) if (child.kind === "repeat" && (child.min !== child.max || !Number.isFinite(child.max))) {
698
- const starts = firstSymbols(child);
699
- if (pendingRepetitionEnds.filter((ends) => boundariesMayOverlap(ends, starts, comparisons)).length > 0) overlappingBoundaryCount++;
700
- else if (!isNullable(child)) overlappingBoundaryCount = 0;
701
- if (overlappingBoundaryCount > MAX_SAFE_OVERLAPPING_VARIABLE_BOUNDARIES) return "overlapping sequential repetition";
702
- const ends = lastSymbols(child);
703
- pendingRepetitionEnds = isNullable(child) ? [...pendingRepetitionEnds, ends] : [ends];
704
- } else if (!isNullable(child)) {
705
- pendingRepetitionEnds = [];
706
- overlappingBoundaryCount = 0;
707
- }
708
- return null;
709
- }
710
- function findSafetyIssue(node) {
711
- switch (node.kind) {
712
- case "atom": return null;
713
- case "assertion": return findSafetyIssue(node.child);
714
- case "sequence": {
715
- const sequenceIssue = findSequenceIssue(node);
716
- if (sequenceIssue) return sequenceIssue;
717
- for (const child of node.children) {
718
- const issue = findSafetyIssue(child);
719
- if (issue) return issue;
720
- }
721
- return null;
722
- }
723
- case "alternation":
724
- for (const branch of node.branches) {
725
- const issue = findSafetyIssue(branch);
726
- if (issue) return issue;
727
- }
728
- return null;
729
- case "repeat": {
730
- const nestedRepetition = containsConsumingRepetition(node.child);
731
- if (node.max > 1 && nestedRepetition && exactWidth(node.child) === null) return "nested repetition";
732
- if (node.max > 1 && containsConsumingAlternation(node.child)) {
733
- const prefixFree = hasPrefixFreeFiniteLanguage(node.child);
734
- if (!prefixFree.safe) return prefixFree.budgetExceeded ? "analysis budget exceeded" : "ambiguous alternatives under repetition";
735
- }
736
- return findSafetyIssue(node.child);
737
- }
738
- }
739
- }
740
- /**
741
- * Whether a RegExp source declares a named group, which turns `\k<name>` into
742
- * a backreference. Escaped characters and character classes cannot open one.
743
- */
744
- function mayHaveNamedGroups(pattern) {
745
- let inClass = false;
746
- for (let index = 0; index < pattern.length; index++) {
747
- const character = pattern[index];
748
- if (character === "\\") index++;
749
- else if (inClass) {
750
- if (character === "]") inClass = false;
751
- } else if (character === "[") inClass = true;
752
- else if (character === "(" && pattern.startsWith("?<", index + 1) && pattern[index + 3] !== "=" && pattern[index + 3] !== "!") return true;
753
- }
754
- return false;
755
- }
756
- /**
757
- * `namedGroups` must describe the whole compiled RegExp when `pattern` is only
758
- * a fragment of it. It defaults to scanning `pattern` itself.
759
- */
760
- function analyzeRegexSafety(pattern, options = {}) {
761
- if (pattern.length > MAX_PATTERN_LENGTH) return "analysis budget exceeded";
762
- const parser = new RegexParser(pattern, options.ignoreCase === true, options.namedGroups ?? mayHaveNamedGroups(pattern));
763
- const node = parser.parse();
764
- if (parser.exceededBudget) return "analysis budget exceeded";
765
- return findSafetyIssue(node);
766
- }
767
- function regexAtomsMayOverlap(left, right, ignoreCase = false) {
768
- const leftParser = new RegexParser(left, ignoreCase, true);
769
- const rightParser = new RegexParser(right, ignoreCase, true);
770
- const leftNode = leftParser.parse();
771
- const rightNode = rightParser.parse();
772
- const leftWords = fixedWords(leftNode, {
773
- words: 0,
774
- symbols: 0,
775
- exceeded: false
776
- });
777
- const rightWords = fixedWords(rightNode, {
778
- words: 0,
779
- symbols: 0,
780
- exceeded: false
781
- });
782
- if (!leftWords || !rightWords || leftWords.length !== 1 || rightWords.length !== 1) return true;
783
- const leftSymbol = leftWords[0][0];
784
- const rightSymbol = rightWords[0][0];
785
- if (!leftSymbol || !rightSymbol) return true;
786
- return symbolsMayOverlap(leftSymbol, rightSymbol);
787
- }
788
- //#endregion
789
- export { analyzeRegexSafety, mayHaveNamedGroups, regexAtomsMayOverlap };