vinext 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -9
- package/dist/build/client-build-config.d.ts +64 -3
- package/dist/build/client-build-config.js +131 -4
- package/dist/build/client-reference-groups.d.ts +163 -0
- package/dist/build/client-reference-groups.js +534 -0
- package/dist/build/module-dependency-cache.d.ts +31 -0
- package/dist/build/module-dependency-cache.js +51 -1
- package/dist/build/next-client-runtime-manifests.d.ts +10 -1
- package/dist/build/next-client-runtime-manifests.js +19 -4
- package/dist/build/nitro-public-files.d.ts +24 -0
- package/dist/build/nitro-public-files.js +60 -0
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/prerender-paths.js +5 -2
- package/dist/build/server-actions-encryption-key.d.ts +23 -0
- package/dist/build/server-actions-encryption-key.js +101 -0
- package/dist/build/ssr-manifest.d.ts +3 -0
- package/dist/build/ssr-manifest.js +10 -1
- package/dist/client/client-rewrite-params.d.ts +9 -0
- package/dist/client/client-rewrite-params.js +20 -0
- package/dist/client/dev-error-overlay.js +2 -1
- package/dist/client/navigation-runtime.d.ts +25 -2
- package/dist/client/navigation-runtime.js +42 -11
- package/dist/client/vinext-next-data.d.ts +0 -1
- package/dist/config/config-matchers.d.ts +15 -40
- package/dist/config/config-matchers.js +183 -255
- package/dist/config/config-source.d.ts +34 -0
- package/dist/config/config-source.js +141 -0
- package/dist/config/header-params.d.ts +29 -0
- package/dist/config/header-params.js +106 -0
- package/dist/config/next-config.d.ts +7 -5
- package/dist/config/next-config.js +120 -7
- package/dist/entries/app-browser-entry.d.ts +14 -1
- package/dist/entries/app-browser-entry.js +26 -36
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +92 -57
- package/dist/entries/app-rsc-manifest.d.ts +10 -0
- package/dist/entries/app-rsc-manifest.js +20 -1
- package/dist/entries/app-ssr-entry.d.ts +4 -1
- package/dist/entries/app-ssr-entry.js +9 -2
- package/dist/entries/pages-client-entry.d.ts +1 -0
- package/dist/entries/pages-client-entry.js +6 -6
- package/dist/entries/pages-server-entry.js +17 -14
- package/dist/index.d.ts +11 -0
- package/dist/index.js +239 -83
- package/dist/init.js +17 -0
- package/dist/plugins/optimize-imports.d.ts +25 -2
- package/dist/plugins/optimize-imports.js +106 -20
- package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
- package/dist/plugins/rsc-client-reference-loaders.js +336 -18
- package/dist/plugins/use-cache-callable.d.ts +5 -0
- package/dist/plugins/use-cache-callable.js +30 -8
- package/dist/plugins/worker-image-imports.d.ts +1 -0
- package/dist/plugins/worker-image-imports.js +1 -1
- package/dist/routing/app-route-graph.d.ts +1 -1
- package/dist/routing/browser-route-manifest.d.ts +43 -0
- package/dist/routing/browser-route-manifest.js +195 -0
- package/dist/routing/hashed-route-patterns.d.ts +4 -0
- package/dist/routing/hashed-route-patterns.js +22 -0
- package/dist/routing/optimistic-route-trie.d.ts +27 -0
- package/dist/routing/optimistic-route-trie.js +102 -0
- package/dist/routing/route-validation.d.ts +6 -1
- package/dist/routing/route-validation.js +26 -10
- package/dist/server/app-action-forwarding.d.ts +8 -0
- package/dist/server/app-action-forwarding.js +15 -1
- package/dist/server/app-browser-entry.js +147 -60
- package/dist/server/app-browser-error.d.ts +3 -1
- package/dist/server/app-browser-error.js +7 -2
- package/dist/server/app-browser-interception-context.d.ts +2 -2
- package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
- package/dist/server/app-browser-mpa-navigation.js +6 -5
- package/dist/server/app-browser-navigation-controller.d.ts +17 -6
- package/dist/server/app-browser-navigation-controller.js +88 -26
- package/dist/server/app-browser-state.d.ts +2 -2
- package/dist/server/app-browser-visible-commit.d.ts +4 -4
- package/dist/server/app-client-reference-preloader.d.ts +23 -0
- package/dist/server/app-client-reference-preloader.js +30 -7
- package/dist/server/app-fallback-renderer.js +2 -1
- package/dist/server/app-middleware.d.ts +6 -0
- package/dist/server/app-middleware.js +8 -10
- package/dist/server/app-optimistic-routing.d.ts +8 -10
- package/dist/server/app-optimistic-routing.js +4 -95
- package/dist/server/app-page-boundary-render.js +8 -1
- package/dist/server/app-page-cache-render.js +1 -0
- package/dist/server/app-page-dispatch.js +2 -0
- package/dist/server/app-page-render.js +3 -1
- package/dist/server/app-page-rsc-render-status.d.ts +1 -0
- package/dist/server/app-page-rsc-render-status.js +1 -0
- package/dist/server/app-page-search-params-observation.d.ts +1 -4
- package/dist/server/app-page-search-params-observation.js +8 -10
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +1 -0
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +11 -7
- package/dist/server/app-prerender-static-params.js +3 -2
- package/dist/server/app-render-dependency.js +42 -2
- package/dist/server/app-request-stage-independent-entry.js +2 -2
- package/dist/server/app-response-stage-entry.js +3 -3
- package/dist/server/app-route-handler-dispatch.js +3 -1
- package/dist/server/app-route-handler-execution.d.ts +2 -0
- package/dist/server/app-route-handler-execution.js +9 -2
- package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
- package/dist/server/app-route-handler-middleware-context.js +3 -3
- package/dist/server/app-route-handler-response.d.ts +2 -1
- package/dist/server/app-route-handler-response.js +2 -2
- package/dist/server/app-route-handler-runtime.d.ts +2 -0
- package/dist/server/app-route-handler-runtime.js +20 -3
- package/dist/server/app-route-module-loader.js +7 -6
- package/dist/server/app-route-tree.d.ts +20 -0
- package/dist/server/app-route-tree.js +18 -0
- package/dist/server/app-router-entry.js +2 -2
- package/dist/server/app-rsc-combined-handler.js +8 -1
- package/dist/server/app-rsc-errors.d.ts +7 -0
- package/dist/server/app-rsc-errors.js +9 -2
- package/dist/server/app-rsc-handler.d.ts +4 -1
- package/dist/server/app-rsc-handler.js +146 -130
- package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.js +3 -1
- package/dist/server/app-rsc-route-matching.d.ts +1 -0
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +23 -6
- package/dist/server/app-server-action-execution.js +50 -56
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +16 -7
- package/dist/server/app-ssr-stream.d.ts +7 -0
- package/dist/server/app-ssr-stream.js +13 -1
- package/dist/server/config-headers.js +12 -3
- package/dist/server/isolate-shared-promise.d.ts +10 -0
- package/dist/server/isolate-shared-promise.js +33 -0
- package/dist/server/isr-cache.js +3 -2
- package/dist/server/middleware-matcher-pattern.d.ts +0 -1
- package/dist/server/middleware-matcher-pattern.js +11 -140
- package/dist/server/middleware-matcher.js +5 -6
- package/dist/server/middleware-response-headers.d.ts +31 -0
- package/dist/server/middleware-response-headers.js +57 -1
- package/dist/server/middleware-runtime.js +26 -13
- package/dist/server/navigation-planner.d.ts +2 -2
- package/dist/server/nitro-public-files-plugin.d.ts +38 -0
- package/dist/server/nitro-public-files-plugin.js +106 -0
- package/dist/server/nitro-public-files.d.ts +21 -0
- package/dist/server/nitro-public-files.js +39 -0
- package/dist/server/pages-asset-tags.d.ts +5 -0
- package/dist/server/pages-asset-tags.js +9 -2
- package/dist/server/pages-client-assets.d.ts +4 -1
- package/dist/server/pages-i18n.d.ts +18 -0
- package/dist/server/pages-i18n.js +18 -2
- package/dist/server/pages-node-compat.d.ts +5 -3
- package/dist/server/pages-node-compat.js +35 -16
- package/dist/server/pages-request-pipeline.d.ts +6 -1
- package/dist/server/pages-request-pipeline.js +31 -35
- package/dist/server/pages-request-stage-entry.js +16 -6
- package/dist/server/pages-response-stage-entry.js +1 -1
- package/dist/server/pages-revalidate.js +1 -0
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +71 -33
- package/dist/server/proxy-trust.d.ts +6 -0
- package/dist/server/proxy-trust.js +12 -6
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +12 -1
- package/dist/server/server-reference-loader.js +10 -1
- package/dist/server/static-file-cache.js +15 -3
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/cache-handler.js +3 -2
- package/dist/shims/cache-request-state.d.ts +40 -3
- package/dist/shims/cache-request-state.js +70 -5
- package/dist/shims/cache-runtime.js +47 -19
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +17 -8
- package/dist/shims/cdn-purge-routes.d.ts +24 -0
- package/dist/shims/cdn-purge-routes.js +77 -0
- package/dist/shims/dynamic.js +17 -4
- package/dist/shims/form.js +8 -3
- package/dist/shims/image-props.d.ts +93 -0
- package/dist/shims/image-props.js +323 -0
- package/dist/shims/image.d.ts +4 -18
- package/dist/shims/image.js +4 -319
- package/dist/shims/internal/headers-state.d.ts +7 -0
- package/dist/shims/internal/headers-state.js +14 -2
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +31 -14
- package/dist/shims/internal/hybrid-client-route-owner.js +8 -8
- package/dist/shims/link.js +5 -3
- package/dist/shims/navigation.d.ts +1 -1
- package/dist/shims/navigation.js +17 -5
- package/dist/shims/og.js +35 -10
- package/dist/shims/request-context.d.ts +13 -0
- package/dist/shims/router.js +19 -40
- package/dist/shims/server.d.ts +31 -4
- package/dist/shims/server.js +58 -10
- package/dist/shims/thenable-params.d.ts +6 -1
- package/dist/shims/thenable-params.js +11 -2
- package/dist/shims/unified-request-context.d.ts +5 -0
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/utils/asset-prefix.d.ts +7 -0
- package/dist/utils/asset-prefix.js +10 -1
- package/dist/utils/client-build-manifest.js +12 -5
- package/dist/utils/client-runtime-metadata.d.ts +1 -0
- package/dist/utils/client-runtime-metadata.js +15 -2
- package/dist/utils/lazy-chunks.d.ts +4 -0
- package/dist/utils/manifest-paths.d.ts +14 -0
- package/dist/utils/manifest-paths.js +22 -1
- package/dist/utils/path-to-regexp.d.ts +21 -0
- package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
- package/dist/utils/plugin-react-version.d.ts +15 -0
- package/dist/utils/plugin-react-version.js +64 -0
- package/dist/utils/public-routes.d.ts +2 -0
- package/dist/utils/public-routes.js +18 -7
- package/package.json +1 -1
- package/dist/server/middleware-path-to-regexp.d.ts +0 -13
- package/dist/utils/regex-safety.d.ts +0 -17
- package/dist/utils/regex-safety.js +0 -789
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { stripBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
3
3
|
import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
|
|
4
|
+
import { createArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
4
5
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
5
6
|
import "./app-elements.js";
|
|
6
7
|
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
@@ -96,14 +97,19 @@ function createAppPageBoundaryRscPayload(options) {
|
|
|
96
97
|
const routeId = AppElementsWire.encodeRouteId(options.pathname, null);
|
|
97
98
|
const layoutEntries = createAppPageBoundaryLayoutEntries(options.route, options.layoutModules);
|
|
98
99
|
const sourcePageSegments = options.sourcePageSegments ?? options.route?.routeSegments;
|
|
100
|
+
const rootLayoutTreePath = layoutEntries[0]?.treePath ?? null;
|
|
99
101
|
return {
|
|
100
102
|
...AppElementsWire.createMetadataEntries({
|
|
101
103
|
interceptionContext: null,
|
|
102
104
|
layoutIds: layoutEntries.map((entry) => entry.id),
|
|
103
|
-
rootLayoutTreePath
|
|
105
|
+
rootLayoutTreePath,
|
|
104
106
|
routeId,
|
|
105
107
|
sourcePage: sourcePageSegments ? createAppPageSourcePage(sourcePageSegments) : null
|
|
106
108
|
}),
|
|
109
|
+
[AppElementsWire.keys.artifactCompatibility]: createArtifactCompatibilityEnvelope({
|
|
110
|
+
deploymentVersion: process.env.__VINEXT_BUILD_ID ?? null,
|
|
111
|
+
rootBoundaryId: rootLayoutTreePath
|
|
112
|
+
}),
|
|
107
113
|
[routeId]: options.element
|
|
108
114
|
};
|
|
109
115
|
}
|
|
@@ -157,6 +163,7 @@ async function renderAppPageBoundaryElementResponse(options) {
|
|
|
157
163
|
isCacheCandidate: options.isCacheCandidate,
|
|
158
164
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
159
165
|
middlewareHeaders: options.middlewareContext.headers,
|
|
166
|
+
preloadRoutePattern: options.route ? options.route.pattern : null,
|
|
160
167
|
navigationContext: options.getNavigationContext() ?? {
|
|
161
168
|
pathname,
|
|
162
169
|
searchParams: requestUrl.searchParams,
|
|
@@ -43,6 +43,7 @@ async function renderAppPageCacheArtifactsImpl(options, renderSpan) {
|
|
|
43
43
|
mirrorNextFlight: options.mirrorNextFlight,
|
|
44
44
|
isStaticGeneration: true,
|
|
45
45
|
isForceStatic: options.isForceStatic,
|
|
46
|
+
preloadRoutePattern: options.route.pattern,
|
|
46
47
|
onSsrError: options.onSsrError && options.isCapturedRscError ? createAppPageSsrErrorHandler((error) => {
|
|
47
48
|
recordAppPageRenderError(renderSpan, error);
|
|
48
49
|
return options.onSsrError?.(error);
|
|
@@ -149,6 +149,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
|
|
|
149
149
|
currentFetchRevalidate: options.currentFetchRevalidate ?? null,
|
|
150
150
|
currentForceDynamicFetchDefault: options.dynamicConfig === "force-dynamic",
|
|
151
151
|
executionContext: getRequestExecutionContext(),
|
|
152
|
+
rootParams: options.rootParams ?? null,
|
|
152
153
|
unstableCacheRevalidation: "foreground"
|
|
153
154
|
});
|
|
154
155
|
const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
|
|
@@ -388,6 +389,7 @@ async function dispatchAppPageInner(options) {
|
|
|
388
389
|
draftModeSecret: options.draftModeSecret,
|
|
389
390
|
dynamicConfig: revalidationDynamicConfig,
|
|
390
391
|
params: revalidationTarget.navigationParams,
|
|
392
|
+
rootParams: options.rootParams,
|
|
391
393
|
routePattern: revalidationTarget.route.pattern,
|
|
392
394
|
routeSegments: revalidationTarget.route.routeSegments,
|
|
393
395
|
setNavigationContext: options.setNavigationContext
|
|
@@ -497,7 +497,8 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
497
497
|
isForceStatic: options.isForceStatic,
|
|
498
498
|
loadSsrHandler: options.loadSsrHandler,
|
|
499
499
|
navigationContext: options.getNavigationContext(),
|
|
500
|
-
rootParams: options.rootParams
|
|
500
|
+
rootParams: options.rootParams,
|
|
501
|
+
routePattern: options.routePattern
|
|
501
502
|
}) : void 0;
|
|
502
503
|
let requestCacheLifeForPrerender = null;
|
|
503
504
|
if (shouldWaitForAllReady) await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);
|
|
@@ -812,6 +813,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
812
813
|
reactMaxHeadersLength: options.reactMaxHeadersLength,
|
|
813
814
|
rootParams: options.rootParams,
|
|
814
815
|
pprFallbackShellSignal: options.pprFallbackShellSignal,
|
|
816
|
+
preloadRoutePattern: options.routePattern,
|
|
815
817
|
formState: options.formState ?? null,
|
|
816
818
|
rscStream: rscForResponse,
|
|
817
819
|
scriptNonce: options.scriptNonce,
|
|
@@ -31,6 +31,7 @@ type CreateAppPageRscRenderStatusResolverOptions = {
|
|
|
31
31
|
loadSsrHandler: () => Promise<AppPageSsrHandler>;
|
|
32
32
|
navigationContext: NavigationContext | null;
|
|
33
33
|
rootParams?: RootParams;
|
|
34
|
+
routePattern: string;
|
|
34
35
|
};
|
|
35
36
|
/**
|
|
36
37
|
* Resolve an RSC-only render's status once its Flight payload is complete.
|
|
@@ -28,6 +28,7 @@ async function resolveAppPageRscRenderStatus(options) {
|
|
|
28
28
|
isForceStatic: options.isForceStatic,
|
|
29
29
|
isStaticGeneration: true,
|
|
30
30
|
onSsrError: () => void 0,
|
|
31
|
+
preloadRoutePattern: options.routePattern,
|
|
31
32
|
rootParams: options.rootParams
|
|
32
33
|
});
|
|
33
34
|
} catch (error) {
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { ThenableParams, ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
2
2
|
import { AppPageSearchParams } from "./app-page-head.js";
|
|
3
3
|
//#region src/server/app-page-search-params-observation.d.ts
|
|
4
|
-
type AppPageSearchParamsObservationOptions = {
|
|
5
|
-
observeReactPromiseStatus?: boolean;
|
|
6
|
-
};
|
|
7
4
|
type ClientPageSsrSearchParamsOptions = {
|
|
8
5
|
isForceStatic?: boolean;
|
|
9
6
|
isPprFallbackShell?: boolean;
|
|
10
7
|
};
|
|
11
8
|
export declare function createAppPageSearchParamsObserver(): ThenableParamsObserver;
|
|
12
|
-
export declare function makeObservedAppPageSearchParamsThenable(pageSearchParams: AppPageSearchParams
|
|
9
|
+
export declare function makeObservedAppPageSearchParamsThenable(pageSearchParams: AppPageSearchParams): ThenableParams<AppPageSearchParams>;
|
|
13
10
|
/**
|
|
14
11
|
* The `searchParams` a client page receives during SSR (see
|
|
15
12
|
* `shims/client-page-root.tsx`). Its RSC payload carries no query, so this is
|
|
@@ -9,17 +9,15 @@ function markAppPageSearchParamsAccess() {
|
|
|
9
9
|
markRenderRequestApiUsage("searchParams");
|
|
10
10
|
}
|
|
11
11
|
function createAppPageSearchParamsObserver() {
|
|
12
|
-
return {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
return {
|
|
13
|
+
observeParamAccess() {
|
|
14
|
+
markAppPageSearchParamsAccess();
|
|
15
|
+
},
|
|
16
|
+
observeThenRead: throwIfStaticGenerationAccessError
|
|
17
|
+
};
|
|
15
18
|
}
|
|
16
|
-
function makeObservedAppPageSearchParamsThenable(pageSearchParams
|
|
17
|
-
|
|
18
|
-
if (options.observeReactPromiseStatus === true) return makeThenableParams(pageSearchParams, {
|
|
19
|
-
...observer,
|
|
20
|
-
observeReactPromiseStatus: true
|
|
21
|
-
});
|
|
22
|
-
return makeThenableParams(pageSearchParams, observer);
|
|
19
|
+
function makeObservedAppPageSearchParamsThenable(pageSearchParams) {
|
|
20
|
+
return makeThenableParams(pageSearchParams, createAppPageSearchParamsObserver());
|
|
23
21
|
}
|
|
24
22
|
/**
|
|
25
23
|
* The `searchParams` a client page receives during SSR (see
|
|
@@ -71,6 +71,8 @@ export type AppPageSsrHandler = {
|
|
|
71
71
|
};
|
|
72
72
|
/** Abort signal for a build-time PPR fallback-shell static render. */
|
|
73
73
|
pprFallbackShellSignal?: AbortSignal;
|
|
74
|
+
/** Route whose client references load before the render; null for none. */
|
|
75
|
+
preloadRoutePattern?: string | null;
|
|
74
76
|
/** When true, wait for the full React tree before emitting bytes. */
|
|
75
77
|
waitForAllReady?: boolean;
|
|
76
78
|
/** Render is producing a static/prerendered HTML artifact. */
|
|
@@ -128,6 +130,11 @@ type RenderAppPageHtmlStreamOptions = {
|
|
|
128
130
|
};
|
|
129
131
|
/** Abort signal for a build-time PPR fallback-shell static render. */
|
|
130
132
|
pprFallbackShellSignal?: AbortSignal;
|
|
133
|
+
/**
|
|
134
|
+
* Route whose client references load before the render, or null for a
|
|
135
|
+
* render without a route. Undefined loads every client reference.
|
|
136
|
+
*/
|
|
137
|
+
preloadRoutePattern?: string | null;
|
|
131
138
|
/** When true, wait for the full React tree before emitting bytes. */
|
|
132
139
|
waitForAllReady?: boolean;
|
|
133
140
|
/** Render is producing a static/prerendered HTML artifact. */
|
|
@@ -78,6 +78,7 @@ async function renderAppPageHtmlStream(options) {
|
|
|
78
78
|
sideStream: options.sideStream,
|
|
79
79
|
capturedRscDataRef: options.capturedRscDataRef,
|
|
80
80
|
pprFallbackShellSignal: options.pprFallbackShellSignal,
|
|
81
|
+
preloadRoutePattern: options.preloadRoutePattern,
|
|
81
82
|
waitForAllReady: options.waitForAllReady,
|
|
82
83
|
isStaticGeneration: options.isStaticGeneration,
|
|
83
84
|
isForceStatic: options.isForceStatic,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AppMiddlewareContext } from "./app-middleware.js";
|
|
2
|
+
import { MiddlewareResponseMergeOptions } from "./middleware-response-headers.js";
|
|
2
3
|
import { EdgeApiExecutionRuntime } from "./edge-api-runtime.js";
|
|
3
4
|
//#region src/server/app-pages-bridge.d.ts
|
|
4
5
|
export type PagesEntry = {
|
|
@@ -24,7 +25,7 @@ type AppRouteMatch = {
|
|
|
24
25
|
type RenderPagesFallbackDependencies = {
|
|
25
26
|
loadPagesEntry: () => Promise<PagesEntry> | PagesEntry;
|
|
26
27
|
buildRequestHeaders: (requestHeaders: Headers, middlewareRequestHeaders: Headers) => Headers | null;
|
|
27
|
-
applyRouteHandlerMiddlewareContext: (response: Response, middlewareContext: AppMiddlewareContext) => Response;
|
|
28
|
+
applyRouteHandlerMiddlewareContext: (response: Response, middlewareContext: AppMiddlewareContext, options?: MiddlewareResponseMergeOptions) => Response;
|
|
28
29
|
/**
|
|
29
30
|
* Returns the `__prerender_bypass` Set-Cookie header emitted by a
|
|
30
31
|
* `draftMode().enable()`/`disable()` call inside middleware, if any. Reading
|
|
@@ -23,15 +23,18 @@ async function renderPagesFallback(options, dependencies) {
|
|
|
23
23
|
if (isRscRequest && !allowRscDocumentFallback) return null;
|
|
24
24
|
const pagesEntry = await loadPagesEntry();
|
|
25
25
|
const pagesRequestHeaders = middlewareContext.requestHeaders ? buildRequestHeaders(request.headers, middlewareContext.requestHeaders) : null;
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const matchRequest = pagesRequestHeaders ? new Request(request.url, {
|
|
27
|
+
headers: pagesRequestHeaders,
|
|
28
|
+
method: request.method
|
|
29
|
+
}) : request;
|
|
30
|
+
const claimPagesRequest = () => pagesRequestHeaders ? cloneRequestWithHeaders(request, pagesRequestHeaders) : request;
|
|
28
31
|
const queryIndex = pathname.indexOf("?");
|
|
29
32
|
const pagesPathname = queryIndex === -1 ? pathname : pathname.slice(0, queryIndex);
|
|
30
33
|
const pagesUrl = pagesPathname + (queryIndex === -1 ? url.search || "" : pathname.slice(queryIndex));
|
|
31
34
|
if (pagesPathname.startsWith("/api/") || pagesPathname === "/api") {
|
|
32
35
|
if (typeof pagesEntry.handleApiRoute !== "function") return null;
|
|
33
36
|
const hasApiMatcher = typeof pagesEntry.matchApiRoute === "function";
|
|
34
|
-
const apiMatch = hasApiMatcher ? pagesEntry.matchApiRoute?.(pagesUrl,
|
|
37
|
+
const apiMatch = hasApiMatcher ? pagesEntry.matchApiRoute?.(pagesUrl, matchRequest) ?? null : null;
|
|
35
38
|
if (hasApiMatcher && apiMatch === null) return null;
|
|
36
39
|
if (apiMatch !== null && matchKind === "static" && apiMatch.route.isDynamic) return null;
|
|
37
40
|
if (apiMatch !== null && matchKind === "dynamic" && !apiMatch.route.isDynamic) return null;
|
|
@@ -41,24 +44,25 @@ async function renderPagesFallback(options, dependencies) {
|
|
|
41
44
|
if (apiMatch !== null) beginRouteCacheability("pages-api", apiMatch.route.pattern);
|
|
42
45
|
const executionContext = getRequestExecutionContext();
|
|
43
46
|
const apiArgs = [
|
|
44
|
-
|
|
47
|
+
claimPagesRequest(),
|
|
45
48
|
pagesUrl,
|
|
46
49
|
executionContext ?? void 0,
|
|
47
|
-
executionContext?.trustedRevalidateOrigin
|
|
50
|
+
executionContext?.trustedRevalidateOrigin,
|
|
48
51
|
executionContext?.hostRuntime ?? "node"
|
|
49
52
|
];
|
|
50
53
|
const pagesApiResponse = await (initialResponseHeaders ? pagesEntry.handleApiRoute(...apiArgs, initialResponseHeaders) : pagesEntry.handleApiRoute(...apiArgs));
|
|
51
54
|
const draftCookie = getDraftModeCookieHeader();
|
|
52
|
-
return applyDraftModeCookie(applyRouteHandlerMiddlewareContext(pagesApiResponse, middlewareContext), draftCookie);
|
|
55
|
+
return applyDraftModeCookie(applyRouteHandlerMiddlewareContext(pagesApiResponse, middlewareContext, { appendResponseChallenges: false }), draftCookie);
|
|
53
56
|
}
|
|
54
57
|
if (typeof pagesEntry.renderPage !== "function") return null;
|
|
55
58
|
const hasPageMatcher = typeof pagesEntry.matchPageRoute === "function";
|
|
56
|
-
const pageMatch = hasPageMatcher ? pagesEntry.matchPageRoute?.(pagesUrl,
|
|
59
|
+
const pageMatch = hasPageMatcher ? pagesEntry.matchPageRoute?.(pagesUrl, matchRequest) ?? null : null;
|
|
57
60
|
if (hasPageMatcher && pageMatch === null) return null;
|
|
58
61
|
if (pageMatch !== null && matchKind === "static" && pageMatch.route.isDynamic) return null;
|
|
59
62
|
if (pageMatch !== null && matchKind === "dynamic" && !pageMatch.route.isDynamic) return null;
|
|
60
63
|
if (appRouteMatch !== null && (pageMatch === null || !pagesRouteHasPriorityOverAppRoute(pageMatch.route, appRouteMatch.route))) return null;
|
|
61
64
|
if (pageMatch !== null) beginRouteCacheability("pages-page", pageMatch.route.pattern);
|
|
65
|
+
const pagesRequest = claimPagesRequest();
|
|
62
66
|
const renderArgs = [
|
|
63
67
|
pagesDataRequest ? cloneRequestWithUrl(pagesRequest, pagesDataRequest.url) : pagesRequest,
|
|
64
68
|
pagesUrl,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isUnknownRecord } from "../utils/record.js";
|
|
2
|
+
import { shareIsolatePromise } from "./isolate-shared-promise.js";
|
|
2
3
|
import { pickRootParams, runWithRootParamsScope } from "../shims/root-params.js";
|
|
3
4
|
//#region src/server/app-prerender-static-params.ts
|
|
4
5
|
/**
|
|
@@ -42,7 +43,7 @@ function createAppPrerenderStaticParamsResolver(sources, rootParamNames) {
|
|
|
42
43
|
let resolvePromise = null;
|
|
43
44
|
const resolveFns = () => {
|
|
44
45
|
if (resolvedFns) return Promise.resolve(resolvedFns);
|
|
45
|
-
if (!resolvePromise) resolvePromise = (async () => {
|
|
46
|
+
if (!resolvePromise) resolvePromise = shareIsolatePromise((async () => {
|
|
46
47
|
resolvedFns = (await Promise.all(usableSources.map(async (source) => {
|
|
47
48
|
if (isGenerateStaticParamsFunction(source)) return source;
|
|
48
49
|
const mod = await source.load();
|
|
@@ -50,7 +51,7 @@ function createAppPrerenderStaticParamsResolver(sources, rootParamNames) {
|
|
|
50
51
|
return isGenerateStaticParamsFunction(fn) ? fn : null;
|
|
51
52
|
}))).filter((fn) => fn !== null);
|
|
52
53
|
return resolvedFns;
|
|
53
|
-
})();
|
|
54
|
+
})());
|
|
54
55
|
return resolvePromise;
|
|
55
56
|
};
|
|
56
57
|
return async (input) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isPromiseLike } from "../utils/promise.js";
|
|
2
|
-
import { createElement, use } from "react";
|
|
2
|
+
import { Fragment, createElement, isValidElement, use } from "react";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
//#region src/server/app-render-dependency.tsx
|
|
5
5
|
const REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference");
|
|
@@ -21,7 +21,47 @@ function invokeAppComponent(component, props) {
|
|
|
21
21
|
if (candidate.$$typeof === REACT_LAZY && candidate._init) return invokeAppComponent(candidate._init(candidate._payload), props);
|
|
22
22
|
if (candidate.$$typeof === REACT_FORWARD_REF && candidate.render) return candidate.render(props, void 0);
|
|
23
23
|
if (isReactOwnedAppComponent(candidate)) return createElement(candidate, props);
|
|
24
|
-
|
|
24
|
+
const result = candidate(props);
|
|
25
|
+
return isPromiseLike(result) ? result : invokeCssWrappedComponent(result, props);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Whether `elementProps` are what `createElement(type, props)` produces: the
|
|
29
|
+
* same values, plus any `type.defaultProps` for keys that are `undefined`.
|
|
30
|
+
* Defaulted values aren't read again, since a default can be a getter.
|
|
31
|
+
*/
|
|
32
|
+
function isElementOfProps(elementProps, props, defaultProps) {
|
|
33
|
+
const keys = new Set(Object.keys(props));
|
|
34
|
+
const defaulted = /* @__PURE__ */ new Set();
|
|
35
|
+
for (const key in defaultProps) if (props[key] === void 0) {
|
|
36
|
+
keys.add(key);
|
|
37
|
+
defaulted.add(key);
|
|
38
|
+
}
|
|
39
|
+
return Object.keys(elementProps).length === keys.size && [...keys].every((key) => Object.hasOwn(elementProps, key) && (defaulted.has(key) || Object.is(elementProps[key], props[key])));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `@vitejs/plugin-rsc` wraps a server component export whose module imports
|
|
43
|
+
* CSS (`__vite_rsc_wrap_css__`). The wrapper returns
|
|
44
|
+
* `<><Css /><Component {...props} /></>`, so a component vinext invokes
|
|
45
|
+
* directly renders as an element with its props after all. React's dev build
|
|
46
|
+
* serializes an element's props as debug info and calls `then` on `params`
|
|
47
|
+
* and `searchParams`, which counts as reading them. Invoke the inner
|
|
48
|
+
* component from an element without props instead, as for an export without
|
|
49
|
+
* CSS.
|
|
50
|
+
*/
|
|
51
|
+
function invokeCssWrappedComponent(result, props) {
|
|
52
|
+
if (!isValidElement(result) || result.type !== Fragment || result.key !== null) return result;
|
|
53
|
+
const children = result.props.children;
|
|
54
|
+
if (!Array.isArray(children) || children.length !== 2) return result;
|
|
55
|
+
const [css, inner] = children;
|
|
56
|
+
if (!isValidElement(inner) || typeof inner.type !== "function" || inner.key !== null) return result;
|
|
57
|
+
const component = inner.type;
|
|
58
|
+
if (!isElementOfProps(inner.props, props, component.defaultProps)) return result;
|
|
59
|
+
const componentProps = inner.props;
|
|
60
|
+
function CssWrappedComponent() {
|
|
61
|
+
return invokeAppComponent(component, componentProps);
|
|
62
|
+
}
|
|
63
|
+
CssWrappedComponent.displayName = component.displayName ?? component.name;
|
|
64
|
+
return createElement(Fragment, null, css, createElement(CssWrappedComponent));
|
|
25
65
|
}
|
|
26
66
|
const appElementRenderDependencies = /* @__PURE__ */ new WeakMap();
|
|
27
67
|
function registerAppElementRenderDependencies(elements, dependenciesByElementId) {
|
|
@@ -26,7 +26,7 @@ const rejectResponseStage = () => Promise.resolve(new Response(null, { status: 4
|
|
|
26
26
|
function handleRequestStage(request, env, ctx, dispatchResponseStage) {
|
|
27
27
|
const originalRequest = request;
|
|
28
28
|
const handleStage = async () => {
|
|
29
|
-
await __ensureInstrumentation();
|
|
29
|
+
await __ensureInstrumentation(ctx);
|
|
30
30
|
const url = new URL(request.url);
|
|
31
31
|
return traceFrameworkRequest({
|
|
32
32
|
callback: () => handleRequest(request, env, ctx, dispatchResponseStage, ctx?.assets).then((response) => applyCdnResponseIdentityHeaders(response, originalRequest)),
|
|
@@ -56,7 +56,7 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
|
|
|
56
56
|
if (validationResponse) return validationResponse;
|
|
57
57
|
didValidateCdnRequest = true;
|
|
58
58
|
if (readinessResponse.status !== 204) return readinessResponse;
|
|
59
|
-
await __ensureHybridPagesApplication();
|
|
59
|
+
await __ensureHybridPagesApplication(ctx);
|
|
60
60
|
}
|
|
61
61
|
let probeMode = null;
|
|
62
62
|
let probeRoute = null;
|
|
@@ -19,7 +19,7 @@ import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
|
|
|
19
19
|
/** Cacheable App response stage. This is the only multi-stage App entry that imports user routes. */
|
|
20
20
|
/** Invoke one transformed public cache function without rendering its owning route. */
|
|
21
21
|
async function invokeCacheFunction(invocation, env, platformCtx, dispatchRequestStage) {
|
|
22
|
-
await __ensureInstrumentation();
|
|
22
|
+
await __ensureInstrumentation(platformCtx);
|
|
23
23
|
const [{ loadServerAction }, { invokeCacheFunction: invokeRegisteredCacheFunction }] = await Promise.all([import("@vitejs/plugin-rsc/core/rsc"), import("../shims/cache-callable-runtime.js")]);
|
|
24
24
|
registerConfiguredCacheAdapters(env);
|
|
25
25
|
ensureFetchPatch();
|
|
@@ -37,8 +37,8 @@ async function handleResponseStage(request, env, platformCtx, props, dispatchReq
|
|
|
37
37
|
if (props.requestOrigin !== new URL(request.url).origin) return new Response("Invalid vinext App response stage", { status: 400 });
|
|
38
38
|
const currentBuildId = process.env.__VINEXT_BUILD_ID ?? null;
|
|
39
39
|
if (props.buildId !== currentBuildId) return new Response("Incompatible vinext App response stage", { status: 409 });
|
|
40
|
-
await __ensureInstrumentation();
|
|
41
|
-
if (props.kind === "app-full-request" && props.prerenderDiscovery) await __ensureHybridPagesApplication();
|
|
40
|
+
await __ensureInstrumentation(platformCtx);
|
|
41
|
+
if (props.kind === "app-full-request" && props.prerenderDiscovery) await __ensureHybridPagesApplication(platformCtx);
|
|
42
42
|
registerConfiguredImageOptimizer(env);
|
|
43
43
|
let ctx = createWorkerRevalidationContext(platformCtx, (internalRequest) => dispatchRequestStage(internalRequest), "node");
|
|
44
44
|
if (props.kind === "app-full-request" && props.prerenderDiscovery) ctx = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
1
|
+
import { closeAfterResponse, createRequestContext, getRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import "../utils/protocol-headers.js";
|
|
3
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
4
|
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
@@ -40,6 +40,7 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
|
|
|
40
40
|
const requestContext = createRequestContext({
|
|
41
41
|
headersContext,
|
|
42
42
|
executionContext: getRequestExecutionContext(),
|
|
43
|
+
phase: "route-handler",
|
|
43
44
|
unstableCacheRevalidation: "foreground"
|
|
44
45
|
});
|
|
45
46
|
const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
|
|
@@ -203,6 +204,7 @@ async function dispatchAppRouteHandlerImpl(options) {
|
|
|
203
204
|
return reportRequestError(error, request, context);
|
|
204
205
|
},
|
|
205
206
|
request: options.request,
|
|
207
|
+
requestSignal: getRequestContext().requestSignal ?? void 0,
|
|
206
208
|
expireSeconds: options.expireSeconds,
|
|
207
209
|
revalidateSeconds,
|
|
208
210
|
revalidateReason,
|
|
@@ -56,6 +56,8 @@ type RunAppRouteHandlerOptions = {
|
|
|
56
56
|
*/
|
|
57
57
|
params: AppRouteParams | null;
|
|
58
58
|
request: Request;
|
|
59
|
+
/** Host signal for the client connection; only the foreground request has one. */
|
|
60
|
+
requestSignal?: AbortSignal;
|
|
59
61
|
routePattern?: string;
|
|
60
62
|
setHeadersAccessPhase?: (phase: HeadersAccessPhase) => HeadersAccessPhase;
|
|
61
63
|
};
|
|
@@ -118,6 +118,7 @@ async function runAppRouteHandler(options) {
|
|
|
118
118
|
options.markDynamicUsage();
|
|
119
119
|
},
|
|
120
120
|
requestMode: options.dynamicConfig === "force-static" || options.dynamicConfig === "error" ? options.dynamicConfig : "auto",
|
|
121
|
+
signal: options.requestSignal,
|
|
121
122
|
staticGenerationErrorMessage(expression) {
|
|
122
123
|
return getAppRouteStaticGenerationErrorMessage(options.routePattern, expression);
|
|
123
124
|
}
|
|
@@ -210,10 +211,16 @@ async function executeAppRouteHandlerImpl(options) {
|
|
|
210
211
|
revalidateSeconds: options.revalidateSeconds,
|
|
211
212
|
requiresCompletedResponseAdmission: isRouteCacheabilityEvaluation()
|
|
212
213
|
})) {
|
|
213
|
-
const completed = await completeAppRouteHandlerResponse(response)
|
|
214
|
+
const completed = await completeAppRouteHandlerResponse(response).catch(async (error) => {
|
|
215
|
+
await _drainPendingRevalidations().catch(() => {});
|
|
216
|
+
throw error;
|
|
217
|
+
});
|
|
214
218
|
response = completed.response;
|
|
215
219
|
cleanupDeferredToBody = !completed.completed;
|
|
216
|
-
if (completed.completed)
|
|
220
|
+
if (completed.completed) {
|
|
221
|
+
markRouteCacheabilityResponseBodyComplete();
|
|
222
|
+
await _drainPendingRevalidations();
|
|
223
|
+
}
|
|
217
224
|
const dynamicUsedDuringCompletion = options.consumeDynamicUsage();
|
|
218
225
|
dynamicUsedInHandler = handlerResult.didAccessDynamicRequest() || dynamicUsedDuringCompletion || dynamicUsedInHandler;
|
|
219
226
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { MiddlewareResponseMergeOptions } from "./middleware-response-headers.js";
|
|
1
2
|
//#region src/server/app-route-handler-middleware-context.d.ts
|
|
2
3
|
export type RouteHandlerMiddlewareContext = {
|
|
3
4
|
headers: Headers | null;
|
|
4
5
|
status: number | null;
|
|
5
6
|
};
|
|
6
7
|
/** Apply request-stage middleware response metadata to a route-handler response. */
|
|
7
|
-
export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext): Response;
|
|
8
|
+
export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext, options?: MiddlewareResponseMergeOptions): Response;
|
|
8
9
|
//#endregion
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mergeMiddlewareResponseHeadersOntoResponse } from "./middleware-response-headers.js";
|
|
2
2
|
//#region src/server/app-route-handler-middleware-context.ts
|
|
3
3
|
/** Apply request-stage middleware response metadata to a route-handler response. */
|
|
4
|
-
function applyRouteHandlerMiddlewareContext(response, middlewareContext) {
|
|
4
|
+
function applyRouteHandlerMiddlewareContext(response, middlewareContext, options = {}) {
|
|
5
5
|
if (!middlewareContext.headers && middlewareContext.status == null) return response;
|
|
6
6
|
const responseHeaders = new Headers(response.headers);
|
|
7
|
-
|
|
7
|
+
mergeMiddlewareResponseHeadersOntoResponse(responseHeaders, middlewareContext.headers, options);
|
|
8
8
|
return new Response(response.body, {
|
|
9
9
|
status: middlewareContext.status ?? response.status,
|
|
10
10
|
statusText: response.statusText,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MiddlewareResponseMergeOptions } from "./middleware-response-headers.js";
|
|
1
2
|
import { CacheControlMetadata, CachedRouteValue } from "../shims/cache-handler.js";
|
|
2
3
|
//#region src/server/app-route-handler-response.d.ts
|
|
3
4
|
export type RouteHandlerMiddlewareContext = {
|
|
@@ -16,7 +17,7 @@ type FinalizeRouteHandlerResponseOptions = {
|
|
|
16
17
|
draftCookie?: string | null;
|
|
17
18
|
isHead: boolean;
|
|
18
19
|
};
|
|
19
|
-
export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext, options?: {
|
|
20
|
+
export declare function applyRouteHandlerMiddlewareContext(response: Response, middlewareContext: RouteHandlerMiddlewareContext, options?: MiddlewareResponseMergeOptions & {
|
|
20
21
|
appendResponseLink?: boolean;
|
|
21
22
|
}): Response;
|
|
22
23
|
export declare function assertSupportedAppRouteHandlerResponse(response: Response): void;
|
|
@@ -5,7 +5,7 @@ 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 {
|
|
8
|
+
import { mergeMiddlewareResponseHeadersOntoResponse } from "./middleware-response-headers.js";
|
|
9
9
|
import { markEdgeRouteHandlerLinkHeaders } from "./app-response-header-provenance.js";
|
|
10
10
|
import { getSetCookieName } from "./cookie-utils.js";
|
|
11
11
|
//#region src/server/app-route-handler-response.ts
|
|
@@ -22,7 +22,7 @@ function applyRouteHandlerMiddlewareContext(response, middlewareContext, options
|
|
|
22
22
|
return response;
|
|
23
23
|
}
|
|
24
24
|
const responseHeaders = new Headers(response.headers);
|
|
25
|
-
|
|
25
|
+
mergeMiddlewareResponseHeadersOntoResponse(responseHeaders, middlewareContext.headers, options);
|
|
26
26
|
if (responseLink && middlewareContext.headers?.get("link")) responseHeaders.append("link", responseLink);
|
|
27
27
|
const result = new Response(response.body, {
|
|
28
28
|
status: middlewareContext.status ?? response.status,
|
|
@@ -30,6 +30,8 @@ type TrackedAppRouteRequestOptions = {
|
|
|
30
30
|
middlewareHeaders?: Headers | null;
|
|
31
31
|
onDynamicAccess?: (access: AppRouteDynamicRequestAccess) => void;
|
|
32
32
|
requestMode?: AppRouteRequestMode;
|
|
33
|
+
/** Host signal for the client connection (UnifiedRequestContext.requestSignal). */
|
|
34
|
+
signal?: AbortSignal;
|
|
33
35
|
staticGenerationErrorMessage?: (expression?: string) => string;
|
|
34
36
|
};
|
|
35
37
|
type TrackedAppRouteRequest = {
|
|
@@ -72,7 +72,20 @@ function buildNextConfig(options) {
|
|
|
72
72
|
skipTrailingSlashRedirect: options.skipTrailingSlashRedirect
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Undici's Request follows its input's signal through a WeakRef, and so does
|
|
77
|
+
* every clone between the host signal and the handler's request. A handler
|
|
78
|
+
* 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 follows the host signal
|
|
80
|
+
* directly and stays reachable for as long as that signal is.
|
|
81
|
+
*/
|
|
82
|
+
const requestsByHostSignal = /* @__PURE__ */ new WeakMap();
|
|
83
|
+
function retainWhileSignalLives(signal, request) {
|
|
84
|
+
const requests = requestsByHostSignal.get(signal);
|
|
85
|
+
if (requests) requests.push(request);
|
|
86
|
+
else requestsByHostSignal.set(signal, [request]);
|
|
87
|
+
}
|
|
88
|
+
function createForceStaticNextRequest(input, nextConfig, signal) {
|
|
76
89
|
const read = (key) => {
|
|
77
90
|
const descriptor = BUILT_IN_REQUEST_PROPERTY_MAP.get(key)?.descriptor;
|
|
78
91
|
if (descriptor?.get) return descriptor.get.call(input);
|
|
@@ -89,7 +102,7 @@ function createForceStaticNextRequest(input, nextConfig) {
|
|
|
89
102
|
redirect: read("redirect"),
|
|
90
103
|
referrer: read("referrer"),
|
|
91
104
|
referrerPolicy: read("referrerPolicy"),
|
|
92
|
-
signal: read("signal"),
|
|
105
|
+
signal: signal ?? read("signal"),
|
|
93
106
|
nextConfig: nextConfig ?? void 0
|
|
94
107
|
});
|
|
95
108
|
}
|
|
@@ -215,7 +228,11 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
215
228
|
const sourceCfDescriptor = Reflect.getOwnPropertyDescriptor(requestWithOverrides, "cf");
|
|
216
229
|
const sourceCfAccessor = sourceCfDescriptor?.get;
|
|
217
230
|
const sourceCfMetadata = sourceCfAccessor ? void 0 : Reflect.get(requestWithOverrides, "cf", requestWithOverrides);
|
|
218
|
-
const nextRequest = requestMode === "force-static" ? createForceStaticNextRequest(requestWithOverrides, nextConfig) : requestWithOverrides instanceof NextRequest && sourceCfDescriptor?.configurable !== false ? requestWithOverrides : new NextRequest(requestWithOverrides, {
|
|
231
|
+
const nextRequest = requestMode === "force-static" ? createForceStaticNextRequest(requestWithOverrides, nextConfig, options.signal) : requestWithOverrides instanceof NextRequest && sourceCfDescriptor?.configurable !== false && !options.signal ? requestWithOverrides : new NextRequest(requestWithOverrides, {
|
|
232
|
+
nextConfig: nextConfig ?? void 0,
|
|
233
|
+
signal: options.signal
|
|
234
|
+
});
|
|
235
|
+
if (options.signal) retainWhileSignalLives(options.signal, nextRequest);
|
|
219
236
|
const rawCfMetadata = sourceCfAccessor ? void 0 : sourceCfMetadata === void 0 ? Reflect.get(nextRequest, "cf", nextRequest) : sourceCfMetadata;
|
|
220
237
|
const hasCfMetadata = sourceCfAccessor !== void 0 || rawCfMetadata !== void 0;
|
|
221
238
|
const originalCfDescriptor = sourceCfDescriptor ?? Reflect.getOwnPropertyDescriptor(nextRequest, "cf");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { runOutsideRequestScopes } from "../shims/internal/als-registry.js";
|
|
2
|
+
import { shareIsolatePromise } from "./isolate-shared-promise.js";
|
|
2
3
|
//#region src/server/app-route-module-loader.ts
|
|
3
4
|
/**
|
|
4
5
|
* Lazy route-module hydration for the App Router RSC entry.
|
|
@@ -63,7 +64,7 @@ async function hydrateInterceptModule(intercept, loader, field, loadingField) {
|
|
|
63
64
|
const cached = loadState?.[field];
|
|
64
65
|
if (cached != null) intercept[field] = cached;
|
|
65
66
|
if (!loader || intercept[field] != null) return;
|
|
66
|
-
const loading = loadState?.[loadingField] ?? runOutsideRequestScopes(loader).then((module) => {
|
|
67
|
+
const loading = loadState?.[loadingField] ?? shareIsolatePromise(runOutsideRequestScopes(loader).then((module) => {
|
|
67
68
|
intercept[field] = module;
|
|
68
69
|
if (loadState) {
|
|
69
70
|
loadState[field] = module;
|
|
@@ -73,7 +74,7 @@ async function hydrateInterceptModule(intercept, loader, field, loadingField) {
|
|
|
73
74
|
}).catch((error) => {
|
|
74
75
|
if (loadState) loadState[loadingField] = null;
|
|
75
76
|
throw error;
|
|
76
|
-
});
|
|
77
|
+
}));
|
|
77
78
|
if (loadState) loadState[loadingField] = loading;
|
|
78
79
|
intercept[field] = await loading;
|
|
79
80
|
}
|
|
@@ -92,13 +93,13 @@ function loadAppInterceptLayouts(intercept) {
|
|
|
92
93
|
pushArrayLoads(loads, intercept.interceptLayouts, intercept.__loadInterceptLayouts);
|
|
93
94
|
pushArrayLoads(loads, intercept.interceptLoadings, intercept.__loadInterceptLoadings);
|
|
94
95
|
if (loads.length === 0) return Promise.resolve(intercept.interceptLayouts ?? []);
|
|
95
|
-
const loading = Promise.all(loads).then(() => {
|
|
96
|
+
const loading = shareIsolatePromise(Promise.all(loads).then(() => {
|
|
96
97
|
if (loadState) loadState.interceptLayoutsLoading = null;
|
|
97
98
|
return intercept.interceptLayouts ?? [];
|
|
98
99
|
}).catch((error) => {
|
|
99
100
|
if (loadState) loadState.interceptLayoutsLoading = null;
|
|
100
101
|
throw error;
|
|
101
|
-
});
|
|
102
|
+
}));
|
|
102
103
|
if (loadState) loadState.interceptLayoutsLoading = loading;
|
|
103
104
|
return loading;
|
|
104
105
|
}
|
|
@@ -143,14 +144,14 @@ function ensureAppRouteModulesLoaded(route) {
|
|
|
143
144
|
route.__loaded = true;
|
|
144
145
|
return route;
|
|
145
146
|
}
|
|
146
|
-
const loading = Promise.all(loads).then(() => {
|
|
147
|
+
const loading = shareIsolatePromise(Promise.all(loads).then(() => {
|
|
147
148
|
route.__loaded = true;
|
|
148
149
|
route.__loading = null;
|
|
149
150
|
return route;
|
|
150
151
|
}).catch((error) => {
|
|
151
152
|
route.__loading = null;
|
|
152
153
|
throw error;
|
|
153
|
-
});
|
|
154
|
+
}));
|
|
154
155
|
route.__loading = loading;
|
|
155
156
|
return loading;
|
|
156
157
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AppElements } from "./app-elements-wire.js";
|
|
2
|
+
import "./app-elements.js";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
//#region src/server/app-route-tree.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Builds the App Router route tree after a sibling that the browser uses to
|
|
7
|
+
* write navigation history. Insertion effects run in tree order, so that
|
|
8
|
+
* sibling's effect runs before React mutates the route tree's DOM, like
|
|
9
|
+
* Next.js' HistoryUpdater.
|
|
10
|
+
*
|
|
11
|
+
* The server and the browser must render this same shape: a second child
|
|
12
|
+
* changes the useId values of everything below it, so SSR passes null in the
|
|
13
|
+
* sibling's place to keep hydrated ids matching.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createAppRouteTree(options: {
|
|
16
|
+
elements: AppElements;
|
|
17
|
+
historyCommit: ReactNode;
|
|
18
|
+
routeId: string;
|
|
19
|
+
}): ReactNode;
|
|
20
|
+
//#endregion
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ElementsContext, Slot } from "../shims/slot.js";
|
|
2
|
+
import { Fragment, createElement } from "react";
|
|
3
|
+
//#region src/server/app-route-tree.ts
|
|
4
|
+
/**
|
|
5
|
+
* Builds the App Router route tree after a sibling that the browser uses to
|
|
6
|
+
* write navigation history. Insertion effects run in tree order, so that
|
|
7
|
+
* sibling's effect runs before React mutates the route tree's DOM, like
|
|
8
|
+
* Next.js' HistoryUpdater.
|
|
9
|
+
*
|
|
10
|
+
* The server and the browser must render this same shape: a second child
|
|
11
|
+
* changes the useId values of everything below it, so SSR passes null in the
|
|
12
|
+
* sibling's place to keep hydrated ids matching.
|
|
13
|
+
*/
|
|
14
|
+
function createAppRouteTree(options) {
|
|
15
|
+
return createElement(Fragment, null, options.historyCommit, createElement(ElementsContext.Provider, { value: options.elements }, createElement(Slot, { id: options.routeId })));
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { createAppRouteTree };
|