vinext 1.3.1 → 1.4.1
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 +25 -22
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +4 -3
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +4 -7
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay-store.d.ts +1 -0
- package/dist/client/dev-error-overlay.d.ts +2 -0
- package/dist/client/dev-error-overlay.js +20 -4
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +2 -0
- package/dist/config/destination-params.d.ts +2 -1
- package/dist/config/destination-params.js +52 -2
- package/dist/config/next-config.d.ts +25 -0
- package/dist/config/next-config.js +82 -4
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -49
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +36 -9
- package/dist/index.js +112 -90
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +21 -5
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +86 -66
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +7 -7
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +5 -4
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +4 -14
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +43 -4
- package/dist/server/app-page-boundary-render.js +10 -14
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -11
- package/dist/server/app-page-dispatch.js +84 -155
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +13 -12
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +102 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -13
- package/dist/server/app-page-render.js +103 -234
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +86 -63
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +12 -8
- package/dist/server/app-page-stream.js +4 -3
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +11 -5
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +1 -1
- package/dist/server/app-route-handler-runtime.js +28 -11
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +12 -12
- package/dist/server/app-rsc-cache-busting.js +31 -72
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +10 -2
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +11 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +80 -83
- package/dist/server/app-rsc-request-normalization.d.ts +10 -16
- package/dist/server/app-rsc-request-normalization.js +12 -18
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +9 -15
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +15 -8
- package/dist/server/app-ssr-entry.d.ts +8 -0
- package/dist/server/app-ssr-entry.js +22 -16
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +37 -6
- package/dist/server/app-worker-stages.js +81 -9
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/bfcache-identity.d.ts +7 -0
- package/dist/server/bfcache-identity.js +10 -1
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-manifest.js +1 -2
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-origin-check.d.ts +2 -1
- package/dist/server/dev-origin-check.js +2 -1
- package/dist/server/dev-server.js +6 -4
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/image-optimization.d.ts +5 -0
- package/dist/server/image-optimization.js +6 -1
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +30 -2
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/middleware-matcher.js +19 -6
- package/dist/server/middleware-runtime.js +6 -2
- package/dist/server/multi-stage.d.ts +57 -12
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.d.ts +1 -1
- package/dist/server/pages-node-compat.js +54 -27
- package/dist/server/pages-page-data.js +2 -1
- package/dist/server/pages-page-handler.js +28 -26
- package/dist/server/pages-page-response.d.ts +9 -0
- package/dist/server/pages-page-response.js +18 -4
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +36 -14
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/pages-router-entry.js +3 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +47 -9
- package/dist/server/request-error-log.d.ts +9 -0
- package/dist/server/request-error-log.js +13 -0
- package/dist/server/request-pipeline.d.ts +15 -4
- package/dist/server/request-pipeline.js +43 -15
- package/dist/server/rsc-completion-metadata.js +3 -0
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/static-file-cache.d.ts +9 -0
- package/dist/server/static-file-cache.js +13 -2
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +23 -26
- package/dist/shims/cache-request-state.js +22 -57
- package/dist/shims/cache-runtime.d.ts +3 -1
- package/dist/shims/cache-runtime.js +94 -48
- package/dist/shims/cache.d.ts +16 -10
- package/dist/shims/cache.js +47 -36
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-hook-error.d.ts +2 -0
- package/dist/shims/client-hook-error.js +16 -1
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +39 -25
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +10 -24
- package/dist/shims/headers.js +22 -70
- package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +8 -11
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +184 -31
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +3 -2
- package/dist/shims/slot.d.ts +16 -0
- package/dist/shims/slot.js +44 -9
- package/dist/shims/unified-request-context.d.ts +7 -1
- package/dist/shims/unified-request-context.js +3 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/cache-life-profiles.d.ts +33 -0
- package/dist/utils/cache-life-profiles.js +111 -0
- package/dist/utils/middleware-request-headers.d.ts +14 -3
- package/dist/utils/middleware-request-headers.js +54 -7
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { AppMiddlewareContext } from "./app-middleware.js";
|
|
2
2
|
import { MiddlewareResponseMergeOptions } from "./middleware-response-headers.js";
|
|
3
3
|
import { EdgeApiExecutionRuntime } from "./edge-api-runtime.js";
|
|
4
|
+
import { RuntimePagesDataKind } from "./pages-route-data-kind.js";
|
|
4
5
|
//#region src/server/app-pages-bridge.d.ts
|
|
5
6
|
export type PagesEntry = {
|
|
7
|
+
getRuntimePageDataKind?: (url: string, request: Request) => RuntimePagesDataKind;
|
|
6
8
|
handleApiRoute?: (request: Request, url: string, ctx: unknown, trustedRevalidateOrigin: string | undefined, edgeRuntime: EdgeApiExecutionRuntime, initialResponseHeaders?: Headers) => Promise<Response> | Response;
|
|
7
9
|
matchApiRoute?: (url: string, request: Request) => PagesRouteMatch | null;
|
|
8
10
|
matchPageRoute?: (url: string, request: Request) => PagesRouteMatch | null;
|
|
@@ -55,6 +57,8 @@ type RenderPagesFallbackOptions = {
|
|
|
55
57
|
pathname?: string;
|
|
56
58
|
pagesDataRequest?: Request | null;
|
|
57
59
|
request: Request;
|
|
60
|
+
/** The shared cache entry answers every host; a request-time render is not stored. */
|
|
61
|
+
sharedAcrossHosts?: boolean;
|
|
58
62
|
url: URL;
|
|
59
63
|
};
|
|
60
64
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
2
2
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
|
-
import { beginRouteCacheability } from "../shims/cacheability-classification.js";
|
|
3
|
+
import { beginRouteCacheability, markRouteCacheabilityDynamic } from "../shims/cacheability-classification.js";
|
|
4
4
|
import { mergeHeaders } from "./worker-utils.js";
|
|
5
5
|
import { pagesRouteHasPriorityOverAppRoute } from "./hybrid-route-priority.js";
|
|
6
6
|
//#region src/server/app-pages-bridge.ts
|
|
@@ -18,7 +18,7 @@ function applyPagesMiddlewareContext(response, middlewareContext) {
|
|
|
18
18
|
* Fallback handler to route App Router requests to the Pages Router when no App Router route matches.
|
|
19
19
|
*/
|
|
20
20
|
async function renderPagesFallback(options, dependencies) {
|
|
21
|
-
const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, url } = options;
|
|
21
|
+
const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, sharedAcrossHosts = false, url } = options;
|
|
22
22
|
const { loadPagesEntry, buildRequestHeaders, applyRouteHandlerMiddlewareContext, getDraftModeCookieHeader } = dependencies;
|
|
23
23
|
if (isRscRequest && !allowRscDocumentFallback) return null;
|
|
24
24
|
const pagesEntry = await loadPagesEntry();
|
|
@@ -61,7 +61,11 @@ async function renderPagesFallback(options, dependencies) {
|
|
|
61
61
|
if (pageMatch !== null && matchKind === "static" && pageMatch.route.isDynamic) return null;
|
|
62
62
|
if (pageMatch !== null && matchKind === "dynamic" && !pageMatch.route.isDynamic) return null;
|
|
63
63
|
if (appRouteMatch !== null && (pageMatch === null || !pagesRouteHasPriorityOverAppRoute(pageMatch.route, appRouteMatch.route))) return null;
|
|
64
|
-
if (pageMatch !== null)
|
|
64
|
+
if (pageMatch !== null) {
|
|
65
|
+
beginRouteCacheability("pages-page", pageMatch.route.pattern);
|
|
66
|
+
const runtimeDataKind = sharedAcrossHosts ? pagesEntry.getRuntimePageDataKind?.(pagesUrl, matchRequest) : void 0;
|
|
67
|
+
if (runtimeDataKind === "server" || runtimeDataKind === "initial") markRouteCacheabilityDynamic("getInitialProps render shares a cache entry across hosts");
|
|
68
|
+
}
|
|
65
69
|
const pagesRequest = claimPagesRequest();
|
|
66
70
|
const renderArgs = [
|
|
67
71
|
pagesDataRequest ? cloneRequestWithUrl(pagesRequest, pagesDataRequest.url) : pagesRequest,
|
|
@@ -17,16 +17,23 @@ export declare function isReactOwnedAppComponent(component: unknown): boolean;
|
|
|
17
17
|
* errors this call throws or rejects with.
|
|
18
18
|
*/
|
|
19
19
|
export declare function invokeAppComponent(component: ComponentType<Record<string, unknown>>, props: Readonly<Record<string, unknown>>, mapError?: (error: unknown) => unknown): ReactNode | Promise<ReactNode>;
|
|
20
|
+
/**
|
|
21
|
+
* Reports how a component's own render ended: `failure` holds what it threw
|
|
22
|
+
* or rejected with, after `mapError`. A suspension isn't an end, as React
|
|
23
|
+
* renders the component again.
|
|
24
|
+
*/
|
|
25
|
+
export type AppComponentSettledCallback = (failure?: {
|
|
26
|
+
error: unknown;
|
|
27
|
+
}) => void;
|
|
20
28
|
/**
|
|
21
29
|
* `invokeAppComponent()`, with every error the component throws or rejects
|
|
22
30
|
* with replaced by `mapError(error)`, including its CSS-wrapped inner one's.
|
|
31
|
+
* `onSettled` hears once how the component, or that inner one, ended.
|
|
23
32
|
*/
|
|
24
|
-
export declare function invokeAppComponentMappingErrors(component: ComponentType<Record<string, unknown>>, props: Readonly<Record<string, unknown>>, mapError: (error: unknown) => unknown): ReactNode | Promise<ReactNode>;
|
|
25
|
-
export declare function registerAppElementRenderDependencies(elements: Readonly<Record<string, unknown>>, dependenciesByElementId: ReadonlyMap<string, AppRenderDependency>): void;
|
|
26
|
-
export declare function releaseAppElementRenderDependency(elements: Readonly<Record<string, unknown>>, elementId: string): void;
|
|
33
|
+
export declare function invokeAppComponentMappingErrors(component: ComponentType<Record<string, unknown>>, props: Readonly<Record<string, unknown>>, mapError: (error: unknown) => unknown, onSettled?: AppComponentSettledCallback): ReactNode | Promise<ReactNode>;
|
|
27
34
|
export declare function createAppRenderDependency(): AppRenderDependency;
|
|
28
35
|
export declare function createAppPageRenderDependency(): AppPageRenderDependency;
|
|
29
36
|
export declare function isAppRenderSuspension(error: unknown): boolean;
|
|
30
37
|
export declare function renderAfterAppDependencies(children: ReactNode, dependencies: readonly AppRenderDependency[]): ReactNode;
|
|
31
|
-
export declare function renderAppComponentWithDependencyBarrier(component: ComponentType<Record<string, unknown>>, props: Readonly<Record<string, unknown>>, dependency: AppRenderDependency): ReactNode;
|
|
38
|
+
export declare function renderAppComponentWithDependencyBarrier(component: ComponentType<Record<string, unknown>>, props: Readonly<Record<string, unknown>>, dependency: AppRenderDependency, mapError?: (error: unknown) => unknown, onSettled?: AppComponentSettledCallback): ReactNode;
|
|
32
39
|
//#endregion
|
|
@@ -21,29 +21,74 @@ function isReactOwnedAppComponent(component) {
|
|
|
21
21
|
* errors this call throws or rejects with.
|
|
22
22
|
*/
|
|
23
23
|
function invokeAppComponent(component, props, mapError) {
|
|
24
|
+
return invokeAppComponentObserved(component, props, mapError, void 0);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Like `invokeAppComponent()`. `onSettled` hears of a value returned
|
|
28
|
+
* synchronously; the caller reports a promise result or a thrown error.
|
|
29
|
+
*/
|
|
30
|
+
function invokeAppComponentObserved(component, props, mapError, onSettled) {
|
|
24
31
|
const candidate = component;
|
|
25
|
-
if (candidate.$$typeof === REACT_MEMO && candidate.type) return
|
|
26
|
-
if (candidate.$$typeof === REACT_LAZY && candidate._init) return
|
|
27
|
-
if (candidate.$$typeof === REACT_FORWARD_REF && candidate.render)
|
|
28
|
-
|
|
32
|
+
if (candidate.$$typeof === REACT_MEMO && candidate.type) return invokeAppComponentObserved(candidate.type, props, mapError, onSettled);
|
|
33
|
+
if (candidate.$$typeof === REACT_LAZY && candidate._init) return invokeAppComponentObserved(candidate._init(candidate._payload), props, mapError, onSettled);
|
|
34
|
+
if (candidate.$$typeof === REACT_FORWARD_REF && candidate.render) {
|
|
35
|
+
const result = candidate.render(props, void 0);
|
|
36
|
+
if (!isPromiseLike(result)) onSettled?.();
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
if (isReactOwnedAppComponent(candidate)) {
|
|
40
|
+
onSettled?.();
|
|
41
|
+
return createElement(candidate, props);
|
|
42
|
+
}
|
|
29
43
|
const result = candidate(props);
|
|
30
|
-
return isPromiseLike(result) ? result : invokeCssWrappedComponent(result, props, mapError);
|
|
44
|
+
return isPromiseLike(result) ? result : invokeCssWrappedComponent(result, props, mapError, onSettled);
|
|
31
45
|
}
|
|
32
46
|
/**
|
|
33
47
|
* `invokeAppComponent()`, with every error the component throws or rejects
|
|
34
48
|
* with replaced by `mapError(error)`, including its CSS-wrapped inner one's.
|
|
49
|
+
* `onSettled` hears once how the component, or that inner one, ended.
|
|
35
50
|
*/
|
|
36
|
-
function invokeAppComponentMappingErrors(component, props, mapError) {
|
|
51
|
+
function invokeAppComponentMappingErrors(component, props, mapError, onSettled) {
|
|
52
|
+
const fail = (error) => {
|
|
53
|
+
if (isAppRenderSuspension(error)) return error;
|
|
54
|
+
const mapped = mapError(error);
|
|
55
|
+
onSettled?.({ error: mapped });
|
|
56
|
+
return mapped;
|
|
57
|
+
};
|
|
37
58
|
try {
|
|
38
|
-
const result =
|
|
39
|
-
return isPromiseLike(result) ?
|
|
40
|
-
throw mapError(error);
|
|
41
|
-
}) : result;
|
|
59
|
+
const result = invokeAppComponentObserved(component, props, mapError, onSettled);
|
|
60
|
+
return isPromiseLike(result) ? trackAppComponentResult(result, fail, onSettled) : result;
|
|
42
61
|
} catch (error) {
|
|
43
|
-
throw
|
|
62
|
+
throw fail(error);
|
|
44
63
|
}
|
|
45
64
|
}
|
|
46
65
|
/**
|
|
66
|
+
* Records how `result` settles on the promise itself, as React's thenables
|
|
67
|
+
* do, with `fail(error)` as a rejection's reason. Flight then reads that
|
|
68
|
+
* outcome rather than tracking the promise, so the result reaches it in the
|
|
69
|
+
* same tick as an unmapped one. A promise chained with `.then()` resolves a
|
|
70
|
+
* tick later, which costs a large page about a tenth more render work.
|
|
71
|
+
*/
|
|
72
|
+
function trackAppComponentResult(result, fail, onSettled) {
|
|
73
|
+
const thenable = result;
|
|
74
|
+
if (thenable.status !== void 0) return Promise.resolve(result).then((value) => {
|
|
75
|
+
onSettled?.();
|
|
76
|
+
return value;
|
|
77
|
+
}, (error) => {
|
|
78
|
+
throw fail(error);
|
|
79
|
+
});
|
|
80
|
+
thenable.status = "pending";
|
|
81
|
+
thenable.then((value) => {
|
|
82
|
+
thenable.status = "fulfilled";
|
|
83
|
+
thenable.value = value;
|
|
84
|
+
onSettled?.();
|
|
85
|
+
}, (error) => {
|
|
86
|
+
thenable.status = "rejected";
|
|
87
|
+
thenable.reason = fail(error);
|
|
88
|
+
});
|
|
89
|
+
return thenable;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
47
92
|
* Whether `elementProps` are what `createElement(type, props)` produces: the
|
|
48
93
|
* same values, plus any `type.defaultProps` for keys that are `undefined`.
|
|
49
94
|
* Defaulted values aren't read again, since a default can be a getter.
|
|
@@ -67,28 +112,33 @@ function isElementOfProps(elementProps, props, defaultProps) {
|
|
|
67
112
|
* component from an element without props instead, as for an export without
|
|
68
113
|
* CSS.
|
|
69
114
|
*/
|
|
70
|
-
function invokeCssWrappedComponent(result, props, mapError) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const component =
|
|
77
|
-
if (!isElementOfProps(inner.props, props, component.defaultProps)) return result;
|
|
78
|
-
const componentProps = inner.props;
|
|
115
|
+
function invokeCssWrappedComponent(result, props, mapError, onSettled) {
|
|
116
|
+
const wrapped = readCssWrappedComponent(result, props);
|
|
117
|
+
if (!wrapped) {
|
|
118
|
+
onSettled?.();
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
const { component, componentProps, css } = wrapped;
|
|
79
122
|
function CssWrappedComponent() {
|
|
80
|
-
return mapError ? invokeAppComponentMappingErrors(component, componentProps, mapError) : invokeAppComponent(component, componentProps);
|
|
123
|
+
return mapError ? invokeAppComponentMappingErrors(component, componentProps, mapError, onSettled) : invokeAppComponent(component, componentProps);
|
|
81
124
|
}
|
|
82
125
|
CssWrappedComponent.displayName = component.displayName ?? component.name;
|
|
83
126
|
return createElement(Fragment, null, css, createElement(CssWrappedComponent));
|
|
84
127
|
}
|
|
85
|
-
|
|
86
|
-
function
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
128
|
+
/** The parts of `result`, if it's a CSS-wrapped export's element for `props`. */
|
|
129
|
+
function readCssWrappedComponent(result, props) {
|
|
130
|
+
if (!isValidElement(result) || result.type !== Fragment || result.key !== null) return null;
|
|
131
|
+
const children = result.props.children;
|
|
132
|
+
if (!Array.isArray(children) || children.length !== 2) return null;
|
|
133
|
+
const [css, inner] = children;
|
|
134
|
+
if (!isValidElement(inner) || typeof inner.type !== "function" || inner.key !== null) return null;
|
|
135
|
+
const component = inner.type;
|
|
136
|
+
if (!isElementOfProps(inner.props, props, component.defaultProps)) return null;
|
|
137
|
+
return {
|
|
138
|
+
component,
|
|
139
|
+
componentProps: inner.props,
|
|
140
|
+
css
|
|
141
|
+
};
|
|
92
142
|
}
|
|
93
143
|
function createAppRenderDependency() {
|
|
94
144
|
let released = false;
|
|
@@ -130,17 +180,15 @@ function renderAfterAppDependencies(children, dependencies) {
|
|
|
130
180
|
}
|
|
131
181
|
return /* @__PURE__ */ jsx(AwaitAppRenderDependencies, {});
|
|
132
182
|
}
|
|
133
|
-
function renderAppComponentWithDependencyBarrier(component, props, dependency) {
|
|
183
|
+
function renderAppComponentWithDependencyBarrier(component, props, dependency, mapError, onSettled) {
|
|
134
184
|
function AppComponentDependencyBarrier() {
|
|
135
185
|
try {
|
|
136
|
-
const result = invokeAppComponent(component, props);
|
|
137
|
-
if (isPromiseLike(result))
|
|
138
|
-
dependency.release();
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
throw error;
|
|
143
|
-
});
|
|
186
|
+
const result = mapError ? invokeAppComponentMappingErrors(component, props, mapError, onSettled) : invokeAppComponent(component, props);
|
|
187
|
+
if (isPromiseLike(result)) {
|
|
188
|
+
const release = () => dependency.release();
|
|
189
|
+
result.then(release, release);
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
144
192
|
dependency.release();
|
|
145
193
|
return result;
|
|
146
194
|
} catch (error) {
|
|
@@ -151,4 +199,4 @@ function renderAppComponentWithDependencyBarrier(component, props, dependency) {
|
|
|
151
199
|
return createElement(AppComponentDependencyBarrier);
|
|
152
200
|
}
|
|
153
201
|
//#endregion
|
|
154
|
-
export { createAppPageRenderDependency, createAppRenderDependency, invokeAppComponent, invokeAppComponentMappingErrors, isAppClientReference, isAppRenderSuspension, isReactOwnedAppComponent,
|
|
202
|
+
export { createAppPageRenderDependency, createAppRenderDependency, invokeAppComponent, invokeAppComponentMappingErrors, isAppClientReference, isAppRenderSuspension, isReactOwnedAppComponent, renderAfterAppDependencies, renderAppComponentWithDependencyBarrier };
|
|
@@ -44,7 +44,7 @@ async function dispatchAppRequestStage(request, ctx, dispatchResponseStage, opti
|
|
|
44
44
|
headRequest,
|
|
45
45
|
middlewareCookieOverlay: null,
|
|
46
46
|
prerenderDiscovery: options.prerenderDiscovery,
|
|
47
|
-
protocolVersion:
|
|
47
|
+
protocolVersion: 13,
|
|
48
48
|
requestOrigin: new URL(request.url).origin,
|
|
49
49
|
scriptNonce: null,
|
|
50
50
|
staticFileSignalToken,
|
|
@@ -32,7 +32,7 @@ function handleRequestStage(request, env, ctx, dispatchResponseStage) {
|
|
|
32
32
|
callback: () => handleRequest(request, env, ctx, dispatchResponseStage, ctx?.assets).then((response) => applyCdnResponseIdentityHeaders(response, originalRequest)),
|
|
33
33
|
getStatus: (response) => response?.status,
|
|
34
34
|
headers: request.headers,
|
|
35
|
-
isRsc:
|
|
35
|
+
isRsc: request.headers.get("RSC") === "1",
|
|
36
36
|
method: request.method,
|
|
37
37
|
target: url.pathname + url.search
|
|
38
38
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isrCacheControl, resolveRouteExpireSeconds } from "./isr-cache.js";
|
|
2
|
-
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
3
2
|
import { applyRouteHandlerMiddlewareContext, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, buildRouteHandlerCachedResponse } from "./app-route-handler-response.js";
|
|
3
|
+
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
4
4
|
import { markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
|
|
5
5
|
import { resolveAppRouteHandlerSpecialError } from "./app-route-handler-policy.js";
|
|
6
6
|
import { completeAppRouteHandlerResponse, runAppRouteHandler, traceAppRouteHandlerExecution } from "./app-route-handler-execution.js";
|
|
@@ -57,7 +57,7 @@ async function readAppRouteHandlerCacheResponse(options) {
|
|
|
57
57
|
setHeadersAccessPhase: options.setHeadersAccessPhase
|
|
58
58
|
}) };
|
|
59
59
|
} catch (error) {
|
|
60
|
-
if (resolveAppRouteHandlerSpecialError(error
|
|
60
|
+
if (resolveAppRouteHandlerSpecialError(error)) return { specialError: error };
|
|
61
61
|
throw error;
|
|
62
62
|
}
|
|
63
63
|
});
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { closeAfterResponse, createRequestContext, getRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
|
-
import "../utils/protocol-headers.js";
|
|
2
|
+
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
3
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
4
|
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
5
5
|
import { reportRequestError } from "./instrumentation.js";
|
|
6
6
|
import { beginRouteCacheability, getRouteCacheabilityDynamicReason } from "../shims/cacheability-classification.js";
|
|
7
7
|
import { applyCdnResponseBuildIdentityHeaders } from "./cache-control.js";
|
|
8
8
|
import { isOnDemandRevalidateRequest } from "./revalidation-request.js";
|
|
9
|
+
import { coalesceOnDemandResponse } from "./isr-cache.js";
|
|
9
10
|
import { markDynamicUsage } from "../shims/internal/headers-state.js";
|
|
10
11
|
import { consumeDynamicUsage, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, isDraftModeRequest, setHeadersAccessPhase } from "../shims/headers.js";
|
|
11
12
|
import { _drainPendingRevalidations } from "../shims/cache-request-state.js";
|
|
12
13
|
import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
13
14
|
import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
|
|
14
|
-
import { setNavigationContext } from "../shims/navigation-context-state.js";
|
|
15
|
-
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
16
15
|
import { traceResponseStart } from "./response-start-tracing.js";
|
|
17
16
|
import { applyRouteHandlerMiddlewareContext, finalizeRouteHandlerResponse } from "./app-route-handler-response.js";
|
|
17
|
+
import { setNavigationContext } from "../shims/navigation-context-state.js";
|
|
18
18
|
import "../shims/navigation.js";
|
|
19
|
+
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
19
20
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
20
21
|
import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
|
|
21
22
|
import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, hasNonStaticAppRouteHandlerMethods, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
|
|
@@ -94,7 +95,8 @@ async function dispatchAppRouteHandlerImpl(options) {
|
|
|
94
95
|
headers: { Allow: allowHeaderForOptions }
|
|
95
96
|
}));
|
|
96
97
|
const resolvedHandlerFn = isAppRouteHandlerFunction(handlerFn) ? handlerFn : void 0;
|
|
97
|
-
const
|
|
98
|
+
const isOnDemandRevalidate = isOnDemandRevalidateRequest(options.request.headers.get(PRERENDER_REVALIDATE_HEADER));
|
|
99
|
+
const isStoredRoute = options.bypassSharedCache !== true && revalidateSeconds !== null && !getRouteCacheabilityDynamicReason() && shouldReadAppRouteHandlerCache({
|
|
98
100
|
dynamicConfig: handler.dynamic,
|
|
99
101
|
handlerFn: resolvedHandlerFn,
|
|
100
102
|
isAutoHead,
|
|
@@ -104,12 +106,13 @@ async function dispatchAppRouteHandlerImpl(options) {
|
|
|
104
106
|
method,
|
|
105
107
|
revalidateSeconds
|
|
106
108
|
});
|
|
107
|
-
const
|
|
109
|
+
const shouldReadRouteCache = isStoredRoute && !isOnDemandRevalidate;
|
|
110
|
+
const revalidateReason = isOnDemandRevalidate ? "on-demand" : shouldReadRouteCache && revalidateSeconds !== Infinity ? "stale" : void 0;
|
|
108
111
|
const fetchCacheMode = resolveAppRouteHandlerFetchCacheMode(handler);
|
|
109
112
|
setCurrentFetchCacheMode(fetchCacheMode);
|
|
110
113
|
setCurrentFetchRevalidate(configuredRevalidateSeconds);
|
|
111
114
|
setCurrentForceDynamicFetchDefault(handler.dynamic === "force-dynamic");
|
|
112
|
-
let isRevalidation =
|
|
115
|
+
let isRevalidation = isStoredRoute && isOnDemandRevalidate;
|
|
113
116
|
if (shouldReadRouteCache && resolvedHandlerFn) {
|
|
114
117
|
const cachedRouteResponse = await readAppRouteHandlerCacheResponse({
|
|
115
118
|
basePath: options.basePath,
|
|
@@ -167,7 +170,7 @@ async function dispatchAppRouteHandlerImpl(options) {
|
|
|
167
170
|
if (cachedRouteResponse) return applyCdnResponseBuildIdentityHeaders(cachedRouteResponse);
|
|
168
171
|
}
|
|
169
172
|
if (resolvedHandlerFn) {
|
|
170
|
-
const
|
|
173
|
+
const handlerOptions = {
|
|
171
174
|
isRevalidation,
|
|
172
175
|
basePath: options.basePath,
|
|
173
176
|
bypassSharedCache: options.bypassSharedCache,
|
|
@@ -210,8 +213,10 @@ async function dispatchAppRouteHandlerImpl(options) {
|
|
|
210
213
|
revalidateReason,
|
|
211
214
|
routePattern: route.pattern,
|
|
212
215
|
setHeadersAccessPhase
|
|
213
|
-
}
|
|
214
|
-
|
|
216
|
+
};
|
|
217
|
+
const runHandler = async () => applyCdnResponseBuildIdentityHeaders(await executeAppRouteHandler(handlerOptions));
|
|
218
|
+
if (isOnDemandRevalidate && isStoredRoute) return coalesceOnDemandResponse(`${method}:${options.isrRouteKey(options.cleanPathname)}`, method, runHandler);
|
|
219
|
+
return runHandler();
|
|
215
220
|
}
|
|
216
221
|
return finalizeFrameworkResponse(new Response(null, { status: 405 }));
|
|
217
222
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isFullyBufferedBody } from "./fully-buffered-response.js";
|
|
2
2
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
3
3
|
import { frameworkTracer } from "./tracer.js";
|
|
4
|
+
import { logRequestError } from "./request-error-log.js";
|
|
4
5
|
import { getRouteCacheabilityCaptureOptions, getRouteCacheabilityDynamicReason, isRouteCacheabilityEvaluation, markRouteCacheabilityExplicitResponsePolicy, markRouteCacheabilityResponseBodyComplete, recordRouteCacheability } from "../shims/cacheability-classification.js";
|
|
5
6
|
import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy, hasExplicitNonCacheableResponsePolicy } from "./cache-control.js";
|
|
6
7
|
import { buildAppRouteMissIsrCacheControl } from "./isr-decision.js";
|
|
@@ -117,7 +118,7 @@ async function runAppRouteHandler(options) {
|
|
|
117
118
|
onDynamicAccess() {
|
|
118
119
|
options.markDynamicUsage();
|
|
119
120
|
},
|
|
120
|
-
requestMode: options.dynamicConfig === "force-static" || options.dynamicConfig === "error" ? options.dynamicConfig : "auto",
|
|
121
|
+
requestMode: options.dynamicConfig === "force-dynamic" || options.dynamicConfig === "force-static" || options.dynamicConfig === "error" ? options.dynamicConfig : "auto",
|
|
121
122
|
signal: options.requestSignal,
|
|
122
123
|
staticGenerationErrorMessage(expression) {
|
|
123
124
|
return getAppRouteStaticGenerationErrorMessage(options.routePattern, expression);
|
|
@@ -167,7 +168,7 @@ async function executeAppRouteHandlerImpl(options) {
|
|
|
167
168
|
})
|
|
168
169
|
};
|
|
169
170
|
} catch (error) {
|
|
170
|
-
if (resolveAppRouteHandlerSpecialError(error,
|
|
171
|
+
if (resolveAppRouteHandlerSpecialError(error, { isAction: isPossibleAppRouteActionRequest(options.request) })) return {
|
|
171
172
|
kind: "special",
|
|
172
173
|
error
|
|
173
174
|
};
|
|
@@ -284,7 +285,8 @@ async function executeAppRouteHandlerImpl(options) {
|
|
|
284
285
|
console.error("[vinext] ISR route cache write error:", cacheErr);
|
|
285
286
|
}
|
|
286
287
|
})();
|
|
287
|
-
options.
|
|
288
|
+
if (options.revalidateReason === "on-demand") await routeWritePromise;
|
|
289
|
+
else options.executionContext?.waitUntil(routeWritePromise);
|
|
288
290
|
}
|
|
289
291
|
let finalized = applyDraftModeCachePolicy(applyRouteHandlerMiddlewareContext(finalizeRouteHandlerResponse(response, {
|
|
290
292
|
pendingCookies,
|
|
@@ -321,7 +323,11 @@ async function executeAppRouteHandlerImpl(options) {
|
|
|
321
323
|
const draftCookie = handlerDraftCookie ?? options.initialDraftModeCookie;
|
|
322
324
|
const shouldApplyDraftPolicy = (options.getActiveDraftModeState?.() ?? options.isDraftMode === true) || draftCookie != null;
|
|
323
325
|
if (handlerDraftCookie != null) markKnownDynamicAppRoute(options.routePattern);
|
|
324
|
-
const specialError = resolveAppRouteHandlerSpecialError(error,
|
|
326
|
+
const specialError = resolveAppRouteHandlerSpecialError(error, { isAction: isPossibleAppRouteActionRequest(options.request) });
|
|
327
|
+
if (specialError && options.consumeDynamicUsage()) recordRouteCacheability({
|
|
328
|
+
cacheable: false,
|
|
329
|
+
dynamicUsage: true
|
|
330
|
+
});
|
|
325
331
|
options.clearRequestContext();
|
|
326
332
|
if (specialError) {
|
|
327
333
|
if (specialError.kind === "redirect") return applyDraftModeCachePolicy(applyRouteHandlerMiddlewareContext(finalizeRouteHandlerResponse(new Response(null, {
|
|
@@ -334,7 +340,7 @@ async function executeAppRouteHandlerImpl(options) {
|
|
|
334
340
|
}), options.middlewareContext, middlewareMergeOptions), shouldApplyDraftPolicy);
|
|
335
341
|
return applyDraftModeCachePolicy(applyRouteHandlerMiddlewareContext(new Response(null, { status: specialError.statusCode }), options.middlewareContext, middlewareMergeOptions), shouldApplyDraftPolicy);
|
|
336
342
|
}
|
|
337
|
-
|
|
343
|
+
logRequestError("[vinext] Route handler error:", error);
|
|
338
344
|
await options.reportRequestError(error, {
|
|
339
345
|
path: options.cleanPathname,
|
|
340
346
|
method: options.request.method,
|
|
@@ -64,6 +64,6 @@ export declare function shouldApplyAppRouteHandlerRevalidateHeader(options: Omit
|
|
|
64
64
|
*/
|
|
65
65
|
export declare function shouldCompleteAppRouteHandlerResponse(options: AppRouteHandlerResponseCacheOptions): boolean;
|
|
66
66
|
export declare function shouldWriteAppRouteHandlerCache(options: AppRouteHandlerResponseCacheOptions): boolean;
|
|
67
|
-
export declare function resolveAppRouteHandlerSpecialError(error: unknown,
|
|
67
|
+
export declare function resolveAppRouteHandlerSpecialError(error: unknown, options?: AppRouteHandlerSpecialErrorOptions): AppRouteHandlerSpecialError | null;
|
|
68
68
|
//#endregion
|
|
69
69
|
export { isPossibleAppRouteActionRequest };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
2
1
|
import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
|
|
2
|
+
import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
3
3
|
import { buildRouteHandlerAllowHeader, collectRouteHandlerMethods } from "./app-route-handler-runtime.js";
|
|
4
4
|
//#region src/server/app-route-handler-policy.ts
|
|
5
5
|
function getAppRouteHandlerRevalidateSeconds(handler) {
|
|
@@ -53,13 +53,13 @@ function shouldCompleteAppRouteHandlerResponse(options) {
|
|
|
53
53
|
function shouldWriteAppRouteHandlerCache(options) {
|
|
54
54
|
return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && !options.dynamicUsedInHandler && (options.method === "GET" || options.isAutoHead);
|
|
55
55
|
}
|
|
56
|
-
function resolveAppRouteHandlerSpecialError(error,
|
|
56
|
+
function resolveAppRouteHandlerSpecialError(error, options) {
|
|
57
57
|
if (!(error && typeof error === "object" && "digest" in error)) return null;
|
|
58
58
|
const digest = String(error.digest);
|
|
59
59
|
const redirect = parseNextRedirectDigest(digest);
|
|
60
60
|
if (redirect) return {
|
|
61
61
|
kind: "redirect",
|
|
62
|
-
location:
|
|
62
|
+
location: redirect.url,
|
|
63
63
|
statusCode: options?.isAction ? 303 : redirect.status
|
|
64
64
|
};
|
|
65
65
|
const httpError = parseNextHttpErrorDigest(digest);
|
|
@@ -5,8 +5,8 @@ import { markRouteCacheabilityExplicitResponsePolicy, recordRouteCacheability }
|
|
|
5
5
|
import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
6
6
|
import { buildAppRouteMissIsrCacheControl, decideIsr } from "./isr-decision.js";
|
|
7
7
|
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
8
|
-
import { mergeMiddlewareResponseHeadersOntoResponse } from "./middleware-response-headers.js";
|
|
9
8
|
import { markEdgeRouteHandlerLinkHeaders } from "./app-response-header-provenance.js";
|
|
9
|
+
import { mergeMiddlewareResponseHeadersOntoResponse } from "./middleware-response-headers.js";
|
|
10
10
|
import { getSetCookieName } from "./cookie-utils.js";
|
|
11
11
|
//#region src/server/app-route-handler-response.ts
|
|
12
12
|
const APP_ROUTE_REWRITE_ERROR = "NextResponse.rewrite() was used in a app route handler, this is not currently supported. Please remove the invocation to continue.";
|
|
@@ -21,7 +21,7 @@ type NextUrlDynamicAccess = "nextUrl.search" | "nextUrl.searchParams" | "nextUrl
|
|
|
21
21
|
type HostDerivedNextUrlDynamicAccess = "nextUrl.protocol" | "nextUrl.username" | "nextUrl.password" | "nextUrl.host" | "nextUrl.hostname" | "nextUrl.port" | DomainLocaleNextUrlDynamicAccess;
|
|
22
22
|
type DomainLocaleNextUrlDynamicAccess = "nextUrl.locale" | "nextUrl.defaultLocale" | "nextUrl.domainLocale";
|
|
23
23
|
type AppRouteDynamicRequestAccess = RequestDynamicAccess | NextUrlDynamicAccess;
|
|
24
|
-
type AppRouteRequestMode = "auto" | "force-static" | "error";
|
|
24
|
+
type AppRouteRequestMode = "auto" | "force-dynamic" | "force-static" | "error";
|
|
25
25
|
type TrackedAppRouteRequestOptions = {
|
|
26
26
|
basePath?: string;
|
|
27
27
|
i18n?: NextI18nConfig | null;
|
|
@@ -2,6 +2,7 @@ import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-r
|
|
|
2
2
|
import { addBasePathToPathname } from "../utils/base-path.js";
|
|
3
3
|
import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
4
4
|
import { NextRequest, RequestCookies, sealRequestCookies, sealRequestHeaders } from "../shims/server.js";
|
|
5
|
+
import { throwIfInsideCacheScope } from "../shims/internal/headers-state.js";
|
|
5
6
|
import { BUILT_IN_REQUEST_PROPERTIES } from "./app-route-request-built-ins.js";
|
|
6
7
|
//#region src/server/app-route-handler-runtime.ts
|
|
7
8
|
const BUILT_IN_REQUEST_PROPERTY_MAP = new Map(BUILT_IN_REQUEST_PROPERTIES.map((property) => [property.key, property]));
|
|
@@ -76,8 +77,14 @@ function buildNextConfig(options) {
|
|
|
76
77
|
* Undici's Request follows its input's signal through a WeakRef, and so does
|
|
77
78
|
* every clone between the host signal and the handler's request. A handler
|
|
78
79
|
* that only listens on `request.signal` (e.g. to stop a stream) would miss the
|
|
79
|
-
* abort once GC collects any of them, so the request
|
|
80
|
-
*
|
|
80
|
+
* abort once GC collects any of them, so the request stays reachable for as
|
|
81
|
+
* long as the host signal is.
|
|
82
|
+
*
|
|
83
|
+
* The request must not follow the host signal itself, though. Undici registers
|
|
84
|
+
* every Request in a FinalizationRegistry whose held value strongly references
|
|
85
|
+
* the followed signal, so the registry would keep the host signal (the WeakMap
|
|
86
|
+
* key) and therefore the request alive forever. It follows a relay instead,
|
|
87
|
+
* which the host signal aborts through a strong listener.
|
|
81
88
|
*/
|
|
82
89
|
const requestsByHostSignal = /* @__PURE__ */ new WeakMap();
|
|
83
90
|
function retainWhileSignalLives(signal, request) {
|
|
@@ -85,6 +92,12 @@ function retainWhileSignalLives(signal, request) {
|
|
|
85
92
|
if (requests) requests.push(request);
|
|
86
93
|
else requestsByHostSignal.set(signal, [request]);
|
|
87
94
|
}
|
|
95
|
+
function followHostSignal(signal) {
|
|
96
|
+
const relay = new AbortController();
|
|
97
|
+
if (signal.aborted) relay.abort(signal.reason);
|
|
98
|
+
else signal.addEventListener("abort", () => relay.abort(signal.reason), { once: true });
|
|
99
|
+
return relay.signal;
|
|
100
|
+
}
|
|
88
101
|
function createForceStaticNextRequest(input, nextConfig, signal) {
|
|
89
102
|
const read = (key) => {
|
|
90
103
|
const descriptor = BUILT_IN_REQUEST_PROPERTY_MAP.get(key)?.descriptor;
|
|
@@ -138,7 +151,8 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
138
151
|
let didAccessDynamicRequest = false;
|
|
139
152
|
const requestMode = options.requestMode ?? "auto";
|
|
140
153
|
const nextConfig = buildNextConfig(options);
|
|
141
|
-
const markDynamicAccess = (access) => {
|
|
154
|
+
const markDynamicAccess = (access, trackedByNext) => {
|
|
155
|
+
if (trackedByNext && requestMode !== "force-dynamic") throwIfInsideCacheScope(access);
|
|
142
156
|
didAccessDynamicRequest = true;
|
|
143
157
|
options.onDynamicAccess?.(access);
|
|
144
158
|
};
|
|
@@ -172,7 +186,7 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
172
186
|
const wrapNextUrl = (nextUrl) => {
|
|
173
187
|
return new Proxy(nextUrl, { get(target, prop) {
|
|
174
188
|
if (isNextDynamicNextUrlProperty(prop) || isHostDerivedNextUrlProperty(prop)) {
|
|
175
|
-
markDynamicAccess(`nextUrl.${String(prop)}
|
|
189
|
+
markDynamicAccess(`nextUrl.${String(prop)}`, isNextDynamicNextUrlProperty(prop));
|
|
176
190
|
return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
177
191
|
}
|
|
178
192
|
if (prop === "clone") return () => wrapNextUrl(target.clone());
|
|
@@ -228,9 +242,10 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
228
242
|
const sourceCfDescriptor = Reflect.getOwnPropertyDescriptor(requestWithOverrides, "cf");
|
|
229
243
|
const sourceCfAccessor = sourceCfDescriptor?.get;
|
|
230
244
|
const sourceCfMetadata = sourceCfAccessor ? void 0 : Reflect.get(requestWithOverrides, "cf", requestWithOverrides);
|
|
231
|
-
const
|
|
245
|
+
const signal = options.signal ? followHostSignal(options.signal) : void 0;
|
|
246
|
+
const nextRequest = requestMode === "force-static" ? createForceStaticNextRequest(requestWithOverrides, nextConfig, signal) : requestWithOverrides instanceof NextRequest && sourceCfDescriptor?.configurable !== false && !signal ? requestWithOverrides : new NextRequest(requestWithOverrides, {
|
|
232
247
|
nextConfig: nextConfig ?? void 0,
|
|
233
|
-
signal
|
|
248
|
+
signal
|
|
234
249
|
});
|
|
235
250
|
if (options.signal) retainWhileSignalLives(options.signal, nextRequest);
|
|
236
251
|
const rawCfMetadata = sourceCfAccessor ? void 0 : sourceCfMetadata === void 0 ? Reflect.get(nextRequest, "cf", nextRequest) : sourceCfMetadata;
|
|
@@ -239,7 +254,7 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
239
254
|
const accessCf = (read, forceStaticValue) => {
|
|
240
255
|
if (requestMode === "force-static") return forceStaticValue;
|
|
241
256
|
if (requestMode === "error") return throwStaticGenerationError("request.cf");
|
|
242
|
-
markDynamicAccess("request.cf");
|
|
257
|
+
markDynamicAccess("request.cf", false);
|
|
243
258
|
return read();
|
|
244
259
|
};
|
|
245
260
|
const controlledCfGetter = () => accessCf(sourceCfAccessor ? () => Reflect.apply(sourceCfAccessor, requestWithOverrides, []) : () => rawCfMetadata, void 0);
|
|
@@ -341,17 +356,19 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
341
356
|
return proxiedNextUrl;
|
|
342
357
|
case "headers":
|
|
343
358
|
case "cookies":
|
|
344
|
-
case "ip":
|
|
345
|
-
case "geo":
|
|
346
359
|
case "url":
|
|
347
360
|
case "body":
|
|
348
361
|
case "blob":
|
|
349
|
-
case "bytes":
|
|
350
362
|
case "json":
|
|
351
363
|
case "text":
|
|
352
364
|
case "arrayBuffer":
|
|
353
365
|
case "formData":
|
|
354
|
-
markDynamicAccess(`request.${String(prop)}
|
|
366
|
+
markDynamicAccess(`request.${String(prop)}`, true);
|
|
367
|
+
return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
368
|
+
case "ip":
|
|
369
|
+
case "geo":
|
|
370
|
+
case "bytes":
|
|
371
|
+
markDynamicAccess(`request.${String(prop)}`, false);
|
|
355
372
|
return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
356
373
|
case "clone": return cloneTrackedRequest;
|
|
357
374
|
default: return getTrackedRequestProperty(target, prop, receiver);
|
|
@@ -37,7 +37,7 @@ var app_router_entry_default = {
|
|
|
37
37
|
callback: async () => applyCdnResponseIdentityHeaders(await handleRequest(request, env, ctx), request),
|
|
38
38
|
getStatus: (response) => response?.status,
|
|
39
39
|
headers: request.headers,
|
|
40
|
-
isRsc:
|
|
40
|
+
isRsc: request.headers.get("RSC") === "1",
|
|
41
41
|
method: request.method,
|
|
42
42
|
target: url.pathname + url.search
|
|
43
43
|
});
|