vinext 1.0.1 → 1.2.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.
- package/README.md +93 -10
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +8 -81
- package/dist/build/prerender.js +33 -8
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.js +7 -6
- package/dist/cli.js +2 -1
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +81 -82
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +14 -0
- package/dist/config/next-config.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +6 -0
- package/dist/entries/app-rsc-entry.js +84 -49
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +7 -2
- package/dist/index.js +193 -73
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +1 -0
- package/dist/init.js +67 -3
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +9 -8
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +3 -4
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +262 -98
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.js +8 -2
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +129 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +19 -8
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +11 -7
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +19 -3
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +63 -43
- package/dist/server/app-page-cache.d.ts +6 -1
- package/dist/server/app-page-cache.js +28 -8
- package/dist/server/app-page-dispatch.d.ts +12 -2
- package/dist/server/app-page-dispatch.js +51 -33
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +3 -3
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +54 -17
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +57 -35
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -3
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-request-stage-dispatch.js +7 -3
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-response-stage-entry.js +10 -2
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +6 -3
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +45 -24
- package/dist/server/app-router-entry.js +27 -8
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +11 -0
- package/dist/server/app-rsc-handler.js +291 -125
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +10 -6
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +8 -5
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +7 -2
- package/dist/server/app-worker-stages.js +4 -4
- package/dist/server/cacheability-request.js +11 -7
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +50 -29
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +18 -1
- package/dist/server/headers.js +19 -2
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +54 -0
- package/dist/server/image-optimization.js +118 -9
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +43 -8
- package/dist/server/metadata-route-response.js +9 -8
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +33 -20
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +19 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +4 -3
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +19 -2
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +50 -120
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +209 -130
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +41 -34
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +37 -18
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +79 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/pages-router-entry.js +4 -3
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +20 -7
- package/dist/server/prod-server.js +343 -129
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +24 -9
- package/dist/server/request-pipeline.js +24 -9
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.js +31 -2
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +15 -11
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +23 -1
- package/dist/server/socket-error-backstop.js +69 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +86 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +6 -42
- package/dist/shims/cache-callable-runtime.js +65 -174
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +12 -20
- package/dist/shims/cache-runtime.js +166 -225
- package/dist/shims/cache.d.ts +4 -4
- package/dist/shims/cache.js +44 -16
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -61
- package/dist/shims/fetch-cache.js +161 -108
- package/dist/shims/form.js +1 -1
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +15 -13
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/headers-state.d.ts +0 -1
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +45 -9
- package/dist/shims/request-context.d.ts +11 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +12 -20
- package/dist/shims/server.d.ts +16 -0
- package/dist/shims/server.js +24 -4
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/shims/url-utils.d.ts +2 -0
- package/dist/shims/url-utils.js +3 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +4 -0
- package/dist/utils/plugin-rsc-version.js +15 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +3 -0
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +9 -5
package/dist/shims/server.js
CHANGED
|
@@ -131,7 +131,8 @@ var NextRequest = class extends Request {
|
|
|
131
131
|
basePath: _nextConfig.basePath,
|
|
132
132
|
nextConfig: {
|
|
133
133
|
i18n,
|
|
134
|
-
trailingSlash: _nextConfig.trailingSlash
|
|
134
|
+
trailingSlash: _nextConfig.trailingSlash,
|
|
135
|
+
skipTrailingSlashRedirect: _nextConfig.skipTrailingSlashRedirect
|
|
135
136
|
}
|
|
136
137
|
} : void 0;
|
|
137
138
|
this._nextUrl = new NextURL(url, void 0, urlConfig);
|
|
@@ -266,6 +267,8 @@ var NextURL = class NextURL {
|
|
|
266
267
|
*/
|
|
267
268
|
_configBasePath;
|
|
268
269
|
_basePath;
|
|
270
|
+
_configTrailingSlash;
|
|
271
|
+
_manualTrailingSlash;
|
|
269
272
|
_trailingSlash;
|
|
270
273
|
_locale;
|
|
271
274
|
_configDefaultLocale;
|
|
@@ -277,7 +280,10 @@ var NextURL = class NextURL {
|
|
|
277
280
|
this._url = new URL(input.toString(), base);
|
|
278
281
|
this._configBasePath = config?.basePath ?? "";
|
|
279
282
|
this._basePath = this._configBasePath;
|
|
280
|
-
this.
|
|
283
|
+
this._configTrailingSlash = config?.nextConfig?.trailingSlash ?? false;
|
|
284
|
+
this._manualTrailingSlash = config?.nextConfig?.skipTrailingSlashRedirect === true;
|
|
285
|
+
this._trailingSlash = this._configTrailingSlash;
|
|
286
|
+
this._analyzeTrailingSlash();
|
|
281
287
|
this._stripBasePath();
|
|
282
288
|
const i18n = config?.nextConfig?.i18n;
|
|
283
289
|
if (i18n) {
|
|
@@ -290,6 +296,15 @@ var NextURL = class NextURL {
|
|
|
290
296
|
this._analyzeI18n();
|
|
291
297
|
}
|
|
292
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* With `skipTrailingSlashRedirect`, take the slash from the parsed pathname
|
|
301
|
+
* (before basePath and locale are stripped), as getNextPathnameInfo does.
|
|
302
|
+
*/
|
|
303
|
+
_analyzeTrailingSlash() {
|
|
304
|
+
if (!this._manualTrailingSlash) return;
|
|
305
|
+
const { pathname } = this._url;
|
|
306
|
+
this._trailingSlash = pathname !== "/" ? pathname.endsWith("/") : this._configTrailingSlash;
|
|
307
|
+
}
|
|
293
308
|
/** Strip basePath prefix from the internal pathname.
|
|
294
309
|
* Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
|
|
295
310
|
* every parse, including `href` reassignment): basePath is only considered
|
|
@@ -348,7 +363,8 @@ var NextURL = class NextURL {
|
|
|
348
363
|
*/
|
|
349
364
|
_applyTrailingSlash(pathname) {
|
|
350
365
|
if (pathname === "" || pathname === "/") return pathname;
|
|
351
|
-
|
|
366
|
+
const pathnameWithoutBasePath = this._basePath ? stripBasePath(pathname, this._basePath) : pathname;
|
|
367
|
+
if (!this._manualTrailingSlash && pathnameWithoutBasePath.startsWith("/_next/")) return removeTrailingSlash(pathname);
|
|
352
368
|
if (this._trailingSlash) return pathname.endsWith("/") ? pathname : pathname + "/";
|
|
353
369
|
return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
354
370
|
}
|
|
@@ -361,6 +377,7 @@ var NextURL = class NextURL {
|
|
|
361
377
|
}
|
|
362
378
|
set href(value) {
|
|
363
379
|
this._url.href = value;
|
|
380
|
+
this._analyzeTrailingSlash();
|
|
364
381
|
this._stripBasePath();
|
|
365
382
|
this._analyzeI18n();
|
|
366
383
|
}
|
|
@@ -467,7 +484,10 @@ var NextURL = class NextURL {
|
|
|
467
484
|
locales: domain.locales ? [...domain.locales] : void 0
|
|
468
485
|
}))
|
|
469
486
|
};
|
|
470
|
-
if (this.
|
|
487
|
+
if (this._manualTrailingSlash) {
|
|
488
|
+
nextConfig.skipTrailingSlashRedirect = true;
|
|
489
|
+
if (this._configTrailingSlash) nextConfig.trailingSlash = true;
|
|
490
|
+
} else if (this._trailingSlash) nextConfig.trailingSlash = true;
|
|
471
491
|
const config = {
|
|
472
492
|
basePath: this._configBasePath,
|
|
473
493
|
nextConfig: Object.keys(nextConfig).length > 0 ? nextConfig : void 0
|
|
@@ -5,5 +5,9 @@ export type ThenableParamsObserver = Readonly<{
|
|
|
5
5
|
observeParamAccess: (keys: readonly string[]) => void;
|
|
6
6
|
observeReactPromiseStatus?: boolean;
|
|
7
7
|
}>;
|
|
8
|
+
/** Serialize backing values without reading a framework fallback-key proxy. */
|
|
9
|
+
export declare function getFallbackParamsSnapshot(value: unknown): Promise<Record<string, unknown>> | undefined;
|
|
10
|
+
/** Reattach only framework metadata; argument values always come from the decoder. */
|
|
11
|
+
export declare function restoreThenableParams<T extends Record<string, unknown>>(decoded: T, original: unknown): ThenableParams<T>;
|
|
8
12
|
export declare function makeThenableParams<T extends Record<string, unknown>>(obj: T, observer?: ThenableParamsObserver): ThenableParams<T>;
|
|
9
13
|
//#endregion
|
|
@@ -4,6 +4,20 @@ import { isOwnPropertyCheck, isWellKnownProperty } from "./internal/thenable-wel
|
|
|
4
4
|
function hasParamProperty(obj, prop) {
|
|
5
5
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
6
6
|
}
|
|
7
|
+
const paramsState = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function getParamsState(value) {
|
|
9
|
+
return value !== null && typeof value === "object" ? paramsState.get(value) : void 0;
|
|
10
|
+
}
|
|
11
|
+
/** Serialize backing values without reading a framework fallback-key proxy. */
|
|
12
|
+
function getFallbackParamsSnapshot(value) {
|
|
13
|
+
const state = getParamsState(value);
|
|
14
|
+
return state?.fallbackShellState ? Promise.resolve(state.plain) : void 0;
|
|
15
|
+
}
|
|
16
|
+
/** Reattach only framework metadata; argument values always come from the decoder. */
|
|
17
|
+
function restoreThenableParams(decoded, original) {
|
|
18
|
+
const state = getParamsState(original);
|
|
19
|
+
return createThenableParams(decoded, state?.observer, state?.fallbackShellState ?? null);
|
|
20
|
+
}
|
|
7
21
|
function observeParamKeys(observer, keys) {
|
|
8
22
|
if (observer) observer.observeParamAccess(keys);
|
|
9
23
|
}
|
|
@@ -81,8 +95,10 @@ function createThenableParamsProxy(promise, handler) {
|
|
|
81
95
|
return new Proxy(promise, handler);
|
|
82
96
|
}
|
|
83
97
|
function makeThenableParams(obj, observer) {
|
|
98
|
+
return createThenableParams(obj, observer, getPprFallbackShellState());
|
|
99
|
+
}
|
|
100
|
+
function createThenableParams(obj, observer, fallbackShellState) {
|
|
84
101
|
const plain = { ...obj };
|
|
85
|
-
const fallbackShellState = getPprFallbackShellState();
|
|
86
102
|
const fallbackParamNames = fallbackShellState && Object.keys(plain).some((key) => fallbackShellState.fallbackParamNames.has(key)) ? fallbackShellState.fallbackParamNames : null;
|
|
87
103
|
let fallbackShellPromise = null;
|
|
88
104
|
let fallbackShellPromiseController = null;
|
|
@@ -98,7 +114,7 @@ function makeThenableParams(obj, observer) {
|
|
|
98
114
|
function isFallbackParam(prop) {
|
|
99
115
|
return typeof prop === "string" && (fallbackParamNames?.has(prop) ?? false);
|
|
100
116
|
}
|
|
101
|
-
|
|
117
|
+
const params = createThenableParamsProxy(promise, {
|
|
102
118
|
get(target, prop, receiver) {
|
|
103
119
|
if (isPromiseContinuation(prop)) {
|
|
104
120
|
const value = Reflect.get(target, prop, receiver);
|
|
@@ -150,6 +166,12 @@ function makeThenableParams(obj, observer) {
|
|
|
150
166
|
return Reflect.ownKeys(plain).filter((prop) => !isWellKnownProperty(prop));
|
|
151
167
|
}
|
|
152
168
|
});
|
|
169
|
+
paramsState.set(params, {
|
|
170
|
+
plain,
|
|
171
|
+
observer,
|
|
172
|
+
fallbackShellState: fallbackParamNames ? fallbackShellState : null
|
|
173
|
+
});
|
|
174
|
+
return params;
|
|
153
175
|
}
|
|
154
176
|
//#endregion
|
|
155
|
-
export { makeThenableParams };
|
|
177
|
+
export { getFallbackParamsSnapshot, makeThenableParams, restoreThenableParams };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExecutionContextLike } from "./request-context.js";
|
|
2
2
|
import { CacheState } from "./cache-request-state.js";
|
|
3
3
|
import { RootParamsState } from "./root-params.js";
|
|
4
|
-
import { FetchCacheState } from "./fetch-cache.js";
|
|
4
|
+
import { FetchCacheState } from "./fetch-cache-state.js";
|
|
5
5
|
import { VinextHeadersShimState } from "./internal/headers-state.js";
|
|
6
6
|
import { RouterState } from "./router-state.js";
|
|
7
7
|
import { markFullyBufferedBody, preserveFullyBufferedBodyMetadata } from "../server/fully-buffered-response.js";
|
|
@@ -17,6 +17,7 @@ function createRequestContext(opts) {
|
|
|
17
17
|
return {
|
|
18
18
|
headersContext: null,
|
|
19
19
|
actionRevalidationKind: 0,
|
|
20
|
+
cacheLifeSink: null,
|
|
20
21
|
pendingRevalidatedTags: /* @__PURE__ */ new Set(),
|
|
21
22
|
pendingRevalidations: /* @__PURE__ */ new Set(),
|
|
22
23
|
dynamicUsageDetected: false,
|
|
@@ -30,6 +30,8 @@ export declare function toSameOriginAppPath(url: string, basePath: string): stri
|
|
|
30
30
|
* `.well-known`-aware redirect rule shipped in `routes-manifest.json`.
|
|
31
31
|
* - Query strings and hash fragments are preserved verbatim.
|
|
32
32
|
* - Idempotent: already-canonical paths round-trip unchanged.
|
|
33
|
+
* - With `skipTrailingSlashRedirect`, every path is returned as written, like
|
|
34
|
+
* Next.js's `__NEXT_MANUAL_TRAILING_SLASH` short-circuit.
|
|
33
35
|
*/
|
|
34
36
|
export declare function normalizePathTrailingSlash(path: string, trailingSlash: boolean): string;
|
|
35
37
|
/**
|
package/dist/shims/url-utils.js
CHANGED
|
@@ -99,9 +99,11 @@ function removeRouteTrailingSlash(route) {
|
|
|
99
99
|
* `.well-known`-aware redirect rule shipped in `routes-manifest.json`.
|
|
100
100
|
* - Query strings and hash fragments are preserved verbatim.
|
|
101
101
|
* - Idempotent: already-canonical paths round-trip unchanged.
|
|
102
|
+
* - With `skipTrailingSlashRedirect`, every path is returned as written, like
|
|
103
|
+
* Next.js's `__NEXT_MANUAL_TRAILING_SLASH` short-circuit.
|
|
102
104
|
*/
|
|
103
105
|
function normalizePathTrailingSlash(path, trailingSlash) {
|
|
104
|
-
if (!path.startsWith("/") || path.startsWith("//")) return path;
|
|
106
|
+
if (!path.startsWith("/") || path.startsWith("//") || process.env.__VINEXT_MANUAL_TRAILING_SLASH === "true") return path;
|
|
105
107
|
const { pathname, query, hash } = parsePath(path);
|
|
106
108
|
if (trailingSlash) {
|
|
107
109
|
if (/\.[^/]+\/?$/.test(pathname)) return `${removeRouteTrailingSlash(pathname)}${query}${hash}`;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { isAbsoluteAssetPrefix, resolveAssetsDir } from "./asset-prefix.js";
|
|
3
3
|
import { manifestFileWithAssetPrefix, manifestFileWithBase } from "./manifest-paths.js";
|
|
4
|
-
import { findClientEntryFile, findPagesClientEntryFile, readClientBuildManifest } from "./client-build-manifest.js";
|
|
5
4
|
import { findClientEntryFileFromVinextManifest, findPagesClientEntryFileFromVinextManifest, readClientEntryManifest } from "./client-entry-manifest.js";
|
|
5
|
+
import { findClientEntryFile, findPagesClientEntryFile, readClientBuildManifest } from "./client-build-manifest.js";
|
|
6
6
|
import { computeDynamicImportPreloads, computeLazyChunks, dynamicImportPreloadsWithBase } from "./lazy-chunks.js";
|
|
7
7
|
//#region src/utils/client-runtime-metadata.ts
|
|
8
8
|
function collectCssGraph(buildManifest, applyBase) {
|
package/dist/utils/hash.d.ts
CHANGED
|
@@ -20,4 +20,11 @@ export declare function fnv1a64(input: string): string;
|
|
|
20
20
|
* key format and produces different values. Do not swap one for the other.
|
|
21
21
|
*/
|
|
22
22
|
export declare function fnv1a52(str: string): number;
|
|
23
|
+
/**
|
|
24
|
+
* Hex-encoded SHA-256 digest of a string's UTF-8 bytes, via Web Crypto so it
|
|
25
|
+
* runs unchanged in Node.js, Workers and browsers. Used for cache keys built
|
|
26
|
+
* from inputs a request can influence, where crafted inputs could collide
|
|
27
|
+
* under a non-cryptographic hash like `fnv1a64`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function sha256Hex(input: string): Promise<string>;
|
|
23
30
|
//#endregion
|
package/dist/utils/hash.js
CHANGED
|
@@ -51,5 +51,15 @@ function fnv1a52(str) {
|
|
|
51
51
|
}
|
|
52
52
|
return (v3 & 15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0 ^ v3 >> 4);
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Hex-encoded SHA-256 digest of a string's UTF-8 bytes, via Web Crypto so it
|
|
56
|
+
* runs unchanged in Node.js, Workers and browsers. Used for cache keys built
|
|
57
|
+
* from inputs a request can influence, where crafted inputs could collide
|
|
58
|
+
* under a non-cryptographic hash like `fnv1a64`.
|
|
59
|
+
*/
|
|
60
|
+
async function sha256Hex(input) {
|
|
61
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
|
|
62
|
+
return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
63
|
+
}
|
|
54
64
|
//#endregion
|
|
55
|
-
export { fnv1a52, fnv1a64 };
|
|
65
|
+
export { fnv1a52, fnv1a64, sha256Hex };
|
package/dist/utils/mdx-scan.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ export declare const mdxScanCache: Map<string, boolean>;
|
|
|
5
5
|
* Check if the project has .mdx files in app/ or pages/ directories.
|
|
6
6
|
*/
|
|
7
7
|
export declare function hasMdxFiles(root: string, appDir: string | null, pagesDir: string | null): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Whether page extensions discover MDX sources, including compound extensions
|
|
10
|
+
* such as `page.mdx`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function pageExtensionsIncludeMdx(pageExtensions: readonly string[]): boolean;
|
|
8
13
|
/**
|
|
9
14
|
* Load a reader that keeps only the ESM of an MDX module, so the JavaScript
|
|
10
15
|
* export helpers can read it. It takes the ESM nodes from the MDX parser that
|
package/dist/utils/mdx-scan.js
CHANGED
|
@@ -33,6 +33,13 @@ function scanDirForMdx(dir) {
|
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
+
* Whether page extensions discover MDX sources, including compound extensions
|
|
37
|
+
* such as `page.mdx`.
|
|
38
|
+
*/
|
|
39
|
+
function pageExtensionsIncludeMdx(pageExtensions) {
|
|
40
|
+
return pageExtensions.some((extension) => extension.toLowerCase().split(".").at(-1) === "mdx");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
36
43
|
* Load a reader that keeps only the ESM of an MDX module, so the JavaScript
|
|
37
44
|
* export helpers can read it. It takes the ESM nodes from the MDX parser that
|
|
38
45
|
* `@mdx-js/rollup` compiles with, resolved beside the plugin vinext
|
|
@@ -57,4 +64,4 @@ async function loadMdxEsmReader(root) {
|
|
|
57
64
|
return (source) => processor.parse(source).children.flatMap((node) => node.type === "mdxjsEsm" && typeof node.value === "string" ? [node.value] : []).join("\n\n");
|
|
58
65
|
}
|
|
59
66
|
//#endregion
|
|
60
|
-
export { hasMdxFiles, loadMdxEsmReader, mdxScanCache };
|
|
67
|
+
export { hasMdxFiles, loadMdxEsmReader, mdxScanCache, pageExtensionsIncludeMdx };
|
|
@@ -7,4 +7,10 @@ export declare const BARE_PACKAGE_SPECIFIER_RE: RegExp;
|
|
|
7
7
|
* scoped names, and Node builtins are not npm package references.
|
|
8
8
|
*/
|
|
9
9
|
export declare function packageNameFromSpecifier(specifier: string): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Turbopack's "foreign code" condition: a module under node_modules whose
|
|
12
|
+
* package is not in the (Turbopack) transpile list. Next.js skips its
|
|
13
|
+
* app-code transforms, such as next/dynamic, for foreign code.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isForeignNodeModule(id: string, transpiledPackages: readonly string[]): boolean;
|
|
10
16
|
//#endregion
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
1
2
|
import { builtinModules } from "node:module";
|
|
2
3
|
//#region src/utils/package-name.ts
|
|
3
4
|
const BUILTIN_MODULES = new Set(builtinModules.flatMap((name) => name.startsWith("node:") ? [name, name.slice(5)] : [name, `node:${name}`]));
|
|
@@ -14,5 +15,15 @@ function packageNameFromSpecifier(specifier) {
|
|
|
14
15
|
if (!packageName || BUILTIN_MODULES.has(packageName)) return null;
|
|
15
16
|
return packageName;
|
|
16
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Turbopack's "foreign code" condition: a module under node_modules whose
|
|
20
|
+
* package is not in the (Turbopack) transpile list. Next.js skips its
|
|
21
|
+
* app-code transforms, such as next/dynamic, for foreign code.
|
|
22
|
+
*/
|
|
23
|
+
function isForeignNodeModule(id, transpiledPackages) {
|
|
24
|
+
const normalizedId = toSlash(id);
|
|
25
|
+
if (!normalizedId.includes("/node_modules/")) return false;
|
|
26
|
+
return !transpiledPackages.some((packageName) => normalizedId.includes(`/node_modules/${packageName}/`));
|
|
27
|
+
}
|
|
17
28
|
//#endregion
|
|
18
|
-
export { BARE_PACKAGE_SPECIFIER_RE, packageNameFromSpecifier };
|
|
29
|
+
export { BARE_PACKAGE_SPECIFIER_RE, isForeignNodeModule, packageNameFromSpecifier };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { findPackageVersion, isVersionBelow } from "./react-version.js";
|
|
2
|
+
//#region src/utils/plugin-rsc-version.ts
|
|
3
|
+
const MINIMUM_PLUGIN_RSC_VERSION = [
|
|
4
|
+
0,
|
|
5
|
+
5,
|
|
6
|
+
37
|
|
7
|
+
];
|
|
8
|
+
/** Return the installed @vitejs/plugin-rsc version, or throw if it is unsupported. */
|
|
9
|
+
function assertPluginRscVersion(resolvedRscPath) {
|
|
10
|
+
const version = findPackageVersion(resolvedRscPath, "@vitejs/plugin-rsc");
|
|
11
|
+
if (!version || isVersionBelow(version, MINIMUM_PLUGIN_RSC_VERSION)) throw new Error(`vinext: App Router requires @vitejs/plugin-rsc ${MINIMUM_PLUGIN_RSC_VERSION.join(".")} or newer (found ${version ?? "an unknown version"}). Upgrade @vitejs/plugin-rsc.`);
|
|
12
|
+
return version;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { assertPluginRscVersion };
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
//#region src/utils/prerender-output-paths.ts
|
|
2
2
|
/**
|
|
3
|
+
* Map a prerendered URL to the file path its artifacts are written under, as
|
|
4
|
+
* Next.js's `normalizePagePath` does. `/index` becomes `/index/index` (and
|
|
5
|
+
* `/index/foo` becomes `/index/index/foo`) so it never shares `/`'s files.
|
|
6
|
+
* Unlike Next.js, dynamic fallback-shell paths such as `/index/[slug]` are
|
|
7
|
+
* also prefixed; build and seed both use this mapping, so they stay in step.
|
|
8
|
+
* Source: https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/page-path/normalize-page-path.ts
|
|
9
|
+
*/
|
|
10
|
+
function toOutputUrlPath(urlPath) {
|
|
11
|
+
return /^\/index(?:\/|$)/.test(urlPath) ? `/index${urlPath}` : urlPath;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
3
14
|
* Determine the HTML output file path for a prerendered URL.
|
|
4
15
|
* Respects trailingSlash config.
|
|
5
16
|
*/
|
|
6
17
|
function getOutputPath(urlPath, trailingSlash, basePath = "") {
|
|
7
18
|
if (urlPath === "/" && basePath === "") return "index.html";
|
|
8
|
-
const clean = (basePath === "" ? urlPath : urlPath === "/" ? trailingSlash ? `${basePath}/` : basePath : `${basePath}${urlPath}`).replace(/^\//, "").replace(/\/$/, "");
|
|
19
|
+
const clean = (basePath === "" ? toOutputUrlPath(urlPath) : urlPath === "/" ? trailingSlash ? `${basePath}/` : basePath : `${basePath}${toOutputUrlPath(urlPath)}`).replace(/^\//, "").replace(/\/$/, "");
|
|
9
20
|
if (trailingSlash) return `${clean}/index.html`;
|
|
10
21
|
return `${clean}.html`;
|
|
11
22
|
}
|
|
@@ -19,16 +30,16 @@ function getRscOutputPath(urlPath, options = {
|
|
|
19
30
|
const cleanBasePath = options.basePath?.replace(/^\//, "");
|
|
20
31
|
return cleanBasePath ? `${cleanBasePath}/index.txt` : "index.txt";
|
|
21
32
|
}
|
|
22
|
-
const clean =
|
|
33
|
+
const clean = `${options.basePath ?? ""}${toOutputUrlPath(urlPath)}`.replace(/^\//, "").replace(/\/$/, "");
|
|
23
34
|
return options.trailingSlash ? `${clean}/index.txt` : `${clean}.txt`;
|
|
24
35
|
}
|
|
25
36
|
if (urlPath === "/") return "index.rsc";
|
|
26
|
-
return urlPath.replace(/^\//, "") + ".rsc";
|
|
37
|
+
return toOutputUrlPath(urlPath).replace(/^\//, "") + ".rsc";
|
|
27
38
|
}
|
|
28
39
|
/** Determine the binary artifact path for a prerendered App Route response. */
|
|
29
40
|
function getAppRouteOutputPath(urlPath) {
|
|
30
41
|
if (urlPath === "/") return "index.route";
|
|
31
|
-
return urlPath.replace(/^\//, "") + ".route";
|
|
42
|
+
return toOutputUrlPath(urlPath).replace(/^\//, "") + ".route";
|
|
32
43
|
}
|
|
33
44
|
//#endregion
|
|
34
45
|
export { getAppRouteOutputPath, getOutputPath, getRscOutputPath };
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
//#region src/utils/public-file-path.d.ts
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Key a public file by the normalized pathname a request for it matches with.
|
|
4
|
+
*
|
|
5
|
+
* Request pathnames are decoded once per segment with path delimiters kept
|
|
6
|
+
* encoded, so `public/a b.txt` is `/a b.txt` and `public/C#.txt` is
|
|
7
|
+
* `/C%23.txt`. Keying only this form keeps a double-encoded alias such as
|
|
8
|
+
* `/a%2520b.txt`, which middleware matchers see as `/a%20b.txt`, from
|
|
9
|
+
* reaching `public/a b.txt`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function publicFileRouteKey(pathname: string): string;
|
|
4
12
|
//#endregion
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
1
2
|
//#region src/utils/public-file-path.ts
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Key a public file by the normalized pathname a request for it matches with.
|
|
5
|
+
*
|
|
6
|
+
* Request pathnames are decoded once per segment with path delimiters kept
|
|
7
|
+
* encoded, so `public/a b.txt` is `/a b.txt` and `public/C#.txt` is
|
|
8
|
+
* `/C%23.txt`. Keying only this form keeps a double-encoded alias such as
|
|
9
|
+
* `/a%2520b.txt`, which middleware matchers see as `/a%20b.txt`, from
|
|
10
|
+
* reaching `public/a b.txt`.
|
|
11
|
+
*/
|
|
12
|
+
function publicFileRouteKey(pathname) {
|
|
13
|
+
return normalizePathnameForRouteMatch(pathname.split("/").map((segment) => encodeURIComponent(segment)).join("/"));
|
|
10
14
|
}
|
|
11
15
|
//#endregion
|
|
12
|
-
export {
|
|
16
|
+
export { publicFileRouteKey };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { publicFileRouteKey } from "./public-file-path.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
//#region src/utils/public-routes.ts
|
|
5
5
|
function scanPublicFileRoutes(root, configuredPublicDir = "public") {
|
|
@@ -37,7 +37,7 @@ function scanPublicFileRoutes(root, configuredPublicDir = "public") {
|
|
|
37
37
|
if (!stat.isFile()) continue;
|
|
38
38
|
} else if (!entry.isFile()) continue;
|
|
39
39
|
const relativePath = path.relative(publicDir, fullPath);
|
|
40
|
-
routes.push(
|
|
40
|
+
routes.push(publicFileRouteKey("/" + relativePath));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
if (fs.existsSync(publicDir)) try {
|
|
@@ -2,4 +2,7 @@
|
|
|
2
2
|
export declare function getReactUpgradeDeps(root: string, options?: {
|
|
3
3
|
fromManifest?: boolean;
|
|
4
4
|
}): string[];
|
|
5
|
+
export declare function isVersionBelow(version: string, minimum: [number, number, number]): boolean;
|
|
6
|
+
/** Walk up from a resolved module entry to find its package version. */
|
|
7
|
+
export declare function findPackageVersion(resolvedEntry: string, packageName: string): string | null;
|
|
5
8
|
//#endregion
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
//#region src/utils/regex-safety.d.ts
|
|
2
2
|
export type RegexSafetyIssue = "nested repetition" | "ambiguous alternatives under repetition" | "ambiguous sequence expansion" | "overlapping sequential repetition" | "analysis budget exceeded";
|
|
3
|
+
/**
|
|
4
|
+
* Whether a RegExp source declares a named group, which turns `\k<name>` into
|
|
5
|
+
* a backreference. Escaped characters and character classes cannot open one.
|
|
6
|
+
*/
|
|
7
|
+
export declare function mayHaveNamedGroups(pattern: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* `namedGroups` must describe the whole compiled RegExp when `pattern` is only
|
|
10
|
+
* a fragment of it. It defaults to scanning `pattern` itself.
|
|
11
|
+
*/
|
|
3
12
|
export declare function analyzeRegexSafety(pattern: string, options?: {
|
|
4
13
|
ignoreCase?: boolean;
|
|
14
|
+
namedGroups?: boolean;
|
|
5
15
|
}): RegexSafetyIssue | null;
|
|
6
16
|
export declare function regexAtomsMayOverlap(left: string, right: string, ignoreCase?: boolean): boolean;
|
|
7
17
|
//#endregion
|
|
@@ -88,13 +88,15 @@ function simpleClassSymbol(raw, ignoreCase) {
|
|
|
88
88
|
var RegexParser = class {
|
|
89
89
|
pattern;
|
|
90
90
|
ignoreCase;
|
|
91
|
+
namedGroups;
|
|
91
92
|
index = 0;
|
|
92
93
|
nodes = 0;
|
|
93
94
|
depth = 0;
|
|
94
95
|
exceededBudget = false;
|
|
95
|
-
constructor(pattern, ignoreCase) {
|
|
96
|
+
constructor(pattern, ignoreCase, namedGroups) {
|
|
96
97
|
this.pattern = pattern;
|
|
97
98
|
this.ignoreCase = ignoreCase;
|
|
99
|
+
this.namedGroups = namedGroups;
|
|
98
100
|
}
|
|
99
101
|
parse() {
|
|
100
102
|
return this.parseAlternation();
|
|
@@ -157,7 +159,7 @@ var RegexParser = class {
|
|
|
157
159
|
kind: "atom",
|
|
158
160
|
symbol: {
|
|
159
161
|
kind: "opaque",
|
|
160
|
-
key: "
|
|
162
|
+
key: "opaque:.",
|
|
161
163
|
pattern: ".",
|
|
162
164
|
ignoreCase: this.ignoreCase
|
|
163
165
|
},
|
|
@@ -240,7 +242,7 @@ var RegexParser = class {
|
|
|
240
242
|
kind: "atom",
|
|
241
243
|
symbol: simpleClassSymbol(raw, this.ignoreCase) ?? {
|
|
242
244
|
kind: "opaque",
|
|
243
|
-
key: raw
|
|
245
|
+
key: `opaque:${raw}`,
|
|
244
246
|
pattern: raw,
|
|
245
247
|
ignoreCase: this.ignoreCase
|
|
246
248
|
},
|
|
@@ -267,6 +269,15 @@ var RegexParser = class {
|
|
|
267
269
|
symbol: shorthand,
|
|
268
270
|
fixedWidth: true
|
|
269
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
|
+
}
|
|
270
281
|
if (/\d/.test(escaped)) return this.node({
|
|
271
282
|
kind: "atom",
|
|
272
283
|
symbol: null,
|
|
@@ -279,6 +290,15 @@ var RegexParser = class {
|
|
|
279
290
|
} else if (escaped === "u" && /^[\da-fA-F]{4}/.test(this.pattern.slice(this.index, this.index + 4))) {
|
|
280
291
|
literal = String.fromCharCode(Number.parseInt(this.pattern.slice(this.index, this.index + 4), 16));
|
|
281
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
|
+
}
|
|
282
302
|
} else if ("nrtvf0".includes(escaped)) literal = {
|
|
283
303
|
n: "\n",
|
|
284
304
|
r: "\r",
|
|
@@ -298,7 +318,7 @@ var RegexParser = class {
|
|
|
298
318
|
kind: "atom",
|
|
299
319
|
symbol: {
|
|
300
320
|
kind: "opaque",
|
|
301
|
-
key: raw
|
|
321
|
+
key: `opaque:${raw}`,
|
|
302
322
|
pattern: raw,
|
|
303
323
|
ignoreCase: this.ignoreCase
|
|
304
324
|
},
|
|
@@ -444,11 +464,12 @@ function fixedWords(node, budget) {
|
|
|
444
464
|
return words;
|
|
445
465
|
}
|
|
446
466
|
case "repeat": {
|
|
447
|
-
if (node.
|
|
467
|
+
if (!Number.isFinite(node.max) || node.min > node.max) return null;
|
|
448
468
|
let words = [[]];
|
|
449
469
|
const childWords = fixedWords(node.child, budget);
|
|
450
470
|
if (!childWords) return null;
|
|
451
|
-
|
|
471
|
+
const repeated = node.min === 0 ? [[]] : [];
|
|
472
|
+
for (let count = 1; count <= node.max; count++) {
|
|
452
473
|
const next = [];
|
|
453
474
|
for (const prefix of words) for (const suffix of childWords) {
|
|
454
475
|
if (++budget.words > MAX_WORDS) {
|
|
@@ -464,8 +485,9 @@ function fixedWords(node, budget) {
|
|
|
464
485
|
next.push(word);
|
|
465
486
|
}
|
|
466
487
|
words = next;
|
|
488
|
+
if (count >= node.min) repeated.push(...words);
|
|
467
489
|
}
|
|
468
|
-
return
|
|
490
|
+
return repeated;
|
|
469
491
|
}
|
|
470
492
|
}
|
|
471
493
|
}
|
|
@@ -508,17 +530,27 @@ function symbolsMayOverlap(left, right) {
|
|
|
508
530
|
if (left.kind === "literal" && right.kind === "opaque") return opaqueMatchesLiteral(right, left);
|
|
509
531
|
return true;
|
|
510
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
|
+
}
|
|
511
548
|
function insertPrefixFreeWord(root, word, comparisons) {
|
|
549
|
+
if (wordMayCollide(root, word, 0, comparisons, false)) return false;
|
|
512
550
|
let node = root;
|
|
513
551
|
for (const symbol of word) {
|
|
514
|
-
if (node.terminal) return false;
|
|
515
552
|
let edge = node.edges.get(symbol.key);
|
|
516
553
|
if (!edge) {
|
|
517
|
-
const candidates = symbol.kind === "literal" ? node.complexEdges : node.edges.values();
|
|
518
|
-
for (const candidate of candidates) {
|
|
519
|
-
if (++comparisons.count > MAX_OPAQUE_COMPARISONS) return false;
|
|
520
|
-
if (symbolsMayOverlap(candidate.symbol, symbol)) return false;
|
|
521
|
-
}
|
|
522
554
|
edge = {
|
|
523
555
|
symbol,
|
|
524
556
|
node: createTrieNode()
|
|
@@ -528,7 +560,6 @@ function insertPrefixFreeWord(root, word, comparisons) {
|
|
|
528
560
|
}
|
|
529
561
|
node = edge.node;
|
|
530
562
|
}
|
|
531
|
-
if (node.terminal || node.edges.size > 0) return false;
|
|
532
563
|
node.terminal = true;
|
|
533
564
|
return true;
|
|
534
565
|
}
|
|
@@ -578,6 +609,7 @@ function ambiguousExpansionFactor(node) {
|
|
|
578
609
|
case "repeat": {
|
|
579
610
|
if (node.min !== node.max || !Number.isFinite(node.max)) return 1;
|
|
580
611
|
const childFactor = ambiguousExpansionFactor(node.child);
|
|
612
|
+
if (childFactor === 1) return 1;
|
|
581
613
|
let factor = 1;
|
|
582
614
|
for (let count = 0; count < node.max; count++) {
|
|
583
615
|
factor *= childFactor;
|
|
@@ -705,16 +737,36 @@ function findSafetyIssue(node) {
|
|
|
705
737
|
}
|
|
706
738
|
}
|
|
707
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
|
+
*/
|
|
708
760
|
function analyzeRegexSafety(pattern, options = {}) {
|
|
709
761
|
if (pattern.length > MAX_PATTERN_LENGTH) return "analysis budget exceeded";
|
|
710
|
-
const parser = new RegexParser(pattern, options.ignoreCase === true);
|
|
762
|
+
const parser = new RegexParser(pattern, options.ignoreCase === true, options.namedGroups ?? mayHaveNamedGroups(pattern));
|
|
711
763
|
const node = parser.parse();
|
|
712
764
|
if (parser.exceededBudget) return "analysis budget exceeded";
|
|
713
765
|
return findSafetyIssue(node);
|
|
714
766
|
}
|
|
715
767
|
function regexAtomsMayOverlap(left, right, ignoreCase = false) {
|
|
716
|
-
const leftParser = new RegexParser(left, ignoreCase);
|
|
717
|
-
const rightParser = new RegexParser(right, ignoreCase);
|
|
768
|
+
const leftParser = new RegexParser(left, ignoreCase, true);
|
|
769
|
+
const rightParser = new RegexParser(right, ignoreCase, true);
|
|
718
770
|
const leftNode = leftParser.parse();
|
|
719
771
|
const rightNode = rightParser.parse();
|
|
720
772
|
const leftWords = fixedWords(leftNode, {
|
|
@@ -734,4 +786,4 @@ function regexAtomsMayOverlap(left, right, ignoreCase = false) {
|
|
|
734
786
|
return symbolsMayOverlap(leftSymbol, rightSymbol);
|
|
735
787
|
}
|
|
736
788
|
//#endregion
|
|
737
|
-
export { analyzeRegexSafety, regexAtomsMayOverlap };
|
|
789
|
+
export { analyzeRegexSafety, mayHaveNamedGroups, regexAtomsMayOverlap };
|