vinext 1.3.1 → 1.4.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 +5 -2
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +1 -1
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay.js +1 -1
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/next-config.d.ts +19 -0
- package/dist/config/next-config.js +64 -1
- 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 -48
- 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 +33 -8
- package/dist/index.js +83 -70
- 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/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 +19 -4
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +79 -63
- 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 +4 -4
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +4 -3
- 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 +2 -12
- 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 +42 -2
- package/dist/server/app-page-boundary-render.js +7 -6
- 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 -10
- package/dist/server/app-page-dispatch.js +84 -154
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +10 -9
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +99 -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 -12
- package/dist/server/app-page-render.js +89 -220
- 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 +67 -61
- 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 +2 -0
- package/dist/server/app-page-stream.js +2 -2
- 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-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +8 -3
- 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.js +17 -4
- package/dist/server/app-rsc-cache-busting.d.ts +2 -2
- package/dist/server/app-rsc-cache-busting.js +4 -4
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +9 -1
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +8 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +30 -24
- package/dist/server/app-rsc-request-normalization.d.ts +0 -4
- package/dist/server/app-rsc-request-normalization.js +1 -4
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +7 -4
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +9 -8
- 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 +25 -3
- package/dist/server/app-worker-stages.js +45 -6
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-server.js +4 -3
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +26 -1
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/multi-stage.d.ts +52 -11
- 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.js +52 -27
- package/dist/server/pages-page-handler.js +11 -20
- 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 +14 -12
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/prod-server.js +5 -1
- package/dist/server/request-pipeline.d.ts +6 -0
- package/dist/server/request-pipeline.js +21 -1
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- 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 +17 -20
- package/dist/shims/cache-request-state.js +16 -21
- package/dist/shims/cache-runtime.js +27 -11
- package/dist/shims/cache.d.ts +8 -7
- package/dist/shims/cache.js +17 -19
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- 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 +34 -24
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +8 -23
- package/dist/shims/headers.js +17 -67
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +3 -1
- 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 +183 -29
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/slot.d.ts +12 -0
- package/dist/shims/slot.js +37 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- 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
|
@@ -3,9 +3,7 @@ import { AppElements, AppElementsInterception, AppElementsSlotBinding } from "./
|
|
|
3
3
|
import "./app-elements.js";
|
|
4
4
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
5
5
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
6
|
-
import { ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
7
6
|
import { Metadata, Viewport } from "../shims/metadata.js";
|
|
8
|
-
import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
9
7
|
import { AppPageRenderDependency } from "./app-render-dependency.js";
|
|
10
8
|
import { AppPageSemanticSegment, resolveAppPageChildSegments } from "./app-page-segment-state.js";
|
|
11
9
|
import { AppPageRenderIdentity } from "./app-page-render-identity.js";
|
|
@@ -172,7 +170,6 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
172
170
|
*/
|
|
173
171
|
renderElementWithMetadataOutlet?: ((metadataOutlet: ReactNode) => ReactNode) | null;
|
|
174
172
|
globalErrorModule?: TErrorModule | null;
|
|
175
|
-
layoutParamAccess?: AppLayoutParamAccessTracker;
|
|
176
173
|
makeThenableParams: MakeThenableParams;
|
|
177
174
|
matchedParams: AppPageParams;
|
|
178
175
|
metadataPlacement?: "body" | "head";
|
|
@@ -211,7 +208,7 @@ export type AppPageRouteHead = {
|
|
|
211
208
|
/** `null` when resolution failed: like Next.js, the head then has no viewport tags. */
|
|
212
209
|
viewport: Promise<Viewport | null>;
|
|
213
210
|
};
|
|
214
|
-
type MakeThenableParams = (params: AppPageParams
|
|
211
|
+
type MakeThenableParams = (params: AppPageParams) => unknown;
|
|
215
212
|
type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {
|
|
216
213
|
interception?: AppElementsInterception | null;
|
|
217
214
|
interceptionId?: string | null;
|
|
@@ -226,6 +223,13 @@ type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule,
|
|
|
226
223
|
* still store the route tree, as a CDN would store Next.js's.
|
|
227
224
|
*/
|
|
228
225
|
isUncacheableRender?: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Hashed segment identities of the layouts the navigating client holds (see
|
|
228
|
+
* app-mounted-layouts.ts). A render that can never be stored leaves out the
|
|
229
|
+
* outermost layouts it names, as Next.js renders only below where a
|
|
230
|
+
* navigation diverges from the client's router state.
|
|
231
|
+
*/
|
|
232
|
+
mountedLayouts?: ReadonlySet<string> | null;
|
|
229
233
|
mountedSlotIds?: ReadonlySet<string> | null;
|
|
230
234
|
renderIdentity?: AppPageRenderIdentity;
|
|
231
235
|
renderMode?: AppRscRenderMode;
|
|
@@ -246,9 +250,12 @@ export type AppPageTemplateEntry<TModule extends AppPageModule = AppPageModule>
|
|
|
246
250
|
treePosition: number;
|
|
247
251
|
};
|
|
248
252
|
export declare function createAppPageTreePath(routeSegments: readonly string[] | null | undefined, treePosition: number): string;
|
|
249
|
-
|
|
253
|
+
/**
|
|
254
|
+
* Renders the layout at `layoutIndex` with a placeholder for its children, so
|
|
255
|
+
* whatever it or a component it renders throws comes out.
|
|
256
|
+
*/
|
|
257
|
+
export declare function probeAppPageLayout<TModule extends AppPageModule>(options: {
|
|
250
258
|
layoutIndex: number;
|
|
251
|
-
layoutParamAccess: AppLayoutParamAccessTracker | undefined;
|
|
252
259
|
makeThenableParams: MakeThenableParams;
|
|
253
260
|
matchedParams: AppPageParams;
|
|
254
261
|
route: Pick<AppPageRouteWiringRoute<TModule>, "layoutTreePositions" | "layouts" | "routeSegments">;
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { APP_RSC_RENDER_MODE_PREFETCH_EMPTY, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
|
|
2
2
|
import { fnv1a64 } from "../utils/hash.js";
|
|
3
3
|
import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
|
|
4
|
-
import {
|
|
5
|
-
import { APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
4
|
+
import { APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
6
5
|
import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_STREAMING_METADATA_BODY_ID_PREFIX } from "./app-elements.js";
|
|
6
|
+
import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
|
|
7
|
+
import { hashMountedLayoutIdentity } from "./app-mounted-layouts.js";
|
|
8
|
+
import { BfcacheChildrenBoundary, BfcacheSegmentBoundary, Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
|
|
9
|
+
import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPageChildSegments, resolveAppPageSegmentStateKey, resolveAppPageTemplateStateKey } from "./app-page-segment-state.js";
|
|
7
10
|
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
8
11
|
import { ErrorBoundary, ForbiddenBoundary, GlobalErrorBoundary, HttpAccessFallbackPassthrough, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
|
|
9
|
-
import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
|
|
10
|
-
import DefaultForbidden from "../shims/default-forbidden.js";
|
|
11
|
-
import DefaultNotFound from "../shims/default-not-found.js";
|
|
12
|
-
import DefaultUnauthorized from "../shims/default-unauthorized.js";
|
|
13
12
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
14
13
|
import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
|
|
15
14
|
import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
|
|
16
|
-
import {
|
|
15
|
+
import { APP_PAGE_NOT_FOUND_BOUNDARY_ID, tagAppPageLayoutError, tagAppPageSlotError } from "./app-page-execution.js";
|
|
16
|
+
import { resolveAppPageBranchParams, resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
17
|
+
import DefaultForbidden from "../shims/default-forbidden.js";
|
|
18
|
+
import DefaultNotFound from "../shims/default-not-found.js";
|
|
19
|
+
import DefaultUnauthorized from "../shims/default-unauthorized.js";
|
|
17
20
|
import { StreamedIconsInsertion } from "../shims/streamed-icons.js";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
21
|
+
import { createAppRenderDependency, invokeAppComponentMappingErrors, isReactOwnedAppComponent, renderAfterAppDependencies, renderAppComponentWithDependencyBarrier } from "./app-render-dependency.js";
|
|
22
|
+
import { createAppPageLayoutGate, registerAppPageLayoutGate } from "./app-page-layout-gate.js";
|
|
20
23
|
import { probeReactServerSubtree } from "./app-page-probe.js";
|
|
21
|
-
import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPageChildSegments, resolveAppPageSegmentStateKey, resolveAppPageTemplateStateKey } from "./app-page-segment-state.js";
|
|
22
24
|
import { createAppPageSegmentPlan } from "./app-page-segment-plan.js";
|
|
23
25
|
import { resolveAppPageModuleTraceSegment, traceGetLayoutOrPageModule } from "./app-page-tracing.js";
|
|
24
26
|
import { Fragment, Suspense } from "react";
|
|
@@ -44,6 +46,21 @@ function createSlotLayoutElement(LayoutComponent, props, slotLayoutIndex, notFou
|
|
|
44
46
|
const SlotLayoutInvoker = () => invokeAppComponentMappingErrors(LayoutComponent, props, (error) => tagAppPageSlotError(error, slotLayoutIndex, notFoundBoundary));
|
|
45
47
|
return /* @__PURE__ */ jsx(SlotLayoutInvoker, {});
|
|
46
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* A route layout, whose notFound(), forbidden() and unauthorized() are caught
|
|
51
|
+
* above it: its own boundaries wrap only its `children`. The layout's index
|
|
52
|
+
* tags what it throws, so the response's fallback finds that boundary from the
|
|
53
|
+
* render. `onSettled` hears how the layout rendered.
|
|
54
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-component-tree.tsx
|
|
55
|
+
*/
|
|
56
|
+
function createRouteLayoutElement(LayoutComponent, props, layoutIndex, dependency, onSettled) {
|
|
57
|
+
const mapError = (error) => tagAppPageLayoutError(error, layoutIndex);
|
|
58
|
+
if (dependency) return renderAppComponentWithDependencyBarrier(LayoutComponent, props, dependency, mapError, onSettled);
|
|
59
|
+
if (isReactOwnedAppComponent(LayoutComponent)) return /* @__PURE__ */ jsx(LayoutComponent, { ...props });
|
|
60
|
+
const RouteLayoutInvoker = () => invokeAppComponentMappingErrors(LayoutComponent, props, mapError, onSettled);
|
|
61
|
+
RouteLayoutInvoker.displayName = LayoutComponent.displayName ?? LayoutComponent.name;
|
|
62
|
+
return /* @__PURE__ */ jsx(RouteLayoutInvoker, {});
|
|
63
|
+
}
|
|
47
64
|
function getDefaultExport(module) {
|
|
48
65
|
return module?.default ?? null;
|
|
49
66
|
}
|
|
@@ -55,37 +72,19 @@ function createAppPageTreePath(routeSegments, treePosition) {
|
|
|
55
72
|
if (treePathSegments.length === 0) return "/";
|
|
56
73
|
return `/${treePathSegments.join("/")}`;
|
|
57
74
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
function
|
|
63
|
-
options.layoutParamAccess?.recordLayoutParamScope(options.layoutId, resolveAppPageSegmentParamScopeKeys(options.routeSegments, options.treePosition));
|
|
64
|
-
const revalidateSeconds = readFiniteRevalidateSeconds(options.layoutModule);
|
|
65
|
-
if (revalidateSeconds !== null) options.layoutParamAccess?.recordLayoutFiniteRevalidate(options.layoutId, revalidateSeconds);
|
|
66
|
-
}
|
|
67
|
-
function probeAppPageLayoutWithTracking(options) {
|
|
75
|
+
/**
|
|
76
|
+
* Renders the layout at `layoutIndex` with a placeholder for its children, so
|
|
77
|
+
* whatever it or a component it renders throws comes out.
|
|
78
|
+
*/
|
|
79
|
+
function probeAppPageLayout(options) {
|
|
68
80
|
const treePosition = options.route.layoutTreePositions?.[options.layoutIndex] ?? 0;
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
layoutId,
|
|
77
|
-
layoutModule,
|
|
78
|
-
layoutParamAccess: options.layoutParamAccess,
|
|
79
|
-
routeSegments: options.route.routeSegments,
|
|
80
|
-
treePosition
|
|
81
|
-
});
|
|
82
|
-
const layoutParams = resolveAppPageSegmentParams(options.route.routeSegments, treePosition, options.matchedParams);
|
|
83
|
-
return probeReactServerSubtree(/* @__PURE__ */ jsx(LayoutComponent, {
|
|
84
|
-
...withUseCacheLayoutMarker(LayoutComponent, { params: options.makeThenableParams(layoutParams, options.layoutParamAccess?.createThenableParamsObserver(layoutId)) }),
|
|
85
|
-
children: APP_PAGE_LAYOUT_PROBE_CHILD
|
|
86
|
-
}));
|
|
87
|
-
};
|
|
88
|
-
return options.layoutParamAccess ? options.layoutParamAccess.runLayoutProbe(layoutId, probe) : probe();
|
|
81
|
+
const LayoutComponent = getDefaultExport(options.route.layouts[options.layoutIndex]);
|
|
82
|
+
if (!LayoutComponent) return null;
|
|
83
|
+
const layoutParams = resolveAppPageSegmentParams(options.route.routeSegments, treePosition, options.matchedParams);
|
|
84
|
+
return probeReactServerSubtree(/* @__PURE__ */ jsx(LayoutComponent, {
|
|
85
|
+
...withUseCacheLayoutMarker(LayoutComponent, { params: options.makeThenableParams(layoutParams) }),
|
|
86
|
+
children: APP_PAGE_LAYOUT_PROBE_CHILD
|
|
87
|
+
}));
|
|
89
88
|
}
|
|
90
89
|
function createAppPageLayoutEntries(route) {
|
|
91
90
|
return route.layouts.map((layoutModule, index) => {
|
|
@@ -426,8 +425,8 @@ function buildAppPageElements(options) {
|
|
|
426
425
|
const notFoundBoundaries = resolveAccessBoundaries(options.route.segmentNotFounds, options.route.segmentNotFoundTreePositions, (entry) => entry.notFoundModule, rootNotFoundModule ? null : DEFAULT_NOT_FOUND_COMPONENT);
|
|
427
426
|
const forbiddenBoundaries = resolveAccessBoundaries(options.route.segmentForbiddens, options.route.segmentForbiddenTreePositions, (entry) => entry.forbiddenModule, rootForbiddenModule ? null : DEFAULT_FORBIDDEN_COMPONENT);
|
|
428
427
|
const unauthorizedBoundaries = resolveAccessBoundaries(options.route.segmentUnauthorizeds, options.route.segmentUnauthorizedTreePositions, (entry) => entry.unauthorizedModule, rootUnauthorizedModule ? null : DEFAULT_UNAUTHORIZED_COMPONENT);
|
|
428
|
+
const layoutGate = createAppPageLayoutGate();
|
|
429
429
|
const layoutDependenciesByIndex = /* @__PURE__ */ new Map();
|
|
430
|
-
const renderDependenciesByElementId = /* @__PURE__ */ new Map();
|
|
431
430
|
const layoutDependenciesBefore = [];
|
|
432
431
|
const slotDependenciesByLayoutIndex = [];
|
|
433
432
|
const templateDependenciesById = /* @__PURE__ */ new Map();
|
|
@@ -488,6 +487,13 @@ function buildAppPageElements(options) {
|
|
|
488
487
|
templateEntries
|
|
489
488
|
});
|
|
490
489
|
const routeResetKey = segmentPlan.routeResetKey;
|
|
490
|
+
const skippedLayoutIds = /* @__PURE__ */ new Set();
|
|
491
|
+
if (options.mountedLayouts && options.isRscRequest === true && options.isUncacheableRender === true && renderMode === "navigation" && interception === null) for (const layoutEntry of layoutEntries) {
|
|
492
|
+
const identity = segmentPlan.bfcacheSegmentIdentities[layoutEntry.id];
|
|
493
|
+
if (identity === void 0) break;
|
|
494
|
+
if (!options.mountedLayouts.has(hashMountedLayoutIdentity(identity))) break;
|
|
495
|
+
skippedLayoutIds.add(layoutEntry.id);
|
|
496
|
+
}
|
|
491
497
|
const slotPlansByKey = new Map(segmentPlan.slots.map((slot) => [slot.key, slot]));
|
|
492
498
|
const resolveRouteSegmentResetKey = (treePosition) => resolveAppPageSegmentStateKey(routeSegments, treePosition, options.matchedParams);
|
|
493
499
|
const metadataEntries = AppElementsWire.createMetadataEntries({
|
|
@@ -530,10 +536,9 @@ function buildAppPageElements(options) {
|
|
|
530
536
|
if (layoutIndex !== void 0) {
|
|
531
537
|
const layoutEntry = layoutEntries[layoutIndex];
|
|
532
538
|
layoutDependenciesBefore[layoutIndex] = [...pageDependencies];
|
|
533
|
-
if (getDefaultExport(layoutEntry.layoutModule)) {
|
|
539
|
+
if (!skippedLayoutIds.has(layoutEntry.id) && getDefaultExport(layoutEntry.layoutModule)) {
|
|
534
540
|
const layoutDependency = createAppRenderDependency();
|
|
535
541
|
layoutDependenciesByIndex.set(layoutIndex, layoutDependency);
|
|
536
|
-
renderDependenciesByElementId.set(layoutEntry.id, layoutDependency);
|
|
537
542
|
pageDependencies.push(layoutDependency);
|
|
538
543
|
}
|
|
539
544
|
slotDependenciesByLayoutIndex[layoutIndex] = [...pageDependencies];
|
|
@@ -581,33 +586,29 @@ function buildAppPageElements(options) {
|
|
|
581
586
|
for (let index = 0; index < layoutEntries.length; index++) {
|
|
582
587
|
const layoutEntry = layoutEntries[index];
|
|
583
588
|
if (isPrefetchLoadingShell && !includesPrefetchTreePosition(layoutEntry.treePosition)) continue;
|
|
589
|
+
if (skippedLayoutIds.has(layoutEntry.id)) continue;
|
|
584
590
|
if (!layoutEntry.layoutModule) continue;
|
|
585
591
|
const layoutComponent = traceGetLayoutOrPageModule(resolveAppPageModuleTraceSegment(routeSegments, layoutEntry.treePosition), () => getDefaultExport(layoutEntry.layoutModule));
|
|
586
592
|
if (!layoutComponent) continue;
|
|
587
593
|
const layoutParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntry.treePosition, options.matchedParams);
|
|
588
|
-
|
|
589
|
-
layoutId: layoutEntry.id,
|
|
590
|
-
layoutModule: layoutEntry.layoutModule,
|
|
591
|
-
layoutParamAccess: options.layoutParamAccess,
|
|
592
|
-
routeSegments: options.route.routeSegments,
|
|
593
|
-
treePosition: layoutEntry.treePosition
|
|
594
|
-
});
|
|
595
|
-
const layoutProps = { params: options.makeThenableParams(layoutParams, options.layoutParamAccess?.createThenableParamsObserver(layoutEntry.id)) };
|
|
594
|
+
const layoutProps = { params: options.makeThenableParams(layoutParams) };
|
|
596
595
|
for (const slot of Object.values(options.route.slots ?? {})) {
|
|
597
596
|
const slotName = slot.name;
|
|
598
597
|
if ((slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1) !== index) continue;
|
|
599
598
|
layoutProps[slotName] = /* @__PURE__ */ jsx(ParallelSlot, { name: slotName });
|
|
600
599
|
}
|
|
601
600
|
const LayoutComponent = layoutComponent;
|
|
602
|
-
const
|
|
603
|
-
|
|
601
|
+
const ancestorLoadingEntry = findNearestAncestorLoadingEntry(layoutEntry.treePosition);
|
|
602
|
+
const holdsResponse = !ancestorLoadingEntry && !isReactOwnedAppComponent(LayoutComponent);
|
|
603
|
+
if (holdsResponse) layoutGate.hold(layoutEntry.id, index);
|
|
604
|
+
let layoutElement = createRouteLayoutElement(LayoutComponent, withUseCacheLayoutMarker(LayoutComponent, {
|
|
604
605
|
...layoutProps,
|
|
605
606
|
children: /* @__PURE__ */ jsx(Children$1, {})
|
|
606
|
-
}),
|
|
607
|
-
|
|
608
|
-
|
|
607
|
+
}), index, layoutDependenciesByIndex.get(index), holdsResponse ? (failure) => layoutGate.settle(layoutEntry.id, failure) : void 0);
|
|
608
|
+
layoutElement = /* @__PURE__ */ jsx(RedirectBoundary, {
|
|
609
|
+
resetKey: resolveRouteSegmentResetKey(layoutEntry.treePosition),
|
|
610
|
+
children: layoutElement
|
|
609
611
|
});
|
|
610
|
-
const ancestorLoadingEntry = findNearestAncestorLoadingEntry(layoutEntry.treePosition);
|
|
611
612
|
const ancestorLoadingComponent = getDefaultExport(ancestorLoadingEntry?.loadingModule);
|
|
612
613
|
if (ancestorLoadingComponent && ancestorLoadingEntry && isOutermostEntryBelowLoading(ancestorLoadingEntry.treePosition, layoutEntry.treePosition, "layout")) {
|
|
613
614
|
const AncestorLoadingComponent = ancestorLoadingComponent;
|
|
@@ -876,6 +877,7 @@ function buildAppPageElements(options) {
|
|
|
876
877
|
children: routeChildren
|
|
877
878
|
});
|
|
878
879
|
const renderedTreePositions = isPrefetchLoadingShell ? orderedTreePositions.filter(includesPrefetchTreePosition) : orderedTreePositions;
|
|
880
|
+
let childSegmentElementId = pageElementId;
|
|
879
881
|
for (let index = renderedTreePositions.length - 1; index >= 0; index--) {
|
|
880
882
|
const treePosition = renderedTreePositions[index];
|
|
881
883
|
const segmentResetKey = resolveRouteSegmentResetKey(treePosition);
|
|
@@ -947,9 +949,13 @@ function buildAppPageElements(options) {
|
|
|
947
949
|
children: layoutHasElement ? /* @__PURE__ */ jsx(Slot, {
|
|
948
950
|
id: layoutEntry.id,
|
|
949
951
|
parallelSlots: createAppPageParallelSlotEntries(layoutIndex, layoutEntries, options.route, getEffectiveSlotParams, resolveSlotOverride),
|
|
950
|
-
children:
|
|
952
|
+
children: /* @__PURE__ */ jsx(BfcacheChildrenBoundary, {
|
|
953
|
+
id: childSegmentElementId,
|
|
954
|
+
children: segmentChildren
|
|
955
|
+
})
|
|
951
956
|
}) : segmentChildren
|
|
952
957
|
});
|
|
958
|
+
if (layoutHasElement) childSegmentElementId = layoutEntry.id;
|
|
953
959
|
}
|
|
954
960
|
const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);
|
|
955
961
|
routeChildren = /* @__PURE__ */ jsx(GlobalErrorBoundary, {
|
|
@@ -965,9 +971,9 @@ function buildAppPageElements(options) {
|
|
|
965
971
|
createAppPageStreamingMetadataBody(streamingMetadataBodyId)
|
|
966
972
|
] });
|
|
967
973
|
elements[routeId] = pageRenderDependency ? renderAfterAppDependencies(routeElement, [pageRenderDependency]) : routeElement;
|
|
968
|
-
Object.assign(elements, metadataEntries, options.route.staticSiblings && options.route.staticSiblings.length > 0 ? { [APP_STATIC_SIBLINGS_KEY]: options.route.staticSiblings } : {}, shouldRenderPrefetchLoadingShell ? { [APP_PREFETCH_LOADING_SHELL_MARKER_KEY]: "LoadingBoundary" } : {});
|
|
969
|
-
|
|
974
|
+
Object.assign(elements, metadataEntries, options.route.staticSiblings && options.route.staticSiblings.length > 0 ? { [APP_STATIC_SIBLINGS_KEY]: options.route.staticSiblings } : {}, shouldRenderPrefetchLoadingShell ? { [APP_PREFETCH_LOADING_SHELL_MARKER_KEY]: "LoadingBoundary" } : {}, skippedLayoutIds.size > 0 ? { [APP_SKIPPED_LAYOUT_IDS_KEY]: [...skippedLayoutIds] } : {});
|
|
975
|
+
registerAppPageLayoutGate(elements, layoutGate);
|
|
970
976
|
return elements;
|
|
971
977
|
}
|
|
972
978
|
//#endregion
|
|
973
|
-
export { buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage, createAppPageTreePath,
|
|
979
|
+
export { buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage, createAppPageTreePath, probeAppPageLayout, resolveAppPageChildSegments, resolveAppPageLoadingModuleAtOrAbove };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
2
2
|
import "../shims/navigation.js";
|
|
3
3
|
import { RootParams } from "../shims/root-params.js";
|
|
4
|
-
import {
|
|
4
|
+
import { InitialNavigationCacheMetadata } from "./app-ssr-stream.js";
|
|
5
|
+
import { AppPageFontData, AppPageSsrHandler } from "./app-page-stream.js";
|
|
6
|
+
import { CdnAppPageDocument } from "../shims/cdn-cache.js";
|
|
5
7
|
//#region src/server/app-page-rsc-render-status.d.ts
|
|
6
8
|
/**
|
|
7
9
|
* The status of a finished RSC render, as Next.js's static generation decides
|
|
@@ -10,6 +12,8 @@ import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
|
10
12
|
*/
|
|
11
13
|
export type AppPageRscRenderStatus = {
|
|
12
14
|
kind: "page";
|
|
15
|
+
/** The page's document, when the resolver rendered one to store. */
|
|
16
|
+
document?: CdnAppPageDocument;
|
|
13
17
|
} | {
|
|
14
18
|
kind: "special-error";
|
|
15
19
|
status: number;
|
|
@@ -22,9 +26,28 @@ export type AppPageRscRenderStatus = {
|
|
|
22
26
|
{
|
|
23
27
|
kind: "unstorable";
|
|
24
28
|
};
|
|
29
|
+
/** What the page's document renders with, as an HTML request renders it. */
|
|
30
|
+
type AppPageRscRenderDocumentOptions = {
|
|
31
|
+
clientTraceMetadata?: readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* When the document's render is given up, as completed-response admission
|
|
34
|
+
* gives up a body it hasn't captured by its deadline.
|
|
35
|
+
*/
|
|
36
|
+
deadlineAt?: number;
|
|
37
|
+
getFontData: () => AppPageFontData;
|
|
38
|
+
getInitialNavigationCacheMetadata: () => InitialNavigationCacheMetadata;
|
|
39
|
+
mirrorNextFlight: () => boolean;
|
|
40
|
+
onSsrError: (error: unknown) => unknown;
|
|
41
|
+
reactMaxHeadersLength?: number;
|
|
42
|
+
};
|
|
25
43
|
type CreateAppPageRscRenderStatusResolverOptions = {
|
|
26
44
|
basePath?: string;
|
|
27
45
|
capturedRscData: Promise<ArrayBuffer>;
|
|
46
|
+
/**
|
|
47
|
+
* Render the page's document from the payload, to be stored beside it.
|
|
48
|
+
* Without it, only a render that threw a special error renders its shell.
|
|
49
|
+
*/
|
|
50
|
+
document?: AppPageRscRenderDocumentOptions;
|
|
28
51
|
getCapturedSpecialError: () => unknown;
|
|
29
52
|
getCapturedSpecialErrors: (error: unknown) => readonly unknown[];
|
|
30
53
|
isForceStatic: boolean;
|
|
@@ -39,6 +62,9 @@ type CreateAppPageRscRenderStatusResolverOptions = {
|
|
|
39
62
|
* a render that threw one renders the document's shell from the same payload,
|
|
40
63
|
* as Next.js's static generation renders HTML beside RSC. Its server
|
|
41
64
|
* components don't run again. A render without a special error is a 200.
|
|
65
|
+
*
|
|
66
|
+
* With `document`, every render renders its document from the payload, as
|
|
67
|
+
* Next.js keeps a page's document and RSC payload in one entry.
|
|
42
68
|
*/
|
|
43
69
|
export declare function createAppPageRscRenderStatusResolver(options: CreateAppPageRscRenderStatusResolverOptions): () => Promise<AppPageRscRenderStatus>;
|
|
44
70
|
/**
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { isRenderDynamicLatched } from "../shims/internal/headers-state.js";
|
|
2
|
+
import "../shims/headers.js";
|
|
3
|
+
import { readStreamAsText } from "../utils/text-stream.js";
|
|
4
|
+
import { buildAppPageFontLinkHeader, resolveAppPageShellSpecialError, resolveAppPageSpecialErrorStoredHeaders } from "./app-page-execution.js";
|
|
5
|
+
import { buildAppPageLinkHeader, isAppSsrRenderResult } from "./app-page-stream.js";
|
|
3
6
|
//#region src/server/app-page-rsc-render-status.ts
|
|
4
7
|
const PAGE_STATUS = { kind: "page" };
|
|
5
8
|
/**
|
|
@@ -8,28 +11,109 @@ const PAGE_STATUS = { kind: "page" };
|
|
|
8
11
|
* a render that threw one renders the document's shell from the same payload,
|
|
9
12
|
* as Next.js's static generation renders HTML beside RSC. Its server
|
|
10
13
|
* components don't run again. A render without a special error is a 200.
|
|
14
|
+
*
|
|
15
|
+
* With `document`, every render renders its document from the payload, as
|
|
16
|
+
* Next.js keeps a page's document and RSC payload in one entry.
|
|
11
17
|
*/
|
|
12
18
|
function createAppPageRscRenderStatusResolver(options) {
|
|
13
19
|
let status;
|
|
14
20
|
return () => status ??= resolveAppPageRscRenderStatus(options);
|
|
15
21
|
}
|
|
16
22
|
async function resolveAppPageRscRenderStatus(options) {
|
|
23
|
+
const deadlineAt = options.document?.deadlineAt;
|
|
24
|
+
if (deadlineAt === void 0) return renderAppPageRscRenderStatus(options);
|
|
25
|
+
const expired = new AbortController();
|
|
26
|
+
const remaining = deadlineAt - Date.now();
|
|
27
|
+
const timer = remaining > 0 ? setTimeout(() => expired.abort(), remaining) : void 0;
|
|
28
|
+
if (timer === void 0) expired.abort();
|
|
29
|
+
try {
|
|
30
|
+
return await unlessExpired(renderAppPageRscRenderStatus(options, expired.signal), expired.signal, () => {}) ?? expiredDocumentStatus(options);
|
|
31
|
+
} finally {
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Settle with `promise`, or with `null` once `signal` aborts. */
|
|
36
|
+
function unlessExpired(promise, signal, discard) {
|
|
37
|
+
if (!signal) return promise;
|
|
38
|
+
if (signal.aborted) {
|
|
39
|
+
promise.then(discard, () => {});
|
|
40
|
+
return Promise.resolve(null);
|
|
41
|
+
}
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const onAbort = () => {
|
|
44
|
+
promise.then(discard, () => {});
|
|
45
|
+
resolve(null);
|
|
46
|
+
};
|
|
47
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
48
|
+
promise.then((value) => {
|
|
49
|
+
signal.removeEventListener("abort", onAbort);
|
|
50
|
+
if (signal.aborted) discard(value);
|
|
51
|
+
else resolve(value);
|
|
52
|
+
}, (error) => {
|
|
53
|
+
signal.removeEventListener("abort", onAbort);
|
|
54
|
+
reject(error);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/** Read the document, or cancel it and settle with `null` once `signal` aborts. */
|
|
59
|
+
async function readDocumentHtml(stream, signal) {
|
|
60
|
+
if (!signal) return readStreamAsText(stream);
|
|
61
|
+
const reader = stream.getReader();
|
|
62
|
+
const decoder = new TextDecoder();
|
|
63
|
+
const chunks = [];
|
|
64
|
+
for (;;) {
|
|
65
|
+
const result = await unlessExpired(reader.read(), signal, () => {});
|
|
66
|
+
if (result === null) {
|
|
67
|
+
reader.cancel().catch(() => {});
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
if (result.done) break;
|
|
71
|
+
chunks.push(decoder.decode(result.value, { stream: true }));
|
|
72
|
+
}
|
|
73
|
+
chunks.push(decoder.decode());
|
|
74
|
+
return chunks.join("");
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A document given up at its deadline isn't stored. A render without a
|
|
78
|
+
* special error is still a 200, but one with a special error needs its shell.
|
|
79
|
+
*/
|
|
80
|
+
function expiredDocumentStatus(options) {
|
|
81
|
+
return options.getCapturedSpecialError() === null ? PAGE_STATUS : { kind: "unstorable" };
|
|
82
|
+
}
|
|
83
|
+
async function renderAppPageRscRenderStatus(options, signal) {
|
|
17
84
|
const rscData = await options.capturedRscData;
|
|
18
|
-
|
|
85
|
+
const documentOptions = options.document;
|
|
86
|
+
if (!documentOptions && options.getCapturedSpecialError() === null) return PAGE_STATUS;
|
|
19
87
|
const ssrHandler = await options.loadSsrHandler();
|
|
88
|
+
if (signal?.aborted) return expiredDocumentStatus(options);
|
|
89
|
+
const fontData = documentOptions?.getFontData() ?? {
|
|
90
|
+
links: [],
|
|
91
|
+
preloads: [],
|
|
92
|
+
styles: []
|
|
93
|
+
};
|
|
94
|
+
const clientTraceMetadataMarker = documentOptions?.clientTraceMetadata && documentOptions.clientTraceMetadata.length > 0 ? crypto.randomUUID() : void 0;
|
|
20
95
|
let rendered;
|
|
21
96
|
try {
|
|
22
|
-
rendered = await ssrHandler.handleSsr(new Response(rscData).body, options.navigationContext, {
|
|
23
|
-
links: [],
|
|
24
|
-
preloads: [],
|
|
25
|
-
styles: []
|
|
26
|
-
}, {
|
|
97
|
+
rendered = await unlessExpired(ssrHandler.handleSsr(new Response(rscData).body, options.navigationContext, fontData, {
|
|
27
98
|
basePath: options.basePath,
|
|
28
99
|
isForceStatic: options.isForceStatic,
|
|
29
|
-
isStaticGeneration: true,
|
|
30
|
-
onSsrError: () => void 0,
|
|
31
100
|
preloadRoutePattern: options.routePattern,
|
|
32
|
-
rootParams: options.rootParams
|
|
101
|
+
rootParams: options.rootParams,
|
|
102
|
+
...documentOptions ? {
|
|
103
|
+
clientTraceMetadata: documentOptions.clientTraceMetadata,
|
|
104
|
+
clientTraceMetadataMarker,
|
|
105
|
+
getInitialNavigationCacheMetadata: documentOptions.getInitialNavigationCacheMetadata,
|
|
106
|
+
isCacheCandidate: true,
|
|
107
|
+
mirrorNextFlight: documentOptions.mirrorNextFlight,
|
|
108
|
+
onSsrError: documentOptions.onSsrError,
|
|
109
|
+
reactMaxHeadersLength: documentOptions.reactMaxHeadersLength,
|
|
110
|
+
signal
|
|
111
|
+
} : {
|
|
112
|
+
isStaticGeneration: true,
|
|
113
|
+
onSsrError: () => void 0
|
|
114
|
+
}
|
|
115
|
+
}), signal, (late) => {
|
|
116
|
+
(isAppSsrRenderResult(late) ? late.htmlStream : late).cancel().catch(() => {});
|
|
33
117
|
});
|
|
34
118
|
} catch (error) {
|
|
35
119
|
const specialError = resolveAppPageShellSpecialError(error, options.getCapturedSpecialErrors(error));
|
|
@@ -41,8 +125,32 @@ async function resolveAppPageRscRenderStatus(options) {
|
|
|
41
125
|
...headers ? { headers } : {}
|
|
42
126
|
};
|
|
43
127
|
}
|
|
44
|
-
(
|
|
45
|
-
|
|
128
|
+
if (rendered === null) return expiredDocumentStatus(options);
|
|
129
|
+
const htmlStream = isAppSsrRenderResult(rendered) ? rendered.htmlStream : rendered;
|
|
130
|
+
if (!documentOptions) {
|
|
131
|
+
htmlStream.cancel().catch(() => {});
|
|
132
|
+
return PAGE_STATUS;
|
|
133
|
+
}
|
|
134
|
+
let html;
|
|
135
|
+
try {
|
|
136
|
+
html = await readDocumentHtml(htmlStream, signal);
|
|
137
|
+
} catch {
|
|
138
|
+
return PAGE_STATUS;
|
|
139
|
+
}
|
|
140
|
+
if (html === null) return expiredDocumentStatus(options);
|
|
141
|
+
if (isRenderDynamicLatched()) return PAGE_STATUS;
|
|
142
|
+
const linkHeader = buildAppPageLinkHeader(isAppSsrRenderResult(rendered) ? rendered.linkHeader : void 0, buildAppPageFontLinkHeader(fontData.preloads), documentOptions.reactMaxHeadersLength);
|
|
143
|
+
if (clientTraceMetadataMarker) {
|
|
144
|
+
const { stripClientTraceMetadataBlock } = await import("./client-trace-metadata.js");
|
|
145
|
+
html = stripClientTraceMetadataBlock(html, clientTraceMetadataMarker);
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
kind: "page",
|
|
149
|
+
document: {
|
|
150
|
+
html,
|
|
151
|
+
...linkHeader ? { linkHeader } : {}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
46
154
|
}
|
|
47
155
|
/**
|
|
48
156
|
* The status Next.js sends an RSC request for a render with this status. Its
|
|
@@ -77,6 +77,8 @@ export type AppPageSsrHandler = {
|
|
|
77
77
|
};
|
|
78
78
|
/** Abort signal for a build-time PPR fallback-shell static render. */
|
|
79
79
|
pprFallbackShellSignal?: AbortSignal;
|
|
80
|
+
/** Aborts a streaming render whose document is given up. */
|
|
81
|
+
signal?: AbortSignal;
|
|
80
82
|
/** Route whose client references load before the render; null for none. */
|
|
81
83
|
preloadRoutePattern?: string | null;
|
|
82
84
|
/** When true, wait for the full React tree before emitting bytes. */
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
|
|
2
2
|
import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
|
|
3
3
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
4
|
-
import "./app-rsc-cache-busting.js";
|
|
5
|
-
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
6
4
|
import { markFrameworkLinkHeaders } from "./app-response-header-provenance.js";
|
|
5
|
+
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
6
|
+
import "./app-rsc-cache-busting.js";
|
|
7
7
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
8
8
|
import { getNextErrorDigest } from "./next-error-digest.js";
|
|
9
9
|
import { isAppRenderAbortError } from "./app-render-abort-error.js";
|
|
@@ -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
|