vinext 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/THIRD_PARTY_LICENSES.md +26 -0
  2. package/dist/build/lifecycle.js +10 -10
  3. package/dist/build/pages-client-assets-module.js +6 -1
  4. package/dist/build/precompress.js +1 -1
  5. package/dist/build/prerender-paths.js +3 -7
  6. package/dist/build/prerender.d.ts +8 -1
  7. package/dist/build/prerender.js +134 -38
  8. package/dist/build/run-prerender.js +4 -3
  9. package/dist/build/server-entry.d.ts +2 -0
  10. package/dist/build/server-entry.js +7 -1
  11. package/dist/client/browser-globals.d.ts +4 -0
  12. package/dist/client/browser-globals.js +5 -0
  13. package/dist/client/navigation-runtime.d.ts +0 -1
  14. package/dist/client/navigation-runtime.js +2 -2
  15. package/dist/config/dotenv.js +14 -3
  16. package/dist/entries/app-rsc-entry.js +3 -2
  17. package/dist/index.js +142 -71
  18. package/dist/init-cloudflare.d.ts +1 -1
  19. package/dist/init-cloudflare.js +6 -6
  20. package/dist/init-platform.js +1 -1
  21. package/dist/init.js +4 -2
  22. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  23. package/dist/plugins/commonjs-syntax.js +22 -0
  24. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  25. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  26. package/dist/plugins/import-meta-url.js +6 -6
  27. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  28. package/dist/plugins/og-asset-ownership.js +24 -13
  29. package/dist/plugins/og-assets.d.ts +18 -0
  30. package/dist/plugins/og-assets.js +50 -8
  31. package/dist/plugins/og-harfbuzz.js +38 -27
  32. package/dist/plugins/optimize-imports.js +2 -1
  33. package/dist/plugins/require-context.d.ts +1 -0
  34. package/dist/plugins/require-context.js +28 -1
  35. package/dist/plugins/scan-build-css.d.ts +12 -0
  36. package/dist/plugins/scan-build-css.js +39 -0
  37. package/dist/plugins/strip-server-exports.d.ts +2 -0
  38. package/dist/plugins/strip-server-exports.js +3 -1
  39. package/dist/plugins/transform-result.d.ts +18 -0
  40. package/dist/plugins/transform-result.js +23 -2
  41. package/dist/plugins/typeof-window.d.ts +10 -0
  42. package/dist/plugins/typeof-window.js +33 -9
  43. package/dist/routing/app-route-graph.d.ts +0 -1
  44. package/dist/routing/app-route-graph.js +2 -4
  45. package/dist/routing/app-route-ids.d.ts +3 -0
  46. package/dist/routing/app-route-ids.js +6 -0
  47. package/dist/server/app-bfcache-id.d.ts +1 -0
  48. package/dist/server/app-bfcache-id.js +7 -1
  49. package/dist/server/app-bfcache-identity.js +1 -2
  50. package/dist/server/app-browser-entry.js +4 -2
  51. package/dist/server/app-browser-hydration.d.ts +1 -1
  52. package/dist/server/app-browser-hydration.js +2 -2
  53. package/dist/server/app-browser-navigation-controller.js +1 -1
  54. package/dist/server/app-browser-state.js +1 -1
  55. package/dist/server/app-browser-stream.d.ts +1 -1
  56. package/dist/server/app-history-state.d.ts +0 -1
  57. package/dist/server/app-history-state.js +2 -5
  58. package/dist/server/app-page-cache-render.js +2 -1
  59. package/dist/server/app-page-render.js +2 -1
  60. package/dist/server/app-page-search-params-observation.js +1 -1
  61. package/dist/server/app-page-stream.js +1 -1
  62. package/dist/server/app-page-tracing.js +2 -1
  63. package/dist/server/app-pages-bridge.js +3 -2
  64. package/dist/server/app-render-abort-error.d.ts +3 -0
  65. package/dist/server/app-render-abort-error.js +8 -0
  66. package/dist/server/app-request-stage-independent-entry.js +4 -7
  67. package/dist/server/app-route-handler-cache.d.ts +2 -1
  68. package/dist/server/app-route-handler-cache.js +11 -7
  69. package/dist/server/app-route-handler-dispatch.js +10 -3
  70. package/dist/server/app-route-handler-execution.d.ts +9 -1
  71. package/dist/server/app-route-handler-execution.js +28 -13
  72. package/dist/server/app-route-handler-policy.js +2 -2
  73. package/dist/server/app-route-handler-response.d.ts +1 -1
  74. package/dist/server/app-route-handler-response.js +14 -5
  75. package/dist/server/app-router-entry.d.ts +2 -1
  76. package/dist/server/app-router-entry.js +5 -9
  77. package/dist/server/app-rsc-errors.d.ts +0 -1
  78. package/dist/server/app-rsc-errors.js +2 -6
  79. package/dist/server/app-rsc-handler.d.ts +1 -0
  80. package/dist/server/app-rsc-handler.js +18 -7
  81. package/dist/server/app-rsc-request-normalization.d.ts +1 -1
  82. package/dist/server/app-rsc-request-normalization.js +3 -2
  83. package/dist/server/app-rsc-response-finalizer.js +4 -1
  84. package/dist/server/app-rsc-route-matching.js +1 -1
  85. package/dist/server/app-server-action-execution.d.ts +2 -1
  86. package/dist/server/app-ssr-entry.js +3 -3
  87. package/dist/server/app-ssr-search-params-gate.js +1 -1
  88. package/dist/server/app-ssr-stream.js +1 -1
  89. package/dist/server/cache-control.js +3 -11
  90. package/dist/server/cacheability-request.js +49 -49
  91. package/dist/server/config-headers.js +1 -1
  92. package/dist/server/dev-server.js +11 -3
  93. package/dist/server/headers.d.ts +2 -0
  94. package/dist/server/headers.js +5 -1
  95. package/dist/server/http-error-responses.js +1 -0
  96. package/dist/server/isr-cache.d.ts +2 -0
  97. package/dist/server/isr-cache.js +6 -1
  98. package/dist/server/metadata-route-response.js +94 -37
  99. package/dist/server/pages-api-route.js +8 -2
  100. package/dist/server/pages-asset-tags.d.ts +1 -0
  101. package/dist/server/pages-asset-tags.js +73 -22
  102. package/dist/server/pages-client-assets.d.ts +2 -0
  103. package/dist/server/pages-page-data.d.ts +6 -1
  104. package/dist/server/pages-page-data.js +71 -65
  105. package/dist/server/pages-page-handler.js +29 -11
  106. package/dist/server/pages-page-response.js +3 -1
  107. package/dist/server/pages-request-pipeline.d.ts +2 -1
  108. package/dist/server/pages-request-pipeline.js +20 -5
  109. package/dist/server/pages-request-stage-entry.js +6 -4
  110. package/dist/server/prerender-manifest.d.ts +6 -0
  111. package/dist/server/prerender-manifest.js +1 -1
  112. package/dist/server/prod-server.js +3 -13
  113. package/dist/server/response-stage-cacheability.js +1 -1
  114. package/dist/server/worker-revalidation-context.d.ts +2 -1
  115. package/dist/server/worker-revalidation-context.js +1 -0
  116. package/dist/server/workers-tracing.d.ts +17 -0
  117. package/dist/server/workers-tracing.js +48 -8
  118. package/dist/shims/cache-request-state.d.ts +3 -14
  119. package/dist/shims/cache-request-state.js +2 -13
  120. package/dist/shims/cache-runtime.js +4 -2
  121. package/dist/shims/cache.d.ts +2 -1
  122. package/dist/shims/cache.js +4 -2
  123. package/dist/shims/cacheability-classification.d.ts +1 -1
  124. package/dist/shims/cacheability-classification.js +2 -2
  125. package/dist/shims/cdn-cache.d.ts +10 -1
  126. package/dist/shims/cdn-cache.js +16 -9
  127. package/dist/shims/error.d.ts +4 -18
  128. package/dist/shims/error.js +17 -10
  129. package/dist/shims/error.react-server.d.ts +4 -6
  130. package/dist/shims/error.react-server.js +4 -1
  131. package/dist/shims/fetch-cache.js +4 -3
  132. package/dist/shims/headers.d.ts +6 -69
  133. package/dist/shims/headers.js +37 -181
  134. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  135. package/dist/shims/internal/cache-context-accessor.js +15 -0
  136. package/dist/shims/internal/headers-state.d.ts +74 -0
  137. package/dist/shims/internal/headers-state.js +157 -0
  138. package/dist/shims/navigation.js +2 -2
  139. package/dist/shims/request-state-types.d.ts +2 -1
  140. package/dist/shims/root-params.js +1 -1
  141. package/dist/shims/server.js +52 -2
  142. package/dist/shims/unified-request-context.d.ts +1 -1
  143. package/dist/utils/encode-cache-tag.d.ts +1 -0
  144. package/dist/utils/encode-cache-tag.js +11 -1
  145. package/dist/utils/vite-cli-invocation.js +8 -1
  146. package/package.json +6 -2
  147. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  148. package/dist/server/metadata-route-cache-policy.js +0 -6
@@ -13,9 +13,9 @@ import React from "react";
13
13
  * Used by apps that import `import Error from 'next/error'` for
14
14
  * custom error handling in getServerSideProps or API routes.
15
15
  *
16
- * Also re-exports the unstable App Router error-boundary HOC
17
- * (`unstable_catchError`) and its `ErrorInfo` type, mirroring
18
- * `next/error`'s public surface.
16
+ * Also exports the App Router error-boundary HOC (`catchError`, plus its
17
+ * former unstable name) and its `ErrorInfo` type, mirroring `next/error`'s
18
+ * public surface.
19
19
  */
20
20
  const statusCodes = {
21
21
  400: "Bad Request",
@@ -83,7 +83,7 @@ var ErrorComponent = class extends React.Component {
83
83
  const _CatchErrorAppRouterContext = AppRouterContext ?? React.createContext(null);
84
84
  var _CatchError = class extends React.Component {
85
85
  static contextType = _CatchErrorAppRouterContext;
86
- static displayName = "unstable_catchError(Next.CatchError)";
86
+ static displayName = "catchError(Next.CatchError)";
87
87
  constructor(props) {
88
88
  super(props);
89
89
  this.state = {
@@ -108,19 +108,24 @@ var _CatchError = class extends React.Component {
108
108
  reset = () => {
109
109
  this.setState({ error: null });
110
110
  };
111
- unstable_retry = () => {
112
- if (this.props.isPagesRouter) throw new Error("`unstable_retry()` can only be used in the App Router. Use `reset()` in the Pages Router.");
111
+ retry = () => {
112
+ if (this.props.isPagesRouter) throw new Error("`retry()` can only be used in the App Router. Use `reset()` in the Pages Router.");
113
113
  React.startTransition(() => {
114
114
  this.context?.refresh();
115
115
  this.reset();
116
116
  });
117
117
  };
118
+ unstable_retry = () => {
119
+ if (this.props.isPagesRouter) throw new Error("`unstable_retry()` can only be used in the App Router. Use `reset()` in the Pages Router.");
120
+ this.retry();
121
+ };
118
122
  render() {
119
123
  if (this.state.error) {
120
124
  const Fallback = this.props.fallback;
121
125
  const errorInfo = {
122
- error: this.state.error.thrownValue instanceof Error ? this.state.error.thrownValue : new Error(String(this.state.error.thrownValue)),
126
+ error: this.state.error.thrownValue,
123
127
  reset: this.reset,
128
+ retry: this.retry,
124
129
  unstable_retry: this.unstable_retry
125
130
  };
126
131
  return React.createElement(Fallback, {
@@ -139,7 +144,7 @@ var _CatchError = class extends React.Component {
139
144
  * Ported from Next.js:
140
145
  * https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/catch-error.tsx
141
146
  */
142
- function unstable_catchError(fallback) {
147
+ function createCatchError(fallback) {
143
148
  const Fallback = ({ props, errorInfo }) => fallback(props, errorInfo);
144
149
  Fallback.displayName = fallback.name || "CatchErrorFallback";
145
150
  function CatchErrorBoundary(allProps) {
@@ -154,8 +159,10 @@ function unstable_catchError(fallback) {
154
159
  props: forwardedProps
155
160
  }, children);
156
161
  }
157
- CatchErrorBoundary.displayName = `unstable_catchError(${fallback.name || "CatchErrorFallback"})`;
162
+ CatchErrorBoundary.displayName = `catchError(${fallback.name || "CatchErrorFallback"})`;
158
163
  return CatchErrorBoundary;
159
164
  }
165
+ const catchError = createCatchError;
166
+ const unstable_catchError = createCatchError;
160
167
  //#endregion
161
- export { ErrorComponent as default, unstable_catchError };
168
+ export { catchError, ErrorComponent as default, unstable_catchError };
@@ -1,8 +1,6 @@
1
+ import { ErrorInfo } from "./error.js";
1
2
  //#region src/shims/error.react-server.d.ts
2
- export type ErrorInfo = {
3
- error: unknown;
4
- reset: () => void;
5
- unstable_retry: () => void;
6
- };
7
3
  export declare function unstable_catchError(): never;
8
- //#endregion
4
+ export declare function catchError(): never;
5
+ //#endregion
6
+ export type { ErrorInfo };
@@ -2,5 +2,8 @@
2
2
  function unstable_catchError() {
3
3
  throw new Error("`unstable_catchError` can only be used in Client Components.");
4
4
  }
5
+ function catchError() {
6
+ throw new Error("`catchError` can only be used in Client Components.");
7
+ }
5
8
  //#endregion
6
- export { unstable_catchError };
9
+ export { catchError, unstable_catchError };
@@ -4,7 +4,8 @@ import { getRequestExecutionContext } from "./request-context.js";
4
4
  import { getDataCacheHandler } from "./cache-handler.js";
5
5
  import { encodeCacheTags } from "../utils/encode-cache-tag.js";
6
6
  import { traceAppFetch } from "../server/app-fetch-tracing.js";
7
- import { getHeadersContext, isInsideAnyCacheScope, markDynamicUsage } from "./headers.js";
7
+ import { isInsideAnyCacheScope, markDynamicUsage } from "./internal/headers-state.js";
8
+ import { getHeadersContext } from "./headers.js";
8
9
  import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife } from "./cache-request-state.js";
9
10
  import { Buffer } from "node:buffer";
10
11
  //#region src/shims/fetch-cache.ts
@@ -688,11 +689,12 @@ function createPatchedFetch() {
688
689
  recordDynamicFetchObservation(input);
689
690
  return recordFetchOutcome(await dedupeFetch(input, cleanInit), "skip", "auto no cache");
690
691
  }
692
+ const tags = encodeCacheTags(nextOpts?.tags ?? []);
691
693
  let revalidateSeconds;
692
694
  if (cacheDirective === "force-cache") revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === "number" ? nextOpts.revalidate : ONE_YEAR_SECONDS;
693
695
  else if (nextOpts?.revalidate === false) revalidateSeconds = ONE_YEAR_SECONDS;
694
696
  else if (typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0) revalidateSeconds = nextOpts.revalidate;
695
- else if (nextOpts?.tags && nextOpts.tags.length > 0) {
697
+ else if (tags.length > 0) {
696
698
  const routeRevalidate = _getState().currentFetchRevalidate;
697
699
  if (routeRevalidate === 0) {
698
700
  const cleanInit = stripNextFromInit(init, cacheDirective);
@@ -712,7 +714,6 @@ function createPatchedFetch() {
712
714
  recordFiniteFetchRevalidate(nextOpts.revalidate);
713
715
  }
714
716
  const reqTags = _getState().currentRequestTags;
715
- const tags = encodeCacheTags(nextOpts?.tags ?? []);
716
717
  if (tags.length > 0) {
717
718
  for (const tag of tags) if (!reqTags.includes(tag)) reqTags.push(tag);
718
719
  }
@@ -1,4 +1,5 @@
1
1
  import { RenderRequestApiKind } from "../server/cache-proof.js";
2
+ import { ConnectionProbeResult, HeadersAccessPhase, RenderDynamicLatch, VinextHeadersShimState, createRenderDynamicLatch, getHeadersAccessPhase, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "./internal/headers-state.js";
2
3
  import { ReadonlyRequestCookies } from "@vinext/types/next/upstream/dist/server/web/spec-extension/adapters/request-cookies";
3
4
  import { ResponseCookie } from "@vinext/types/next/upstream/dist/compiled/@edge-runtime/cookies/index";
4
5
  //#region src/shims/headers.d.ts
@@ -16,61 +17,6 @@ export type HeadersContext = {
16
17
  type HeadersContextFromRequestOptions = {
17
18
  draftModeSecret?: string;
18
19
  };
19
- export type HeadersAccessPhase = "render" | "action" | "route-handler";
20
- /**
21
- * Whether the current render has used a dynamic API. Unlike
22
- * `dynamicUsageDetected`, nothing clears it, and one object is shared by every
23
- * child scope of the request, so usage inside isolated scopes (such as the
24
- * layout probe) stays visible to later readers.
25
- */
26
- export type RenderDynamicLatch = {
27
- dynamic: boolean;
28
- listeners: Set<() => void>;
29
- };
30
- export declare function createRenderDynamicLatch(): RenderDynamicLatch;
31
- export type VinextHeadersShimState = {
32
- headersContext: HeadersContext | null;
33
- dynamicUsageDetected: boolean;
34
- renderDynamicLatch: RenderDynamicLatch;
35
- renderRequestApiUsage: Set<RenderRequestApiKind>;
36
- connectionProbe: ConnectionProbeState | null;
37
- /** Error recorded by throwIfInsideCacheScope for dev diagnostics, persists even if caught by user code. */
38
- invalidDynamicUsageError: unknown;
39
- pendingSetCookies: string[];
40
- draftModeCookieHeader: string | null;
41
- phase: HeadersAccessPhase;
42
- };
43
- type ConnectionProbeState = {
44
- active: boolean;
45
- dynamicUsageTarget: VinextHeadersShimState;
46
- interrupted: boolean;
47
- interrupt: () => void;
48
- pending: Promise<never>;
49
- };
50
- type ConnectionProbeResult<T> = {
51
- completed: true;
52
- result: T;
53
- } | {
54
- completed: false;
55
- };
56
- /**
57
- * Dynamic usage flag — set when a component calls connection(), cookies(),
58
- * headers(), or noStore() during rendering. When true, ISR caching is
59
- * bypassed and the response gets Cache-Control: no-store.
60
- */
61
- /**
62
- * Mark the current render as requiring dynamic (uncached) rendering.
63
- * Called by connection(), cookies(), headers(), and noStore().
64
- */
65
- export declare function markDynamicUsage(): void;
66
- /** Whether the current render has used a dynamic API at any point so far. */
67
- export declare function isRenderDynamicLatched(): boolean;
68
- /**
69
- * Call `listener` once when the current render first uses a dynamic API.
70
- * Returns an unsubscribe function. The listener never runs if the render is
71
- * already latched; check `isRenderDynamicLatched()` first.
72
- */
73
- export declare function onRenderDynamicLatched(listener: () => void): () => void;
74
20
  /**
75
21
  * Measure dynamic usage in a child async scope without clearing the parent.
76
22
  * Concurrent work that already belongs to the request (such as deferred
@@ -81,22 +27,10 @@ export declare function runWithIsolatedDynamicUsage<T>(fn: () => T | Promise<T>)
81
27
  result: T;
82
28
  dynamicDetected: boolean;
83
29
  }>;
84
- export declare function markRenderRequestApiUsage(kind: RenderRequestApiKind): void;
85
- export declare function throwIfStaticGenerationAccessError(): void;
86
30
  export declare function runWithConnectionProbe<T>(fn: () => T | Promise<T>): Promise<ConnectionProbeResult<T>>;
87
31
  export declare function suspendConnectionProbe(): Promise<never> | null;
88
32
  export declare function peekRenderRequestApiUsage(): RenderRequestApiKind[];
89
33
  export declare function consumeRenderRequestApiUsage(): RenderRequestApiKind[];
90
- /** Whether work is executing inside a cache boundary that owns its reuse. */
91
- export declare function isInsideAnyCacheScope(): boolean;
92
- /**
93
- * Throw if the current execution is inside a "use cache" or unstable_cache()
94
- * scope. Called by dynamic request APIs (headers, cookies, connection) to
95
- * prevent request-specific data from being frozen into cached results.
96
- *
97
- * @param apiName - The name of the API being called (e.g. "connection()")
98
- */
99
- export declare function throwIfInsideCacheScope(apiName: string): void;
100
34
  /**
101
35
  * Check, consume, and return any invalid dynamic usage error recorded during
102
36
  * the render (e.g. cookies() called inside "use cache"). This error persists
@@ -121,7 +55,6 @@ export declare function consumeDynamicUsage(): boolean;
121
55
  */
122
56
  export declare function peekDynamicUsage(): boolean;
123
57
  export declare function setHeadersAccessPhase(phase: HeadersAccessPhase): HeadersAccessPhase;
124
- export declare function getHeadersAccessPhase(): HeadersAccessPhase;
125
58
  /**
126
59
  * Set the headers/cookies context for the current RSC render.
127
60
  * Called by the framework's RSC entry before rendering each request.
@@ -151,6 +84,8 @@ export declare function hasEffectiveRequestCookieChanges(cookieHeader: string |
151
84
  export declare function applyEffectiveRequestCookieHeader(cookieHeader: string): void;
152
85
  /** Restore a middleware draft-mode transition inside a staged render scope. */
153
86
  export declare function restoreDraftModeTransition(cookieHeader: string): void;
87
+ /** Replace request API inputs while retaining dynamic usage and pending mutations. */
88
+ export declare function replaceHeadersContext(ctx: HeadersContext): void;
154
89
  export declare function setHeadersContext(ctx: HeadersContext | null): void;
155
90
  /**
156
91
  * Run a function with headers context, ensuring the context propagates
@@ -224,6 +159,8 @@ export declare function getAndClearPendingCookies(): string[];
224
159
  * Get any Set-Cookie header generated by draftMode().enable()/disable().
225
160
  * Called by the framework after rendering to attach the header to the response.
226
161
  */
162
+ /** Check a pending draft transition without consuming its outgoing cookie. */
163
+ export declare function hasDraftModeCookieHeader(): boolean;
227
164
  export declare function getDraftModeCookieHeader(): string | null;
228
165
  export declare function isDraftModeRequest(request: Request, draftModeSecret: string): boolean;
229
166
  /**
@@ -288,4 +225,4 @@ declare class RequestCookies {
288
225
  [SYNCHRONIZE_REQUEST_COOKIES](): void;
289
226
  }
290
227
  //#endregion
291
- export type { RequestCookies };
228
+ export { type HeadersAccessPhase, type RenderDynamicLatch, type RequestCookies, type VinextHeadersShimState, createRenderDynamicLatch, getHeadersAccessPhase, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
@@ -1,11 +1,11 @@
1
- import { getOrCreateAls } from "./internal/als-registry.js";
2
- import { ensureRenderDynamicLatch, getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
1
+ import { ensureRenderDynamicLatch, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
3
2
  import { MIDDLEWARE_SET_COOKIE_HEADER } from "../utils/protocol-headers.js";
4
3
  import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
5
4
  import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
6
5
  import { FLIGHT_HEADERS, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER } from "../server/headers.js";
7
6
  import { serializeSetCookie, validateCookieName } from "./internal/cookie-serialize.js";
8
7
  import { createPprFallbackShellSuspensePromise } from "./ppr-fallback-shell.js";
8
+ import { createRenderDynamicLatch, getHeadersAccessPhase, getHeadersShimState, headersShimAls, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "./internal/headers-state.js";
9
9
  //#region src/shims/headers.ts
10
10
  /**
11
11
  * next/headers shim
@@ -16,26 +16,6 @@ import { createPprFallbackShellSuspensePromise } from "./ppr-fallback-shell.js";
16
16
  * In Next.js 15+, cookies() and headers() return Promises (async).
17
17
  * We support both the sync (legacy) and async patterns.
18
18
  */
19
- function createRenderDynamicLatch() {
20
- return {
21
- dynamic: false,
22
- listeners: /* @__PURE__ */ new Set()
23
- };
24
- }
25
- const _FALLBACK_KEY = Symbol.for("vinext.nextHeadersShim.fallback");
26
- const _g = globalThis;
27
- const _als = getOrCreateAls("vinext.nextHeadersShim.als");
28
- const _fallbackState = _g[_FALLBACK_KEY] ??= {
29
- headersContext: null,
30
- dynamicUsageDetected: false,
31
- renderDynamicLatch: createRenderDynamicLatch(),
32
- renderRequestApiUsage: /* @__PURE__ */ new Set(),
33
- connectionProbe: null,
34
- invalidDynamicUsageError: null,
35
- pendingSetCookies: [],
36
- draftModeCookieHeader: null,
37
- phase: "render"
38
- };
39
19
  function splitMiddlewareSetCookieHeader(value) {
40
20
  const cookies = [];
41
21
  let start = 0;
@@ -103,72 +83,6 @@ function mergeMiddlewareSetCookies(ctx, rawHeader) {
103
83
  }
104
84
  return merged;
105
85
  }
106
- function _getState() {
107
- if (isInsideUnifiedScope()) return getRequestContext();
108
- return _als.getStore() ?? _fallbackState;
109
- }
110
- /**
111
- * Dynamic usage flag — set when a component calls connection(), cookies(),
112
- * headers(), or noStore() during rendering. When true, ISR caching is
113
- * bypassed and the response gets Cache-Control: no-store.
114
- */
115
- /**
116
- * Mark the current render as requiring dynamic (uncached) rendering.
117
- * Called by connection(), cookies(), headers(), and noStore().
118
- */
119
- function markDynamicUsage() {
120
- const state = _getState();
121
- if (state.headersContext?.forceStatic) return;
122
- state.dynamicUsageDetected = true;
123
- const latches = [ensureRenderDynamicLatch(state)];
124
- forEachConnectionProbeTarget(state, (target) => {
125
- target.dynamicUsageDetected = true;
126
- latches.push(ensureRenderDynamicLatch(target));
127
- });
128
- for (const latch of latches) latchRenderDynamic(latch);
129
- }
130
- function latchRenderDynamic(latch) {
131
- if (latch.dynamic) return;
132
- latch.dynamic = true;
133
- const listeners = [...latch.listeners];
134
- latch.listeners.clear();
135
- for (const listener of listeners) try {
136
- listener();
137
- } catch (error) {
138
- console.error(error);
139
- }
140
- }
141
- /** Whether the current render has used a dynamic API at any point so far. */
142
- function isRenderDynamicLatched() {
143
- return ensureRenderDynamicLatch(_getState()).dynamic;
144
- }
145
- /**
146
- * Call `listener` once when the current render first uses a dynamic API.
147
- * Returns an unsubscribe function. The listener never runs if the render is
148
- * already latched; check `isRenderDynamicLatched()` first.
149
- */
150
- function onRenderDynamicLatched(listener) {
151
- const latch = ensureRenderDynamicLatch(_getState());
152
- if (latch.dynamic) return () => {};
153
- latch.listeners.add(listener);
154
- return () => {
155
- latch.listeners.delete(listener);
156
- };
157
- }
158
- function forEachConnectionProbeTarget(state, visit) {
159
- let target = state.connectionProbe?.dynamicUsageTarget ?? null;
160
- const seen = /* @__PURE__ */ new Set([state]);
161
- while (target && !seen.has(target)) {
162
- seen.add(target);
163
- visit(target);
164
- target = target.connectionProbe?.dynamicUsageTarget ?? null;
165
- }
166
- }
167
- function propagateInvalidDynamicUsageError(state, error) {
168
- forEachConnectionProbeTarget(state, (target) => {
169
- if (target.invalidDynamicUsageError == null) target.invalidDynamicUsageError = error;
170
- });
171
- }
172
86
  /**
173
87
  * Measure dynamic usage in a child async scope without clearing the parent.
174
88
  * Concurrent work that already belongs to the request (such as deferred
@@ -192,23 +106,16 @@ async function runWithIsolatedDynamicUsage(fn) {
192
106
  return runInChildState(childState);
193
107
  });
194
108
  }
195
- const parentState = _getState();
109
+ const parentState = getHeadersShimState();
196
110
  const childState = {
197
111
  ...parentState,
198
112
  renderDynamicLatch: ensureRenderDynamicLatch(parentState),
199
113
  dynamicUsageDetected: false
200
114
  };
201
- return await _als.run(childState, () => runInChildState(childState));
202
- }
203
- function markRenderRequestApiUsage(kind) {
204
- _getState().renderRequestApiUsage.add(kind);
205
- }
206
- function throwIfStaticGenerationAccessError() {
207
- const accessError = _getState().headersContext?.accessError;
208
- if (accessError) throw accessError;
115
+ return await headersShimAls.run(childState, () => runInChildState(childState));
209
116
  }
210
117
  async function runWithConnectionProbe(fn) {
211
- const parentState = _getState();
118
+ const parentState = getHeadersShimState();
212
119
  const parentInvalidDynamicUsageError = parentState.invalidDynamicUsageError;
213
120
  let interruptProbe = () => {};
214
121
  const interrupted = new Promise((resolve) => {
@@ -254,79 +161,23 @@ async function runWithConnectionProbe(fn) {
254
161
  renderDynamicLatch: ensureRenderDynamicLatch(parentState),
255
162
  connectionProbe: probe
256
163
  };
257
- return await _als.run(childState, () => runInChildState(childState));
164
+ return await headersShimAls.run(childState, () => runInChildState(childState));
258
165
  }
259
166
  function suspendConnectionProbe() {
260
- const probe = _getState().connectionProbe;
167
+ const probe = getHeadersShimState().connectionProbe;
261
168
  if (!probe?.active) return null;
262
169
  probe.interrupt();
263
170
  return probe.pending;
264
171
  }
265
172
  function peekRenderRequestApiUsage() {
266
- return [..._getState().renderRequestApiUsage].sort();
173
+ return [...getHeadersShimState().renderRequestApiUsage].sort();
267
174
  }
268
175
  function consumeRenderRequestApiUsage() {
269
- const state = _getState();
176
+ const state = getHeadersShimState();
270
177
  const observed = [...state.renderRequestApiUsage].sort();
271
178
  state.renderRequestApiUsage = /* @__PURE__ */ new Set();
272
179
  return observed;
273
180
  }
274
- /** Symbol used by cache-runtime.ts to store the "use cache" ALS on globalThis */
275
- const _USE_CACHE_ALS_KEY = Symbol.for("vinext.cacheRuntime.contextAls");
276
- /** Symbol used by cache.ts to store the unstable_cache ALS on globalThis */
277
- const _UNSTABLE_CACHE_ALS_KEY = Symbol.for("vinext.unstableCache.als");
278
- function _getGlobalCacheScopeStore(key) {
279
- const value = Reflect.get(globalThis, key);
280
- if (!value || typeof value !== "object") return null;
281
- const getStore = Reflect.get(value, "getStore");
282
- if (typeof getStore !== "function") return null;
283
- return getStore.call(value);
284
- }
285
- function _getUseCacheGuardContext() {
286
- const store = _getGlobalCacheScopeStore(_USE_CACHE_ALS_KEY);
287
- if (!store || typeof store !== "object") return null;
288
- return store;
289
- }
290
- function _isInsidePublicUseCache() {
291
- const ctx = _getUseCacheGuardContext();
292
- return ctx !== null && ctx.variant !== "private";
293
- }
294
- function _isInsideUnstableCache() {
295
- return _getGlobalCacheScopeStore(_UNSTABLE_CACHE_ALS_KEY) === true;
296
- }
297
- /** Whether work is executing inside a cache boundary that owns its reuse. */
298
- function isInsideAnyCacheScope() {
299
- return _getUseCacheGuardContext() !== null || _isInsideUnstableCache();
300
- }
301
- /**
302
- * Throw if the current execution is inside a "use cache" or unstable_cache()
303
- * scope. Called by dynamic request APIs (headers, cookies, connection) to
304
- * prevent request-specific data from being frozen into cached results.
305
- *
306
- * @param apiName - The name of the API being called (e.g. "connection()")
307
- */
308
- function throwIfInsideCacheScope(apiName) {
309
- if (_isInsidePublicUseCache()) {
310
- const error = /* @__PURE__ */ new Error(`\`${apiName}\` cannot be called inside "use cache". If you need this data inside a cached function, call \`${apiName}\` outside and pass the required data as an argument.`);
311
- try {
312
- const cacheCtx = _getUseCacheGuardContext();
313
- if (cacheCtx) cacheCtx.invalidDynamicUsageError = error;
314
- const ctx = getRequestContext();
315
- if (ctx) ctx.invalidDynamicUsageError = error;
316
- propagateInvalidDynamicUsageError(_getState(), error);
317
- } catch {}
318
- throw error;
319
- }
320
- if (_isInsideUnstableCache()) {
321
- const error = /* @__PURE__ */ new Error(`\`${apiName}\` cannot be called inside a function cached with \`unstable_cache()\`. If you need this data inside a cached function, call \`${apiName}\` outside and pass the required data as an argument.`);
322
- try {
323
- const ctx = getRequestContext();
324
- if (ctx) ctx.invalidDynamicUsageError = error;
325
- propagateInvalidDynamicUsageError(_getState(), error);
326
- } catch {}
327
- throw error;
328
- }
329
- }
330
181
  /**
331
182
  * Check, consume, and return any invalid dynamic usage error recorded during
332
183
  * the render (e.g. cookies() called inside "use cache"). This error persists
@@ -337,7 +188,7 @@ function throwIfInsideCacheScope(apiName) {
337
188
  * https://github.com/vercel/next.js/commit/f5e54c06726b571a042fce67417e40a29f6b8689
338
189
  */
339
190
  function consumeInvalidDynamicUsageError() {
340
- const state = _getState();
191
+ const state = getHeadersShimState();
341
192
  const err = state.invalidDynamicUsageError;
342
193
  state.invalidDynamicUsageError = null;
343
194
  return err;
@@ -347,7 +198,7 @@ function consumeInvalidDynamicUsageError() {
347
198
  * Called by the server after rendering to decide on caching.
348
199
  */
349
200
  function consumeDynamicUsage() {
350
- const state = _getState();
201
+ const state = getHeadersShimState();
351
202
  const used = state.dynamicUsageDetected;
352
203
  state.dynamicUsageDetected = false;
353
204
  return used;
@@ -360,7 +211,7 @@ function consumeDynamicUsage() {
360
211
  * that leave no other observable trace.
361
212
  */
362
213
  function peekDynamicUsage() {
363
- return _getState().dynamicUsageDetected;
214
+ return getHeadersShimState().dynamicUsageDetected;
364
215
  }
365
216
  function _setStatePhase(state, phase) {
366
217
  const previous = state.phase;
@@ -369,14 +220,11 @@ function _setStatePhase(state, phase) {
369
220
  return previous;
370
221
  }
371
222
  function _areCookiesMutableInCurrentPhase() {
372
- const phase = _getState().phase;
223
+ const phase = getHeadersShimState().phase;
373
224
  return phase === "action" || phase === "route-handler";
374
225
  }
375
226
  function setHeadersAccessPhase(phase) {
376
- return _setStatePhase(_getState(), phase);
377
- }
378
- function getHeadersAccessPhase() {
379
- return _getState().phase;
227
+ return _setStatePhase(getHeadersShimState(), phase);
380
228
  }
381
229
  /**
382
230
  * Set the headers/cookies context for the current RSC render.
@@ -393,7 +241,7 @@ function getHeadersAccessPhase() {
393
241
  * request context for afterFiles/fallback rewrite has/missing evaluation.
394
242
  */
395
243
  function getHeadersContext() {
396
- return _getState().headersContext;
244
+ return getHeadersShimState().headersContext;
397
245
  }
398
246
  /** Serialize the effective request-cookie view, including middleware Set-Cookie overlays. */
399
247
  function getEffectiveRequestCookieHeader() {
@@ -418,7 +266,7 @@ function hasEffectiveRequestCookieChanges(cookieHeader) {
418
266
  * that split view without changing the request Headers object.
419
267
  */
420
268
  function applyEffectiveRequestCookieHeader(cookieHeader) {
421
- const context = _getState().headersContext;
269
+ const context = getHeadersShimState().headersContext;
422
270
  if (!context) return;
423
271
  rebuildCookiesFromHeader(context, cookieHeader);
424
272
  context.readonlyCookies = void 0;
@@ -426,7 +274,7 @@ function applyEffectiveRequestCookieHeader(cookieHeader) {
426
274
  }
427
275
  /** Restore a middleware draft-mode transition inside a staged render scope. */
428
276
  function restoreDraftModeTransition(cookieHeader) {
429
- const state = _getState();
277
+ const state = getHeadersShimState();
430
278
  const context = state.headersContext;
431
279
  if (!context) return;
432
280
  const entry = setCookieNameValue(cookieHeader);
@@ -437,8 +285,12 @@ function restoreDraftModeTransition(cookieHeader) {
437
285
  context.draftModeEnabled = entry.value === validateDraftModeSecret(context.draftModeSecret ?? "");
438
286
  state.draftModeCookieHeader = cookieHeader;
439
287
  }
288
+ /** Replace request API inputs while retaining dynamic usage and pending mutations. */
289
+ function replaceHeadersContext(ctx) {
290
+ getHeadersShimState().headersContext = ctx;
291
+ }
440
292
  function setHeadersContext(ctx) {
441
- const state = _getState();
293
+ const state = getHeadersShimState();
442
294
  if (ctx !== null) {
443
295
  state.headersContext = ctx;
444
296
  state.dynamicUsageDetected = false;
@@ -474,7 +326,7 @@ function runWithHeadersContext(ctx, fn) {
474
326
  draftModeCookieHeader: null,
475
327
  phase: "render"
476
328
  };
477
- return _als.run(state, fn);
329
+ return headersShimAls.run(state, fn);
478
330
  }
479
331
  /**
480
332
  * Apply middleware-forwarded request headers to the current headers context.
@@ -496,7 +348,7 @@ function runWithHeadersContext(ctx, fn) {
496
348
  * middleware-modified view.
497
349
  */
498
350
  function applyMiddlewareRequestHeaders(middlewareResponseHeaders) {
499
- const state = _getState();
351
+ const state = getHeadersShimState();
500
352
  if (!state.headersContext) return;
501
353
  const ctx = state.headersContext;
502
354
  const previousCookieHeader = ctx.headers.get("cookie");
@@ -700,7 +552,7 @@ function headers() {
700
552
  } catch (error) {
701
553
  return _decorateRejectedRequestApiPromise(error);
702
554
  }
703
- const state = _getState();
555
+ const state = getHeadersShimState();
704
556
  if (!state.headersContext) return _decorateRejectedRequestApiPromise(/* @__PURE__ */ new Error("headers() can only be called from a Server Component, Route Handler, or Server Action. Make sure you're not calling it from a Client Component."));
705
557
  if (state.headersContext.accessError) return _decorateRejectedRequestApiPromise(state.headersContext.accessError);
706
558
  markDynamicUsage();
@@ -720,7 +572,7 @@ function cookiesImpl() {
720
572
  } catch (error) {
721
573
  return _decorateRejectedRequestApiPromise(error);
722
574
  }
723
- const state = _getState();
575
+ const state = getHeadersShimState();
724
576
  if (!state.headersContext) return _decorateRejectedRequestApiPromise(/* @__PURE__ */ new Error("cookies() can only be called from a Server Component, Route Handler, or Server Action."));
725
577
  if (state.headersContext.accessError) return _decorateRejectedRequestApiPromise(state.headersContext.accessError);
726
578
  markDynamicUsage();
@@ -738,7 +590,7 @@ function cookies() {
738
590
  * Called by the framework after rendering to attach headers to the response.
739
591
  */
740
592
  function getAndClearPendingCookies() {
741
- const state = _getState();
593
+ const state = getHeadersShimState();
742
594
  const cookies = state.pendingSetCookies;
743
595
  state.pendingSetCookies = [];
744
596
  return cookies;
@@ -748,8 +600,12 @@ const DRAFT_MODE_COOKIE = "__prerender_bypass";
748
600
  * Get any Set-Cookie header generated by draftMode().enable()/disable().
749
601
  * Called by the framework after rendering to attach the header to the response.
750
602
  */
603
+ /** Check a pending draft transition without consuming its outgoing cookie. */
604
+ function hasDraftModeCookieHeader() {
605
+ return getHeadersShimState().draftModeCookieHeader !== null;
606
+ }
751
607
  function getDraftModeCookieHeader() {
752
- const state = _getState();
608
+ const state = getHeadersShimState();
753
609
  const header = state.draftModeCookieHeader;
754
610
  state.draftModeCookieHeader = null;
755
611
  return header;
@@ -780,7 +636,7 @@ function isDraftModeRequest(request, draftModeSecret) {
780
636
  * callers fall back to an explicitly supplied request when needed.
781
637
  */
782
638
  function getActiveDraftModeState() {
783
- const context = _getState().headersContext;
639
+ const context = getHeadersShimState().headersContext;
784
640
  if (!context) return null;
785
641
  if (context.draftModeEnabled !== void 0) return context.draftModeEnabled;
786
642
  const secret = context.draftModeSecret;
@@ -820,7 +676,7 @@ function requireActiveDraftModeContext(state, expectedContext, expression) {
820
676
  */
821
677
  async function draftMode() {
822
678
  markRenderRequestApiUsage("draftMode");
823
- const state = _getState();
679
+ const state = getHeadersShimState();
824
680
  const context = state.headersContext;
825
681
  if (!context) throw createDraftModeScopeError("draftMode()");
826
682
  const secret = ensureContextDraftModeSecret(context);
@@ -908,7 +764,7 @@ var RequestCookies = class {
908
764
  });
909
765
  const serialized = serializeMutableCookie(responseCookie);
910
766
  this[APPLY_RESPONSE_COOKIE](responseCookie);
911
- _getState().pendingSetCookies.push(serialized);
767
+ getHeadersShimState().pendingSetCookies.push(serialized);
912
768
  return this;
913
769
  }
914
770
  delete(nameOrOptions) {
@@ -922,7 +778,7 @@ var RequestCookies = class {
922
778
  });
923
779
  const serialized = serializeMutableCookie(responseCookie);
924
780
  this[APPLY_RESPONSE_COOKIE](responseCookie);
925
- _getState().pendingSetCookies.push(serialized);
781
+ getHeadersShimState().pendingSetCookies.push(serialized);
926
782
  return this;
927
783
  }
928
784
  get size() {
@@ -978,4 +834,4 @@ function serializeMutableCookie(cookie) {
978
834
  });
979
835
  }
980
836
  //#endregion
981
- export { applyEffectiveRequestCookieHeader, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, createRenderDynamicLatch, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getEffectiveRequestCookieHeader, getHeadersAccessPhase, getHeadersContext, hasEffectiveRequestCookieChanges, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, peekDynamicUsage, peekRenderRequestApiUsage, restoreDraftModeTransition, runWithConnectionProbe, runWithHeadersContext, runWithIsolatedDynamicUsage, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
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 };
@@ -0,0 +1,16 @@
1
+ import { CacheLifeConfig } from "../cache-request-state.js";
2
+ //#region src/shims/internal/cache-context-accessor.d.ts
3
+ type CacheContextLike = {
4
+ tags: string[];
5
+ lifeConfigs: CacheLifeConfig[];
6
+ variant: string;
7
+ readRootParamNames?: Set<string>;
8
+ hasExplicitRevalidate: boolean;
9
+ hasExplicitExpire: boolean;
10
+ dynamicNestedCacheError: Error | undefined;
11
+ };
12
+ export declare function _registerCacheContextAccessor(fn: () => CacheContextLike | null): void;
13
+ export declare function getRegisteredCacheContext(): CacheContextLike | null;
14
+ /** Record a root-param dependency on the active public `"use cache"` scope. */
15
+ export declare function _recordUseCacheRootParamRead(name: string): void;
16
+ //#endregion