vinext 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/README.md +93 -10
  2. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  3. package/dist/build/app-page-static-eligibility.js +82 -0
  4. package/dist/build/client-build-config.d.ts +10 -0
  5. package/dist/build/client-build-config.js +18 -2
  6. package/dist/build/pages-client-assets-module.d.ts +8 -0
  7. package/dist/build/pages-client-assets-module.js +21 -1
  8. package/dist/build/prerender-paths.js +8 -81
  9. package/dist/build/prerender.js +33 -8
  10. package/dist/build/run-prerender.js +1 -1
  11. package/dist/build/server-manifest.d.ts +7 -0
  12. package/dist/build/server-manifest.js +11 -1
  13. package/dist/build/ssr-manifest.d.ts +2 -0
  14. package/dist/build/ssr-manifest.js +6 -2
  15. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  16. package/dist/cache/cache-adapters-virtual.js +3 -3
  17. package/dist/check.js +7 -6
  18. package/dist/cli.js +2 -1
  19. package/dist/client/client-redirect-matcher.d.ts +14 -0
  20. package/dist/client/client-redirect-matcher.js +37 -0
  21. package/dist/client/client-redirects.d.ts +27 -0
  22. package/dist/client/client-redirects.js +28 -0
  23. package/dist/client/client-rewrites.d.ts +2 -1
  24. package/dist/client/client-rewrites.js +1 -1
  25. package/dist/client/navigation-runtime.d.ts +11 -0
  26. package/dist/client/navigation-runtime.js +1 -1
  27. package/dist/config/config-matchers.d.ts +26 -11
  28. package/dist/config/config-matchers.js +81 -82
  29. package/dist/config/destination-params.d.ts +47 -0
  30. package/dist/config/destination-params.js +116 -0
  31. package/dist/config/next-config.d.ts +14 -0
  32. package/dist/config/next-config.js +21 -3
  33. package/dist/entries/app-rsc-entry.d.ts +6 -0
  34. package/dist/entries/app-rsc-entry.js +84 -49
  35. package/dist/entries/pages-client-entry.js +3 -1
  36. package/dist/entries/pages-server-entry.js +13 -37
  37. package/dist/index.d.ts +7 -2
  38. package/dist/index.js +193 -73
  39. package/dist/init-cloudflare.d.ts +9 -0
  40. package/dist/init-cloudflare.js +107 -31
  41. package/dist/init-platform.d.ts +4 -0
  42. package/dist/init-platform.js +27 -2
  43. package/dist/init.d.ts +1 -0
  44. package/dist/init.js +67 -3
  45. package/dist/plugins/ast-scope.d.ts +7 -0
  46. package/dist/plugins/ast-scope.js +59 -3
  47. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  48. package/dist/plugins/cache-flight-codec.js +68 -0
  49. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  50. package/dist/plugins/commonjs-esm-facade.js +80 -0
  51. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  52. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  53. package/dist/plugins/fonts.d.ts +8 -11
  54. package/dist/plugins/fonts.js +71 -34
  55. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  56. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  57. package/dist/plugins/middleware-server-only.d.ts +5 -4
  58. package/dist/plugins/middleware-server-only.js +8 -5
  59. package/dist/plugins/pages-node-externals.js +1 -1
  60. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  61. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  62. package/dist/plugins/strip-server-exports.js +262 -98
  63. package/dist/plugins/transform-result.d.ts +9 -5
  64. package/dist/plugins/transitive-externals.js +1 -1
  65. package/dist/plugins/typeof-window.d.ts +2 -2
  66. package/dist/plugins/use-cache-callable.js +8 -2
  67. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  68. package/dist/plugins/worker-server-only-imports.js +31 -0
  69. package/dist/plugins/worker-use-server.d.ts +25 -0
  70. package/dist/plugins/worker-use-server.js +129 -0
  71. package/dist/routing/file-matcher.d.ts +1 -0
  72. package/dist/routing/file-matcher.js +1 -1
  73. package/dist/server/api-handler.d.ts +1 -0
  74. package/dist/server/api-handler.js +19 -8
  75. package/dist/server/app-browser-action-result.d.ts +1 -1
  76. package/dist/server/app-browser-action-result.js +9 -2
  77. package/dist/server/app-browser-entry.js +11 -7
  78. package/dist/server/app-browser-history-controller.d.ts +2 -0
  79. package/dist/server/app-browser-history-controller.js +8 -0
  80. package/dist/server/app-browser-interception-context.js +26 -2
  81. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  82. package/dist/server/app-browser-navigation-controller.js +94 -11
  83. package/dist/server/app-browser-server-action-client.js +1 -1
  84. package/dist/server/app-fallback-renderer.d.ts +2 -0
  85. package/dist/server/app-fallback-renderer.js +1 -0
  86. package/dist/server/app-history-state.d.ts +3 -0
  87. package/dist/server/app-history-state.js +7 -0
  88. package/dist/server/app-middleware.d.ts +11 -0
  89. package/dist/server/app-middleware.js +19 -3
  90. package/dist/server/app-optimistic-routing.js +1 -1
  91. package/dist/server/app-page-boundary-render.d.ts +5 -0
  92. package/dist/server/app-page-boundary-render.js +6 -4
  93. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  94. package/dist/server/app-page-cache-finalizer.js +41 -7
  95. package/dist/server/app-page-cache-render.d.ts +18 -0
  96. package/dist/server/app-page-cache-render.js +63 -43
  97. package/dist/server/app-page-cache.d.ts +6 -1
  98. package/dist/server/app-page-cache.js +28 -8
  99. package/dist/server/app-page-dispatch.d.ts +12 -2
  100. package/dist/server/app-page-dispatch.js +51 -33
  101. package/dist/server/app-page-element-builder.d.ts +7 -0
  102. package/dist/server/app-page-element-builder.js +27 -42
  103. package/dist/server/app-page-execution.d.ts +15 -12
  104. package/dist/server/app-page-execution.js +30 -40
  105. package/dist/server/app-page-head.d.ts +5 -0
  106. package/dist/server/app-page-head.js +9 -3
  107. package/dist/server/app-page-ppr-runtime.js +1 -1
  108. package/dist/server/app-page-probe.d.ts +0 -109
  109. package/dist/server/app-page-probe.js +3 -136
  110. package/dist/server/app-page-render-identity.d.ts +0 -1
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render-observation.js +3 -3
  113. package/dist/server/app-page-render.d.ts +13 -5
  114. package/dist/server/app-page-render.js +219 -119
  115. package/dist/server/app-page-request.d.ts +0 -1
  116. package/dist/server/app-page-request.js +54 -17
  117. package/dist/server/app-page-response.d.ts +4 -3
  118. package/dist/server/app-page-response.js +4 -3
  119. package/dist/server/app-page-route-wiring.d.ts +17 -5
  120. package/dist/server/app-page-route-wiring.js +57 -35
  121. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  122. package/dist/server/app-page-rsc-render-status.js +54 -0
  123. package/dist/server/app-page-stream.d.ts +15 -8
  124. package/dist/server/app-page-stream.js +6 -0
  125. package/dist/server/app-pages-bridge.d.ts +1 -1
  126. package/dist/server/app-pages-bridge.js +2 -3
  127. package/dist/server/app-prerender-endpoints.js +9 -6
  128. package/dist/server/app-request-stage-dispatch.js +7 -3
  129. package/dist/server/app-request-stage-independent-entry.js +29 -9
  130. package/dist/server/app-response-header-provenance.d.ts +2 -0
  131. package/dist/server/app-response-header-provenance.js +10 -4
  132. package/dist/server/app-response-stage-entry.js +10 -2
  133. package/dist/server/app-route-handler-cache.d.ts +1 -0
  134. package/dist/server/app-route-handler-cache.js +1 -0
  135. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  136. package/dist/server/app-route-handler-dispatch.js +6 -3
  137. package/dist/server/app-route-handler-execution.d.ts +1 -0
  138. package/dist/server/app-route-handler-execution.js +1 -0
  139. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  140. package/dist/server/app-route-handler-runtime.js +45 -24
  141. package/dist/server/app-router-entry.js +27 -8
  142. package/dist/server/app-rsc-cache-busting.js +1 -1
  143. package/dist/server/app-rsc-errors.js +20 -16
  144. package/dist/server/app-rsc-handler.d.ts +11 -0
  145. package/dist/server/app-rsc-handler.js +291 -125
  146. package/dist/server/app-rsc-request-normalization.d.ts +3 -1
  147. package/dist/server/app-rsc-request-normalization.js +4 -2
  148. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  149. package/dist/server/app-rsc-response-stage.js +10 -6
  150. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  151. package/dist/server/app-rsc-route-matching.js +36 -19
  152. package/dist/server/app-segment-config.d.ts +2 -1
  153. package/dist/server/app-server-action-execution.d.ts +2 -1
  154. package/dist/server/app-server-action-execution.js +62 -23
  155. package/dist/server/app-ssr-entry.d.ts +3 -2
  156. package/dist/server/app-ssr-entry.js +8 -5
  157. package/dist/server/app-ssr-stream.d.ts +6 -1
  158. package/dist/server/app-ssr-stream.js +34 -15
  159. package/dist/server/app-worker-stages.d.ts +7 -2
  160. package/dist/server/app-worker-stages.js +4 -4
  161. package/dist/server/cacheability-request.js +11 -7
  162. package/dist/server/client-build-files.d.ts +16 -0
  163. package/dist/server/client-build-files.js +36 -0
  164. package/dist/server/client-reuse-manifest.js +1 -1
  165. package/dist/server/config-headers.js +2 -0
  166. package/dist/server/dev-server.js +50 -29
  167. package/dist/server/dev-stack-sourcemap.js +18 -23
  168. package/dist/server/document-initial-head.d.ts +0 -11
  169. package/dist/server/document-initial-head.js +1 -1
  170. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  171. package/dist/server/forwarded-middleware-context.js +22 -0
  172. package/dist/server/headers.d.ts +18 -1
  173. package/dist/server/headers.js +19 -2
  174. package/dist/server/http-conditional.d.ts +11 -0
  175. package/dist/server/http-conditional.js +10 -1
  176. package/dist/server/http-error-responses.d.ts +1 -1
  177. package/dist/server/image-optimization.d.ts +54 -0
  178. package/dist/server/image-optimization.js +118 -9
  179. package/dist/server/isr-cache.d.ts +10 -0
  180. package/dist/server/isr-cache.js +43 -8
  181. package/dist/server/metadata-route-response.js +9 -8
  182. package/dist/server/middleware-matcher-pattern.js +8 -4
  183. package/dist/server/middleware-matcher.d.ts +2 -0
  184. package/dist/server/middleware-matcher.js +23 -2
  185. package/dist/server/middleware-response-headers.js +2 -0
  186. package/dist/server/middleware-runtime.d.ts +13 -0
  187. package/dist/server/middleware-runtime.js +33 -20
  188. package/dist/server/middleware.d.ts +1 -1
  189. package/dist/server/middleware.js +3 -1
  190. package/dist/server/multi-stage.d.ts +19 -0
  191. package/dist/server/navigation-planner.js +1 -1
  192. package/dist/server/node-response-signal.d.ts +16 -0
  193. package/dist/server/node-response-signal.js +26 -0
  194. package/dist/server/normalize-path.d.ts +0 -13
  195. package/dist/server/normalize-path.js +1 -34
  196. package/dist/server/open-redirect.d.ts +47 -0
  197. package/dist/server/open-redirect.js +74 -1
  198. package/dist/server/pages-api-route.d.ts +3 -2
  199. package/dist/server/pages-api-route.js +4 -3
  200. package/dist/server/pages-cache-tag.d.ts +12 -0
  201. package/dist/server/pages-cache-tag.js +19 -0
  202. package/dist/server/pages-client-assets.d.ts +2 -0
  203. package/dist/server/pages-data-route.d.ts +10 -0
  204. package/dist/server/pages-data-route.js +19 -2
  205. package/dist/server/pages-document-asset-props.d.ts +5 -1
  206. package/dist/server/pages-document-asset-props.js +13 -5
  207. package/dist/server/pages-document-splice.d.ts +19 -0
  208. package/dist/server/pages-document-splice.js +55 -0
  209. package/dist/server/pages-i18n.d.ts +12 -1
  210. package/dist/server/pages-i18n.js +18 -4
  211. package/dist/server/pages-node-compat.d.ts +16 -5
  212. package/dist/server/pages-node-compat.js +20 -12
  213. package/dist/server/pages-page-data.d.ts +32 -24
  214. package/dist/server/pages-page-data.js +50 -120
  215. package/dist/server/pages-page-handler.d.ts +0 -6
  216. package/dist/server/pages-page-handler.js +209 -130
  217. package/dist/server/pages-page-response.d.ts +12 -6
  218. package/dist/server/pages-page-response.js +41 -34
  219. package/dist/server/pages-request-pipeline.d.ts +10 -2
  220. package/dist/server/pages-request-pipeline.js +37 -18
  221. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  222. package/dist/server/pages-request-stage-entry.js +79 -16
  223. package/dist/server/pages-response-stage-entry.js +4 -0
  224. package/dist/server/pages-revalidate.js +1 -1
  225. package/dist/server/pages-router-entry.js +4 -3
  226. package/dist/server/prerender-manifest.d.ts +3 -3
  227. package/dist/server/prerender-manifest.js +4 -3
  228. package/dist/server/prerender-work-unit-setup.js +4 -0
  229. package/dist/server/prod-server.d.ts +20 -7
  230. package/dist/server/prod-server.js +343 -129
  231. package/dist/server/proper-error.d.ts +4 -0
  232. package/dist/server/proper-error.js +31 -0
  233. package/dist/server/request-pipeline.d.ts +24 -9
  234. package/dist/server/request-pipeline.js +24 -9
  235. package/dist/server/response-compression.d.ts +43 -0
  236. package/dist/server/response-compression.js +111 -0
  237. package/dist/server/revalidation-request.d.ts +1 -0
  238. package/dist/server/revalidation-request.js +1 -1
  239. package/dist/server/rsc-stream-hints.js +31 -2
  240. package/dist/server/seed-cache.d.ts +1 -0
  241. package/dist/server/seed-cache.js +15 -11
  242. package/dist/server/server-reference-loader.d.ts +4 -0
  243. package/dist/server/server-reference-loader.js +29 -0
  244. package/dist/server/socket-error-backstop.d.ts +23 -1
  245. package/dist/server/socket-error-backstop.js +69 -17
  246. package/dist/server/static-file-signal.d.ts +15 -4
  247. package/dist/server/static-file-signal.js +46 -12
  248. package/dist/server/worker-image-optimization.d.ts +34 -0
  249. package/dist/server/worker-image-optimization.js +86 -0
  250. package/dist/server/worker-stages.d.ts +1 -1
  251. package/dist/server/worker-stages.js +2 -2
  252. package/dist/server/worker-utils.d.ts +8 -3
  253. package/dist/server/worker-utils.js +12 -7
  254. package/dist/shims/app-router-scroll.js +4 -1
  255. package/dist/shims/app-router-tree-context.d.ts +5 -0
  256. package/dist/shims/app-router-tree-context.js +27 -0
  257. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  258. package/dist/shims/cache-adapter-instantiate.js +118 -0
  259. package/dist/shims/cache-callable-runtime.d.ts +6 -42
  260. package/dist/shims/cache-callable-runtime.js +65 -174
  261. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  262. package/dist/shims/cache-flight-arguments.js +56 -0
  263. package/dist/shims/cache-handler.js +1 -9
  264. package/dist/shims/cache-request-state.d.ts +15 -0
  265. package/dist/shims/cache-request-state.js +31 -8
  266. package/dist/shims/cache-runtime.d.ts +12 -20
  267. package/dist/shims/cache-runtime.js +166 -225
  268. package/dist/shims/cache.d.ts +4 -4
  269. package/dist/shims/cache.js +44 -16
  270. package/dist/shims/cacheability-classification.d.ts +7 -0
  271. package/dist/shims/cdn-cache.d.ts +8 -0
  272. package/dist/shims/cdn-cache.js +17 -1
  273. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  274. package/dist/shims/disable-smooth-scroll.js +36 -0
  275. package/dist/shims/document-placeholders.d.ts +19 -0
  276. package/dist/shims/document-placeholders.js +45 -0
  277. package/dist/shims/document.js +21 -5
  278. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  279. package/dist/shims/dynamic-preload-chunks.js +13 -9
  280. package/dist/shims/dynamic.d.ts +1 -1
  281. package/dist/shims/dynamic.js +60 -8
  282. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  283. package/dist/shims/error-boundary-navigation.js +19 -1
  284. package/dist/shims/error-boundary.d.ts +10 -10
  285. package/dist/shims/error-boundary.js +26 -7
  286. package/dist/shims/fetch-cache-state.d.ts +66 -0
  287. package/dist/shims/fetch-cache-state.js +92 -0
  288. package/dist/shims/fetch-cache.d.ts +3 -61
  289. package/dist/shims/fetch-cache.js +161 -108
  290. package/dist/shims/form.js +1 -1
  291. package/dist/shims/head.d.ts +10 -6
  292. package/dist/shims/head.js +15 -13
  293. package/dist/shims/headers.d.ts +13 -0
  294. package/dist/shims/headers.js +47 -4
  295. package/dist/shims/image.js +2 -1
  296. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  297. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  298. package/dist/shims/internal/headers-state.d.ts +0 -1
  299. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  300. package/dist/shims/internal/work-store-scope.js +24 -0
  301. package/dist/shims/metadata.js +3 -3
  302. package/dist/shims/navigation-errors.d.ts +6 -0
  303. package/dist/shims/navigation-errors.js +11 -1
  304. package/dist/shims/navigation.d.ts +7 -0
  305. package/dist/shims/navigation.js +45 -9
  306. package/dist/shims/request-context.d.ts +11 -0
  307. package/dist/shims/request-state-types.d.ts +2 -1
  308. package/dist/shims/router.js +12 -20
  309. package/dist/shims/server.d.ts +16 -0
  310. package/dist/shims/server.js +24 -4
  311. package/dist/shims/thenable-params.d.ts +4 -0
  312. package/dist/shims/thenable-params.js +25 -3
  313. package/dist/shims/unified-request-context.d.ts +1 -1
  314. package/dist/shims/unified-request-context.js +1 -0
  315. package/dist/shims/url-utils.d.ts +2 -0
  316. package/dist/shims/url-utils.js +3 -1
  317. package/dist/utils/client-runtime-metadata.js +1 -1
  318. package/dist/utils/hash.d.ts +7 -0
  319. package/dist/utils/hash.js +11 -1
  320. package/dist/utils/mdx-scan.d.ts +5 -0
  321. package/dist/utils/mdx-scan.js +8 -1
  322. package/dist/utils/package-name.d.ts +6 -0
  323. package/dist/utils/package-name.js +12 -1
  324. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  325. package/dist/utils/plugin-rsc-version.js +15 -0
  326. package/dist/utils/prerender-output-paths.js +15 -4
  327. package/dist/utils/public-file-path.d.ts +10 -2
  328. package/dist/utils/public-file-path.js +13 -9
  329. package/dist/utils/public-routes.js +2 -2
  330. package/dist/utils/react-version.d.ts +3 -0
  331. package/dist/utils/react-version.js +1 -1
  332. package/dist/utils/regex-safety.d.ts +10 -0
  333. package/dist/utils/regex-safety.js +70 -18
  334. package/package.json +9 -5
@@ -1,5 +1,6 @@
1
1
  import { getAstName } from "./ast-utils.js";
2
2
  import { magicStringTransformResult } from "./transform-result.js";
3
+ import { findAstBindingScope, walkAstScopes } from "./ast-scope.js";
3
4
  import { parseAst } from "vite";
4
5
  import MagicString from "magic-string";
5
6
  //#region src/plugins/strip-server-exports.ts
@@ -12,6 +13,8 @@ const SERVER_EXPORTS = /* @__PURE__ */ new Set([
12
13
  "unstable_getStaticProps",
13
14
  "unstable_getStaticPaths"
14
15
  ]);
16
+ const UNUSED_LOOP_TARGET = "({ x: 0 }).x";
17
+ const CATCH_BOUND_NAME = "\0catch-bound";
15
18
  const SERVER_PROPS_SSG_CONFLICT = "You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps";
16
19
  const EXPORT_ALL_IN_PAGE_ERROR = "Using `export * from '...'` in a page is disallowed. Please use `export { default } from '...'` instead.\nRead more: https://nextjs.org/docs/messages/export-all-in-page";
17
20
  function hasServerExportCandidate(code) {
@@ -127,64 +130,96 @@ function renderExportDeclaration(code, statement, removed) {
127
130
  if (kept.length === 0) return "";
128
131
  return `export { ${kept.map((specifier) => code.slice(specifier.start, specifier.end)).join(", ")} }${statement.source ? ` from ${code.slice(statement.source.start, statement.end)}` : ";"}`;
129
132
  }
130
- function renderBindingPattern(code, pattern, removedNames) {
133
+ /**
134
+ * Render a binding or assignment pattern without the removed names. `slice`
135
+ * copies kept subexpressions (defaults, computed keys) so callers can apply
136
+ * edits nested inside them.
137
+ */
138
+ function renderBindingPattern(slice, pattern, removedNames) {
131
139
  if (pattern.type === "Identifier") return removedNames.has(pattern.name) ? null : pattern.name;
140
+ if (pattern.type === "MemberExpression") {
141
+ const root = assignmentTargetIdentifiers(pattern)[0];
142
+ return root && removedNames.has(root.name) ? null : slice(pattern.start, pattern.end);
143
+ }
132
144
  if (pattern.type === "RestElement") {
133
- const argument = renderBindingPattern(code, pattern.argument, removedNames);
145
+ const argument = renderBindingPattern(slice, pattern.argument, removedNames);
134
146
  return argument ? `...${argument}` : null;
135
147
  }
136
148
  if (pattern.type === "AssignmentPattern") {
137
- const left = renderBindingPattern(code, pattern.left, removedNames);
138
- return left ? `${left} = ${code.slice(pattern.right.start, pattern.right.end)}` : null;
149
+ const left = renderBindingPattern(slice, pattern.left, removedNames);
150
+ return left ? `${left} = ${slice(pattern.right.start, pattern.right.end)}` : null;
139
151
  }
140
152
  if (pattern.type === "ObjectPattern") {
141
153
  const properties = pattern.properties.flatMap((property) => {
142
154
  if (property.type === "RestElement") {
143
- const rendered = renderBindingPattern(code, property, removedNames);
155
+ const rendered = renderBindingPattern(slice, property, removedNames);
144
156
  return rendered ? [rendered] : [];
145
157
  }
146
- const value = renderBindingPattern(code, property.value, removedNames);
158
+ const value = renderBindingPattern(slice, property.value, removedNames);
147
159
  if (!value) return [];
148
160
  if (property.shorthand && property.value.type === "Identifier") return [value];
149
- const key = code.slice(property.key.start, property.key.end);
161
+ const key = slice(property.key.start, property.key.end);
150
162
  return [`${property.computed ? `[${key}]` : key}: ${value}`];
151
163
  });
152
164
  return properties.length > 0 ? `{ ${properties.join(", ")} }` : null;
153
165
  }
154
166
  if (pattern.type === "ArrayPattern") {
155
- const elements = pattern.elements.map((element) => element ? renderBindingPattern(code, element, removedNames) : null);
167
+ const elements = pattern.elements.map((element) => element ? renderBindingPattern(slice, element, removedNames) : null);
156
168
  while (elements.length > 0 && elements.at(-1) === null) elements.pop();
157
169
  return elements.length > 0 ? `[${elements.map((element) => element ?? "").join(", ")}]` : null;
158
170
  }
159
- return code.slice(pattern.start, pattern.end);
171
+ return slice(pattern.start, pattern.end);
160
172
  }
161
- function assignmentRootName(node) {
162
- if (node.type === "Identifier") return node.name;
163
- if (node.type === "MemberExpression") return assignmentRootName(node.object);
173
+ /** Edits pointing a loop head's removed targets at `UNUSED_LOOP_TARGET`. */
174
+ function throwawayTargetEdits(pattern, removedNames) {
175
+ if (pattern.type === "Identifier" || pattern.type === "MemberExpression") {
176
+ const root = assignmentTargetIdentifiers(pattern)[0];
177
+ return root && removedNames.has(root.name) ? [{
178
+ start: pattern.start,
179
+ end: pattern.end,
180
+ replacement: UNUSED_LOOP_TARGET
181
+ }] : [];
182
+ }
183
+ if (pattern.type === "RestElement") return throwawayTargetEdits(pattern.argument, removedNames);
184
+ if (pattern.type === "AssignmentPattern") return throwawayTargetEdits(pattern.left, removedNames);
185
+ if (pattern.type === "ArrayPattern") return pattern.elements.flatMap((element) => element ? throwawayTargetEdits(element, removedNames) : []);
186
+ if (pattern.type === "ObjectPattern") return pattern.properties.flatMap((property) => {
187
+ if (property.type === "RestElement") return throwawayTargetEdits(property, removedNames);
188
+ const edits = throwawayTargetEdits(property.value, removedNames);
189
+ if (!property.shorthand) return edits;
190
+ return edits.map((edit) => ({
191
+ ...edit,
192
+ replacement: `${property.key.name}: ${UNUSED_LOOP_TARGET}`
193
+ }));
194
+ });
195
+ return [];
164
196
  }
165
- function assignmentBindingNames(node) {
166
- if (node.type === "ArrayPattern" || node.type === "ObjectPattern") return bindingNames(node);
167
- const rootName = assignmentRootName(node);
168
- return rootName ? [rootName] : [];
197
+ /** Pattern parts `renderBindingPattern` drops, including their defaults and keys. */
198
+ function prunedPatternParts(pattern, removedNames) {
199
+ const isPruned = (part) => renderBindingPattern((start, end) => "".padEnd(end - start), part, removedNames) === null;
200
+ if (isPruned(pattern)) return [pattern];
201
+ if (pattern.type === "AssignmentPattern") return prunedPatternParts(pattern.left, removedNames);
202
+ if (pattern.type === "RestElement") return prunedPatternParts(pattern.argument, removedNames);
203
+ if (pattern.type === "ArrayPattern") return pattern.elements.flatMap((element) => element ? prunedPatternParts(element, removedNames) : []);
204
+ if (pattern.type === "ObjectPattern") return pattern.properties.flatMap((property) => {
205
+ if (property.type === "RestElement") return prunedPatternParts(property, removedNames);
206
+ return isPruned(property.value) ? [property] : prunedPatternParts(property.value, removedNames);
207
+ });
208
+ return [];
169
209
  }
170
- function isAssignmentTargetIdentifier(node, left) {
171
- if (left.type === "Identifier") return node.start === left.start;
172
- if (left.type === "ArrayPattern" || left.type === "ObjectPattern") return bindingIdentifiers(left).some((identifier) => identifier.start === node.start);
173
- if (left.type === "MemberExpression") {
174
- let object = left.object;
175
- while (object.type === "MemberExpression") object = object.object;
176
- return object.type === "Identifier" && object.start === node.start;
177
- }
178
- return false;
210
+ /** Identifiers an assignment target writes: pattern bindings and member roots. */
211
+ function assignmentTargetIdentifiers(node) {
212
+ if (!node) return [];
213
+ if (node.type === "Identifier") return [node];
214
+ if (node.type === "MemberExpression") return assignmentTargetIdentifiers(node.object);
215
+ if (node.type === "RestElement") return assignmentTargetIdentifiers(node.argument);
216
+ if (node.type === "AssignmentPattern") return assignmentTargetIdentifiers(node.left);
217
+ if (node.type === "ArrayPattern") return node.elements.flatMap((element) => assignmentTargetIdentifiers(element));
218
+ if (node.type === "ObjectPattern") return node.properties.flatMap((property) => assignmentTargetIdentifiers(property.type === "RestElement" ? property.argument : property.value));
219
+ return [];
179
220
  }
180
- function findLexicalScope(ancestors) {
181
- return [...ancestors].reverse().find((ancestor) => [
182
- "BlockStatement",
183
- "SwitchStatement",
184
- "ForStatement",
185
- "ForInStatement",
186
- "ForOfStatement"
187
- ].includes(ancestor.type));
221
+ function isAssignmentTargetIdentifier(node, left) {
222
+ return assignmentTargetIdentifiers(left).some((identifier) => identifier.start === node.start);
188
223
  }
189
224
  function validatePageExports(code) {
190
225
  if (!hasExportAllCandidate(code)) return;
@@ -227,14 +262,41 @@ function stripServerExports(code) {
227
262
  const forcedBindings = /* @__PURE__ */ new Set();
228
263
  const candidateBindings = /* @__PURE__ */ new Set();
229
264
  const bindings = /* @__PURE__ */ new Map();
265
+ const redeclarations = [];
266
+ const loopHeadDeclarations = /* @__PURE__ */ new Set();
267
+ const catchBoundNames = /* @__PURE__ */ new Map();
268
+ const iterationHeadDeclarators = /* @__PURE__ */ new Set();
269
+ const removedNamesFor = (declarator) => {
270
+ const catchBound = catchBoundNames.get(declarator);
271
+ const iterationHead = iterationHeadDeclarators.has(declarator);
272
+ if (!catchBound && !iterationHead) return deadBindings;
273
+ return new Set([...deadBindings].filter((name) => !catchBound?.has(name) && (!iterationHead || forcedBindings.has(name) || candidateBindings.has(name))));
274
+ };
275
+ const iterationHeadDeclarations = /* @__PURE__ */ new Set();
276
+ const declarationsOf = (name) => {
277
+ const binding = bindings.get(name);
278
+ return [...binding ? [binding] : [], ...redeclarations.filter((redeclaration) => redeclaration.name === name)];
279
+ };
280
+ const renderEdit = (edit) => typeof edit.replacement === "function" ? edit.replacement() : edit.replacement;
281
+ const renderRange = (start, end) => {
282
+ const nested = [...new Map(edits.filter((edit) => edit.start >= start && edit.end <= end).map((edit) => [`${edit.start}:${edit.end}`, edit])).values()].sort((left, right) => left.start - right.start || right.end - left.end);
283
+ let rendered = "";
284
+ let cursor = start;
285
+ for (const edit of nested) {
286
+ if (edit.start < cursor) continue;
287
+ rendered += code.slice(cursor, edit.start) + renderEdit(edit);
288
+ cursor = edit.end;
289
+ }
290
+ return rendered + code.slice(cursor, end);
291
+ };
230
292
  const bindingPositions = /* @__PURE__ */ new Set();
231
293
  const references = /* @__PURE__ */ new Map();
232
- const shadowRanges = /* @__PURE__ */ new Map();
294
+ const memberTargetReads = /* @__PURE__ */ new Map();
233
295
  const exportSpecifierRemovals = /* @__PURE__ */ new Map();
234
296
  const variableRemovals = /* @__PURE__ */ new Map();
235
297
  const importRemovals = /* @__PURE__ */ new Map();
236
- const assignmentStatements = [];
237
- const removedAssignments = /* @__PURE__ */ new Set();
298
+ const assignments = [];
299
+ const rewrittenAssignments = /* @__PURE__ */ new Map();
238
300
  for (const statement of statements) {
239
301
  const declaration = statement.type === "ExportNamedDeclaration" ? statement.declaration : statement;
240
302
  if (declaration?.type === "FunctionDeclaration" && declaration.id) {
@@ -282,48 +344,89 @@ function stripServerExports(code) {
282
344
  declaredNames: [name]
283
345
  });
284
346
  }
285
- else if (statement.type === "ExpressionStatement") {
286
- const expression = statement.expression;
287
- if (expression.type === "AssignmentExpression") {
288
- const left = expression.left;
289
- const names = assignmentBindingNames(left);
290
- if (names.length > 0) assignmentStatements.push({
291
- statement,
292
- left,
293
- bindingNames: names
294
- });
295
- }
296
- }
297
347
  }
298
- const addShadowRange = (name, range) => {
299
- if (!range || range.type === "Program") return;
300
- const ranges = shadowRanges.get(name) ?? [];
301
- ranges.push(range);
302
- shadowRanges.set(name, ranges);
303
- };
348
+ const localIdentifiers = /* @__PURE__ */ new Set();
349
+ walkAstScopes(ast, (node, scope) => {
350
+ if (node.type !== "Identifier") return;
351
+ if (findAstBindingScope(scope, node.name)?.parent) localIdentifiers.add(node.start);
352
+ });
353
+ const isLocal = (identifier) => localIdentifiers.has(identifier.start);
304
354
  walkAstWithAncestors(ast.body, (node, parent, ancestors = []) => {
305
- if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
306
- for (const parameter of node.params) for (const name of bindingNames(parameter)) addShadowRange(name, node);
307
- if (node.type === "FunctionDeclaration" && node.id) addShadowRange(node.id.name, findLexicalScope(ancestors));
308
- else if (node.type === "FunctionExpression" && node.id) addShadowRange(node.id.name, node);
309
- } else if (node.type === "ClassDeclaration" && node.id) addShadowRange(node.id.name, findLexicalScope(ancestors));
310
- else if (node.type === "ClassExpression" && node.id) addShadowRange(node.id.name, node);
311
- else if (node.type === "CatchClause" && node.param) for (const name of bindingNames(node.param)) addShadowRange(name, node.body);
312
- else if (node.type === "VariableDeclarator" && parent?.type === "VariableDeclaration") {
313
- const scope = parent.kind === "var" ? [...ancestors].reverse().find((ancestor) => [
355
+ if (node.type === "VariableDeclarator" && parent?.type === "VariableDeclaration") {
356
+ const varScope = parent.kind === "var" ? [...ancestors].reverse().find((ancestor) => [
314
357
  "FunctionDeclaration",
315
358
  "FunctionExpression",
316
- "ArrowFunctionExpression"
317
- ].includes(ancestor.type)) : findLexicalScope(ancestors);
318
- for (const name of bindingNames(node.id)) addShadowRange(name, scope);
359
+ "ArrowFunctionExpression",
360
+ "StaticBlock"
361
+ ].includes(ancestor.type)) : void 0;
362
+ const owner = ancestors.at(-2);
363
+ if (parent.kind === "var" && !varScope && owner && owner.type !== "ExportNamedDeclaration") {
364
+ if (owner.init === parent || owner.left === parent) loopHeadDeclarations.add(parent);
365
+ if (owner.left === parent) {
366
+ iterationHeadDeclarations.add(parent);
367
+ iterationHeadDeclarators.add(node);
368
+ }
369
+ const identifiers = bindingIdentifiers(node.id);
370
+ for (const identifier of identifiers) bindingPositions.add(identifier.start);
371
+ const catchBound = new Set(identifiers.filter((identifier) => isLocal(identifier)).map((identifier) => identifier.name));
372
+ if (catchBound.size > 0) catchBoundNames.set(node, catchBound);
373
+ const declaredNames = identifiers.map((identifier) => catchBound.has(identifier.name) ? CATCH_BOUND_NAME : identifier.name);
374
+ for (const identifier of identifiers) {
375
+ const name = identifier.name;
376
+ if (catchBound.has(name)) continue;
377
+ const binding = {
378
+ name,
379
+ node,
380
+ parent,
381
+ kind: "variable",
382
+ implementation: iterationHeadDeclarators.has(node) ? identifier : node.init ?? node,
383
+ declaredNames
384
+ };
385
+ if (bindings.has(name)) redeclarations.push(binding);
386
+ else bindings.set(name, binding);
387
+ }
388
+ }
319
389
  }
320
390
  });
321
391
  walkAstWithAncestors(ast.body, (node, parent, ancestors = []) => {
392
+ if (node.type === "AssignmentExpression") {
393
+ const names = assignmentTargetIdentifiers(node.left).filter((identifier) => !isLocal(identifier)).map((identifier) => identifier.name);
394
+ if (names.length > 0) {
395
+ const statement = parent?.type === "ExpressionStatement" && parent.expression === node ? parent : void 0;
396
+ assignments.push({
397
+ expression: node,
398
+ statement,
399
+ topLevel: statement !== void 0 && ancestors.length === 1,
400
+ bindingNames: names
401
+ });
402
+ }
403
+ return;
404
+ }
405
+ if (node.type === "ForInStatement" || node.type === "ForOfStatement") {
406
+ const left = node.left;
407
+ const names = (left.type === "VariableDeclaration" ? bindingIdentifiers(left.declarations[0]?.id) : assignmentTargetIdentifiers(left)).filter((identifier) => !isLocal(identifier)).map((identifier) => identifier.name);
408
+ if (names.length > 0) assignments.push({
409
+ expression: node,
410
+ statement: node,
411
+ topLevel: ancestors.length === 0,
412
+ bindingNames: names,
413
+ loop: true
414
+ });
415
+ return;
416
+ }
322
417
  if (!isReferenceIdentifier(node, parent)) return;
323
418
  if (bindingPositions.has(node.start)) return;
324
- if (isInsideRanges(node.start, shadowRanges.get(node.name) ?? [])) return;
325
- const assignment = [...ancestors].reverse().find((ancestor) => ancestor.type === "AssignmentExpression");
326
- if (assignment && isAssignmentTargetIdentifier(node, assignment.left)) return;
419
+ if (isLocal(node)) return;
420
+ const writer = [...ancestors].reverse().find((ancestor) => ancestor.type === "AssignmentExpression" || (ancestor.type === "ForInStatement" || ancestor.type === "ForOfStatement") && node.start >= ancestor.left.start && node.end <= ancestor.left.end);
421
+ if (writer && isAssignmentTargetIdentifier(node, writer.left)) {
422
+ const left = writer.left;
423
+ if (node !== left && !bindingIdentifiers(left).some((target) => target.start === node.start) && !(writer.type === "AssignmentExpression" && left.type === "MemberExpression")) {
424
+ const positions = memberTargetReads.get(node.name) ?? [];
425
+ positions.push(node.start);
426
+ memberTargetReads.set(node.name, positions);
427
+ }
428
+ return;
429
+ }
327
430
  const positions = references.get(node.name) ?? [];
328
431
  positions.push(node.start);
329
432
  references.set(node.name, positions);
@@ -388,26 +491,76 @@ function stripServerExports(code) {
388
491
  let changed = true;
389
492
  while (changed) {
390
493
  changed = false;
391
- for (const { statement, left, bindingNames: names } of assignmentStatements) {
494
+ for (const { expression, statement, topLevel, bindingNames: names, loop } of assignments) {
392
495
  const removableNames = new Set(names.filter((name) => forcedBindings.has(name) || deadBindings.has(name)));
393
496
  if (removableNames.size === 0) continue;
394
- if (removedAssignments.has(statement)) continue;
395
- const expression = statement.expression;
396
- const renderedLeft = left.type === "ArrayPattern" || left.type === "ObjectPattern" ? renderBindingPattern(code, left, removableNames) : null;
397
- removedAssignments.add(statement);
497
+ if ((rewrittenAssignments.get(expression) ?? 0) >= removableNames.size) continue;
498
+ rewrittenAssignments.set(expression, removableNames.size);
499
+ if (loop) {
500
+ const head = expression.left;
501
+ const pattern = head.type === "VariableDeclaration" ? head.declarations[0].id : head;
502
+ if (![...removableNames].some((name) => forcedBindings.has(name) || candidateBindings.has(name))) {
503
+ if (head.type !== "VariableDeclaration") edits.push(...throwawayTargetEdits(head, removableNames));
504
+ continue;
505
+ }
506
+ const prunedNames = head.type === "VariableDeclaration" ? new Set([...removableNames].filter((name) => forcedBindings.has(name) || candidateBindings.has(name))) : removableNames;
507
+ if (renderBindingPattern((start, end) => code.slice(start, end), pattern, prunedNames)) {
508
+ for (const part of prunedPatternParts(pattern, prunedNames)) if (addDeadRange(part)) changed = true;
509
+ if (head.type !== "VariableDeclaration") edits.push({
510
+ start: head.start,
511
+ end: head.end,
512
+ replacement: () => renderBindingPattern(renderRange, head, removableNames)
513
+ });
514
+ continue;
515
+ }
516
+ edits.push({
517
+ start: expression.start,
518
+ end: expression.end,
519
+ replacement: topLevel ? "" : ";"
520
+ });
521
+ if (addDeadRange(expression)) changed = true;
522
+ continue;
523
+ }
524
+ const left = expression.left;
525
+ const renderedLeft = left.type === "ArrayPattern" || left.type === "ObjectPattern" ? renderBindingPattern((start, end) => code.slice(start, end), left, removableNames) : null;
526
+ const right = expression.right;
527
+ const renderRight = () => renderRange(right.start, right.end);
528
+ const target = statement ?? expression;
529
+ if (renderedLeft) {
530
+ for (const part of prunedPatternParts(left, removableNames)) if (addDeadRange(part)) changed = true;
531
+ edits.push({
532
+ start: target.start,
533
+ end: target.end,
534
+ replacement: () => {
535
+ const assignment = `${renderBindingPattern(renderRange, left, removableNames)} ${expression.operator} ${renderRight()}`;
536
+ if (!statement) return `(${assignment})`;
537
+ return left.type === "ObjectPattern" ? `(${assignment});` : `${assignment};`;
538
+ }
539
+ });
540
+ continue;
541
+ }
542
+ if (!statement && ![...removableNames].some((name) => forcedBindings.has(name) || candidateBindings.has(name))) {
543
+ edits.push({
544
+ start: target.start,
545
+ end: target.end,
546
+ replacement: () => `(${renderRight()})`
547
+ });
548
+ continue;
549
+ }
398
550
  edits.push({
399
- start: statement.start,
400
- end: statement.end,
401
- replacement: renderedLeft ? `${left.type === "ObjectPattern" ? `(${renderedLeft} ${expression.operator} ${code.slice(expression.right.start, expression.right.end)})` : `${renderedLeft} ${expression.operator} ${code.slice(expression.right.start, expression.right.end)}`};` : ""
551
+ start: target.start,
552
+ end: target.end,
553
+ replacement: statement ? topLevel ? "" : ";" : "void 0"
402
554
  });
403
- if (!renderedLeft && addDeadRange(statement)) changed = true;
555
+ if (addDeadRange(target)) changed = true;
404
556
  }
405
557
  const removableBindings = /* @__PURE__ */ new Set();
406
558
  for (const [name] of bindings) if (forcedBindings.has(name) || candidateBindings.has(name) || (references.get(name) ?? []).some((position) => isInsideRanges(position, deadRanges))) removableBindings.add(name);
559
+ const removableImplementations = (names, { shared }) => [...names].flatMap((name) => declarationsOf(name).filter((binding) => shared || binding.declaredNames.every((declared) => names.has(declared))).map((binding) => binding.implementation));
407
560
  let closureChanged = true;
408
561
  while (closureChanged) {
409
562
  closureChanged = false;
410
- const implementations = [...removableBindings].map((name) => bindings.get(name)?.implementation).filter((implementation) => Boolean(implementation));
563
+ const implementations = removableImplementations(removableBindings, { shared: true });
411
564
  for (const [name] of bindings) {
412
565
  if (removableBindings.has(name)) continue;
413
566
  if ((references.get(name) ?? []).some((position) => isInsideRanges(position, implementations))) {
@@ -419,10 +572,11 @@ function stripServerExports(code) {
419
572
  let pruneChanged = true;
420
573
  while (pruneChanged) {
421
574
  pruneChanged = false;
422
- const implementations = [...removableBindings].map((name) => bindings.get(name)?.implementation).filter((implementation) => Boolean(implementation));
575
+ const implementations = removableImplementations(removableBindings, { shared: false });
423
576
  for (const name of removableBindings) {
424
577
  if (forcedBindings.has(name)) continue;
425
- if ((references.get(name) ?? []).some((position) => !isInsideRanges(position, deadRanges) && !isInsideRanges(position, implementations))) {
578
+ const isLive = (position) => !isInsideRanges(position, deadRanges) && !isInsideRanges(position, implementations);
579
+ if ((references.get(name) ?? []).some(isLive) || !candidateBindings.has(name) && (memberTargetReads.get(name) ?? []).some(isLive)) {
426
580
  removableBindings.delete(name);
427
581
  pruneChanged = true;
428
582
  }
@@ -436,15 +590,18 @@ function stripServerExports(code) {
436
590
  changed = true;
437
591
  if (binding.kind === "function" || binding.kind === "class") addDeadRange(binding.implementation);
438
592
  }
439
- for (const binding of new Set(bindings.values())) {
593
+ for (const binding of /* @__PURE__ */ new Set([...bindings.values(), ...redeclarations])) {
440
594
  if (binding.kind !== "variable") continue;
441
- if (!binding.declaredNames.every((name) => deadBindings.has(name))) continue;
595
+ const removedNames = removedNamesFor(binding.node);
596
+ if (!binding.declaredNames.every((name) => removedNames.has(name))) {
597
+ for (const part of prunedPatternParts(binding.node.id, removedNames)) if (addDeadRange(part)) changed = true;
598
+ continue;
599
+ }
442
600
  if (addDeadRange(binding.implementation)) changed = true;
443
601
  }
444
602
  }
445
- for (const name of deadBindings) {
446
- const binding = bindings.get(name);
447
- if (!binding) continue;
603
+ for (const binding of [...deadBindings].flatMap(declarationsOf)) {
604
+ const name = binding.name;
448
605
  if (forcedBindings.has(name)) {
449
606
  if ((binding.kind === "function" || binding.kind === "class") && binding.parent.type !== "ExportNamedDeclaration") edits.push({
450
607
  start: binding.node.start,
@@ -482,17 +639,24 @@ function stripServerExports(code) {
482
639
  replacement: renderExportDeclaration(code, statement, removed)
483
640
  });
484
641
  for (const [declaration, removed] of variableRemovals) {
485
- const rendered = declaration.declarations.flatMap((declarator) => {
486
- if (!removed.has(declarator)) return [code.slice(declarator.start, declarator.end)];
487
- const pattern = renderBindingPattern(code, declarator.id, deadBindings);
488
- if (!pattern) return [];
489
- return [`${pattern}${declarator.init ? ` = ${code.slice(declarator.init.start, declarator.init.end)}` : ""}`];
490
- });
491
642
  const exportStatement = statements.find((statement) => statement.type === "ExportNamedDeclaration" && statement.declaration === declaration);
492
643
  edits.push({
493
644
  start: exportStatement?.start ?? declaration.start,
494
645
  end: declaration.end,
495
- replacement: rendered.length > 0 ? `${exportStatement ? "export " : ""}${declaration.kind} ${rendered.join(", ")};` : ""
646
+ replacement: () => {
647
+ const rendered = declaration.declarations.flatMap((declarator) => {
648
+ if (!removed.has(declarator)) return [renderRange(declarator.start, declarator.end)];
649
+ const pattern = renderBindingPattern(renderRange, declarator.id, removedNamesFor(declarator));
650
+ if (!pattern) return [];
651
+ return [`${pattern}${declarator.init ? ` = ${renderRange(declarator.init.start, declarator.init.end)}` : ""}`];
652
+ });
653
+ if (rendered.length > 0) {
654
+ const terminator = loopHeadDeclarations.has(declaration) ? "" : ";";
655
+ return `${exportStatement ? "export " : ""}${declaration.kind} ${rendered.join(", ")}${terminator}`;
656
+ }
657
+ if (iterationHeadDeclarations.has(declaration)) return UNUSED_LOOP_TARGET;
658
+ return exportStatement || statements.includes(declaration) || loopHeadDeclarations.has(declaration) ? "" : ";";
659
+ }
496
660
  });
497
661
  }
498
662
  for (const [statement, removed] of importRemovals) edits.push({
@@ -502,12 +666,12 @@ function stripServerExports(code) {
502
666
  });
503
667
  if (edits.length === 0) return null;
504
668
  const string = new MagicString(code);
505
- const uniqueEdits = [...new Map(edits.map((edit) => [`${edit.start}:${edit.end}`, edit])).values()].sort((left, right) => right.start - left.start || right.end - left.end);
506
- let lastStart = Number.POSITIVE_INFINITY;
669
+ const uniqueEdits = [...new Map(edits.map((edit) => [`${edit.start}:${edit.end}`, edit])).values()].sort((left, right) => left.start - right.start || right.end - left.end);
670
+ let lastEnd = Number.NEGATIVE_INFINITY;
507
671
  for (const edit of uniqueEdits) {
508
- if (edit.end > lastStart) continue;
509
- string.overwrite(edit.start, edit.end, edit.replacement);
510
- lastStart = edit.start;
672
+ if (edit.start < lastEnd) continue;
673
+ string.overwrite(edit.start, edit.end, renderEdit(edit));
674
+ lastEnd = edit.end;
511
675
  }
512
676
  return magicStringTransformResult(string);
513
677
  }
@@ -1,8 +1,12 @@
1
1
  import MagicString from "magic-string";
2
2
  //#region src/plugins/transform-result.d.ts
3
- export type MagicStringTransformResult = {
3
+ export type MagicStringTransformResult<TMap = ReturnType<MagicString["generateMap"]>> = {
4
4
  code: string;
5
- map: ReturnType<MagicString["generateMap"]>;
5
+ map: TMap;
6
+ };
7
+ type MagicStringOutput<TMap> = {
8
+ toString(): string;
9
+ generateMap(options: Parameters<MagicString["generateMap"]>[0]): TMap;
6
10
  };
7
11
  type SourcemapEnvironment = {
8
12
  mode?: string;
@@ -13,15 +17,15 @@ type SourcemapEnvironment = {
13
17
  };
14
18
  };
15
19
  /** Build the standard code + sourcemap result returned by source transforms. */
16
- export declare function magicStringTransformResult(output: MagicString, options?: Parameters<MagicString["generateMap"]>[0]): MagicStringTransformResult;
20
+ export declare function magicStringTransformResult<TMap = ReturnType<MagicString["generateMap"]>>(output: MagicStringOutput<TMap>, options?: Parameters<MagicString["generateMap"]>[0]): MagicStringTransformResult<TMap>;
17
21
  /**
18
22
  * Drop the sourcemap from a transform result when the build environment
19
23
  * discards it, mirroring Vite's own transforms
20
24
  * (`config.build.sourcemap ? s.generateMap(...) : null`). Dev and builds with
21
25
  * sourcemaps enabled keep the result unchanged.
22
26
  */
23
- export declare function omitUnusedBuildSourcemap(environment: SourcemapEnvironment | undefined, result: MagicStringTransformResult | null): {
27
+ export declare function omitUnusedBuildSourcemap<TMap = ReturnType<MagicString["generateMap"]>>(environment: SourcemapEnvironment | undefined, result: MagicStringTransformResult<TMap> | null): {
24
28
  code: string;
25
- map: MagicStringTransformResult["map"] | null;
29
+ map: TMap | null;
26
30
  } | null;
27
31
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { canonicalizeFilePath, stripViteModuleQuery } from "../utils/path.js";
3
- import { BARE_PACKAGE_SPECIFIER_RE, packageNameFromSpecifier } from "../utils/package-name.js";
4
3
  import { isServerEnvironment } from "./environment.js";
4
+ import { BARE_PACKAGE_SPECIFIER_RE, packageNameFromSpecifier } from "../utils/package-name.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { createIdResolver } from "vite";
7
7
  //#region src/plugins/transitive-externals.ts
@@ -23,6 +23,6 @@ export declare function getTypeofWindowReplacement(environment: EnvironmentLike)
23
23
  * parser's module record in {@link moduleRecordHasScannedFoldTargets} is exact.
24
24
  */
25
25
  export declare function mayFoldChangeScannedImports(code: string): boolean;
26
- export declare function replaceTypeofWindow(code: string, replacement: WindowType, id?: string): MagicStringTransformResult | null;
27
- export declare function replaceConsumerEnvironmentConditions(code: string, replacements: ConsumerEnvironmentReplacements, id?: string): MagicStringTransformResult | null;
26
+ export declare function replaceTypeofWindow(code: string, replacement: WindowType, id?: string): MagicStringTransformResult<import("magic-string").SourceMap> | null;
27
+ export declare function replaceConsumerEnvironmentConditions(code: string, replacements: ConsumerEnvironmentReplacements, id?: string): MagicStringTransformResult<import("magic-string").SourceMap> | null;
28
28
  //#endregion
@@ -72,9 +72,11 @@ function getFunctionDirectiveExportNames(transforms, ast, directive) {
72
72
  }
73
73
  function getCacheWrapperOptions(meta) {
74
74
  const argumentCount = getArgumentCount(meta);
75
+ const captureCount = "bindVars" in meta ? meta.bindVars.length : 0;
75
76
  return {
76
77
  acceptsSecondArgument: acceptsSecondArgument(meta),
77
- ...argumentCount === void 0 ? {} : { argumentCount }
78
+ ...argumentCount === void 0 ? {} : { argumentCount },
79
+ ...captureCount === 0 ? {} : { captureCount }
78
80
  };
79
81
  }
80
82
  async function createUseCacheCallablePlugin(options) {
@@ -190,7 +192,11 @@ async function createUseCacheCallablePlugin(options) {
190
192
  hoistRuntime: true,
191
193
  noExport: true,
192
194
  runtime: (value, name, meta) => runtime(value, name, matchUseCacheDirective(meta.directiveMatch[0]), meta),
193
- encode: (value) => `$$cacheRuntime.encryptCacheCaptures(${value})`,
195
+ encode: (value, name) => {
196
+ if (name === void 0) throw new Error("vinext: inline \"use cache\" functions require @vitejs/plugin-rsc 0.5.37 or newer.");
197
+ const referenceId = `${reference.referenceKey}#${secureExportName(name)}`;
198
+ return `$$cacheRuntime.encryptCacheCaptures(${JSON.stringify(referenceId)}, ${value})`;
199
+ },
194
200
  decode: (value) => value
195
201
  });
196
202
  if (!result.output.hasChanged()) {
@@ -0,0 +1,20 @@
1
+ import { Plugin } from "vite";
2
+ //#region src/plugins/worker-server-only-imports.d.ts
3
+ export declare const SERVER_ONLY_SPECIFIER_RE: RegExp;
4
+ /**
5
+ * Reject `server-only` imports inside browser Web Worker bundles.
6
+ *
7
+ * Vite bundles every worker in a fresh plugin container built from
8
+ * `worker.plugins`, so neither `vinext:validate-server-only-client-imports`
9
+ * nor @vitejs/plugin-rsc's `rsc:validate-imports` sees worker modules in
10
+ * production builds. Next.js compiles workers as part of the browser graph
11
+ * and fails the build for these imports with both webpack and Turbopack.
12
+ *
13
+ * Like `rsc:validate-imports`, this guards resolution rather than scanning
14
+ * source, so every specifier form (static, dynamic, re-export, require) is
15
+ * caught before vinext's no-op `server-only` alias applies. `"use server"`
16
+ * modules need no exemption: `vinext:worker-use-server` replaces them with
17
+ * Server Function references, so their imports are never resolved.
18
+ */
19
+ export declare function createWorkerServerOnlyImportsPlugin(): Plugin;
20
+ //#endregion
@@ -0,0 +1,31 @@
1
+ //#region src/plugins/worker-server-only-imports.ts
2
+ const SERVER_ONLY_SPECIFIER_RE = /^server-only$/;
3
+ /**
4
+ * Reject `server-only` imports inside browser Web Worker bundles.
5
+ *
6
+ * Vite bundles every worker in a fresh plugin container built from
7
+ * `worker.plugins`, so neither `vinext:validate-server-only-client-imports`
8
+ * nor @vitejs/plugin-rsc's `rsc:validate-imports` sees worker modules in
9
+ * production builds. Next.js compiles workers as part of the browser graph
10
+ * and fails the build for these imports with both webpack and Turbopack.
11
+ *
12
+ * Like `rsc:validate-imports`, this guards resolution rather than scanning
13
+ * source, so every specifier form (static, dynamic, re-export, require) is
14
+ * caught before vinext's no-op `server-only` alias applies. `"use server"`
15
+ * modules need no exemption: `vinext:worker-use-server` replaces them with
16
+ * Server Function references, so their imports are never resolved.
17
+ */
18
+ function createWorkerServerOnlyImportsPlugin() {
19
+ return {
20
+ name: "vinext:worker-validate-server-only-imports",
21
+ resolveId: {
22
+ order: "pre",
23
+ filter: { id: SERVER_ONLY_SPECIFIER_RE },
24
+ handler(_source, importer) {
25
+ throw new Error(`You're importing a module that depends on "server-only". This API is only available in Server Components in the App Router, but ${importer ?? "this module"} is reachable from a browser Web Worker bundle.`);
26
+ }
27
+ }
28
+ };
29
+ }
30
+ //#endregion
31
+ export { SERVER_ONLY_SPECIFIER_RE, createWorkerServerOnlyImportsPlugin };