vinext 0.0.41 → 0.0.43
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 +0 -1
- package/dist/build/client-build-config.d.ts +119 -0
- package/dist/build/client-build-config.js +149 -0
- package/dist/build/client-build-config.js.map +1 -0
- package/dist/build/layout-classification-types.d.ts +62 -0
- package/dist/build/layout-classification-types.js +1 -0
- package/dist/build/layout-classification.d.ts +60 -0
- package/dist/build/layout-classification.js +98 -0
- package/dist/build/layout-classification.js.map +1 -0
- package/dist/build/report.d.ts +15 -1
- package/dist/build/report.js +50 -1
- package/dist/build/report.js.map +1 -1
- package/dist/build/route-classification-manifest.d.ts +53 -0
- package/dist/build/route-classification-manifest.js +145 -0
- package/dist/build/route-classification-manifest.js.map +1 -0
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/ssr-manifest.d.ts +19 -0
- package/dist/build/ssr-manifest.js +71 -0
- package/dist/build/ssr-manifest.js.map +1 -0
- package/dist/check.js +2 -2
- package/dist/check.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/entry.js +1 -1
- package/dist/config/config-matchers.js +1 -0
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +315 -101
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/index.d.ts +1 -169
- package/dist/index.js +112 -432
- package/dist/index.js.map +1 -1
- package/dist/plugins/fonts.d.ts +49 -1
- package/dist/plugins/fonts.js +96 -3
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/postcss.d.ts +27 -0
- package/dist/plugins/postcss.js +94 -0
- package/dist/plugins/postcss.js.map +1 -0
- package/dist/plugins/strip-server-exports.d.ts +14 -0
- package/dist/plugins/strip-server-exports.js +73 -0
- package/dist/plugins/strip-server-exports.js.map +1 -0
- package/dist/routing/app-router.d.ts +6 -4
- package/dist/routing/app-router.js +44 -25
- package/dist/routing/app-router.js.map +1 -1
- package/dist/server/app-browser-entry.js +307 -100
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-error.d.ts +8 -0
- package/dist/server/app-browser-error.js +9 -0
- package/dist/server/app-browser-error.js.map +1 -0
- package/dist/server/app-browser-state.d.ts +93 -0
- package/dist/server/app-browser-state.js +132 -0
- package/dist/server/app-browser-state.js.map +1 -0
- package/dist/server/app-elements.d.ts +92 -0
- package/dist/server/app-elements.js +122 -0
- package/dist/server/app-elements.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +2 -1
- package/dist/server/app-page-boundary-render.js +40 -1
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +6 -3
- package/dist/server/app-page-cache.js +14 -8
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +36 -3
- package/dist/server/app-page-execution.js +50 -10
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +10 -4
- package/dist/server/app-page-probe.js +24 -15
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render.d.ts +7 -4
- package/dist/server/app-page-render.js +13 -4
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +52 -4
- package/dist/server/app-page-request.js +86 -16
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +1 -0
- package/dist/server/app-page-response.js +1 -0
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +22 -8
- package/dist/server/app-page-route-wiring.js +219 -83
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-render-dependency.d.ts +13 -0
- package/dist/server/app-render-dependency.js +35 -0
- package/dist/server/app-render-dependency.js.map +1 -0
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +5 -3
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.js +2 -0
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +1 -0
- package/dist/server/app-route-handler-runtime.js +26 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-ssr-entry.js +6 -2
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/dev-server.js +2 -4
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/middleware.js +1 -5
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/prod-server.d.ts +3 -3
- package/dist/server/prod-server.js +1 -1
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +2 -1
- package/dist/server/request-pipeline.js +34 -5
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +1 -0
- package/dist/shims/cache-runtime.js +0 -5
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -8
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/client-hook-error.d.ts +14 -0
- package/dist/shims/client-hook-error.js +19 -0
- package/dist/shims/client-hook-error.js.map +1 -0
- package/dist/shims/constants.d.ts +3 -3
- package/dist/shims/constants.js +3 -3
- package/dist/shims/constants.js.map +1 -1
- package/dist/shims/document.d.ts +6 -6
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error-boundary.js +1 -1
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/form.d.ts +3 -3
- package/dist/shims/head-state.d.ts +1 -0
- package/dist/shims/head-state.js +0 -5
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/headers.d.ts +11 -0
- package/dist/shims/headers.js +13 -10
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-state.d.ts +1 -0
- package/dist/shims/i18n-state.js +0 -4
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/internal/app-router-context.d.ts +6 -6
- package/dist/shims/internal/router-context.d.ts +2 -2
- package/dist/shims/layout-segment-context.d.ts +2 -2
- package/dist/shims/link.js +19 -11
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +3 -3
- package/dist/shims/navigation-state.d.ts +2 -0
- package/dist/shims/navigation-state.js +0 -13
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +56 -9
- package/dist/shims/navigation.js +112 -28
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/navigation.react-server.d.ts +14 -0
- package/dist/shims/navigation.react-server.js +29 -0
- package/dist/shims/navigation.react-server.js.map +1 -0
- package/dist/shims/request-context.d.ts +1 -0
- package/dist/shims/request-context.js +0 -9
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router-state.js +0 -5
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/slot.d.ts +11 -7
- package/dist/shims/slot.js +28 -19
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +2 -0
- package/dist/shims/unified-request-context.js +0 -14
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/utils/mdx-scan.d.ts +10 -0
- package/dist/utils/mdx-scan.js +36 -0
- package/dist/utils/mdx-scan.js.map +1 -0
- package/dist/utils/public-routes.d.ts +5 -0
- package/dist/utils/public-routes.js +50 -0
- package/dist/utils/public-routes.js.map +1 -0
- package/package.json +3 -3
- package/dist/plugins/fix-use-server-closure-collision.d.ts +0 -29
- package/dist/plugins/fix-use-server-closure-collision.js +0 -204
- package/dist/plugins/fix-use-server-closure-collision.js.map +0 -1
package/dist/shims/slot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot.js","names":["React"],"sources":["../../src/shims/slot.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"slot.js","names":["React"],"sources":["../../src/shims/slot.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { UNMATCHED_SLOT, type AppElementValue, type AppElements } from \"../server/app-elements.js\";\nimport { notFound } from \"./navigation.js\";\n\nconst EMPTY_ELEMENTS: AppElements = Object.freeze({});\nconst warnedMissingEntryIds = new Set<string>();\n\nexport { UNMATCHED_SLOT };\n\n/**\n * Holds resolved AppElements (not a Promise). React 19's use(Promise) during\n * hydration triggers \"async Client Component\" for native Promises that lack\n * React's internal .status property. Storing resolved values sidesteps this.\n */\nexport const ElementsContext = React.createContext<AppElements>(EMPTY_ELEMENTS);\n\nexport const ChildrenContext = React.createContext<React.ReactNode>(null);\n\nexport const ParallelSlotsContext = React.createContext<Readonly<\n Record<string, React.ReactNode>\n> | null>(null);\n\nexport function mergeElements(\n prev: AppElements,\n next: AppElements,\n clearAbsentSlots = false,\n): AppElements {\n const merged: Record<string, AppElementValue> = { ...prev, ...next };\n // On soft navigation, unmatched parallel slots preserve their previous subtree\n // instead of firing notFound(). Only hard navigation (full page load) should 404.\n // This matches Next.js behavior for parallel route persistence.\n for (const key of Object.keys(merged)) {\n if (key.startsWith(\"slot:\") && merged[key] === UNMATCHED_SLOT && Object.hasOwn(prev, key)) {\n merged[key] = prev[key];\n }\n }\n // On traversal (browser back/forward), the server renders the full destination\n // route tree. A slot absent from next means the destination route tree does not\n // include it, so clear it rather than keeping the stale prev value. This only\n // runs for traversals because soft forward navigations may omit parent layout\n // slots that should be preserved.\n if (clearAbsentSlots) {\n for (const key of Object.keys(merged)) {\n if (key.startsWith(\"slot:\") && !Object.hasOwn(next, key)) {\n delete merged[key];\n }\n }\n }\n return merged;\n}\n\nexport function Slot({\n id,\n children,\n parallelSlots,\n}: {\n id: string;\n children?: React.ReactNode;\n parallelSlots?: Readonly<Record<string, React.ReactNode>>;\n}) {\n const elements = React.useContext(ElementsContext);\n\n if (!Object.hasOwn(elements, id)) {\n if (process.env.NODE_ENV !== \"production\" && !id.startsWith(\"slot:\")) {\n if (!warnedMissingEntryIds.has(id)) {\n warnedMissingEntryIds.add(id);\n console.warn(\"[vinext] Missing App Router element entry during render: \" + id);\n }\n }\n return null;\n }\n\n const element = elements[id];\n if (element === UNMATCHED_SLOT) {\n notFound();\n }\n\n return (\n <ParallelSlotsContext.Provider value={parallelSlots ?? null}>\n <ChildrenContext.Provider value={children ?? null}>{element}</ChildrenContext.Provider>\n </ParallelSlotsContext.Provider>\n );\n}\n\nexport function Children() {\n return React.useContext(ChildrenContext);\n}\n\nexport function ParallelSlot({ name }: { name: string }) {\n const slots = React.useContext(ParallelSlotsContext);\n return slots?.[name] ?? null;\n}\n"],"mappings":";;;;;;AAMA,MAAM,iBAA8B,OAAO,OAAO,EAAE,CAAC;AACrD,MAAM,wCAAwB,IAAI,KAAa;;;;;;AAS/C,MAAa,kBAAkBA,QAAM,cAA2B,eAAe;AAE/E,MAAa,kBAAkBA,QAAM,cAA+B,KAAK;AAEzE,MAAa,uBAAuBA,QAAM,cAEhC,KAAK;AAEf,SAAgB,cACd,MACA,MACA,mBAAmB,OACN;CACb,MAAM,SAA0C;EAAE,GAAG;EAAM,GAAG;EAAM;AAIpE,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,IAAI,WAAW,QAAQ,IAAI,OAAO,SAAS,kBAAkB,OAAO,OAAO,MAAM,IAAI,CACvF,QAAO,OAAO,KAAK;AAQvB,KAAI;OACG,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,IAAI,WAAW,QAAQ,IAAI,CAAC,OAAO,OAAO,MAAM,IAAI,CACtD,QAAO,OAAO;;AAIpB,QAAO;;AAGT,SAAgB,KAAK,EACnB,IACA,UACA,iBAKC;CACD,MAAM,WAAWA,QAAM,WAAW,gBAAgB;AAElD,KAAI,CAAC,OAAO,OAAO,UAAU,GAAG,EAAE;AAChC,MAAI,QAAQ,IAAI,aAAa,gBAAgB,CAAC,GAAG,WAAW,QAAQ;OAC9D,CAAC,sBAAsB,IAAI,GAAG,EAAE;AAClC,0BAAsB,IAAI,GAAG;AAC7B,YAAQ,KAAK,8DAA8D,GAAG;;;AAGlF,SAAO;;CAGT,MAAM,UAAU,SAAS;AACzB,KAAI,YAAY,eACd,WAAU;AAGZ,QACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO,iBAAiB;YACrD,oBAAC,gBAAgB,UAAjB;GAA0B,OAAO,YAAY;aAAO;GAAmC,CAAA;EACzD,CAAA;;AAIpC,SAAgB,WAAW;AACzB,QAAOA,QAAM,WAAW,gBAAgB;;AAG1C,SAAgB,aAAa,EAAE,QAA0B;AAEvD,QADcA,QAAM,WAAW,qBAAqB,GACrC,SAAS"}
|
|
@@ -29,6 +29,7 @@ declare function createRequestContext(opts?: Partial<UnifiedRequestContext>): Un
|
|
|
29
29
|
* All shim modules will read/write their state from `ctx` for the
|
|
30
30
|
* duration of the call, including async continuations.
|
|
31
31
|
*/
|
|
32
|
+
declare function runWithRequestContext<T>(ctx: UnifiedRequestContext, fn: () => Promise<T>): Promise<T>;
|
|
32
33
|
declare function runWithRequestContext<T>(ctx: UnifiedRequestContext, fn: () => T | Promise<T>): T | Promise<T>;
|
|
33
34
|
/**
|
|
34
35
|
* Run `fn` in a nested unified scope derived from the current request context.
|
|
@@ -39,6 +40,7 @@ declare function runWithRequestContext<T>(ctx: UnifiedRequestContext, fn: () =>
|
|
|
39
40
|
*
|
|
40
41
|
* @internal
|
|
41
42
|
*/
|
|
43
|
+
declare function runWithUnifiedStateMutation<T>(mutate: (ctx: UnifiedRequestContext) => void, fn: () => Promise<T>): Promise<T>;
|
|
42
44
|
declare function runWithUnifiedStateMutation<T>(mutate: (ctx: UnifiedRequestContext) => void, fn: () => T | Promise<T>): T | Promise<T>;
|
|
43
45
|
/**
|
|
44
46
|
* Get the current unified request context.
|
|
@@ -44,23 +44,9 @@ function createRequestContext(opts) {
|
|
|
44
44
|
...opts
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Run `fn` within a unified request context scope.
|
|
49
|
-
* All shim modules will read/write their state from `ctx` for the
|
|
50
|
-
* duration of the call, including async continuations.
|
|
51
|
-
*/
|
|
52
47
|
function runWithRequestContext(ctx, fn) {
|
|
53
48
|
return _als.run(ctx, fn);
|
|
54
49
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Run `fn` in a nested unified scope derived from the current request context.
|
|
57
|
-
* Used by legacy runWith* wrappers to reset or override one sub-state while
|
|
58
|
-
* preserving proper async isolation for continuations created inside `fn`.
|
|
59
|
-
* The child scope is a shallow clone of the parent store, so untouched fields
|
|
60
|
-
* keep sharing their existing references while overridden slices can be reset.
|
|
61
|
-
*
|
|
62
|
-
* @internal
|
|
63
|
-
*/
|
|
64
50
|
function runWithUnifiedStateMutation(mutate, fn) {
|
|
65
51
|
const parentCtx = _als.getStore();
|
|
66
52
|
if (!parentCtx) return fn();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-request-context.js","names":[],"sources":["../../src/shims/unified-request-context.ts"],"sourcesContent":["/**\n * Unified per-request context backed by a single AsyncLocalStorage.\n *\n * Consolidates the 5–6 nested ALS scopes that previously wrapped every\n * App Router request (headers, navigation, cache-state, private-cache,\n * fetch-cache, execution-context) into one flat store.\n *\n * Each shim module checks `isInsideUnifiedScope()` and reads its sub-fields\n * from the unified store, falling back to its own standalone ALS when\n * outside (SSR environment, Pages Router, tests).\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type {\n CacheState,\n ExecutionContextLike,\n FetchCacheState,\n HeadState,\n I18nState,\n NavigationState,\n PrivateCacheState,\n RouterState,\n VinextHeadersShimState,\n} from \"./request-state-types.js\";\n\n// ---------------------------------------------------------------------------\n// Unified context shape\n// ---------------------------------------------------------------------------\n\n/**\n * Flat union of all per-request state previously spread across\n * VinextHeadersShimState, NavigationState, CacheState, PrivateCacheState,\n * FetchCacheState, and ExecutionContextLike.\n *\n * Each field group is documented with its source shim module.\n */\nexport type UnifiedRequestContext = {\n // ── request-context.ts ─────────────────────────────────────────────\n /** Cloudflare Workers ExecutionContext, or null on Node.js dev. */\n executionContext: ExecutionContextLike | null;\n\n // ── cache-for-request.ts ──────────────────────────────────────────\n /** Per-request cache for cacheForRequest(). Keyed by factory function reference. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n requestCache: WeakMap<(...args: any[]) => any, unknown>;\n} & VinextHeadersShimState &\n I18nState &\n NavigationState &\n CacheState &\n PrivateCacheState &\n FetchCacheState &\n RouterState &\n HeadState;\n\n// ---------------------------------------------------------------------------\n// ALS setup — stored on globalThis via Symbol.for so all Vite environments\n// (RSC/SSR/client) share the same instance.\n// ---------------------------------------------------------------------------\n\nconst _ALS_KEY = Symbol.for(\"vinext.unifiedRequestContext.als\");\nconst _REQUEST_CONTEXT_ALS_KEY = Symbol.for(\"vinext.requestContext.als\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??=\n new AsyncLocalStorage<UnifiedRequestContext>()) as AsyncLocalStorage<UnifiedRequestContext>;\n\nfunction _getInheritedExecutionContext(): ExecutionContextLike | null {\n const unifiedStore = _als.getStore();\n if (unifiedStore) return unifiedStore.executionContext;\n\n const executionContextAls = _g[_REQUEST_CONTEXT_ALS_KEY] as\n | AsyncLocalStorage<ExecutionContextLike | null>\n | undefined;\n return executionContextAls?.getStore() ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a fresh `UnifiedRequestContext` with defaults for all fields.\n * Pass partial overrides for the fields you need to pre-populate.\n */\nexport function createRequestContext(opts?: Partial<UnifiedRequestContext>): UnifiedRequestContext {\n return {\n headersContext: null,\n dynamicUsageDetected: false,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n phase: \"render\",\n i18nContext: null,\n serverContext: null,\n serverInsertedHTMLCallbacks: [],\n requestScopedCacheLife: null,\n _privateCache: null,\n currentRequestTags: [],\n executionContext: _getInheritedExecutionContext(), // inherits from standalone ALS if present\n requestCache: new WeakMap(),\n ssrContext: null,\n ssrHeadChildren: [],\n ...opts,\n };\n}\n\n/**\n * Run `fn` within a unified request context scope.\n * All shim modules will read/write their state from `ctx` for the\n * duration of the call, including async continuations.\n */\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n return _als.run(ctx, fn);\n}\n\n/**\n * Run `fn` in a nested unified scope derived from the current request context.\n * Used by legacy runWith* wrappers to reset or override one sub-state while\n * preserving proper async isolation for continuations created inside `fn`.\n * The child scope is a shallow clone of the parent store, so untouched fields\n * keep sharing their existing references while overridden slices can be reset.\n *\n * @internal\n */\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n const parentCtx = _als.getStore();\n if (!parentCtx) return fn();\n\n const childCtx = { ...parentCtx };\n // NOTE: This is a shallow clone. Array fields (pendingSetCookies,\n // serverInsertedHTMLCallbacks, currentRequestTags, ssrHeadChildren), the\n // _privateCache Map, requestCache WeakMap, and object fields (headersContext,\n // i18nContext, serverContext, ssrContext, executionContext,\n // requestScopedCacheLife) still share references with the parent until\n // replaced. requestCache is intentionally shared — nested scopes within\n // the same request should see the same cached values. The mutate\n // callback must replace those reference-typed slices (for example\n // `ctx.currentRequestTags = []`) rather than mutating them in-place (for\n // example `ctx.currentRequestTags.push(...)`) or the parent scope will\n // observe those changes too. Keep this enumeration in sync with\n // UnifiedRequestContext: when adding a new reference-typed field, add it\n // here too and verify callers still follow the replace-not-mutate rule.\n mutate(childCtx);\n return _als.run(childCtx, fn);\n}\n\n/**\n * Get the current unified request context.\n * Returns the ALS store when inside a `runWithRequestContext()` scope,\n * or a fresh detached context otherwise. Unlike the legacy per-shim fallback\n * singletons, this detached value is ephemeral — mutations do not persist\n * across calls. This is intentional to prevent state leakage outside request\n * scopes.\n *\n * Only direct callers observe this detached fallback. Shim `_getState()`\n * helpers should continue to gate on `isInsideUnifiedScope()` and fall back\n * to their standalone ALS/fallback singletons outside the unified scope.\n * If called inside a standalone `runWithExecutionContext()` scope, the\n * detached context still reflects that inherited `executionContext`.\n */\nexport function getRequestContext(): UnifiedRequestContext {\n return _als.getStore() ?? createRequestContext();\n}\n\n/**\n * Check whether the current execution is inside a `runWithRequestContext()` scope.\n * Shim modules use this to decide whether to read from the unified store\n * or fall back to their own standalone ALS.\n */\nexport function isInsideUnifiedScope(): boolean {\n return _als.getStore() != null;\n}\n"],"mappings":";;;;;;;;;;;;;AA2DA,MAAM,WAAW,OAAO,IAAI,mCAAmC;AAC/D,MAAM,2BAA2B,OAAO,IAAI,4BAA4B;AACxE,MAAM,KAAK;AACX,MAAM,OAAQ,GAAG,cACf,IAAI,mBAA0C;AAEhD,SAAS,gCAA6D;CACpE,MAAM,eAAe,KAAK,UAAU;AACpC,KAAI,aAAc,QAAO,aAAa;AAKtC,QAH4B,GAAG,2BAGH,UAAU,IAAI;;;;;;AAW5C,SAAgB,qBAAqB,MAA8D;AACjG,QAAO;EACL,gBAAgB;EAChB,sBAAsB;EACtB,mBAAmB,EAAE;EACrB,uBAAuB;EACvB,OAAO;EACP,aAAa;EACb,eAAe;EACf,6BAA6B,EAAE;EAC/B,wBAAwB;EACxB,eAAe;EACf,oBAAoB,EAAE;EACtB,kBAAkB,+BAA+B;EACjD,8BAAc,IAAI,SAAS;EAC3B,YAAY;EACZ,iBAAiB,EAAE;EACnB,GAAG;EACJ
|
|
1
|
+
{"version":3,"file":"unified-request-context.js","names":[],"sources":["../../src/shims/unified-request-context.ts"],"sourcesContent":["/**\n * Unified per-request context backed by a single AsyncLocalStorage.\n *\n * Consolidates the 5–6 nested ALS scopes that previously wrapped every\n * App Router request (headers, navigation, cache-state, private-cache,\n * fetch-cache, execution-context) into one flat store.\n *\n * Each shim module checks `isInsideUnifiedScope()` and reads its sub-fields\n * from the unified store, falling back to its own standalone ALS when\n * outside (SSR environment, Pages Router, tests).\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type {\n CacheState,\n ExecutionContextLike,\n FetchCacheState,\n HeadState,\n I18nState,\n NavigationState,\n PrivateCacheState,\n RouterState,\n VinextHeadersShimState,\n} from \"./request-state-types.js\";\n\n// ---------------------------------------------------------------------------\n// Unified context shape\n// ---------------------------------------------------------------------------\n\n/**\n * Flat union of all per-request state previously spread across\n * VinextHeadersShimState, NavigationState, CacheState, PrivateCacheState,\n * FetchCacheState, and ExecutionContextLike.\n *\n * Each field group is documented with its source shim module.\n */\nexport type UnifiedRequestContext = {\n // ── request-context.ts ─────────────────────────────────────────────\n /** Cloudflare Workers ExecutionContext, or null on Node.js dev. */\n executionContext: ExecutionContextLike | null;\n\n // ── cache-for-request.ts ──────────────────────────────────────────\n /** Per-request cache for cacheForRequest(). Keyed by factory function reference. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n requestCache: WeakMap<(...args: any[]) => any, unknown>;\n} & VinextHeadersShimState &\n I18nState &\n NavigationState &\n CacheState &\n PrivateCacheState &\n FetchCacheState &\n RouterState &\n HeadState;\n\n// ---------------------------------------------------------------------------\n// ALS setup — stored on globalThis via Symbol.for so all Vite environments\n// (RSC/SSR/client) share the same instance.\n// ---------------------------------------------------------------------------\n\nconst _ALS_KEY = Symbol.for(\"vinext.unifiedRequestContext.als\");\nconst _REQUEST_CONTEXT_ALS_KEY = Symbol.for(\"vinext.requestContext.als\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??=\n new AsyncLocalStorage<UnifiedRequestContext>()) as AsyncLocalStorage<UnifiedRequestContext>;\n\nfunction _getInheritedExecutionContext(): ExecutionContextLike | null {\n const unifiedStore = _als.getStore();\n if (unifiedStore) return unifiedStore.executionContext;\n\n const executionContextAls = _g[_REQUEST_CONTEXT_ALS_KEY] as\n | AsyncLocalStorage<ExecutionContextLike | null>\n | undefined;\n return executionContextAls?.getStore() ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a fresh `UnifiedRequestContext` with defaults for all fields.\n * Pass partial overrides for the fields you need to pre-populate.\n */\nexport function createRequestContext(opts?: Partial<UnifiedRequestContext>): UnifiedRequestContext {\n return {\n headersContext: null,\n dynamicUsageDetected: false,\n pendingSetCookies: [],\n draftModeCookieHeader: null,\n phase: \"render\",\n i18nContext: null,\n serverContext: null,\n serverInsertedHTMLCallbacks: [],\n requestScopedCacheLife: null,\n _privateCache: null,\n currentRequestTags: [],\n executionContext: _getInheritedExecutionContext(), // inherits from standalone ALS if present\n requestCache: new WeakMap(),\n ssrContext: null,\n ssrHeadChildren: [],\n ...opts,\n };\n}\n\n/**\n * Run `fn` within a unified request context scope.\n * All shim modules will read/write their state from `ctx` for the\n * duration of the call, including async continuations.\n */\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => Promise<T>,\n): Promise<T>;\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T>;\nexport function runWithRequestContext<T>(\n ctx: UnifiedRequestContext,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n return _als.run(ctx, fn);\n}\n\n/**\n * Run `fn` in a nested unified scope derived from the current request context.\n * Used by legacy runWith* wrappers to reset or override one sub-state while\n * preserving proper async isolation for continuations created inside `fn`.\n * The child scope is a shallow clone of the parent store, so untouched fields\n * keep sharing their existing references while overridden slices can be reset.\n *\n * @internal\n */\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => Promise<T>,\n): Promise<T>;\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => T | Promise<T>,\n): T | Promise<T>;\nexport function runWithUnifiedStateMutation<T>(\n mutate: (ctx: UnifiedRequestContext) => void,\n fn: () => T | Promise<T>,\n): T | Promise<T> {\n const parentCtx = _als.getStore();\n if (!parentCtx) return fn();\n\n const childCtx = { ...parentCtx };\n // NOTE: This is a shallow clone. Array fields (pendingSetCookies,\n // serverInsertedHTMLCallbacks, currentRequestTags, ssrHeadChildren), the\n // _privateCache Map, requestCache WeakMap, and object fields (headersContext,\n // i18nContext, serverContext, ssrContext, executionContext,\n // requestScopedCacheLife) still share references with the parent until\n // replaced. requestCache is intentionally shared — nested scopes within\n // the same request should see the same cached values. The mutate\n // callback must replace those reference-typed slices (for example\n // `ctx.currentRequestTags = []`) rather than mutating them in-place (for\n // example `ctx.currentRequestTags.push(...)`) or the parent scope will\n // observe those changes too. Keep this enumeration in sync with\n // UnifiedRequestContext: when adding a new reference-typed field, add it\n // here too and verify callers still follow the replace-not-mutate rule.\n mutate(childCtx);\n return _als.run(childCtx, fn);\n}\n\n/**\n * Get the current unified request context.\n * Returns the ALS store when inside a `runWithRequestContext()` scope,\n * or a fresh detached context otherwise. Unlike the legacy per-shim fallback\n * singletons, this detached value is ephemeral — mutations do not persist\n * across calls. This is intentional to prevent state leakage outside request\n * scopes.\n *\n * Only direct callers observe this detached fallback. Shim `_getState()`\n * helpers should continue to gate on `isInsideUnifiedScope()` and fall back\n * to their standalone ALS/fallback singletons outside the unified scope.\n * If called inside a standalone `runWithExecutionContext()` scope, the\n * detached context still reflects that inherited `executionContext`.\n */\nexport function getRequestContext(): UnifiedRequestContext {\n return _als.getStore() ?? createRequestContext();\n}\n\n/**\n * Check whether the current execution is inside a `runWithRequestContext()` scope.\n * Shim modules use this to decide whether to read from the unified store\n * or fall back to their own standalone ALS.\n */\nexport function isInsideUnifiedScope(): boolean {\n return _als.getStore() != null;\n}\n"],"mappings":";;;;;;;;;;;;;AA2DA,MAAM,WAAW,OAAO,IAAI,mCAAmC;AAC/D,MAAM,2BAA2B,OAAO,IAAI,4BAA4B;AACxE,MAAM,KAAK;AACX,MAAM,OAAQ,GAAG,cACf,IAAI,mBAA0C;AAEhD,SAAS,gCAA6D;CACpE,MAAM,eAAe,KAAK,UAAU;AACpC,KAAI,aAAc,QAAO,aAAa;AAKtC,QAH4B,GAAG,2BAGH,UAAU,IAAI;;;;;;AAW5C,SAAgB,qBAAqB,MAA8D;AACjG,QAAO;EACL,gBAAgB;EAChB,sBAAsB;EACtB,mBAAmB,EAAE;EACrB,uBAAuB;EACvB,OAAO;EACP,aAAa;EACb,eAAe;EACf,6BAA6B,EAAE;EAC/B,wBAAwB;EACxB,eAAe;EACf,oBAAoB,EAAE;EACtB,kBAAkB,+BAA+B;EACjD,8BAAc,IAAI,SAAS;EAC3B,YAAY;EACZ,iBAAiB,EAAE;EACnB,GAAG;EACJ;;AAgBH,SAAgB,sBACd,KACA,IACgB;AAChB,QAAO,KAAK,IAAI,KAAK,GAAG;;AAoB1B,SAAgB,4BACd,QACA,IACgB;CAChB,MAAM,YAAY,KAAK,UAAU;AACjC,KAAI,CAAC,UAAW,QAAO,IAAI;CAE3B,MAAM,WAAW,EAAE,GAAG,WAAW;AAcjC,QAAO,SAAS;AAChB,QAAO,KAAK,IAAI,UAAU,GAAG;;;;;;;;;;;;;;;;AAiB/B,SAAgB,oBAA2C;AACzD,QAAO,KAAK,UAAU,IAAI,sBAAsB;;;;;;;AAQlD,SAAgB,uBAAgC;AAC9C,QAAO,KAAK,UAAU,IAAI"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/utils/mdx-scan.d.ts
|
|
2
|
+
/** Module-level cache for hasMdxFiles — avoids re-scanning per Vite environment. */
|
|
3
|
+
declare const mdxScanCache: Map<string, boolean>;
|
|
4
|
+
/**
|
|
5
|
+
* Check if the project has .mdx files in app/ or pages/ directories.
|
|
6
|
+
*/
|
|
7
|
+
declare function hasMdxFiles(root: string, appDir: string | null, pagesDir: string | null): boolean;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { hasMdxFiles, mdxScanCache };
|
|
10
|
+
//# sourceMappingURL=mdx-scan.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
//#region src/utils/mdx-scan.ts
|
|
4
|
+
/** Module-level cache for hasMdxFiles — avoids re-scanning per Vite environment. */
|
|
5
|
+
const mdxScanCache = /* @__PURE__ */ new Map();
|
|
6
|
+
/**
|
|
7
|
+
* Check if the project has .mdx files in app/ or pages/ directories.
|
|
8
|
+
*/
|
|
9
|
+
function hasMdxFiles(root, appDir, pagesDir) {
|
|
10
|
+
const cacheKey = `${root}\0${appDir ?? ""}\0${pagesDir ?? ""}`;
|
|
11
|
+
if (mdxScanCache.has(cacheKey)) return mdxScanCache.get(cacheKey);
|
|
12
|
+
const dirs = [appDir, pagesDir].filter(Boolean);
|
|
13
|
+
for (const dir of dirs) if (fs.existsSync(dir) && scanDirForMdx(dir)) {
|
|
14
|
+
mdxScanCache.set(cacheKey, true);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
mdxScanCache.set(cacheKey, false);
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
function scanDirForMdx(dir) {
|
|
21
|
+
try {
|
|
22
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
25
|
+
const full = path.join(dir, entry.name);
|
|
26
|
+
if (entry.isDirectory()) {
|
|
27
|
+
if (scanDirForMdx(full)) return true;
|
|
28
|
+
} else if (entry.isFile() && entry.name.toLowerCase().endsWith(".mdx")) return true;
|
|
29
|
+
}
|
|
30
|
+
} catch {}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { hasMdxFiles, mdxScanCache };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=mdx-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdx-scan.js","names":[],"sources":["../../src/utils/mdx-scan.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/** Module-level cache for hasMdxFiles — avoids re-scanning per Vite environment. */\nexport const mdxScanCache = new Map<string, boolean>();\n\n/**\n * Check if the project has .mdx files in app/ or pages/ directories.\n */\nexport function hasMdxFiles(root: string, appDir: string | null, pagesDir: string | null): boolean {\n const cacheKey = `${root}\\0${appDir ?? \"\"}\\0${pagesDir ?? \"\"}`;\n if (mdxScanCache.has(cacheKey)) return mdxScanCache.get(cacheKey)!;\n const dirs = [appDir, pagesDir].filter(Boolean) as string[];\n for (const dir of dirs) {\n if (fs.existsSync(dir) && scanDirForMdx(dir)) {\n mdxScanCache.set(cacheKey, true);\n return true;\n }\n }\n mdxScanCache.set(cacheKey, false);\n return false;\n}\n\nfunction scanDirForMdx(dir: string): boolean {\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (scanDirForMdx(full)) return true;\n } else if (entry.isFile() && entry.name.toLowerCase().endsWith(\".mdx\")) {\n return true;\n }\n }\n } catch {\n // ignore unreadable dirs\n }\n return false;\n}\n"],"mappings":";;;;AAIA,MAAa,+BAAe,IAAI,KAAsB;;;;AAKtD,SAAgB,YAAY,MAAc,QAAuB,UAAkC;CACjG,MAAM,WAAW,GAAG,KAAK,IAAI,UAAU,GAAG,IAAI,YAAY;AAC1D,KAAI,aAAa,IAAI,SAAS,CAAE,QAAO,aAAa,IAAI,SAAS;CACjE,MAAM,OAAO,CAAC,QAAQ,SAAS,CAAC,OAAO,QAAQ;AAC/C,MAAK,MAAM,OAAO,KAChB,KAAI,GAAG,WAAW,IAAI,IAAI,cAAc,IAAI,EAAE;AAC5C,eAAa,IAAI,UAAU,KAAK;AAChC,SAAO;;AAGX,cAAa,IAAI,UAAU,MAAM;AACjC,QAAO;;AAGT,SAAS,cAAc,KAAsB;AAC3C,KAAI;EACF,MAAM,UAAU,GAAG,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC;AAC5D,OAAK,MAAM,SAAS,SAAS;AAC3B,OAAI,MAAM,KAAK,WAAW,IAAI,IAAI,MAAM,SAAS,eAAgB;GACjE,MAAM,OAAO,KAAK,KAAK,KAAK,MAAM,KAAK;AACvC,OAAI,MAAM,aAAa;QACjB,cAAc,KAAK,CAAE,QAAO;cACvB,MAAM,QAAQ,IAAI,MAAM,KAAK,aAAa,CAAC,SAAS,OAAO,CACpE,QAAO;;SAGL;AAGR,QAAO"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
//#region src/utils/public-routes.ts
|
|
4
|
+
function scanPublicFileRoutes(root) {
|
|
5
|
+
const publicDir = path.join(root, "public");
|
|
6
|
+
const routes = [];
|
|
7
|
+
const visitedDirs = /* @__PURE__ */ new Set();
|
|
8
|
+
function walk(dir) {
|
|
9
|
+
let realDir;
|
|
10
|
+
try {
|
|
11
|
+
realDir = fs.realpathSync(dir);
|
|
12
|
+
} catch {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (visitedDirs.has(realDir)) return;
|
|
16
|
+
visitedDirs.add(realDir);
|
|
17
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
18
|
+
for (const entry of entries) {
|
|
19
|
+
const fullPath = path.join(dir, entry.name);
|
|
20
|
+
if (entry.isDirectory()) {
|
|
21
|
+
walk(fullPath);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (entry.isSymbolicLink()) {
|
|
25
|
+
let stat;
|
|
26
|
+
try {
|
|
27
|
+
stat = fs.statSync(fullPath);
|
|
28
|
+
} catch {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (stat.isDirectory()) {
|
|
32
|
+
walk(fullPath);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (!stat.isFile()) continue;
|
|
36
|
+
} else if (!entry.isFile()) continue;
|
|
37
|
+
const relativePath = path.relative(publicDir, fullPath).split(path.sep).join("/");
|
|
38
|
+
routes.push("/" + relativePath);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (fs.existsSync(publicDir)) try {
|
|
42
|
+
walk(publicDir);
|
|
43
|
+
} catch {}
|
|
44
|
+
routes.sort();
|
|
45
|
+
return routes;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { scanPublicFileRoutes };
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=public-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-routes.js","names":[],"sources":["../../src/utils/public-routes.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport function scanPublicFileRoutes(root: string): string[] {\n const publicDir = path.join(root, \"public\");\n const routes: string[] = [];\n const visitedDirs = new Set<string>();\n\n function walk(dir: string): void {\n let realDir: string;\n try {\n realDir = fs.realpathSync(dir);\n } catch {\n return;\n }\n if (visitedDirs.has(realDir)) return;\n visitedDirs.add(realDir);\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n continue;\n }\n if (entry.isSymbolicLink()) {\n let stat: fs.Stats;\n try {\n stat = fs.statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n walk(fullPath);\n continue;\n }\n if (!stat.isFile()) continue;\n } else if (!entry.isFile()) {\n continue;\n }\n const relativePath = path.relative(publicDir, fullPath).split(path.sep).join(\"/\");\n routes.push(\"/\" + relativePath);\n }\n }\n\n if (fs.existsSync(publicDir)) {\n try {\n walk(publicDir);\n } catch {\n // ignore unreadable dirs\n }\n }\n\n routes.sort();\n return routes;\n}\n"],"mappings":";;;AAGA,SAAgB,qBAAqB,MAAwB;CAC3D,MAAM,YAAY,KAAK,KAAK,MAAM,SAAS;CAC3C,MAAM,SAAmB,EAAE;CAC3B,MAAM,8BAAc,IAAI,KAAa;CAErC,SAAS,KAAK,KAAmB;EAC/B,IAAI;AACJ,MAAI;AACF,aAAU,GAAG,aAAa,IAAI;UACxB;AACN;;AAEF,MAAI,YAAY,IAAI,QAAQ,CAAE;AAC9B,cAAY,IAAI,QAAQ;EAExB,MAAM,UAAU,GAAG,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC;AAC5D,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,WAAW,KAAK,KAAK,KAAK,MAAM,KAAK;AAC3C,OAAI,MAAM,aAAa,EAAE;AACvB,SAAK,SAAS;AACd;;AAEF,OAAI,MAAM,gBAAgB,EAAE;IAC1B,IAAI;AACJ,QAAI;AACF,YAAO,GAAG,SAAS,SAAS;YACtB;AACN;;AAEF,QAAI,KAAK,aAAa,EAAE;AACtB,UAAK,SAAS;AACd;;AAEF,QAAI,CAAC,KAAK,QAAQ,CAAE;cACX,CAAC,MAAM,QAAQ,CACxB;GAEF,MAAM,eAAe,KAAK,SAAS,WAAW,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,IAAI;AACjF,UAAO,KAAK,MAAM,aAAa;;;AAInC,KAAI,GAAG,WAAW,UAAU,CAC1B,KAAI;AACF,OAAK,UAAU;SACT;AAKV,QAAO,MAAM;AACb,QAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vinext",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.43",
|
|
4
4
|
"description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
"@vitejs/plugin-react": "^6.0.1",
|
|
69
69
|
"@vitejs/plugin-rsc": "^0.5.23",
|
|
70
70
|
"react-server-dom-webpack": "^19.2.5",
|
|
71
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.
|
|
72
|
-
"vite-plus": "0.1.
|
|
71
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.17",
|
|
72
|
+
"vite-plus": "0.1.17"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@mdx-js/rollup": "^3.0.0",
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Plugin } from "vite";
|
|
2
|
-
|
|
3
|
-
//#region src/plugins/fix-use-server-closure-collision.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Fix 'use server' closure variable collision with local declarations.
|
|
6
|
-
*
|
|
7
|
-
* @vitejs/plugin-rsc uses `periscopic` to find closure variables for
|
|
8
|
-
* 'use server' inline functions. Due to how periscopic handles block scopes,
|
|
9
|
-
* `const X = ...` declared inside a 'use server' function body is tracked in
|
|
10
|
-
* the BlockStatement scope (not the FunctionDeclaration scope). When periscopic
|
|
11
|
-
* searches for the owner of a reference `X`, it finds the block scope — which
|
|
12
|
-
* is neither the function scope nor the module scope — so it incorrectly
|
|
13
|
-
* classifies `X` as a closure variable from the outer scope.
|
|
14
|
-
*
|
|
15
|
-
* The result: plugin-rsc injects `const [X] = await decryptActionBoundArgs(...)`
|
|
16
|
-
* at the top of the hoisted function, colliding with the existing `const X = ...`
|
|
17
|
-
* declaration in the body. This causes a SyntaxError.
|
|
18
|
-
*
|
|
19
|
-
* Fix: before plugin-rsc sees the file, detect any 'use server' function whose
|
|
20
|
-
* local `const/let/var` declarations shadow an outer-scope variable, and rename
|
|
21
|
-
* the inner declarations (+ usages within that function) to `__local_X`. This
|
|
22
|
-
* eliminates the collision without changing semantics.
|
|
23
|
-
*
|
|
24
|
-
* This is a general fix that works for any library — not just @payloadcms/next.
|
|
25
|
-
*/
|
|
26
|
-
declare const fixUseServerClosureCollisionPlugin: Plugin;
|
|
27
|
-
//#endregion
|
|
28
|
-
export { fixUseServerClosureCollisionPlugin };
|
|
29
|
-
//# sourceMappingURL=fix-use-server-closure-collision.d.ts.map
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { parseAst } from "vite";
|
|
2
|
-
import MagicString from "magic-string";
|
|
3
|
-
//#region src/plugins/fix-use-server-closure-collision.ts
|
|
4
|
-
/**
|
|
5
|
-
* Fix 'use server' closure variable collision with local declarations.
|
|
6
|
-
*
|
|
7
|
-
* @vitejs/plugin-rsc uses `periscopic` to find closure variables for
|
|
8
|
-
* 'use server' inline functions. Due to how periscopic handles block scopes,
|
|
9
|
-
* `const X = ...` declared inside a 'use server' function body is tracked in
|
|
10
|
-
* the BlockStatement scope (not the FunctionDeclaration scope). When periscopic
|
|
11
|
-
* searches for the owner of a reference `X`, it finds the block scope — which
|
|
12
|
-
* is neither the function scope nor the module scope — so it incorrectly
|
|
13
|
-
* classifies `X` as a closure variable from the outer scope.
|
|
14
|
-
*
|
|
15
|
-
* The result: plugin-rsc injects `const [X] = await decryptActionBoundArgs(...)`
|
|
16
|
-
* at the top of the hoisted function, colliding with the existing `const X = ...`
|
|
17
|
-
* declaration in the body. This causes a SyntaxError.
|
|
18
|
-
*
|
|
19
|
-
* Fix: before plugin-rsc sees the file, detect any 'use server' function whose
|
|
20
|
-
* local `const/let/var` declarations shadow an outer-scope variable, and rename
|
|
21
|
-
* the inner declarations (+ usages within that function) to `__local_X`. This
|
|
22
|
-
* eliminates the collision without changing semantics.
|
|
23
|
-
*
|
|
24
|
-
* This is a general fix that works for any library — not just @payloadcms/next.
|
|
25
|
-
*/
|
|
26
|
-
const fixUseServerClosureCollisionPlugin = {
|
|
27
|
-
name: "vinext:fix-use-server-closure-collision",
|
|
28
|
-
enforce: "pre",
|
|
29
|
-
transform(code, id) {
|
|
30
|
-
if (!code.includes("use server")) return null;
|
|
31
|
-
if (!/\.(js|jsx|ts|tsx|mjs|cjs)$/.test(id.split("?")[0])) return null;
|
|
32
|
-
let ast;
|
|
33
|
-
try {
|
|
34
|
-
ast = parseAst(code);
|
|
35
|
-
} catch {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
function collectPatternNames(pattern, names) {
|
|
39
|
-
if (!pattern) return;
|
|
40
|
-
if (pattern.type === "Identifier") names.add(pattern.name);
|
|
41
|
-
else if (pattern.type === "ObjectPattern") for (const prop of pattern.properties) collectPatternNames(prop.value ?? prop.argument, names);
|
|
42
|
-
else if (pattern.type === "ArrayPattern") for (const elem of pattern.elements) collectPatternNames(elem, names);
|
|
43
|
-
else if (pattern.type === "RestElement" || pattern.type === "AssignmentPattern") collectPatternNames(pattern.left ?? pattern.argument, names);
|
|
44
|
-
}
|
|
45
|
-
function hasUseServerDirective(body) {
|
|
46
|
-
for (const stmt of body) {
|
|
47
|
-
if (stmt.type === "ExpressionStatement" && stmt.expression?.type === "Literal" && typeof stmt.expression.value === "string") {
|
|
48
|
-
if (stmt.expression.value === "use server") return true;
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
const s = new MagicString(code);
|
|
56
|
-
const renamedRanges = /* @__PURE__ */ new Set();
|
|
57
|
-
let changed = false;
|
|
58
|
-
function visitNode(node, ancestorNames) {
|
|
59
|
-
if (!node || typeof node !== "object") return;
|
|
60
|
-
if (!(node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression")) {
|
|
61
|
-
const namesForChildren = new Set(ancestorNames);
|
|
62
|
-
if (node.type === "CatchClause" && node.param) collectPatternNames(node.param, namesForChildren);
|
|
63
|
-
collectFunctionScopedNames(node, namesForChildren);
|
|
64
|
-
const immediateStmts = node.type === "Program" ? node.body : node.type === "BlockStatement" ? node.body : [];
|
|
65
|
-
for (const stmt of immediateStmts) if (stmt?.type === "VariableDeclaration") for (const decl of stmt.declarations) collectPatternNames(decl.id, namesForChildren);
|
|
66
|
-
else if (stmt?.type === "ClassDeclaration" && stmt.id?.name) namesForChildren.add(stmt.id.name);
|
|
67
|
-
else if (stmt?.type === "ImportDeclaration") {
|
|
68
|
-
for (const spec of stmt.specifiers ?? []) if (spec.local?.name) namesForChildren.add(spec.local.name);
|
|
69
|
-
}
|
|
70
|
-
for (const key of Object.keys(node)) {
|
|
71
|
-
if (key === "type") continue;
|
|
72
|
-
const child = node[key];
|
|
73
|
-
if (Array.isArray(child)) for (const c of child) visitNode(c, namesForChildren);
|
|
74
|
-
else if (child && typeof child === "object" && child.type) visitNode(child, namesForChildren);
|
|
75
|
-
}
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const namesForBody = new Set(ancestorNames);
|
|
79
|
-
for (const p of node.params ?? []) collectPatternNames(p, namesForBody);
|
|
80
|
-
const bodyStmts = node.body?.type === "BlockStatement" ? node.body.body : [];
|
|
81
|
-
if (hasUseServerDirective(bodyStmts)) {
|
|
82
|
-
const localDecls = /* @__PURE__ */ new Set();
|
|
83
|
-
collectAllDeclaredNames(node.body, localDecls);
|
|
84
|
-
const collisionRenames = /* @__PURE__ */ new Map();
|
|
85
|
-
for (const name of localDecls) if (namesForBody.has(name)) {
|
|
86
|
-
let to = `__local_${name}`;
|
|
87
|
-
let suffix = 0;
|
|
88
|
-
while (localDecls.has(to) || namesForBody.has(to)) {
|
|
89
|
-
to = `__local_${suffix}_${name}`;
|
|
90
|
-
suffix++;
|
|
91
|
-
}
|
|
92
|
-
collisionRenames.set(name, to);
|
|
93
|
-
}
|
|
94
|
-
if (collisionRenames.size > 0) {
|
|
95
|
-
for (const [name, to] of collisionRenames) renamingWalk(node.body, name, to);
|
|
96
|
-
changed = true;
|
|
97
|
-
}
|
|
98
|
-
const namesForChildren = new Set(namesForBody);
|
|
99
|
-
for (const name of localDecls) if (collisionRenames.has(name)) {
|
|
100
|
-
namesForChildren.delete(name);
|
|
101
|
-
namesForChildren.add(collisionRenames.get(name));
|
|
102
|
-
} else namesForChildren.add(name);
|
|
103
|
-
for (const stmt of bodyStmts) visitNode(stmt, namesForChildren);
|
|
104
|
-
for (const p of node.params ?? []) visitNode(p, ancestorNames);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
const namesForChildren = new Set(namesForBody);
|
|
108
|
-
collectFunctionScopedNames(node.body, namesForChildren);
|
|
109
|
-
for (const stmt of bodyStmts) if (stmt?.type === "VariableDeclaration" && stmt.kind !== "var") for (const decl of stmt.declarations) collectPatternNames(decl.id, namesForChildren);
|
|
110
|
-
for (const key of Object.keys(node)) {
|
|
111
|
-
if (key === "type") continue;
|
|
112
|
-
const child = node[key];
|
|
113
|
-
if (Array.isArray(child)) for (const c of child) visitNode(c, namesForChildren);
|
|
114
|
-
else if (child && typeof child === "object" && child.type) visitNode(child, namesForChildren);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function renamingWalk(node, from, to, parent) {
|
|
118
|
-
if (!node || typeof node !== "object") return;
|
|
119
|
-
if (node.type === "Identifier" && node.name === from) {
|
|
120
|
-
if (parent?.type === "MemberExpression" && parent.property === node && !parent.computed) return;
|
|
121
|
-
if (parent?.type === "Property" && parent.key === node && !parent.computed) {
|
|
122
|
-
if (parent.shorthand) {
|
|
123
|
-
const rangeKey = `${node.start}:${node.end}`;
|
|
124
|
-
if (!renamedRanges.has(rangeKey)) {
|
|
125
|
-
renamedRanges.add(rangeKey);
|
|
126
|
-
s.update(node.start, node.end, `${from}: ${to}`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
if (parent?.type === "Property" && parent.shorthand && parent.value === node) return;
|
|
132
|
-
if (parent?.type === "LabeledStatement" && parent.label === node) return;
|
|
133
|
-
if ((parent?.type === "BreakStatement" || parent?.type === "ContinueStatement") && parent.label === node) return;
|
|
134
|
-
const rangeKey = `${node.start}:${node.end}`;
|
|
135
|
-
if (!renamedRanges.has(rangeKey)) {
|
|
136
|
-
renamedRanges.add(rangeKey);
|
|
137
|
-
s.update(node.start, node.end, to);
|
|
138
|
-
}
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
|
|
142
|
-
const nestedDecls = /* @__PURE__ */ new Set();
|
|
143
|
-
for (const p of node.params ?? []) collectPatternNames(p, nestedDecls);
|
|
144
|
-
collectAllDeclaredNames(node.body, nestedDecls);
|
|
145
|
-
if (nestedDecls.has(from)) return;
|
|
146
|
-
if (node.body?.type === "BlockStatement" && hasUseServerDirective(node.body.body)) return;
|
|
147
|
-
}
|
|
148
|
-
for (const key of Object.keys(node)) {
|
|
149
|
-
if (key === "type" || key === "start" || key === "end") continue;
|
|
150
|
-
const child = node[key];
|
|
151
|
-
if (Array.isArray(child)) for (const c of child) renamingWalk(c, from, to, node);
|
|
152
|
-
else if (child && typeof child === "object" && child.type) renamingWalk(child, from, to, node);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function collectFunctionScopedNames(node, names) {
|
|
156
|
-
if (!node || typeof node !== "object") return;
|
|
157
|
-
if (node.type === "FunctionDeclaration") {
|
|
158
|
-
if (node.id?.name) names.add(node.id.name);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
if (node.type === "ClassDeclaration") {
|
|
162
|
-
if (node.id?.name) names.add(node.id.name);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") return;
|
|
166
|
-
if (node.type === "VariableDeclaration" && node.kind === "var") for (const decl of node.declarations) collectPatternNames(decl.id, names);
|
|
167
|
-
for (const key of Object.keys(node)) {
|
|
168
|
-
if (key === "type") continue;
|
|
169
|
-
const child = node[key];
|
|
170
|
-
if (Array.isArray(child)) for (const c of child) collectFunctionScopedNames(c, names);
|
|
171
|
-
else if (child && typeof child === "object" && child.type) collectFunctionScopedNames(child, names);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function collectAllDeclaredNames(node, names) {
|
|
175
|
-
if (!node || typeof node !== "object") return;
|
|
176
|
-
if (node.type === "VariableDeclaration") for (const decl of node.declarations) collectPatternNames(decl.id, names);
|
|
177
|
-
if (node.type === "FunctionDeclaration") {
|
|
178
|
-
if (node.id?.name) names.add(node.id.name);
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
if (node.type === "ClassDeclaration") {
|
|
182
|
-
if (node.id?.name) names.add(node.id.name);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") return;
|
|
186
|
-
for (const key of Object.keys(node)) {
|
|
187
|
-
if (key === "type") continue;
|
|
188
|
-
const child = node[key];
|
|
189
|
-
if (Array.isArray(child)) for (const c of child) collectAllDeclaredNames(c, names);
|
|
190
|
-
else if (child && typeof child === "object" && child.type) collectAllDeclaredNames(child, names);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
visitNode(ast, /* @__PURE__ */ new Set());
|
|
194
|
-
if (!changed) return null;
|
|
195
|
-
return {
|
|
196
|
-
code: s.toString(),
|
|
197
|
-
map: s.generateMap({ hires: "boundary" })
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
//#endregion
|
|
202
|
-
export { fixUseServerClosureCollisionPlugin };
|
|
203
|
-
|
|
204
|
-
//# sourceMappingURL=fix-use-server-closure-collision.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fix-use-server-closure-collision.js","names":[],"sources":["../../src/plugins/fix-use-server-closure-collision.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { parseAst } from \"vite\";\nimport MagicString from \"magic-string\";\n\n/**\n * Fix 'use server' closure variable collision with local declarations.\n *\n * @vitejs/plugin-rsc uses `periscopic` to find closure variables for\n * 'use server' inline functions. Due to how periscopic handles block scopes,\n * `const X = ...` declared inside a 'use server' function body is tracked in\n * the BlockStatement scope (not the FunctionDeclaration scope). When periscopic\n * searches for the owner of a reference `X`, it finds the block scope — which\n * is neither the function scope nor the module scope — so it incorrectly\n * classifies `X` as a closure variable from the outer scope.\n *\n * The result: plugin-rsc injects `const [X] = await decryptActionBoundArgs(...)`\n * at the top of the hoisted function, colliding with the existing `const X = ...`\n * declaration in the body. This causes a SyntaxError.\n *\n * Fix: before plugin-rsc sees the file, detect any 'use server' function whose\n * local `const/let/var` declarations shadow an outer-scope variable, and rename\n * the inner declarations (+ usages within that function) to `__local_X`. This\n * eliminates the collision without changing semantics.\n *\n * This is a general fix that works for any library — not just @payloadcms/next.\n */\nexport const fixUseServerClosureCollisionPlugin: Plugin = {\n name: \"vinext:fix-use-server-closure-collision\",\n enforce: \"pre\" as const,\n transform(code: string, id: string) {\n // Quick bail-out: only files that contain 'use server' inline\n if (!code.includes(\"use server\")) return null;\n // Only JS/TS files\n if (!/\\.(js|jsx|ts|tsx|mjs|cjs)$/.test(id.split(\"?\")[0])) return null;\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n let ast: any;\n try {\n ast = parseAst(code);\n } catch {\n return null;\n }\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n function collectPatternNames(pattern: any, names: Set<string>) {\n if (!pattern) return;\n if (pattern.type === \"Identifier\") {\n names.add(pattern.name);\n } else if (pattern.type === \"ObjectPattern\") {\n for (const prop of pattern.properties) {\n collectPatternNames(prop.value ?? prop.argument, names);\n }\n } else if (pattern.type === \"ArrayPattern\") {\n for (const elem of pattern.elements) {\n collectPatternNames(elem, names);\n }\n } else if (pattern.type === \"RestElement\" || pattern.type === \"AssignmentPattern\") {\n collectPatternNames(pattern.left ?? pattern.argument, names);\n }\n }\n\n // Check if a block body has 'use server' as its leading directive prologue.\n // Only the first contiguous run of string-literal expression statements\n // counts — a \"use server\" string mid-function is not a directive.\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n function hasUseServerDirective(body: any[]): boolean {\n for (const stmt of body) {\n if (\n stmt.type === \"ExpressionStatement\" &&\n stmt.expression?.type === \"Literal\" &&\n typeof stmt.expression.value === \"string\"\n ) {\n if (stmt.expression.value === \"use server\") return true;\n // Any other string literal in the prologue — keep scanning\n continue;\n }\n // First non-string-literal statement ends the prologue\n break;\n }\n return false;\n }\n\n // Find all 'use server' inline functions and check for collisions.\n //\n // `ancestorNames` accumulates the names that are in scope in all ancestor\n // function/program bodies as we descend — this is the correct set to\n // compare against, not a whole-AST walk (which would pick up siblings).\n const s = new MagicString(code);\n // Track source ranges already rewritten so renamingWalk never calls\n // s.update() twice on the same span (MagicString throws if it does).\n const renamedRanges = new Set<string>();\n let changed = false;\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n function visitNode(node: any, ancestorNames: Set<string>) {\n if (!node || typeof node !== \"object\") return;\n\n const isFn =\n node.type === \"FunctionDeclaration\" ||\n node.type === \"FunctionExpression\" ||\n node.type === \"ArrowFunctionExpression\";\n\n if (!isFn) {\n // Non-function nodes (Program, BlockStatement, IfStatement, CatchClause,\n // etc.) don't introduce a new function scope, but they may contain\n // variable declarations and catch bindings that are visible to nested\n // functions as ancestor names. Accumulate those into a new set before\n // recursing so we don't mutate the caller's set.\n const namesForChildren = new Set(ancestorNames);\n\n // CatchClause: `catch (e)` — `e` is in scope for the catch body\n if (node.type === \"CatchClause\" && node.param) {\n collectPatternNames(node.param, namesForChildren);\n }\n\n // Collect names visible at function scope from this node:\n // - FunctionDeclaration names (hoisted to enclosing scope)\n // - ClassDeclaration names (block-scoped like let, but treated as\n // function-scoped for our purposes since periscopic sees them)\n // - var declarations (hoisted to function scope, found anywhere)\n // We do NOT collect let/const from nested blocks here — those are\n // block-scoped and not visible to sibling/outer function declarations.\n collectFunctionScopedNames(node, namesForChildren);\n // Also collect let/const/var/class/import declared as immediate children\n // of this node (e.g. top-level Program statements, or the direct body of\n // a BlockStatement) — those ARE in scope for everything in the same block.\n const immediateStmts =\n node.type === \"Program\" ? node.body : node.type === \"BlockStatement\" ? node.body : [];\n for (const stmt of immediateStmts) {\n if (stmt?.type === \"VariableDeclaration\") {\n for (const decl of stmt.declarations) collectPatternNames(decl.id, namesForChildren);\n } else if (stmt?.type === \"ClassDeclaration\" && stmt.id?.name) {\n namesForChildren.add(stmt.id.name);\n } else if (stmt?.type === \"ImportDeclaration\") {\n for (const spec of stmt.specifiers ?? []) {\n // ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier\n // all have `local.name` as the binding name in this module.\n if (spec.local?.name) namesForChildren.add(spec.local.name);\n }\n }\n }\n\n for (const key of Object.keys(node)) {\n if (key === \"type\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const c of child) visitNode(c, namesForChildren);\n } else if (child && typeof child === \"object\" && child.type) {\n visitNode(child, namesForChildren);\n }\n }\n return;\n }\n\n // Build the ancestor name set visible inside this function:\n // everything the parent saw, plus this function's own params.\n const namesForBody = new Set(ancestorNames);\n for (const p of node.params ?? []) collectPatternNames(p, namesForBody);\n\n // Check whether the body has the 'use server' directive.\n const bodyStmts = node.body?.type === \"BlockStatement\" ? node.body.body : [];\n const isServerFn = hasUseServerDirective(bodyStmts);\n\n if (isServerFn) {\n // Collect ALL variables declared anywhere in this function body.\n // This includes direct bodyStmts, but also for...of/for...in loop\n // variables, declarations inside if/try/while blocks, etc.\n // periscopic puts these in the BlockStatement scope (not the function\n // scope), so they get mis-classified as closure vars from the outer scope.\n // We use collectAllDeclaredNames (recursive, crosses blocks, stops at\n // nested function bodies) to catch every possible declaration site.\n const localDecls = new Set<string>();\n collectAllDeclaredNames(node.body, localDecls);\n\n // Find collisions: local decls that shadow a name from ancestor scopes.\n // collisionRenames maps original name → chosen rename target, taking\n // into account that `__local_${name}` may itself already be declared\n // (e.g. the user wrote `const __local_cookies = ...`). In that case\n // we try `__local_0_${name}`, `__local_1_${name}`, … until we find a\n // free name. This prevents a secondary collision.\n const collisionRenames = new Map<string, string>();\n for (const name of localDecls) {\n if (namesForBody.has(name)) {\n let to = `__local_${name}`;\n let suffix = 0;\n while (localDecls.has(to) || namesForBody.has(to)) {\n to = `__local_${suffix}_${name}`;\n suffix++;\n }\n collisionRenames.set(name, to);\n }\n }\n\n if (collisionRenames.size > 0) {\n for (const [name, to] of collisionRenames) {\n renamingWalk(node.body, name, to);\n }\n changed = true;\n }\n\n // Build the ancestor set for children of this server function.\n // Colliding names have been renamed in this body, e.g. `cookies` →\n // `__local_cookies`. The original name no longer exists as a binding\n // in this scope, so we must remove it from the set and add the renamed\n // version instead. Leaving the original name in would cause nested\n // server functions to see it as an ancestor binding and spuriously flag\n // their own independent `const cookies` as a collision.\n const namesForChildren = new Set(namesForBody);\n for (const name of localDecls) {\n if (collisionRenames.has(name)) {\n namesForChildren.delete(name);\n namesForChildren.add(collisionRenames.get(name)!);\n } else {\n namesForChildren.add(name);\n }\n }\n\n // Recurse into children — nested 'use server' functions must be visited.\n // Skip node.body itself (already handled by renamingWalk above for\n // collisions); we recurse into each statement individually so that\n // nested functions inside the body get their own visitNode pass with\n // the correct ancestorNames.\n for (const stmt of bodyStmts) {\n visitNode(stmt, namesForChildren);\n }\n // Also visit params (they can contain default expressions with closures)\n for (const p of node.params ?? []) visitNode(p, ancestorNames);\n return;\n }\n\n // Not a server function — build the ancestor set for nested functions:\n // - var declarations anywhere in this function body (function-scoped)\n // - FunctionDeclaration names anywhere in this function body\n // - let/const only from the top-level statements of this function body\n // (block-scoped — not visible to nested fns in sibling blocks)\n const namesForChildren = new Set(namesForBody);\n collectFunctionScopedNames(node.body, namesForChildren);\n for (const stmt of bodyStmts) {\n if (stmt?.type === \"VariableDeclaration\" && stmt.kind !== \"var\") {\n for (const decl of stmt.declarations) collectPatternNames(decl.id, namesForChildren);\n }\n }\n\n for (const key of Object.keys(node)) {\n if (key === \"type\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const c of child) visitNode(c, namesForChildren);\n } else if (child && typeof child === \"object\" && child.type) {\n visitNode(child, namesForChildren);\n }\n }\n }\n\n // Walk an AST subtree renaming all variable-reference Identifier nodes\n // matching `from` to `to`.\n //\n // Correctness rules:\n // - Non-computed MemberExpression.property is NOT a variable reference\n // - Non-computed Property.key is NOT a variable reference\n // - Shorthand Property { x } must be expanded to { x: __local_x }\n // - A nested function that re-declares `from` in its params OR anywhere\n // in its body via var/const/let (including inside control flow) is a\n // new binding — stop descending into it\n // - Never call s.update() on the same source range twice\n //\n // `parent` is the direct parent AST node, used to detect property contexts.\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n function renamingWalk(node: any, from: string, to: string, parent?: any) {\n if (!node || typeof node !== \"object\") return;\n\n if (node.type === \"Identifier\" && node.name === from) {\n // Non-computed member expression property: obj.cookies — not a ref\n if (parent?.type === \"MemberExpression\" && parent.property === node && !parent.computed) {\n return;\n }\n\n // Non-computed property key in an object literal\n if (parent?.type === \"Property\" && parent.key === node && !parent.computed) {\n if (parent.shorthand) {\n // { cookies } — key and value are the same AST node.\n // Expand to { cookies: __local_cookies } by rewriting at the key\n // visit; skip the value visit via the guard below.\n const rangeKey = `${node.start}:${node.end}`;\n if (!renamedRanges.has(rangeKey)) {\n renamedRanges.add(rangeKey);\n s.update(node.start, node.end, `${from}: ${to}`);\n }\n }\n // Either way, key is not a variable reference — do not rename it.\n return;\n }\n\n // Value side of a shorthand property — same node as key, already handled\n if (parent?.type === \"Property\" && parent.shorthand && parent.value === node) {\n return;\n }\n\n // LabeledStatement label: `cookies: for (...)` — not a variable reference\n if (parent?.type === \"LabeledStatement\" && parent.label === node) {\n return;\n }\n\n // break/continue label: `break cookies` / `continue cookies` — not a variable reference\n if (\n (parent?.type === \"BreakStatement\" || parent?.type === \"ContinueStatement\") &&\n parent.label === node\n ) {\n return;\n }\n\n const rangeKey = `${node.start}:${node.end}`;\n if (!renamedRanges.has(rangeKey)) {\n renamedRanges.add(rangeKey);\n s.update(node.start, node.end, to);\n }\n return;\n }\n\n // For nested function nodes, check whether they re-declare `from`.\n // If they do, stop — the name in that nested scope is a different binding.\n // We must check ALL var declarations anywhere in the body (var hoists),\n // not just top-level statements.\n if (\n node.type === \"FunctionDeclaration\" ||\n node.type === \"FunctionExpression\" ||\n node.type === \"ArrowFunctionExpression\"\n ) {\n const nestedDecls = new Set<string>();\n // Params\n for (const p of node.params ?? []) collectPatternNames(p, nestedDecls);\n // Recursively find all var/const/let declarations in the body,\n // including those nested inside if/for/while/etc.\n collectAllDeclaredNames(node.body, nestedDecls);\n if (nestedDecls.has(from)) return;\n\n // Also stop at nested 'use server' functions — visitNode will handle them\n // independently with the correct collision set, preventing double-rewrites.\n if (node.body?.type === \"BlockStatement\" && hasUseServerDirective(node.body.body)) {\n return;\n }\n }\n\n for (const key of Object.keys(node)) {\n if (key === \"type\" || key === \"start\" || key === \"end\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const c of child) renamingWalk(c, from, to, node);\n } else if (child && typeof child === \"object\" && child.type) {\n renamingWalk(child, from, to, node);\n }\n }\n }\n\n // Collect names that are visible at function scope from a given subtree.\n //\n // Two separate helpers with different traversal rules:\n //\n // collectFunctionScopedNames(node, names)\n // Collects `var` declarations and `FunctionDeclaration` names anywhere\n // in the subtree, crossing block boundaries (if/for/while/try/catch)\n // but NOT crossing nested function bodies. `let`/`const` in nested\n // blocks are intentionally skipped — they are block-scoped and not\n // visible outside that block.\n // Use this when building ancestorNames for nested functions.\n //\n // collectAllDeclaredNames(node, names)\n // Collects ALL var/let/const declarations anywhere in the subtree,\n // crossing block boundaries but not nested function bodies.\n // Used only by renamingWalk's re-declaration check, where we want to\n // know if ANY declaration of `from` exists in a nested function's scope\n // (params already handled separately).\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n function collectFunctionScopedNames(node: any, names: Set<string>) {\n if (!node || typeof node !== \"object\") return;\n // FunctionDeclaration: its name is a binding in the enclosing scope.\n // Record it, then stop — don't recurse into the body (different scope).\n if (node.type === \"FunctionDeclaration\") {\n if (node.id?.name) names.add(node.id.name);\n return;\n }\n // ClassDeclaration: like FunctionDeclaration, its name is a binding in\n // the enclosing scope. Don't recurse into the body.\n if (node.type === \"ClassDeclaration\") {\n if (node.id?.name) names.add(node.id.name);\n return;\n }\n // FunctionExpression / ArrowFunctionExpression names are only in scope\n // inside their own body, not the enclosing scope — skip entirely.\n if (node.type === \"FunctionExpression\" || node.type === \"ArrowFunctionExpression\") {\n return;\n }\n // var declarations are function-scoped — collect them wherever they appear.\n // let/const at a nested block level are block-scoped and NOT visible to\n // sibling or outer function declarations, so skip them here.\n if (node.type === \"VariableDeclaration\" && node.kind === \"var\") {\n for (const decl of node.declarations) collectPatternNames(decl.id, names);\n }\n for (const key of Object.keys(node)) {\n if (key === \"type\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const c of child) collectFunctionScopedNames(c, names);\n } else if (child && typeof child === \"object\" && child.type) {\n collectFunctionScopedNames(child, names);\n }\n }\n }\n\n // Collect ALL declared names (var/let/const/class/function) in a subtree,\n // crossing blocks but not nested function bodies or class bodies.\n // Used by renamingWalk's re-declaration check where any shadowing\n // declaration — regardless of kind — must stop the rename from descending\n // further, and by the server-function local-decl scan to detect all\n // possible collision sites (including class declarations in the body).\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n function collectAllDeclaredNames(node: any, names: Set<string>) {\n if (!node || typeof node !== \"object\") return;\n if (node.type === \"VariableDeclaration\") {\n for (const decl of node.declarations) collectPatternNames(decl.id, names);\n }\n // FunctionDeclaration name is a binding in the enclosing scope — record it.\n if (node.type === \"FunctionDeclaration\") {\n if (node.id?.name) names.add(node.id.name);\n return; // don't recurse into its body\n }\n // ClassDeclaration name is a binding in the enclosing scope — record it.\n if (node.type === \"ClassDeclaration\") {\n if (node.id?.name) names.add(node.id.name);\n return; // don't recurse into the class body (separate scope)\n }\n if (node.type === \"FunctionExpression\" || node.type === \"ArrowFunctionExpression\") {\n return; // different scope — stop\n }\n for (const key of Object.keys(node)) {\n if (key === \"type\") continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const c of child) collectAllDeclaredNames(c, names);\n } else if (child && typeof child === \"object\" && child.type) {\n collectAllDeclaredNames(child, names);\n }\n }\n }\n\n visitNode(ast, new Set());\n\n if (!changed) return null;\n return { code: s.toString(), map: s.generateMap({ hires: \"boundary\" }) };\n },\n};\n"],"mappings":"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"}
|