vinext 1.0.1 → 1.1.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 +72 -1
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/prerender-paths.js +3 -78
- package/dist/build/prerender.js +33 -8
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +64 -43
- package/dist/index.d.ts +4 -1
- package/dist/index.js +59 -30
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- package/dist/server/app-browser-entry.js +11 -7
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +93 -10
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +63 -43
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +4 -4
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-route-handler-dispatch.js +1 -1
- package/dist/server/app-router-entry.js +3 -3
- package/dist/server/app-rsc-handler.d.ts +4 -0
- package/dist/server/app-rsc-handler.js +212 -96
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +6 -4
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cacheability-request.js +9 -5
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +12 -2
- package/dist/server/headers.d.ts +14 -0
- package/dist/server/headers.js +15 -1
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.js +2 -2
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-page-handler.js +21 -4
- package/dist/server/pages-request-stage-entry.js +8 -4
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +153 -69
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +165 -225
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +5 -4
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/fetch-cache.d.ts +6 -0
- package/dist/shims/fetch-cache.js +19 -1
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/headers-state.d.ts +0 -1
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +14 -4
- package/dist/shims/request-context.d.ts +9 -0
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +3 -3
|
@@ -29,6 +29,11 @@ type CapturedError = {
|
|
|
29
29
|
type RedirectBoundaryState = {
|
|
30
30
|
redirect: string | null;
|
|
31
31
|
redirectType: "push" | "replace" | null;
|
|
32
|
+
previousResetKey: string | null;
|
|
33
|
+
};
|
|
34
|
+
type RedirectBoundaryProps = {
|
|
35
|
+
children?: React.ReactNode;
|
|
36
|
+
resetKey?: string | null;
|
|
32
37
|
};
|
|
33
38
|
type ErrorBoundaryInnerProps = {
|
|
34
39
|
isImplicitRootErrorBoundary?: boolean;
|
|
@@ -39,18 +44,13 @@ export type ErrorBoundaryState = {
|
|
|
39
44
|
previousPathname: string | null;
|
|
40
45
|
previousResetKey: string | null;
|
|
41
46
|
};
|
|
42
|
-
export declare class RedirectErrorBoundary extends React.Component<{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
children?: React.ReactNode;
|
|
47
|
-
});
|
|
48
|
-
static getDerivedStateFromError(error: unknown): RedirectBoundaryState;
|
|
47
|
+
export declare class RedirectErrorBoundary extends React.Component<RedirectBoundaryProps, RedirectBoundaryState> {
|
|
48
|
+
constructor(props: RedirectBoundaryProps);
|
|
49
|
+
static getDerivedStateFromProps(props: RedirectBoundaryProps, state: RedirectBoundaryState): RedirectBoundaryState | null;
|
|
50
|
+
static getDerivedStateFromError(error: unknown): Omit<RedirectBoundaryState, "previousResetKey">;
|
|
49
51
|
render(): string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined> | null | undefined;
|
|
50
52
|
}
|
|
51
|
-
export declare function RedirectBoundary({ children }:
|
|
52
|
-
children?: React.ReactNode;
|
|
53
|
-
}): React.JSX.Element;
|
|
53
|
+
export declare function RedirectBoundary({ children, resetKey }: RedirectBoundaryProps): React.JSX.Element;
|
|
54
54
|
/**
|
|
55
55
|
* Generic ErrorBoundary used to wrap route segments with error.tsx.
|
|
56
56
|
* This must be a client component since error boundaries use
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
3
3
|
import { decodeRedirectError, isRedirectError } from "./navigation-errors.js";
|
|
4
4
|
import "./navigation-server.js";
|
|
5
|
-
import { useErrorBoundaryPathname, useErrorBoundaryRouter } from "./error-boundary-navigation.js";
|
|
5
|
+
import { isRedirectToCurrentUrl, useErrorBoundaryPathname, useErrorBoundaryRouter } from "./error-boundary-navigation.js";
|
|
6
6
|
import DefaultGlobalError from "./default-global-error.js";
|
|
7
7
|
import { handleAppNavigationFailure } from "../client/app-nav-failure-handler.js";
|
|
8
8
|
import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
|
|
@@ -43,9 +43,13 @@ function removeDevErrorRecoveryListener(listener) {
|
|
|
43
43
|
if (typeof window === "undefined") return;
|
|
44
44
|
window.removeEventListener(VINEXT_DEV_ERROR_RECOVERY_EVENT, listener);
|
|
45
45
|
}
|
|
46
|
-
function HandleRedirect({ redirect, redirectType, reset }) {
|
|
46
|
+
function HandleRedirect({ redirect, redirectType, reset, stopsSelfRedirect }) {
|
|
47
47
|
const router = useErrorBoundaryRouter();
|
|
48
48
|
React.useEffect(() => {
|
|
49
|
+
if (stopsSelfRedirect && isRedirectToCurrentUrl(redirect)) {
|
|
50
|
+
console.error("[vinext] redirect() resolved to the current URL — not following it, to prevent an infinite loop.");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
49
53
|
React.startTransition(() => {
|
|
50
54
|
if (redirectType === "push") router.push(redirect);
|
|
51
55
|
else router.replace(redirect);
|
|
@@ -55,7 +59,8 @@ function HandleRedirect({ redirect, redirectType, reset }) {
|
|
|
55
59
|
redirect,
|
|
56
60
|
redirectType,
|
|
57
61
|
reset,
|
|
58
|
-
router
|
|
62
|
+
router,
|
|
63
|
+
stopsSelfRedirect
|
|
59
64
|
]);
|
|
60
65
|
return null;
|
|
61
66
|
}
|
|
@@ -64,7 +69,17 @@ var RedirectErrorBoundary = class extends React.Component {
|
|
|
64
69
|
super(props);
|
|
65
70
|
this.state = {
|
|
66
71
|
redirect: null,
|
|
67
|
-
redirectType: null
|
|
72
|
+
redirectType: null,
|
|
73
|
+
previousResetKey: normalizeBoundaryResetKey(props.resetKey)
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
static getDerivedStateFromProps(props, state) {
|
|
77
|
+
const resetKey = normalizeBoundaryResetKey(props.resetKey);
|
|
78
|
+
if (resetKey === state.previousResetKey) return null;
|
|
79
|
+
return {
|
|
80
|
+
redirect: null,
|
|
81
|
+
redirectType: null,
|
|
82
|
+
previousResetKey: resetKey
|
|
68
83
|
};
|
|
69
84
|
}
|
|
70
85
|
static getDerivedStateFromError(error) {
|
|
@@ -90,13 +105,17 @@ var RedirectErrorBoundary = class extends React.Component {
|
|
|
90
105
|
reset: () => this.setState({
|
|
91
106
|
redirect: null,
|
|
92
107
|
redirectType: null
|
|
93
|
-
})
|
|
108
|
+
}),
|
|
109
|
+
stopsSelfRedirect: this.props.resetKey !== void 0
|
|
94
110
|
});
|
|
95
111
|
return this.props.children;
|
|
96
112
|
}
|
|
97
113
|
};
|
|
98
|
-
function RedirectBoundary({ children }) {
|
|
99
|
-
return /* @__PURE__ */ jsx(RedirectErrorBoundary, {
|
|
114
|
+
function RedirectBoundary({ children, resetKey }) {
|
|
115
|
+
return /* @__PURE__ */ jsx(RedirectErrorBoundary, {
|
|
116
|
+
resetKey,
|
|
117
|
+
children
|
|
118
|
+
});
|
|
100
119
|
}
|
|
101
120
|
/**
|
|
102
121
|
* Generic ErrorBoundary used to wrap route segments with error.tsx.
|
|
@@ -103,6 +103,12 @@ export declare function setRefreshStaleFetchesInForeground(enabled: boolean): vo
|
|
|
103
103
|
* try { await render(); } finally { cleanup(); }
|
|
104
104
|
*/
|
|
105
105
|
export declare function withFetchCache(): () => void;
|
|
106
|
+
/**
|
|
107
|
+
* Run `fn` with the request's fetch settings but its own record of the tags and
|
|
108
|
+
* URLs its fetches touch, so work done on the request's behalf after the fact
|
|
109
|
+
* (a background regeneration) leaves the request's response untouched.
|
|
110
|
+
*/
|
|
111
|
+
export declare function runWithDetachedFetchObservations<T>(fn: () => Promise<T>): Promise<T>;
|
|
106
112
|
/**
|
|
107
113
|
* Run an async function with patched fetch caching enabled.
|
|
108
114
|
* Uses `AsyncLocalStorage.run()` for proper per-request isolation
|
|
@@ -834,6 +834,24 @@ function withFetchCache() {
|
|
|
834
834
|
};
|
|
835
835
|
}
|
|
836
836
|
/**
|
|
837
|
+
* Run `fn` with the request's fetch settings but its own record of the tags and
|
|
838
|
+
* URLs its fetches touch, so work done on the request's behalf after the fact
|
|
839
|
+
* (a background regeneration) leaves the request's response untouched.
|
|
840
|
+
*/
|
|
841
|
+
function runWithDetachedFetchObservations(fn) {
|
|
842
|
+
if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((uCtx) => {
|
|
843
|
+
uCtx.cacheableFetchUrls = /* @__PURE__ */ new Set();
|
|
844
|
+
uCtx.currentRequestTags = [];
|
|
845
|
+
uCtx.dynamicFetchUrls = /* @__PURE__ */ new Set();
|
|
846
|
+
}, fn);
|
|
847
|
+
return _als.run({
|
|
848
|
+
..._getState(),
|
|
849
|
+
cacheableFetchUrls: /* @__PURE__ */ new Set(),
|
|
850
|
+
currentRequestTags: [],
|
|
851
|
+
dynamicFetchUrls: /* @__PURE__ */ new Set()
|
|
852
|
+
}, fn);
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
837
855
|
* Run an async function with patched fetch caching enabled.
|
|
838
856
|
* Uses `AsyncLocalStorage.run()` for proper per-request isolation
|
|
839
857
|
* of collected fetch tags in concurrent server environments.
|
|
@@ -897,4 +915,4 @@ function getOriginalFetch() {
|
|
|
897
915
|
return originalFetch;
|
|
898
916
|
}
|
|
899
917
|
//#endregion
|
|
900
|
-
export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekCacheableFetchObservations, peekDynamicFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground, withFetchCache };
|
|
918
|
+
export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekCacheableFetchObservations, peekDynamicFetchObservations, runWithDetachedFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground, withFetchCache };
|
package/dist/shims/form.js
CHANGED
|
@@ -4,9 +4,9 @@ import { VINEXT_MOUNTED_SLOTS_HEADER } from "../server/app-rsc-vary.js";
|
|
|
4
4
|
import "../server/headers.js";
|
|
5
5
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
6
6
|
import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
|
|
7
|
+
import { withBasePath } from "./url-utils.js";
|
|
7
8
|
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
8
9
|
import "../server/app-elements.js";
|
|
9
|
-
import { withBasePath } from "./url-utils.js";
|
|
10
10
|
import { createRscRequestHeaders, createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
|
|
11
11
|
import { hasAppNavigationRuntime } from "../client/navigation-runtime.js";
|
|
12
12
|
import { getMountedSlotsHeader, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
|
package/dist/shims/headers.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RenderRequestApiKind } from "../server/cache-proof.js";
|
|
2
|
+
import { CacheLifeConfig } from "./cache-request-state.js";
|
|
2
3
|
import { ConnectionProbeResult, HeadersAccessPhase, RenderDynamicLatch, VinextHeadersShimState, createRenderDynamicLatch, getHeadersAccessPhase, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "./internal/headers-state.js";
|
|
3
4
|
import { ReadonlyRequestCookies } from "@vinext/types/next/upstream/dist/server/web/spec-extension/adapters/request-cookies";
|
|
4
5
|
import { ResponseCookie } from "@vinext/types/next/upstream/dist/compiled/@edge-runtime/cookies/index";
|
|
@@ -27,6 +28,18 @@ export declare function runWithIsolatedDynamicUsage<T>(fn: () => T | Promise<T>)
|
|
|
27
28
|
result: T;
|
|
28
29
|
dynamicDetected: boolean;
|
|
29
30
|
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Run a pre-render probe without letting its dynamic API usage classify the
|
|
33
|
+
* request. Next.js has no probe: only the render decides whether a page is
|
|
34
|
+
* dynamic, and the render runs the probed layouts and page again. Returns the
|
|
35
|
+
* probe's own usage and cacheLife for a caller whose probe response replaces
|
|
36
|
+
* the render.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runWithDetachedDynamicUsage<T>(fn: () => T | Promise<T>): Promise<{
|
|
39
|
+
result: T;
|
|
40
|
+
dynamicDetected: boolean;
|
|
41
|
+
cacheLife: CacheLifeConfig | null;
|
|
42
|
+
}>;
|
|
30
43
|
export declare function runWithConnectionProbe<T>(fn: () => T | Promise<T>): Promise<ConnectionProbeResult<T>>;
|
|
31
44
|
export declare function suspendConnectionProbe(): Promise<never> | null;
|
|
32
45
|
export declare function peekRenderRequestApiUsage(): RenderRequestApiKind[];
|
package/dist/shims/headers.js
CHANGED
|
@@ -114,6 +114,49 @@ async function runWithIsolatedDynamicUsage(fn) {
|
|
|
114
114
|
};
|
|
115
115
|
return await headersShimAls.run(childState, () => runInChildState(childState));
|
|
116
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Run a pre-render probe without letting its dynamic API usage classify the
|
|
119
|
+
* request. Next.js has no probe: only the render decides whether a page is
|
|
120
|
+
* dynamic, and the render runs the probed layouts and page again. Returns the
|
|
121
|
+
* probe's own usage and cacheLife for a caller whose probe response replaces
|
|
122
|
+
* the render.
|
|
123
|
+
*/
|
|
124
|
+
async function runWithDetachedDynamicUsage(fn) {
|
|
125
|
+
const runInChildState = async (childState, cacheLifeSink) => {
|
|
126
|
+
return {
|
|
127
|
+
result: await fn(),
|
|
128
|
+
cacheLife: cacheLifeSink?.cacheLife ?? null,
|
|
129
|
+
dynamicDetected: childState.dynamicUsageDetected || childState.renderDynamicLatch.dynamic
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
if (isInsideUnifiedScope()) {
|
|
133
|
+
let childState = null;
|
|
134
|
+
const cacheLifeSink = { cacheLife: null };
|
|
135
|
+
return await runWithUnifiedStateMutation((context) => {
|
|
136
|
+
context.cacheLifeSink = cacheLifeSink;
|
|
137
|
+
context.dynamicUsageDetected = false;
|
|
138
|
+
context.renderDynamicLatch = createRenderDynamicLatch();
|
|
139
|
+
context.renderRequestApiUsage = /* @__PURE__ */ new Set();
|
|
140
|
+
context.requestCache = /* @__PURE__ */ new WeakMap();
|
|
141
|
+
context.cacheableFetchUrls = /* @__PURE__ */ new Set();
|
|
142
|
+
context.currentRequestTags = [];
|
|
143
|
+
context.dynamicFetchUrls = /* @__PURE__ */ new Set();
|
|
144
|
+
context.requestScopedCacheLife = null;
|
|
145
|
+
context.unstableCacheObservations = /* @__PURE__ */ new Map();
|
|
146
|
+
childState = context;
|
|
147
|
+
}, () => {
|
|
148
|
+
if (!childState) throw new Error("Dynamic usage scope was not initialized");
|
|
149
|
+
return runInChildState(childState, cacheLifeSink);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const childState = {
|
|
153
|
+
...getHeadersShimState(),
|
|
154
|
+
dynamicUsageDetected: false,
|
|
155
|
+
renderDynamicLatch: createRenderDynamicLatch(),
|
|
156
|
+
renderRequestApiUsage: /* @__PURE__ */ new Set()
|
|
157
|
+
};
|
|
158
|
+
return await headersShimAls.run(childState, () => runInChildState(childState, null));
|
|
159
|
+
}
|
|
117
160
|
async function runWithConnectionProbe(fn) {
|
|
118
161
|
const parentState = getHeadersShimState();
|
|
119
162
|
const parentInvalidDynamicUsageError = parentState.invalidDynamicUsageError;
|
|
@@ -129,8 +172,7 @@ async function runWithConnectionProbe(fn) {
|
|
|
129
172
|
if (probe.interrupted) return;
|
|
130
173
|
probe.interrupted = true;
|
|
131
174
|
interruptProbe();
|
|
132
|
-
}
|
|
133
|
-
pending: new Promise(() => {})
|
|
175
|
+
}
|
|
134
176
|
};
|
|
135
177
|
const runInChildState = async (childState) => {
|
|
136
178
|
try {
|
|
@@ -141,6 +183,7 @@ async function runWithConnectionProbe(fn) {
|
|
|
141
183
|
return await Promise.race([completed, interrupted]);
|
|
142
184
|
} finally {
|
|
143
185
|
probe.active = false;
|
|
186
|
+
interruptProbe();
|
|
144
187
|
childState.connectionProbe = parentState.connectionProbe ?? probe;
|
|
145
188
|
if (childState.dynamicUsageDetected) parentState.dynamicUsageDetected = true;
|
|
146
189
|
if (childState.invalidDynamicUsageError !== parentInvalidDynamicUsageError && parentState.invalidDynamicUsageError === parentInvalidDynamicUsageError) parentState.invalidDynamicUsageError = childState.invalidDynamicUsageError;
|
|
@@ -167,7 +210,7 @@ function suspendConnectionProbe() {
|
|
|
167
210
|
const probe = getHeadersShimState().connectionProbe;
|
|
168
211
|
if (!probe?.active) return null;
|
|
169
212
|
probe.interrupt();
|
|
170
|
-
return
|
|
213
|
+
return new Promise(() => {});
|
|
171
214
|
}
|
|
172
215
|
function peekRenderRequestApiUsage() {
|
|
173
216
|
return [...getHeadersShimState().renderRequestApiUsage].sort();
|
|
@@ -834,4 +877,4 @@ function serializeMutableCookie(cookie) {
|
|
|
834
877
|
});
|
|
835
878
|
}
|
|
836
879
|
//#endregion
|
|
837
|
-
export { applyEffectiveRequestCookieHeader, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, createRenderDynamicLatch, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getEffectiveRequestCookieHeader, getHeadersAccessPhase, getHeadersContext, hasDraftModeCookieHeader, hasEffectiveRequestCookieChanges, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, peekDynamicUsage, peekRenderRequestApiUsage, replaceHeadersContext, restoreDraftModeTransition, runWithConnectionProbe, runWithHeadersContext, runWithIsolatedDynamicUsage, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
|
|
880
|
+
export { applyEffectiveRequestCookieHeader, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, createRenderDynamicLatch, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getEffectiveRequestCookieHeader, getHeadersAccessPhase, getHeadersContext, hasDraftModeCookieHeader, hasEffectiveRequestCookieChanges, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, peekDynamicUsage, peekRenderRequestApiUsage, replaceHeadersContext, restoreDraftModeTransition, runWithConnectionProbe, runWithDetachedDynamicUsage, runWithHeadersContext, runWithIsolatedDynamicUsage, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* props before a server component is invoked.
|
|
6
6
|
*/
|
|
7
7
|
export declare const APP_PAGE_USE_CACHE_MARKER = "$$isPage";
|
|
8
|
-
export declare function markAppPagePropsForUseCache<T extends object>(props: T): T;
|
|
9
|
-
export declare function isMarkedAppPagePropsObject(value: object): boolean;
|
|
10
8
|
/**
|
|
11
9
|
* Whether `fn` is a transformed `"use cache"` function, including a bound
|
|
12
10
|
* one. Like Next.js's `isUseCacheFunction`, this survives `.bind()`: React's
|
|
@@ -23,6 +21,8 @@ export declare function isUseCacheFunctionReference(fn: unknown): boolean;
|
|
|
23
21
|
* module, or bound.
|
|
24
22
|
*/
|
|
25
23
|
export declare function withUseCachePageMarker<T extends Record<string, unknown>>(fn: unknown, props: T): T;
|
|
24
|
+
/** Layout components and their metadata resolvers retain framework params too. */
|
|
25
|
+
export declare function withUseCacheLayoutMarker<T extends Record<string, unknown>>(fn: unknown, props: T): T;
|
|
26
26
|
/**
|
|
27
27
|
* Whether `value` is page props carrying the `$$isPage` marker. Only plain
|
|
28
28
|
* objects qualify: the framework always passes a plain props object, and
|
|
@@ -30,4 +30,7 @@ export declare function withUseCachePageMarker<T extends Record<string, unknown>
|
|
|
30
30
|
* observed as a param access.
|
|
31
31
|
*/
|
|
32
32
|
export declare function hasUseCachePageMarker(value: unknown): value is Record<string, unknown>;
|
|
33
|
+
export declare function hasUseCacheLayoutMarker(value: unknown): value is Record<string, unknown>;
|
|
34
|
+
/** Remove only this invocation's marker before Flight keys and decodes props. */
|
|
35
|
+
export declare function withoutUseCacheSegmentMarker(props: Record<string, unknown>, isPage: boolean): Record<string, unknown>;
|
|
33
36
|
//#endregion
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
//#region src/shims/internal/app-page-props-cache-key.ts
|
|
2
|
-
const APP_PAGE_PROPS_CACHE_KEY_MARKER = Symbol.for("vinext.appPagePropsCacheKeyMarker");
|
|
3
2
|
const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
|
|
4
3
|
const SERVER_REFERENCE_TAG = Symbol.for("react.server.reference");
|
|
5
4
|
/**
|
|
@@ -15,18 +14,8 @@ const USE_CACHE_SERVER_REFERENCE_ID_RE = /#\$\$vinext_cache_[0-9a-f]{64}$/;
|
|
|
15
14
|
* props before a server component is invoked.
|
|
16
15
|
*/
|
|
17
16
|
const APP_PAGE_USE_CACHE_MARKER = "$$isPage";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
configurable: false,
|
|
21
|
-
enumerable: false,
|
|
22
|
-
value: true,
|
|
23
|
-
writable: false
|
|
24
|
-
});
|
|
25
|
-
return props;
|
|
26
|
-
}
|
|
27
|
-
function isMarkedAppPagePropsObject(value) {
|
|
28
|
-
return Reflect.get(value, APP_PAGE_PROPS_CACHE_KEY_MARKER) === true;
|
|
29
|
-
}
|
|
17
|
+
/** Layout marker, matching Next.js's `$$isLayout` prop (create-component-tree.tsx). */
|
|
18
|
+
const APP_LAYOUT_USE_CACHE_MARKER = "$$isLayout";
|
|
30
19
|
/**
|
|
31
20
|
* Whether `fn` is a transformed `"use cache"` function, including a bound
|
|
32
21
|
* one. Like Next.js's `isUseCacheFunction`, this survives `.bind()`: React's
|
|
@@ -53,6 +42,13 @@ function withUseCachePageMarker(fn, props) {
|
|
|
53
42
|
[APP_PAGE_USE_CACHE_MARKER]: true
|
|
54
43
|
} : props;
|
|
55
44
|
}
|
|
45
|
+
/** Layout components and their metadata resolvers retain framework params too. */
|
|
46
|
+
function withUseCacheLayoutMarker(fn, props) {
|
|
47
|
+
return isUseCacheFunctionReference(fn) ? {
|
|
48
|
+
...props,
|
|
49
|
+
[APP_LAYOUT_USE_CACHE_MARKER]: true
|
|
50
|
+
} : props;
|
|
51
|
+
}
|
|
56
52
|
/**
|
|
57
53
|
* Whether `value` is page props carrying the `$$isPage` marker. Only plain
|
|
58
54
|
* objects qualify: the framework always passes a plain props object, and
|
|
@@ -60,9 +56,22 @@ function withUseCachePageMarker(fn, props) {
|
|
|
60
56
|
* observed as a param access.
|
|
61
57
|
*/
|
|
62
58
|
function hasUseCachePageMarker(value) {
|
|
59
|
+
return hasUseCacheSegmentMarker(value, APP_PAGE_USE_CACHE_MARKER);
|
|
60
|
+
}
|
|
61
|
+
function hasUseCacheLayoutMarker(value) {
|
|
62
|
+
return hasUseCacheSegmentMarker(value, APP_LAYOUT_USE_CACHE_MARKER);
|
|
63
|
+
}
|
|
64
|
+
/** Remove only this invocation's marker before Flight keys and decodes props. */
|
|
65
|
+
function withoutUseCacheSegmentMarker(props, isPage) {
|
|
66
|
+
const marker = isPage ? APP_PAGE_USE_CACHE_MARKER : APP_LAYOUT_USE_CACHE_MARKER;
|
|
67
|
+
if (props[marker] !== true) return props;
|
|
68
|
+
const { [marker]: _marker, ...segmentProps } = props;
|
|
69
|
+
return segmentProps;
|
|
70
|
+
}
|
|
71
|
+
function hasUseCacheSegmentMarker(value, marker) {
|
|
63
72
|
if (value === null || typeof value !== "object") return false;
|
|
64
73
|
const prototype = Object.getPrototypeOf(value);
|
|
65
|
-
return (prototype === Object.prototype || prototype === null) && value[
|
|
74
|
+
return (prototype === Object.prototype || prototype === null) && value[marker] === true;
|
|
66
75
|
}
|
|
67
76
|
//#endregion
|
|
68
|
-
export { APP_PAGE_USE_CACHE_MARKER,
|
|
77
|
+
export { APP_PAGE_USE_CACHE_MARKER, hasUseCacheLayoutMarker, hasUseCachePageMarker, isUseCacheFunctionReference, withUseCacheLayoutMarker, withUseCachePageMarker, withoutUseCacheSegmentMarker };
|
package/dist/shims/metadata.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isAbsoluteOrProtocolRelativeUrl } from "./url-utils.js";
|
|
2
|
+
import { withUseCacheLayoutMarker, withUseCachePageMarker } from "./internal/app-page-props-cache-key.js";
|
|
2
3
|
import { makeThenableParams } from "./thenable-params.js";
|
|
3
|
-
import { withUseCachePageMarker } from "./internal/app-page-props-cache-key.js";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/shims/metadata.tsx
|
|
@@ -19,7 +19,7 @@ const USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL = Symbol.for("vinext.useCacheAcce
|
|
|
19
19
|
async function resolveModuleViewport(mod, params = {}, searchParams, parent = Promise.resolve(mergeViewport([])), searchParamsObserver) {
|
|
20
20
|
if (typeof mod.generateViewport === "function") {
|
|
21
21
|
const asyncParams = makeThenableParams(params);
|
|
22
|
-
const props = searchParams === void 0 ? { params: asyncParams } : withUseCachePageMarker(mod.generateViewport, {
|
|
22
|
+
const props = searchParams === void 0 ? withUseCacheLayoutMarker(mod.generateViewport, { params: asyncParams }) : withUseCachePageMarker(mod.generateViewport, {
|
|
23
23
|
params: asyncParams,
|
|
24
24
|
searchParams: makeThenableParams(searchParams, searchParamsObserver)
|
|
25
25
|
});
|
|
@@ -268,7 +268,7 @@ async function resolveModuleMetadata(mod, params = {}, searchParams, parent = Pr
|
|
|
268
268
|
if (typeof mod.generateMetadata === "function") {
|
|
269
269
|
const generateMetadata = mod.generateMetadata;
|
|
270
270
|
const asyncParams = makeThenableParams(params);
|
|
271
|
-
const props = searchParams === void 0 ? { params: asyncParams } : withUseCachePageMarker(generateMetadata, {
|
|
271
|
+
const props = searchParams === void 0 ? withUseCacheLayoutMarker(generateMetadata, { params: asyncParams }) : withUseCachePageMarker(generateMetadata, {
|
|
272
272
|
params: asyncParams,
|
|
273
273
|
searchParams: makeThenableParams(searchParams, searchParamsObserver)
|
|
274
274
|
});
|
|
@@ -12,6 +12,12 @@ export declare enum RedirectType {
|
|
|
12
12
|
push = "push",
|
|
13
13
|
replace = "replace"
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Whether `error` was thrown by redirect(), notFound() or another navigation
|
|
17
|
+
* function in the render that caught it, rather than decoded from an RSC
|
|
18
|
+
* render's digest.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isThrownNavigationError(error: unknown): boolean;
|
|
15
21
|
/**
|
|
16
22
|
* The omitted redirect type is resolved by the catch site: push for Server
|
|
17
23
|
* Actions and replace for ordinary SSR/RSC rendering.
|
|
@@ -25,14 +25,24 @@ let RedirectType = /* @__PURE__ */ function(RedirectType) {
|
|
|
25
25
|
RedirectType["replace"] = "replace";
|
|
26
26
|
return RedirectType;
|
|
27
27
|
}({});
|
|
28
|
+
const THROWN_NAVIGATION_ERROR_MARKER = Symbol.for("vinext.navigationError.thrown");
|
|
28
29
|
var VinextNavigationError = class extends Error {
|
|
29
30
|
digest;
|
|
31
|
+
[THROWN_NAVIGATION_ERROR_MARKER] = true;
|
|
30
32
|
constructor(message, digest) {
|
|
31
33
|
super(message);
|
|
32
34
|
this.digest = digest;
|
|
33
35
|
}
|
|
34
36
|
};
|
|
35
37
|
/**
|
|
38
|
+
* Whether `error` was thrown by redirect(), notFound() or another navigation
|
|
39
|
+
* function in the render that caught it, rather than decoded from an RSC
|
|
40
|
+
* render's digest.
|
|
41
|
+
*/
|
|
42
|
+
function isThrownNavigationError(error) {
|
|
43
|
+
return typeof error === "object" && error !== null && Reflect.get(error, THROWN_NAVIGATION_ERROR_MARKER) === true;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
36
46
|
* The omitted redirect type is resolved by the catch site: push for Server
|
|
37
47
|
* Actions and replace for ordinary SSR/RSC rendering.
|
|
38
48
|
*/
|
|
@@ -103,4 +113,4 @@ function unstable_rethrow(error) {
|
|
|
103
113
|
if (error instanceof Error && "cause" in error) unstable_rethrow(error.cause);
|
|
104
114
|
}
|
|
105
115
|
//#endregion
|
|
106
|
-
export { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow };
|
|
116
|
+
export { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, isThrownNavigationError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow };
|
|
@@ -49,6 +49,13 @@ export type CachedRscResponse = {
|
|
|
49
49
|
mountedSlotsHeader?: string | null;
|
|
50
50
|
paramsHeader: string | null;
|
|
51
51
|
preparedElements?: AppElements;
|
|
52
|
+
/**
|
|
53
|
+
* Streamed `redirect()` side-channel headers. A replayed snapshot must keep
|
|
54
|
+
* them so the navigation follows the redirect instead of decoding the
|
|
55
|
+
* redirect payload as a page.
|
|
56
|
+
*/
|
|
57
|
+
redirectHeader?: string;
|
|
58
|
+
redirectTypeHeader?: string;
|
|
52
59
|
renderedPathAndSearch: string | null;
|
|
53
60
|
serverStaleTime?: ServerStaleTime;
|
|
54
61
|
url: string;
|
package/dist/shims/navigation.js
CHANGED
|
@@ -2,16 +2,16 @@ import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
|
2
2
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
3
3
|
import { stripBasePath } from "../utils/base-path.js";
|
|
4
4
|
import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "../server/app-rsc-vary.js";
|
|
5
|
-
import { NEXT_ROUTER_STALE_TIME_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_STALE_TIME_PENDING_HEADER } from "../server/headers.js";
|
|
5
|
+
import { NEXT_ROUTER_STALE_TIME_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_STALE_TIME_PENDING_HEADER } from "../server/headers.js";
|
|
6
6
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
7
7
|
import { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
|
|
8
|
-
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
9
|
-
import "../server/app-elements.js";
|
|
10
8
|
import { getPprFallbackShellState, markPprFallbackShellDynamicBoundary } from "./ppr-fallback-shell.js";
|
|
11
9
|
import { AppRouterContext } from "./internal/app-router-context.js";
|
|
12
10
|
import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-route-owner-direct.js";
|
|
13
11
|
import { isHashOnlyBrowserUrlChange, toCanonicalBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
|
|
14
12
|
import { retryScrollTo, scrollToHashTarget, scrollToHashTargetOnNextFrame } from "./hash-scroll.js";
|
|
13
|
+
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
14
|
+
import "../server/app-elements.js";
|
|
15
15
|
import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearClientHydrationContext, clearServerInsertedHTML, flushServerInsertedHTML, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getLayoutSegmentContext, getNavigationContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
|
|
16
16
|
import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
|
|
17
17
|
import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
|
|
@@ -662,6 +662,8 @@ function createCachedRscResponseSnapshot(response, buffer, responseUrl = null) {
|
|
|
662
662
|
kind: "resolved",
|
|
663
663
|
seconds: extracted.metadata.serverStaleTimeSeconds
|
|
664
664
|
} : parsedServerStaleTime;
|
|
665
|
+
const redirectHeader = response.headers.get(VINEXT_RSC_REDIRECT_HEADER);
|
|
666
|
+
const redirectTypeHeader = response.headers.get(VINEXT_RSC_REDIRECT_TYPE_HEADER);
|
|
665
667
|
return {
|
|
666
668
|
compatibilityIdHeader: response.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
|
|
667
669
|
buffer: extracted.buffer,
|
|
@@ -670,6 +672,8 @@ function createCachedRscResponseSnapshot(response, buffer, responseUrl = null) {
|
|
|
670
672
|
...dynamicStaleTimeSeconds !== void 0 ? { dynamicStaleTimeSeconds } : {},
|
|
671
673
|
mountedSlotsHeader: response.headers.get(VINEXT_MOUNTED_SLOTS_HEADER),
|
|
672
674
|
paramsHeader: response.headers.get(VINEXT_PARAMS_HEADER),
|
|
675
|
+
...redirectHeader === null ? {} : { redirectHeader },
|
|
676
|
+
...redirectTypeHeader === null ? {} : { redirectTypeHeader },
|
|
673
677
|
renderedPathAndSearch: parseRenderedPathAndSearchHeader(response.headers.get(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER)),
|
|
674
678
|
...serverStaleTime === void 0 ? {} : { serverStaleTime },
|
|
675
679
|
url: responseUrl ?? response.url
|
|
@@ -739,6 +743,8 @@ function restoreRscResponse(cached, copy = true) {
|
|
|
739
743
|
if (cached.serverStaleTime?.kind === "pending") headers.set(VINEXT_STALE_TIME_PENDING_HEADER, "1");
|
|
740
744
|
else if (cached.serverStaleTime !== void 0) headers.set(NEXT_ROUTER_STALE_TIME_HEADER, String(cached.serverStaleTime.seconds));
|
|
741
745
|
if (cached.paramsHeader != null) headers.set(VINEXT_PARAMS_HEADER, cached.paramsHeader);
|
|
746
|
+
if (cached.redirectHeader !== void 0) headers.set(VINEXT_RSC_REDIRECT_HEADER, cached.redirectHeader);
|
|
747
|
+
if (cached.redirectTypeHeader !== void 0) headers.set(VINEXT_RSC_REDIRECT_TYPE_HEADER, cached.redirectTypeHeader);
|
|
742
748
|
if (cached.renderedPathAndSearch != null) headers.set(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, encodeURIComponent(cached.renderedPathAndSearch));
|
|
743
749
|
const response = new Response(copy ? cached.buffer.slice(0) : cached.buffer, {
|
|
744
750
|
status: 200,
|
|
@@ -826,7 +832,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
|
|
|
826
832
|
entry.size = snapshot.buffer.byteLength;
|
|
827
833
|
adjustPrefetchCacheByteSize(cache, entry.size - previousSize);
|
|
828
834
|
entry.expiresAt = resolvePrefetchedRscResponseExpiresAt(entry.timestamp, entry.snapshot, behavior.fallbackTtlMs ?? PREFETCH_CACHE_TTL, behavior.searchAgnosticShell === true ? "ignore" : behavior.dynamicStaleTime ?? (behavior.optimisticRouteShell === true ? "ignore" : "verbatim"));
|
|
829
|
-
if (behavior.prepareSnapshot) try {
|
|
835
|
+
if (behavior.prepareSnapshot && snapshot.redirectHeader === void 0) try {
|
|
830
836
|
const preparedElements = await behavior.prepareSnapshot(snapshot);
|
|
831
837
|
if (cache.get(cacheKey) !== entry) return;
|
|
832
838
|
entry.preparedElements = preparedElements;
|
|
@@ -1781,6 +1787,7 @@ if (!isServer) {
|
|
|
1781
1787
|
}
|
|
1782
1788
|
});
|
|
1783
1789
|
window.history.pushState = function patchedPushState(data, unused, url) {
|
|
1790
|
+
getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
|
|
1784
1791
|
if (isAppOwnedHistoryState(data)) {
|
|
1785
1792
|
const previousHistoryState = window.history.state;
|
|
1786
1793
|
state.originalPushState.call(window.history, data, unused, url);
|
|
@@ -1792,10 +1799,12 @@ if (!isServer) {
|
|
|
1792
1799
|
getNavigationRuntime()?.functions.claimCurrentHistoryTreeSnapshot?.("push", previousHistoryState);
|
|
1793
1800
|
if (state.suppressUrlNotifyCount === 0) {
|
|
1794
1801
|
resetStaleLinkStatus();
|
|
1802
|
+
if (url) getNavigationRuntime()?.functions.discardPendingNavigation?.();
|
|
1795
1803
|
commitClientNavigationState();
|
|
1796
1804
|
}
|
|
1797
1805
|
};
|
|
1798
1806
|
window.history.replaceState = function patchedReplaceState(data, unused, url) {
|
|
1807
|
+
getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
|
|
1799
1808
|
if (isAppOwnedHistoryState(data)) {
|
|
1800
1809
|
const previousHistoryState = window.history.state;
|
|
1801
1810
|
state.originalReplaceState.call(window.history, data, unused, url);
|
|
@@ -1807,6 +1816,7 @@ if (!isServer) {
|
|
|
1807
1816
|
getNavigationRuntime()?.functions.claimCurrentHistoryTreeSnapshot?.("replace", previousHistoryState);
|
|
1808
1817
|
if (state.suppressUrlNotifyCount === 0) {
|
|
1809
1818
|
resetStaleLinkStatus();
|
|
1819
|
+
if (url) getNavigationRuntime()?.functions.discardPendingNavigation?.();
|
|
1810
1820
|
commitClientNavigationState();
|
|
1811
1821
|
}
|
|
1812
1822
|
};
|
|
@@ -44,6 +44,15 @@ export type ExecutionContextLike = {
|
|
|
44
44
|
isInternalPagesRevalidation?: boolean;
|
|
45
45
|
/** Marks a build-secret-authorized Worker request that may run prerender discovery hooks. */
|
|
46
46
|
isPrerenderPathDiscovery?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Installed only by the prerender server: records the page's special error
|
|
49
|
+
* that escaped the shell, with the headers to store, for the build.
|
|
50
|
+
*/
|
|
51
|
+
recordPrerenderSpecialError?: (marker: PrerenderSpecialErrorMarker) => void;
|
|
52
|
+
};
|
|
53
|
+
export type PrerenderSpecialErrorMarker = {
|
|
54
|
+
headers: Record<string, string>;
|
|
55
|
+
status: number;
|
|
47
56
|
};
|
|
48
57
|
/**
|
|
49
58
|
* Run `fn` with the given `ExecutionContext` available via
|
|
@@ -5,5 +5,9 @@ export type ThenableParamsObserver = Readonly<{
|
|
|
5
5
|
observeParamAccess: (keys: readonly string[]) => void;
|
|
6
6
|
observeReactPromiseStatus?: boolean;
|
|
7
7
|
}>;
|
|
8
|
+
/** Serialize backing values without reading a framework fallback-key proxy. */
|
|
9
|
+
export declare function getFallbackParamsSnapshot(value: unknown): Promise<Record<string, unknown>> | undefined;
|
|
10
|
+
/** Reattach only framework metadata; argument values always come from the decoder. */
|
|
11
|
+
export declare function restoreThenableParams<T extends Record<string, unknown>>(decoded: T, original: unknown): ThenableParams<T>;
|
|
8
12
|
export declare function makeThenableParams<T extends Record<string, unknown>>(obj: T, observer?: ThenableParamsObserver): ThenableParams<T>;
|
|
9
13
|
//#endregion
|
|
@@ -4,6 +4,20 @@ import { isOwnPropertyCheck, isWellKnownProperty } from "./internal/thenable-wel
|
|
|
4
4
|
function hasParamProperty(obj, prop) {
|
|
5
5
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
6
6
|
}
|
|
7
|
+
const paramsState = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function getParamsState(value) {
|
|
9
|
+
return value !== null && typeof value === "object" ? paramsState.get(value) : void 0;
|
|
10
|
+
}
|
|
11
|
+
/** Serialize backing values without reading a framework fallback-key proxy. */
|
|
12
|
+
function getFallbackParamsSnapshot(value) {
|
|
13
|
+
const state = getParamsState(value);
|
|
14
|
+
return state?.fallbackShellState ? Promise.resolve(state.plain) : void 0;
|
|
15
|
+
}
|
|
16
|
+
/** Reattach only framework metadata; argument values always come from the decoder. */
|
|
17
|
+
function restoreThenableParams(decoded, original) {
|
|
18
|
+
const state = getParamsState(original);
|
|
19
|
+
return createThenableParams(decoded, state?.observer, state?.fallbackShellState ?? null);
|
|
20
|
+
}
|
|
7
21
|
function observeParamKeys(observer, keys) {
|
|
8
22
|
if (observer) observer.observeParamAccess(keys);
|
|
9
23
|
}
|
|
@@ -81,8 +95,10 @@ function createThenableParamsProxy(promise, handler) {
|
|
|
81
95
|
return new Proxy(promise, handler);
|
|
82
96
|
}
|
|
83
97
|
function makeThenableParams(obj, observer) {
|
|
98
|
+
return createThenableParams(obj, observer, getPprFallbackShellState());
|
|
99
|
+
}
|
|
100
|
+
function createThenableParams(obj, observer, fallbackShellState) {
|
|
84
101
|
const plain = { ...obj };
|
|
85
|
-
const fallbackShellState = getPprFallbackShellState();
|
|
86
102
|
const fallbackParamNames = fallbackShellState && Object.keys(plain).some((key) => fallbackShellState.fallbackParamNames.has(key)) ? fallbackShellState.fallbackParamNames : null;
|
|
87
103
|
let fallbackShellPromise = null;
|
|
88
104
|
let fallbackShellPromiseController = null;
|
|
@@ -98,7 +114,7 @@ function makeThenableParams(obj, observer) {
|
|
|
98
114
|
function isFallbackParam(prop) {
|
|
99
115
|
return typeof prop === "string" && (fallbackParamNames?.has(prop) ?? false);
|
|
100
116
|
}
|
|
101
|
-
|
|
117
|
+
const params = createThenableParamsProxy(promise, {
|
|
102
118
|
get(target, prop, receiver) {
|
|
103
119
|
if (isPromiseContinuation(prop)) {
|
|
104
120
|
const value = Reflect.get(target, prop, receiver);
|
|
@@ -150,6 +166,12 @@ function makeThenableParams(obj, observer) {
|
|
|
150
166
|
return Reflect.ownKeys(plain).filter((prop) => !isWellKnownProperty(prop));
|
|
151
167
|
}
|
|
152
168
|
});
|
|
169
|
+
paramsState.set(params, {
|
|
170
|
+
plain,
|
|
171
|
+
observer,
|
|
172
|
+
fallbackShellState: fallbackParamNames ? fallbackShellState : null
|
|
173
|
+
});
|
|
174
|
+
return params;
|
|
153
175
|
}
|
|
154
176
|
//#endregion
|
|
155
|
-
export { makeThenableParams };
|
|
177
|
+
export { getFallbackParamsSnapshot, makeThenableParams, restoreThenableParams };
|
|
@@ -17,6 +17,7 @@ function createRequestContext(opts) {
|
|
|
17
17
|
return {
|
|
18
18
|
headersContext: null,
|
|
19
19
|
actionRevalidationKind: 0,
|
|
20
|
+
cacheLifeSink: null,
|
|
20
21
|
pendingRevalidatedTags: /* @__PURE__ */ new Set(),
|
|
21
22
|
pendingRevalidations: /* @__PURE__ */ new Set(),
|
|
22
23
|
dynamicUsageDetected: false,
|