@wular/pnext 0.0.4 → 0.0.7

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 (395) hide show
  1. package/README.md +22 -16
  2. package/bin/pnext +6 -1
  3. package/config/lint/base.js +7 -7
  4. package/config/ts/base.json +2 -4
  5. package/config/ts/react.json +2 -6
  6. package/package.json +23 -2
  7. package/reference/compat.md +87 -22
  8. package/reference/config.md +40 -93
  9. package/reference/css.md +42 -33
  10. package/reference/dev.md +26 -33
  11. package/reference/env.md +18 -20
  12. package/reference/getting-started.md +132 -0
  13. package/reference/metadata.md +31 -46
  14. package/reference/navigation.md +65 -105
  15. package/reference/performance.md +21 -142
  16. package/reference/rendering.md +78 -75
  17. package/reference/routing.md +97 -107
  18. package/reference/typegen.md +27 -29
  19. package/src/api/cache.ts +36 -37
  20. package/src/api/client-cache.ts +2 -2
  21. package/src/api/client-navigation.ts +121 -114
  22. package/src/api/dynamic.tsx +58 -55
  23. package/src/api/link.tsx +52 -53
  24. package/src/api/navigation.ts +59 -58
  25. package/src/api/server.ts +152 -144
  26. package/src/api/suspense.ts +4 -4
  27. package/src/cli/adapters/vercel-warm.ts +126 -121
  28. package/src/cli/adapters/vercel.ts +437 -443
  29. package/src/cli/analyze.ts +333 -144
  30. package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
  31. package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
  32. package/src/cli/build.ts +976 -978
  33. package/src/cli/create.ts +72 -64
  34. package/src/cli/dev.ts +116 -116
  35. package/src/cli/index.ts +94 -85
  36. package/src/cli/migrate/package-json.ts +73 -71
  37. package/src/cli/migrate/report.ts +32 -33
  38. package/src/cli/migrate/{index.ts → run.ts} +48 -49
  39. package/src/cli/migrate/scan.ts +46 -46
  40. package/src/cli/migrate/spinner.ts +9 -9
  41. package/src/cli/migrate/tsconfig.ts +35 -35
  42. package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
  43. package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
  44. package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
  45. package/src/cli/start.ts +65 -66
  46. package/src/{typegen.ts → cli/typegen.ts} +59 -59
  47. package/src/client/build.ts +802 -768
  48. package/src/client/chunk-fold.ts +245 -240
  49. package/src/client/{paths.ts → chunk-name.ts} +6 -6
  50. package/src/client/entry.ts +162 -147
  51. package/src/client/prebuilt.ts +231 -223
  52. package/src/client/profile.ts +29 -29
  53. package/src/client/react-compiler.ts +20 -15
  54. package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
  55. package/src/client/reference-stub.ts +51 -51
  56. package/src/client/reference.ts +19 -19
  57. package/src/{api → client}/router/events.ts +32 -17
  58. package/src/{api → client}/router/history.ts +16 -16
  59. package/src/{api → client}/router/hub.ts +52 -53
  60. package/src/{api/router.ts → client/router/index.ts} +61 -60
  61. package/src/{api → client}/router/policies.ts +24 -24
  62. package/src/{api → client}/router/runtime.ts +2022 -1995
  63. package/src/{api → client}/router/types.ts +98 -98
  64. package/src/compat/actions/client-plugin.ts +42 -43
  65. package/src/compat/actions/client-stub.ts +14 -14
  66. package/src/compat/actions/{action-client.ts → client.ts} +194 -193
  67. package/src/compat/actions/config.ts +63 -64
  68. package/src/compat/actions/detect.ts +68 -68
  69. package/src/compat/actions/discovery.ts +105 -105
  70. package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
  71. package/src/compat/actions/early-submit.ts +1 -1
  72. package/src/compat/actions/endpoint.ts +198 -198
  73. package/src/compat/actions/extensions.ts +811 -0
  74. package/src/compat/actions/flight.ts +23 -23
  75. package/src/compat/actions/form-state.ts +34 -34
  76. package/src/compat/actions/hoist.ts +382 -236
  77. package/src/compat/actions/ids.ts +7 -12
  78. package/src/compat/actions/index.ts +8 -8
  79. package/src/compat/actions/instances.ts +46 -46
  80. package/src/compat/actions/origin.ts +47 -48
  81. package/src/compat/actions/protocol.ts +22 -22
  82. package/src/compat/actions/registry.ts +19 -19
  83. package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
  84. package/src/compat/actions/rewrite.ts +125 -125
  85. package/src/compat/actions/{action-router.ts → router.ts} +10 -10
  86. package/src/compat/actions/serve.ts +132 -136
  87. package/src/compat/actions/server-tag.ts +4 -4
  88. package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
  89. package/src/compat/actions/unrecognized-error.ts +4 -4
  90. package/src/compat/{index.ts → aliases.ts} +112 -109
  91. package/src/compat/bundler/bun-externals.ts +18 -18
  92. package/src/compat/bundler/cjs-exports.ts +271 -223
  93. package/src/compat/bundler/config.ts +116 -111
  94. package/src/compat/bundler/externals.ts +12 -12
  95. package/src/compat/bundler/import-meta-url.ts +19 -19
  96. package/src/compat/bundler/modularize-imports.ts +36 -33
  97. package/src/compat/bundler/new-url-asset.ts +22 -24
  98. package/src/compat/bundler/optimize-package-imports.ts +111 -107
  99. package/src/compat/bundler/polyfill.ts +28 -28
  100. package/src/compat/bundler/react-compiler.ts +35 -29
  101. package/src/compat/bundler/react-profiler.tsx +11 -11
  102. package/src/compat/bundler/relay-transform.ts +48 -47
  103. package/src/compat/bundler/require-context.ts +119 -113
  104. package/src/compat/bundler/resolve-extensions.ts +19 -19
  105. package/src/compat/bundler/source-cache.ts +25 -25
  106. package/src/compat/bundler/static-imports.ts +7 -7
  107. package/src/compat/bundler/symlink-imports.ts +46 -46
  108. package/src/compat/bundler/tsconfig-paths.ts +13 -15
  109. package/src/compat/bundler/wasm.ts +58 -60
  110. package/src/compat/bundler/webpack-loaders.ts +254 -241
  111. package/src/compat/bundler/worker.ts +101 -104
  112. package/src/compat/cache/build-flags.ts +29 -29
  113. package/src/compat/cache/build-prerender-errors.ts +40 -44
  114. package/src/compat/cache/custom-handler.ts +60 -53
  115. package/src/compat/cache/fetch-patch.ts +240 -240
  116. package/src/compat/cache/handler.ts +27 -31
  117. package/src/compat/cache/modern-handler.ts +148 -126
  118. package/src/compat/cache/resume-data-cache.ts +47 -45
  119. package/src/compat/cache/revalidate.ts +233 -232
  120. package/src/compat/cache/runtime-error.ts +35 -35
  121. package/src/compat/cache/use-cache-transform.ts +442 -417
  122. package/src/compat/cache/use-cache.ts +650 -614
  123. package/src/compat/cache-control.ts +140 -142
  124. package/src/compat/client/base-path.ts +21 -20
  125. package/src/compat/client/css-order.ts +18 -18
  126. package/src/compat/client/errors/bare-boundary.ts +11 -11
  127. package/src/compat/client/errors/control-flow.ts +23 -23
  128. package/src/compat/client/errors/error-boundary.ts +61 -61
  129. package/src/compat/client/errors/global-error.ts +101 -91
  130. package/src/compat/client/errors/install.ts +71 -72
  131. package/src/compat/client/errors/lazy.ts +23 -23
  132. package/src/compat/client/errors/primitive-throw.ts +47 -45
  133. package/src/compat/client/errors/soft-refresh.ts +4 -4
  134. package/src/compat/client/link-status.ts +33 -33
  135. package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
  136. package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
  137. package/src/compat/client/navigation-scroll.ts +63 -63
  138. package/src/compat/client/optimistic-routing.ts +93 -88
  139. package/src/compat/client/prefetch-cache.ts +23 -24
  140. package/src/compat/client/route-announcer.ts +35 -35
  141. package/src/compat/client/segment-cache-policy.ts +20 -20
  142. package/src/compat/client/segment-cache.ts +309 -315
  143. package/src/compat/client/segment-prefetch.ts +127 -132
  144. package/src/compat/client/trailing-slash.ts +5 -4
  145. package/src/compat/css/chunking.ts +113 -116
  146. package/src/compat/css/inline-css.ts +21 -21
  147. package/src/compat/css/lightningcss.ts +37 -38
  148. package/src/compat/css/modules.ts +161 -175
  149. package/src/compat/css/nonce.ts +7 -7
  150. package/src/compat/css/sass-plugin.ts +18 -21
  151. package/src/compat/css/sass.ts +150 -152
  152. package/src/compat/css/styled-jsx-runtime.ts +27 -27
  153. package/src/compat/css/styled-jsx.ts +21 -21
  154. package/src/compat/edge-runtime.ts +27 -27
  155. package/src/compat/{adapter → export}/build-complete.ts +72 -75
  156. package/src/compat/export/client.ts +29 -31
  157. package/src/compat/export/{index.ts → emit.ts} +111 -110
  158. package/src/compat/export/standalone.ts +62 -54
  159. package/src/compat/image-optimizer/cache.ts +51 -49
  160. package/src/compat/image-optimizer/detect.ts +52 -52
  161. package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
  162. package/src/compat/image-optimizer/source.ts +77 -80
  163. package/src/compat/lifecycle/after-scope.ts +26 -26
  164. package/src/compat/lifecycle/after.ts +48 -45
  165. package/src/compat/lifecycle/error-funnel.ts +98 -102
  166. package/src/compat/lifecycle/error-serialize.ts +30 -26
  167. package/src/compat/lifecycle/error-ui.ts +67 -32
  168. package/src/compat/lifecycle/instrumentation-client.ts +36 -38
  169. package/src/compat/lifecycle/instrumentation.ts +85 -85
  170. package/src/compat/lifecycle/node-console.ts +11 -11
  171. package/src/compat/lifecycle/testmode.ts +160 -132
  172. package/src/compat/mdx/compile.ts +60 -57
  173. package/src/compat/mdx/plugin.ts +11 -11
  174. package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
  175. package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
  176. package/src/compat/metadata.ts +75 -81
  177. package/src/compat/next/cache.ts +68 -69
  178. package/src/compat/next/canonical-url.ts +9 -9
  179. package/src/compat/next/client-cache.ts +19 -19
  180. package/src/compat/next/client-navigation.ts +112 -116
  181. package/src/compat/next/client-only.ts +1 -1
  182. package/src/compat/next/client-script.tsx +99 -93
  183. package/src/compat/next/client-server.ts +10 -10
  184. package/src/compat/next/config-loader.ts +176 -173
  185. package/src/compat/next/config.ts +7 -7
  186. package/src/compat/next/constants.cjs +6 -6
  187. package/src/compat/next/constants.ts +6 -6
  188. package/src/compat/next/custom-server.ts +26 -24
  189. package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
  190. package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
  191. package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
  192. package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
  193. package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
  194. package/src/compat/next/dynamic.tsx +21 -18
  195. package/src/compat/next/error.tsx +52 -52
  196. package/src/compat/next/font/cache.ts +74 -74
  197. package/src/compat/next/font/google.ts +2 -2
  198. package/src/compat/next/font/index.ts +1 -1
  199. package/src/compat/next/font/local.ts +3 -3
  200. package/src/compat/next/font/runtime-client.ts +17 -15
  201. package/src/compat/next/font/runtime.ts +443 -408
  202. package/src/compat/next/font/shared.ts +120 -108
  203. package/src/compat/next/form.tsx +63 -63
  204. package/src/compat/next/head.tsx +2 -2
  205. package/src/compat/next/headers.ts +103 -95
  206. package/src/compat/next/image/client.tsx +220 -0
  207. package/src/compat/next/image/config.ts +56 -58
  208. package/src/compat/next/image/optimizer.ts +40 -36
  209. package/src/compat/next/image/patterns.ts +37 -40
  210. package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
  211. package/src/compat/next/image/shared.ts +65 -57
  212. package/src/compat/next/image/static-metadata.ts +98 -107
  213. package/src/compat/next/image/validate.ts +79 -88
  214. package/src/compat/next/image.tsx +19 -23
  215. package/src/compat/next/index.ts +1 -1
  216. package/src/compat/next/legacy-image.tsx +59 -60
  217. package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
  218. package/src/compat/next/link.tsx +158 -158
  219. package/src/compat/next/navigation.cjs +12 -3
  220. package/src/compat/next/navigation.ts +48 -50
  221. package/src/compat/next/offline.ts +27 -27
  222. package/src/compat/next/og.ts +121 -124
  223. package/src/compat/next/preferred-region.ts +13 -14
  224. package/src/compat/next/redirects.ts +58 -56
  225. package/src/compat/next/resource-hints.ts +73 -76
  226. package/src/compat/next/rewrites.ts +130 -133
  227. package/src/compat/next/root-params.ts +45 -45
  228. package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
  229. package/src/compat/next/router.cjs +4 -2
  230. package/src/compat/next/router.ts +58 -61
  231. package/src/compat/next/script.tsx +108 -108
  232. package/src/compat/next/server-only.ts +1 -1
  233. package/src/compat/next/server.ts +19 -19
  234. package/src/compat/next/svgr.ts +18 -17
  235. package/src/compat/next/telemetry.ts +24 -24
  236. package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
  237. package/src/compat/next/user-agent.ts +53 -49
  238. package/src/compat/next/web-vitals.ts +22 -24
  239. package/src/compat/otel/api.ts +41 -41
  240. package/src/compat/otel/client-trace-metadata.ts +25 -27
  241. package/src/compat/otel/fetch-span.ts +29 -29
  242. package/src/compat/otel/tracer.ts +331 -331
  243. package/src/compat/pages/api.ts +456 -0
  244. package/src/compat/pages/client-plugin.ts +36 -36
  245. package/src/compat/pages/router-state.ts +34 -34
  246. package/src/compat/pages/{index.ts → router.ts} +130 -135
  247. package/src/compat/ppr/io.ts +12 -12
  248. package/src/compat/ppr/missing-root-params.ts +34 -38
  249. package/src/compat/ppr/root-params-scan.ts +66 -66
  250. package/src/compat/ppr/root-params-transform.ts +24 -26
  251. package/src/compat/ppr/root-params.ts +30 -30
  252. package/src/compat/ppr/segment-config-incompat.ts +6 -7
  253. package/src/compat/protocol.ts +71 -70
  254. package/src/compat/react/action-state.ts +47 -48
  255. package/src/compat/react/client-lite.ts +15 -15
  256. package/src/compat/react/client.ts +4 -4
  257. package/src/compat/react/compiler-runtime.ts +11 -11
  258. package/src/compat/react/dom-client.ts +44 -44
  259. package/src/compat/react/dom-react-server.ts +10 -16
  260. package/src/compat/react/dom-server.ts +10 -10
  261. package/src/compat/react/dom.ts +52 -52
  262. package/src/compat/react/hooks-extra.ts +34 -35
  263. package/src/compat/react/parity.ts +64 -61
  264. package/src/compat/react/preact.ts +81 -82
  265. package/src/compat/react/react-server.ts +28 -28
  266. package/src/compat/react/router-shim.ts +1 -1
  267. package/src/compat/react/server-component-use.ts +8 -8
  268. package/src/compat/react/server-inserted-html.ts +30 -31
  269. package/src/compat/react/server.ts +53 -55
  270. package/src/compat/react/use.ts +32 -32
  271. package/src/compat/react/view-transition.ts +20 -20
  272. package/src/compat/register/actions.ts +35 -824
  273. package/src/compat/register/boot.ts +41 -41
  274. package/src/compat/register/build-tier.ts +5 -5
  275. package/src/compat/register/build.ts +74 -70
  276. package/src/compat/register/bundler.ts +161 -156
  277. package/src/compat/register/cache.ts +20 -20
  278. package/src/compat/register/client-errors.ts +3 -3
  279. package/src/compat/register/config.ts +6 -6
  280. package/src/compat/register/css-extras.ts +30 -34
  281. package/src/compat/register/edge-runtime.ts +3 -3
  282. package/src/compat/register/errors.ts +10 -12
  283. package/src/compat/register/export.ts +16 -16
  284. package/src/compat/register/font.ts +11 -11
  285. package/src/compat/register/hooks.ts +2 -2
  286. package/src/compat/register/image.ts +40 -40
  287. package/src/compat/register/index.ts +59 -62
  288. package/src/compat/register/instrumentation-client.ts +10 -10
  289. package/src/compat/register/lifecycle.ts +25 -28
  290. package/src/compat/register/mdx.ts +10 -10
  291. package/src/compat/register/middleware.ts +226 -16
  292. package/src/compat/register/otel.ts +80 -88
  293. package/src/compat/register/pages-api.ts +10 -463
  294. package/src/compat/register/ppr.ts +16 -16
  295. package/src/compat/register/protocol.ts +17 -18
  296. package/src/compat/register/proxy.ts +49 -51
  297. package/src/compat/register/render.ts +79 -76
  298. package/src/compat/register/routing.ts +162 -159
  299. package/src/compat/register/segment.ts +24 -1897
  300. package/src/compat/register/static-image.ts +3 -3
  301. package/src/compat/register/{misc.ts → taint.ts} +9 -9
  302. package/src/compat/register/typed-routes.ts +14 -14
  303. package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
  304. package/src/compat/register/validation.ts +18 -18
  305. package/src/compat/segment/loading-boundary.ts +43 -45
  306. package/src/compat/segment/page-slot.ts +69 -69
  307. package/src/compat/segment/serve.ts +1884 -0
  308. package/src/compat/segment/tree.ts +113 -112
  309. package/src/compat/segment/vary-key.ts +38 -38
  310. package/src/compat/segment/vary-params.ts +138 -142
  311. package/src/compat/static-params.ts +14 -12
  312. package/src/compat/tsconfig-defaults.ts +87 -91
  313. package/src/compat/typecheck/{index.ts → check.ts} +234 -212
  314. package/src/compat/typecheck/worker.ts +15 -12
  315. package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
  316. package/src/compat/typed-routes/manifest.ts +174 -170
  317. package/src/compat/typed-routes/typegen.ts +127 -110
  318. package/src/compat/validation/errors.ts +16 -19
  319. package/src/compat/validation/prerender-diagnostics.ts +521 -504
  320. package/src/compat/validation/{index.ts → validate.ts} +647 -648
  321. package/src/compat-bootstrap.ts +16 -16
  322. package/src/config.ts +86 -69
  323. package/src/css/build.ts +230 -227
  324. package/src/css/postcss.ts +79 -80
  325. package/src/css/worker.ts +14 -15
  326. package/src/dev/client-actions.ts +10 -10
  327. package/src/dev/client-chunk-store.ts +27 -27
  328. package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
  329. package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
  330. package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
  331. package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
  332. package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
  333. package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
  334. package/src/dev/server.ts +804 -820
  335. package/src/env.ts +46 -43
  336. package/src/extensions.ts +491 -478
  337. package/src/index.ts +8 -8
  338. package/src/internal.ts +20 -23
  339. package/src/{islands → render}/boundary-error.ts +3 -3
  340. package/src/render/hooks.ts +71 -71
  341. package/src/render/island-context.ts +14 -14
  342. package/src/render/metadata.ts +310 -310
  343. package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
  344. package/src/{ppr.ts → render/ppr.ts} +244 -245
  345. package/src/render/renderer.ts +2087 -2082
  346. package/src/render/resource-hints.ts +16 -17
  347. package/src/render/slots.tsx +224 -235
  348. package/src/{islands → render}/static-children.ts +9 -12
  349. package/src/{islands → render}/static-slots.ts +37 -37
  350. package/src/{cache/context.ts → request/cache.ts} +20 -20
  351. package/src/request/context.ts +107 -107
  352. package/src/{dynamic/source.ts → resolve/dynamic.ts} +139 -139
  353. package/src/resolve/engine.ts +90 -77
  354. package/src/resolve/imports.ts +475 -463
  355. package/src/resolve/scan-facts.ts +318 -296
  356. package/src/resolve/source-text.ts +37 -37
  357. package/src/{dynamic → resolve}/tree-shake.ts +132 -128
  358. package/src/routing/forwarded.ts +19 -19
  359. package/src/routing/handler.ts +84 -91
  360. package/src/routing/href.ts +87 -70
  361. package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
  362. package/src/{proxy.ts → routing/proxy.ts} +306 -312
  363. package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
  364. package/src/routing/routes.ts +827 -815
  365. package/src/routing/slots.ts +164 -160
  366. package/src/runtime/loader.ts +954 -0
  367. package/src/{dev → runtime}/module-cache.ts +309 -287
  368. package/src/{dev → runtime}/module-generations.ts +9 -9
  369. package/src/{dev → runtime}/module-transform.ts +81 -72
  370. package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
  371. package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
  372. package/src/runtime/vendor.ts +428 -406
  373. package/src/styles.d.ts +9 -0
  374. package/src/types.ts +324 -335
  375. package/src/utils/ansi.ts +5 -5
  376. package/src/utils/{source.ts → code.ts} +15 -12
  377. package/src/utils/content-type.ts +3 -3
  378. package/src/utils/decode.ts +2 -2
  379. package/src/utils/dev-profile.ts +13 -13
  380. package/src/utils/error-log.ts +6 -6
  381. package/src/utils/esbuild.ts +18 -18
  382. package/src/utils/fs-cache.ts +13 -13
  383. package/src/utils/fs.ts +57 -49
  384. package/src/utils/html.ts +20 -24
  385. package/src/utils/native-require.ts +8 -8
  386. package/src/utils/serialize.ts +139 -146
  387. package/src/utils/verbose.ts +18 -18
  388. package/reference/overview.md +0 -35
  389. package/src/cli/analyze-print.ts +0 -181
  390. package/src/compat/middleware/manifest.ts +0 -210
  391. package/src/compat/next/image-client.tsx +0 -215
  392. package/src/compat/next/link-usage.ts +0 -29
  393. package/src/css/index.ts +0 -2
  394. package/src/render/index.ts +0 -1
  395. package/src/style-modules.d.ts +0 -9
@@ -13,50 +13,50 @@
13
13
  // Lazy: the oxc-parser native binding costs ~12.6 MB RSS; load it only when a parse happens.
14
14
  const parseSync: typeof import('oxc-parser').parseSync = (...args) =>
15
15
  // eslint-disable-next-line @typescript-eslint/no-require-imports
16
- loadNative(() => require('oxc-parser') as typeof import('oxc-parser')).parseSync(...args);
17
- import { loadNative } from '../utils/native-require';
18
- import { spliceSource } from '../dev/module-transform';
16
+ loadNative(() => require('oxc-parser') as typeof import('oxc-parser')).parseSync(...args)
17
+ import { loadNative } from '../utils/native-require'
18
+ import { spliceSource } from '../runtime/module-transform'
19
19
 
20
20
  export interface ScanEdge {
21
- specifier: string;
21
+ specifier: string
22
22
  /** Bound names: `default`, `*` (namespace object), or the imported names. */
23
- exports: string[];
23
+ exports: string[]
24
24
  /** Byte offset of the statement — edges are consumed in true source order. */
25
- index: number;
25
+ index: number
26
26
  /** `export * from`: binds every named export of the target, none of them known here. */
27
- star?: boolean;
27
+ star?: boolean
28
28
  /** `export … from` rather than `import`. */
29
- reexport?: boolean;
29
+ reexport?: boolean
30
30
  }
31
31
 
32
32
  /** One module specifier literal, with the span of its quoted text. */
33
33
  export interface SpecifierEdge {
34
- specifier: string;
34
+ specifier: string
35
35
  /** Span of the quoted literal, quotes included. */
36
- start: number;
37
- end: number;
36
+ start: number
37
+ end: number
38
38
  /** `side-effect` is `import 'x'`: no clause, so no `from` for a textual pass to key on. */
39
- kind: 'import' | 'side-effect' | 'export' | 'dynamic' | 'require';
39
+ kind: 'import' | 'side-effect' | 'export' | 'dynamic' | 'require'
40
40
  }
41
41
 
42
42
  export interface ImportBinding {
43
43
  /** Name in the target module; `default`/`*` for the default/namespace forms. */
44
- imported: string;
45
- local: string;
44
+ imported: string
45
+ local: string
46
46
  /** `import type …` / `{ type X }`: erased, but part of the statement's text. */
47
- type: boolean;
47
+ type: boolean
48
48
  }
49
49
 
50
50
  /** A static `import` statement, spans included — the unit the folded passes splice. */
51
51
  export interface ImportStatement {
52
- specifier: string;
52
+ specifier: string
53
53
  /** Statement span (`import` … `;`). */
54
- start: number;
55
- end: number;
54
+ start: number
55
+ end: number
56
56
  /** Span of the quoted specifier literal inside the statement. */
57
- specifierStart: number;
58
- specifierEnd: number;
59
- bindings: ImportBinding[];
57
+ specifierStart: number
58
+ specifierEnd: number
59
+ bindings: ImportBinding[]
60
60
  }
61
61
 
62
62
  /**
@@ -65,14 +65,14 @@ export interface ImportStatement {
65
65
  * parse, so a folded pass on an already-scanned source costs nothing beyond the lookup.
66
66
  */
67
67
  export interface RewriteFacts {
68
- edges: SpecifierEdge[];
69
- imports: ImportStatement[];
70
- importMetas: { start: number; end: number }[];
68
+ edges: SpecifierEdge[]
69
+ imports: ImportStatement[]
70
+ importMetas: { start: number; end: number }[]
71
71
  /**
72
72
  * The parse recovered from errors, so the record may be incomplete — folded
73
73
  * passes fall back to their textual form rather than silently under-rewrite.
74
74
  */
75
- unreliable: boolean;
75
+ unreliable: boolean
76
76
  }
77
77
 
78
78
  /**
@@ -81,45 +81,45 @@ export interface RewriteFacts {
81
81
  * call with such a loader; consumers gate on their own `dynamic` binding set.
82
82
  */
83
83
  export interface DynamicCallFact {
84
- name: string;
84
+ name: string
85
85
  /** Callee identifier start — aligns with the textual call scan's index. */
86
- start: number;
86
+ start: number
87
87
  /** Call end (past the closing paren). */
88
- end: number;
88
+ end: number
89
89
  /** Loader target, cooked value. */
90
- specifier: string;
90
+ specifier: string
91
91
  /** Span of the quoted specifier literal, quotes included. */
92
- specifierStart: number;
93
- specifierEnd: number;
92
+ specifierStart: number
93
+ specifierEnd: number
94
94
  /** From the `.then(m => m.X)` arm (or awaited member); `default` otherwise. */
95
- exportName: string;
95
+ exportName: string
96
96
  /** First arg is a string literal (`dynamic('./x')` form), not a loader fn. */
97
- literal?: boolean;
97
+ literal?: boolean
98
98
  /** End of the loader argument — options/appended args follow it. */
99
- loaderEnd: number;
99
+ loaderEnd: number
100
100
  /** Second-argument span, when present. */
101
- optionsStart?: number;
102
- optionsEnd?: number;
101
+ optionsStart?: number
102
+ optionsEnd?: number
103
103
  }
104
104
 
105
105
  export interface ScanFacts {
106
106
  /** Static value imports and `export … from` re-exports, in source order. */
107
- imports: ScanEdge[];
107
+ imports: ScanEdge[]
108
108
  /** `import('literal')` expressions, in source order. */
109
- dynamicImports: { specifier: string; index: number }[];
109
+ dynamicImports: { specifier: string; index: number }[]
110
110
  /** `require('literal')` calls — CJS sources still reach these scanners. */
111
- requires: { specifier: string; index: number; specifierStart: number }[];
111
+ requires: { specifier: string; index: number; specifierStart: number }[]
112
112
  /** This module's own value export names, `default` included. */
113
- exportNames: string[];
113
+ exportNames: string[]
114
114
  /** Specifiers of `export * from` (whose names live in the target). */
115
- exportStars: string[];
115
+ exportStars: string[]
116
116
  /** A real `'use client'` directive — prologue position only, never a comment. */
117
- useClient: boolean;
117
+ useClient: boolean
118
118
  /** Loader-shaped calls (see `DynamicCallFact`); only sources that can bind `dynamic` are walked. */
119
- dynamicCalls: DynamicCallFact[];
119
+ dynamicCalls: DynamicCallFact[]
120
120
  }
121
121
 
122
- const stylesheetOrData = /\.(?:css|scss|sass|less|styl|json)$/;
122
+ const stylesheetOrData = /\.(?:css|scss|sass|less|styl|json)$/
123
123
 
124
124
  const emptyFacts: ScanFacts = {
125
125
  imports: [],
@@ -129,43 +129,43 @@ const emptyFacts: ScanFacts = {
129
129
  exportStars: [],
130
130
  useClient: false,
131
131
  dynamicCalls: [],
132
- };
132
+ }
133
133
 
134
134
  const emptyRewriteFacts: RewriteFacts = {
135
135
  edges: [],
136
136
  imports: [],
137
137
  importMetas: [],
138
138
  unreliable: false,
139
- };
139
+ }
140
140
 
141
- const memo = new Map<string, { scan: ScanFacts; rewrite: RewriteFacts }>();
142
- let hits = 0;
143
- let misses = 0;
141
+ const memo = new Map<string, { scan: ScanFacts; rewrite: RewriteFacts }>()
142
+ let hits = 0
143
+ let misses = 0
144
144
 
145
145
  export function scanFacts(file: string, source: string): ScanFacts {
146
146
  // The module walk reaches stylesheets/data as ordinary edges; they hold no
147
147
  // module facts and are not parseable as script.
148
- if (stylesheetOrData.test(file)) return emptyFacts;
149
- return parsed(file, source).scan;
148
+ if (stylesheetOrData.test(file)) return emptyFacts
149
+ return parsed(file, source).scan
150
150
  }
151
151
 
152
152
  /** Every specifier a module pulls in — static, dynamic and `require`, in source order. */
153
153
  export function importSpecifiers(source: string, sourcefile = 'source') {
154
- const facts = scanFacts(sourcefile, source);
154
+ const facts = scanFacts(sourcefile, source)
155
155
  return [
156
156
  ...facts.imports.map(edge => edge.specifier),
157
157
  ...facts.dynamicImports.map(entry => entry.specifier),
158
158
  ...facts.requires.map(entry => entry.specifier),
159
- ];
159
+ ]
160
160
  }
161
161
 
162
162
  export function moduleExportNames(source: string, sourcefile = 'source.tsx') {
163
- return scanFacts(sourcefile, source).exportNames;
163
+ return scanFacts(sourcefile, source).exportNames
164
164
  }
165
165
 
166
166
  /** Specifiers of `export * from` — their names live in the target module. */
167
167
  export function moduleExportStars(source: string, sourcefile = 'source.tsx') {
168
- return scanFacts(sourcefile, source).exportStars;
168
+ return scanFacts(sourcefile, source).exportStars
169
169
  }
170
170
 
171
171
  /**
@@ -173,27 +173,27 @@ export function moduleExportStars(source: string, sourcefile = 'source.tsx') {
173
173
  * without a fact is an unanalyzable loader: no detection, nothing to splice.
174
174
  */
175
175
  export function dynamicCallFacts(source: string, file = 'module.tsx'): DynamicCallFact[] {
176
- if (stylesheetOrData.test(file)) return [];
177
- return parsed(file, source).scan.dynamicCalls;
176
+ if (stylesheetOrData.test(file)) return []
177
+ return parsed(file, source).scan.dynamicCalls
178
178
  }
179
179
 
180
180
  /** Module-record spans for the rewrite passes (see `RewriteFacts`). */
181
181
  export function rewriteFacts(file: string, source: string): RewriteFacts {
182
- if (stylesheetOrData.test(file)) return emptyRewriteFacts;
183
- return parsed(file, source).rewrite;
182
+ if (stylesheetOrData.test(file)) return emptyRewriteFacts
183
+ return parsed(file, source).rewrite
184
184
  }
185
185
 
186
186
  function parsed(file: string, source: string, lang = langForFile(file)) {
187
- const key = `${lang}\0${source.length}\0${Bun.hash(source).toString()}`;
188
- const cached = memo.get(key);
187
+ const key = `${lang}\0${source.length}\0${Bun.hash(source).toString()}`
188
+ const cached = memo.get(key)
189
189
  if (cached) {
190
- hits += 1;
191
- return cached;
190
+ hits += 1
191
+ return cached
192
192
  }
193
- misses += 1;
194
- const facts = parseFacts(file, source, lang);
195
- memo.set(key, facts);
196
- return facts;
193
+ misses += 1
194
+ const facts = parseFacts(file, source, lang)
195
+ memo.set(key, facts)
196
+ return facts
197
197
  }
198
198
 
199
199
  /**
@@ -207,68 +207,76 @@ export function rewriteSpecifierLiterals(
207
207
  file: string,
208
208
  replace: (specifier: string, kind: SpecifierEdge['kind']) => string | undefined,
209
209
  ): string {
210
- const facts = rewriteFacts(file, source);
210
+ const facts = rewriteFacts(file, source)
211
211
  // A partially recovered parse has a partial record; the textual scan the
212
212
  // folded passes replaced is the safe answer there.
213
- const edges = facts.unreliable ? textualEdges(source) : facts.edges;
214
- const edits: { start: number; end: number; value: string }[] = [];
213
+ const edges = facts.unreliable ? textualEdges(source) : facts.edges
214
+ const edits: { start: number; end: number; value: string }[] = []
215
215
  for (const edge of edges) {
216
- const value = replace(edge.specifier, edge.kind);
217
- if (value !== undefined) edits.push({ start: edge.start, end: edge.end, value });
216
+ const value = replace(edge.specifier, edge.kind)
217
+ if (value !== undefined) edits.push({ start: edge.start, end: edge.end, value })
218
218
  }
219
- return edits.length > 0 ? spliceSource(source, edits) : source;
219
+ return edits.length > 0 ? spliceSource(source, edits) : source
220
220
  }
221
221
 
222
- const textualSpecifier = /(\bfrom\s*|\b(?:import|require)\s*\(\s*)(['"])([^'"]+)\2/g;
222
+ const textualSpecifier = /(\bfrom\s*|\b(?:import|require)\s*\(\s*)(['"])([^'"]+)\2/g
223
223
 
224
224
  function textualEdges(source: string): SpecifierEdge[] {
225
- const edges: SpecifierEdge[] = [];
226
- textualSpecifier.lastIndex = 0;
227
- let match: RegExpExecArray | null;
225
+ const edges: SpecifierEdge[] = []
226
+ textualSpecifier.lastIndex = 0
227
+ let match: RegExpExecArray | null
228
228
  while ((match = textualSpecifier.exec(source))) {
229
- const start = match.index + match[1]!.length;
229
+ const start = match.index + match[1]!.length
230
230
  edges.push({
231
231
  specifier: match[3]!,
232
232
  start,
233
233
  end: start + match[3]!.length + 2,
234
- kind: match[1]!.includes('require') ? 'require' : match[1]!.includes('import') ? 'dynamic' : 'import',
235
- });
234
+ kind: match[1]!.includes('require')
235
+ ? 'require'
236
+ : match[1]!.includes('import')
237
+ ? 'dynamic'
238
+ : 'import',
239
+ })
236
240
  }
237
- return edges;
241
+ return edges
238
242
  }
239
243
 
240
244
  /** Memo effectiveness, for the dev-boot benches. */
241
245
  export function scanFactsStats() {
242
- return { hits, misses, sources: memo.size };
246
+ return { hits, misses, sources: memo.size }
243
247
  }
244
248
 
245
249
  function parseFacts(file: string, source: string, lang: ParserLang) {
246
250
  // Parse errors are recovered, never thrown: a scan of a half-typed file in
247
251
  // the dev watcher must still yield whatever the parser did understand.
248
- const result = parseSync(file, source, { lang });
249
- const imports: ScanEdge[] = [];
250
- const exportNames: string[] = [];
251
- const exportStars: string[] = [];
252
- const edges: SpecifierEdge[] = [];
253
- const importStatements: ImportStatement[] = [];
252
+ const result = parseSync(file, source, { lang })
253
+ const imports: ScanEdge[] = []
254
+ const exportNames: string[] = []
255
+ const exportStars: string[] = []
256
+ const edges: SpecifierEdge[] = []
257
+ const importStatements: ImportStatement[] = []
254
258
 
255
259
  for (const statement of result.module.staticImports) {
256
- const names: string[] = [];
257
- const bindings: ImportBinding[] = [];
258
- let bindsValue = statement.entries.length === 0;
260
+ const names: string[] = []
261
+ const bindings: ImportBinding[] = []
262
+ let bindsValue = statement.entries.length === 0
259
263
  for (const entry of statement.entries) {
260
- const kind: string = entry.importName.kind;
264
+ const kind: string = entry.importName.kind
261
265
  bindings.push({
262
266
  imported:
263
- kind === 'Default' ? 'default' : kind === 'NamespaceObject' ? '*' : (entry.importName.name ?? ''),
267
+ kind === 'Default'
268
+ ? 'default'
269
+ : kind === 'NamespaceObject'
270
+ ? '*'
271
+ : (entry.importName.name ?? ''),
264
272
  local: entry.localName.value ?? '',
265
273
  type: entry.isType,
266
- });
267
- if (entry.isType) continue;
268
- bindsValue = true;
269
- if (kind === 'Default') names.push('default');
270
- else if (kind === 'NamespaceObject') names.push('*');
271
- else if (entry.importName.name) names.push(entry.importName.name);
274
+ })
275
+ if (entry.isType) continue
276
+ bindsValue = true
277
+ if (kind === 'Default') names.push('default')
278
+ else if (kind === 'NamespaceObject') names.push('*')
279
+ else if (entry.importName.name) names.push(entry.importName.name)
272
280
  }
273
281
  importStatements.push({
274
282
  specifier: statement.moduleRequest.value,
@@ -277,86 +285,91 @@ function parseFacts(file: string, source: string, lang: ParserLang) {
277
285
  specifierStart: statement.moduleRequest.start,
278
286
  specifierEnd: statement.moduleRequest.end,
279
287
  bindings,
280
- });
288
+ })
281
289
  edges.push({
282
290
  specifier: statement.moduleRequest.value,
283
291
  start: statement.moduleRequest.start,
284
292
  end: statement.moduleRequest.end,
285
293
  kind: statement.entries.length === 0 ? 'side-effect' : 'import',
286
- });
294
+ })
287
295
  // `import type { … }` binds nothing at runtime: not an edge.
288
- if (!bindsValue) continue;
296
+ if (!bindsValue) continue
289
297
  imports.push({
290
298
  specifier: statement.moduleRequest.value,
291
299
  exports: names,
292
300
  index: statement.start,
293
- });
301
+ })
294
302
  }
295
303
 
296
304
  // One `export { a, b } from 'x'` reports the same moduleRequest per entry.
297
- const seenExportRequests = new Set<number>();
305
+ const seenExportRequests = new Set<number>()
298
306
  for (const statement of result.module.staticExports) {
299
307
  for (const entry of statement.entries) {
300
- const request = entry.moduleRequest;
301
- if (!request || seenExportRequests.has(request.start)) continue;
302
- seenExportRequests.add(request.start);
303
- edges.push({ specifier: request.value, start: request.start, end: request.end, kind: 'export' });
308
+ const request = entry.moduleRequest
309
+ if (!request || seenExportRequests.has(request.start)) continue
310
+ seenExportRequests.add(request.start)
311
+ edges.push({
312
+ specifier: request.value,
313
+ start: request.start,
314
+ end: request.end,
315
+ kind: 'export',
316
+ })
304
317
  }
305
318
  }
306
319
 
307
320
  for (const statement of result.module.staticExports) {
308
- const edges = new Map<string, ScanEdge>();
321
+ const edges = new Map<string, ScanEdge>()
309
322
  for (const entry of statement.entries) {
310
- if (entry.isType) continue;
311
- const exportKind: string = entry.exportName.kind;
312
- if (exportKind === 'Default') exportNames.push('default');
313
- else if (entry.exportName.name) exportNames.push(entry.exportName.name);
314
-
315
- const specifier = entry.moduleRequest?.value;
316
- if (!specifier) continue;
317
- const importKind: string = entry.importName.kind;
318
- const star = importKind === 'AllButDefault';
319
- if (star) exportStars.push(specifier);
320
- let edge = edges.get(specifier);
323
+ if (entry.isType) continue
324
+ const exportKind: string = entry.exportName.kind
325
+ if (exportKind === 'Default') exportNames.push('default')
326
+ else if (entry.exportName.name) exportNames.push(entry.exportName.name)
327
+
328
+ const specifier = entry.moduleRequest?.value
329
+ if (!specifier) continue
330
+ const importKind: string = entry.importName.kind
331
+ const star = importKind === 'AllButDefault'
332
+ if (star) exportStars.push(specifier)
333
+ let edge = edges.get(specifier)
321
334
  if (!edge) {
322
- edge = { specifier, exports: [], index: statement.start, reexport: true };
323
- edges.set(specifier, edge);
324
- imports.push(edge);
335
+ edge = { specifier, exports: [], index: statement.start, reexport: true }
336
+ edges.set(specifier, edge)
337
+ imports.push(edge)
325
338
  }
326
- if (star) edge.star = true;
327
- else if (importKind === 'All') edge.exports.push('*');
328
- else if (entry.importName.name) edge.exports.push(entry.importName.name);
339
+ if (star) edge.star = true
340
+ else if (importKind === 'All') edge.exports.push('*')
341
+ else if (entry.importName.name) edge.exports.push(entry.importName.name)
329
342
  }
330
343
  }
331
344
 
332
- imports.sort((a, b) => a.index - b.index);
345
+ imports.sort((a, b) => a.index - b.index)
333
346
 
334
- const dynamicImports: { specifier: string; index: number }[] = [];
347
+ const dynamicImports: { specifier: string; index: number }[] = []
335
348
  for (const entry of result.module.dynamicImports) {
336
- const raw = source.slice(entry.moduleRequest.start, entry.moduleRequest.end);
337
- const specifier = literalSpecifier(raw);
338
- if (specifier === undefined) continue;
339
- dynamicImports.push({ specifier, index: entry.start });
349
+ const raw = source.slice(entry.moduleRequest.start, entry.moduleRequest.end)
350
+ const specifier = literalSpecifier(raw)
351
+ if (specifier === undefined) continue
352
+ dynamicImports.push({ specifier, index: entry.start })
340
353
  // The literal's own span, without the whitespace `moduleRequest` includes.
341
- const lead = raw.length - raw.trimStart().length;
354
+ const lead = raw.length - raw.trimStart().length
342
355
  edges.push({
343
356
  specifier,
344
357
  start: entry.moduleRequest.start + lead,
345
358
  end: entry.moduleRequest.start + lead + specifier.length + 2,
346
359
  kind: 'dynamic',
347
- });
360
+ })
348
361
  }
349
362
 
350
- const requires = requireCalls(source, result.comments);
363
+ const requires = requireCalls(source, result.comments)
351
364
  for (const call of requires) {
352
365
  edges.push({
353
366
  specifier: call.specifier,
354
367
  start: call.specifierStart,
355
368
  end: call.specifierStart + call.specifier.length + 2,
356
369
  kind: 'require',
357
- });
370
+ })
358
371
  }
359
- edges.sort((a, b) => a.start - b.start);
372
+ edges.sort((a, b) => a.start - b.start)
360
373
 
361
374
  return {
362
375
  scan: {
@@ -367,7 +380,7 @@ function parseFacts(file: string, source: string, lang: ParserLang) {
367
380
  exportStars,
368
381
  useClient: hasUseClient(source, result),
369
382
  // `result.program` deserializes the whole AST: walk it only for sources
370
- // that can bind `dynamic()` at all (same cheap gate as dynamic/source.ts).
383
+ // that can bind `dynamic()` at all (same cheap gate as resolve/dynamic.ts).
371
384
  dynamicCalls:
372
385
  source.includes('@wular/pnext') || source.includes('next/dynamic')
373
386
  ? collectDynamicCalls(result.program as unknown as AstNode)
@@ -379,7 +392,7 @@ function parseFacts(file: string, source: string, lang: ParserLang) {
379
392
  importMetas: result.module.importMetas.map(meta => ({ start: meta.start, end: meta.end })),
380
393
  unreliable: result.errors.length > 0,
381
394
  },
382
- };
395
+ }
383
396
  }
384
397
 
385
398
  /**
@@ -388,23 +401,23 @@ function parseFacts(file: string, source: string, lang: ParserLang) {
388
401
  * consulted for the prologue shapes the scanner will not commit to.
389
402
  */
390
403
  function hasUseClient(source: string, result: { program: { body: readonly Directive[] } }) {
391
- const sniffed = sniffDirective(source, 'use client');
392
- if (sniffed !== undefined) return sniffed;
404
+ const sniffed = sniffDirective(source, 'use client')
405
+ if (sniffed !== undefined) return sniffed
393
406
  // Uncertain, but a directive is its raw text: no occurrence, no directive.
394
- if (!source.includes('use client')) return false;
395
- return hasDirective(result.program.body, 'use client');
407
+ if (!source.includes('use client')) return false
408
+ return hasDirective(result.program.body, 'use client')
396
409
  }
397
410
 
398
411
  interface Directive {
399
- type: string;
400
- directive?: string | null;
412
+ type: string
413
+ directive?: string | null
401
414
  }
402
415
 
403
416
  // A string literal is only a directive if what follows it ends the statement; a
404
417
  // continuation token means it was an expression (`'use client' + x`).
405
- const continuesExpression = /[+\-*/%.,?:=<>!&|^~([`)\]}]/;
406
- const wordContinuation = /^(?:in|instanceof)\b/;
407
- const lineTerminator = /[\n\r\u2028\u2029]/;
418
+ const continuesExpression = /[+\-*/%.,?:=<>!&|^~([`)\]}]/
419
+ const wordContinuation = /^(?:in|instanceof)\b/
420
+ const lineTerminator = /[\n\r\u2028\u2029]/
408
421
 
409
422
  /**
410
423
  * Directive-prologue sniff over raw source. Returns undefined - not a guess - for any shape it cannot decide
@@ -412,77 +425,82 @@ const lineTerminator = /[\n\r\u2028\u2029]/;
412
425
  * AST.
413
426
  */
414
427
  function sniffDirective(source: string, directive: string): boolean | undefined {
415
- let index = 0;
428
+ let index = 0
416
429
  if (source.startsWith('#!')) {
417
- const nl = source.search(lineTerminator);
418
- if (nl < 0) return false;
419
- index = nl + 1;
430
+ const nl = source.search(lineTerminator)
431
+ if (nl < 0) return false
432
+ index = nl + 1
420
433
  }
421
434
  for (;;) {
422
- index = skipTrivia(source, index);
423
- if (index < 0) return undefined;
424
- const quote = source[index];
425
- if (quote !== '"' && quote !== "'") return false; // prologue is over
435
+ index = skipTrivia(source, index)
436
+ if (index < 0) return undefined
437
+ const quote = source[index]
438
+ if (quote !== '"' && quote !== "'") return false // prologue is over
426
439
 
427
- let end = index + 1;
440
+ let end = index + 1
428
441
  while (end < source.length) {
429
- const char = source[end]!;
442
+ const char = source[end]!
430
443
  // An escape makes the raw text differ from the directive, but decoding it
431
444
  // exactly is the AST's job, not this scanner's.
432
- if (char === '\\' || lineTerminator.test(char)) return undefined;
433
- if (char === quote) break;
434
- end += 1;
445
+ if (char === '\\' || lineTerminator.test(char)) return undefined
446
+ if (char === quote) break
447
+ end += 1
435
448
  }
436
- if (end >= source.length) return undefined; // unterminated literal
437
- const raw = source.slice(index + 1, end);
449
+ if (end >= source.length) return undefined // unterminated literal
450
+ const raw = source.slice(index + 1, end)
438
451
 
439
- const after = skipTrivia(source, end + 1);
440
- if (after < 0) return undefined;
441
- const next = source[after];
442
- let terminated = after >= source.length || next === ';';
452
+ const after = skipTrivia(source, end + 1)
453
+ if (after < 0) return undefined
454
+ const next = source[after]
455
+ let terminated = after >= source.length || next === ';'
443
456
  if (!terminated && lineTerminator.test(source.slice(end + 1, after))) {
444
457
  // ASI closes the statement unless the next token continues the expression.
445
- terminated = !continuesExpression.test(next!) && !wordContinuation.test(source.slice(after, after + 11));
458
+ terminated =
459
+ !continuesExpression.test(next!) && !wordContinuation.test(source.slice(after, after + 11))
446
460
  }
447
- if (!terminated) return undefined;
448
- if (raw === directive) return true;
449
- index = next === ';' ? after + 1 : after;
450
- if (index >= source.length) return false;
461
+ if (!terminated) return undefined
462
+ if (raw === directive) return true
463
+ index = next === ';' ? after + 1 : after
464
+ if (index >= source.length) return false
451
465
  }
452
466
  }
453
467
 
454
468
  /** Past whitespace and comments; -1 for an unterminated block comment. */
455
469
  function skipTrivia(source: string, index: number) {
456
470
  for (;;) {
457
- while (index < source.length && /\s/.test(source[index]!)) index += 1;
458
- if (source[index] !== '/') return index;
471
+ while (index < source.length && /\s/.test(source[index]!)) index += 1
472
+ if (source[index] !== '/') return index
459
473
  if (source[index + 1] === '/') {
460
- let end = index + 2;
461
- while (end < source.length && !lineTerminator.test(source[end]!)) end += 1;
462
- index = end;
463
- continue;
474
+ let end = index + 2
475
+ while (end < source.length && !lineTerminator.test(source[end]!)) end += 1
476
+ index = end
477
+ continue
464
478
  }
465
479
  if (source[index + 1] === '*') {
466
- const end = source.indexOf('*/', index + 2);
467
- if (end < 0) return -1;
468
- index = end + 2;
469
- continue;
480
+ const end = source.indexOf('*/', index + 2)
481
+ if (end < 0) return -1
482
+ index = end + 2
483
+ continue
470
484
  }
471
- return index;
485
+ return index
472
486
  }
473
487
  }
474
488
 
475
- function hasDirective(body: readonly { type: string; directive?: string | null }[], directive: string) {
489
+ function hasDirective(
490
+ body: readonly { type: string; directive?: string | null }[],
491
+ directive: string,
492
+ ) {
476
493
  // The prologue ends at the first non-directive statement; comments and other
477
494
  // directives before it do not.
478
495
  for (const statement of body) {
479
- if (statement.type !== 'ExpressionStatement' || typeof statement.directive !== 'string') return false;
480
- if (statement.directive === directive) return true;
496
+ if (statement.type !== 'ExpressionStatement' || typeof statement.directive !== 'string')
497
+ return false
498
+ if (statement.directive === directive) return true
481
499
  }
482
- return false;
500
+ return false
483
501
  }
484
502
 
485
- const requirePattern = /\brequire\s*\(\s*(['"])([^'"]+)\1\s*\)/g;
503
+ const requirePattern = /\brequire\s*\(\s*(['"])([^'"]+)\1\s*\)/g
486
504
 
487
505
  /**
488
506
  * CJS `require` is an ordinary call, not a module record entry, so it stays on a regex - but a regex reads
@@ -491,87 +509,87 @@ const requirePattern = /\brequire\s*\(\s*(['"])([^'"]+)\1\s*\)/g;
491
509
  * that lands inside one.
492
510
  */
493
511
  function requireCalls(source: string, comments: readonly { start: number; end: number }[]) {
494
- const calls: { specifier: string; index: number; specifierStart: number }[] = [];
495
- if (!source.includes('require')) return calls;
496
- requirePattern.lastIndex = 0;
497
- let match: RegExpExecArray | null;
512
+ const calls: { specifier: string; index: number; specifierStart: number }[] = []
513
+ if (!source.includes('require')) return calls
514
+ requirePattern.lastIndex = 0
515
+ let match: RegExpExecArray | null
498
516
  // Both comments and matches ascend, so one shared cursor walks them together.
499
- let cursor = 0;
517
+ let cursor = 0
500
518
  while ((match = requirePattern.exec(source))) {
501
- const index = match.index;
502
- while (cursor < comments.length && comments[cursor]!.end <= index) cursor += 1;
503
- if (cursor < comments.length && index >= comments[cursor]!.start) continue;
519
+ const index = match.index
520
+ while (cursor < comments.length && comments[cursor]!.end <= index) cursor += 1
521
+ if (cursor < comments.length && index >= comments[cursor]!.start) continue
504
522
  calls.push({
505
523
  specifier: match[2]!,
506
524
  index,
507
525
  specifierStart: index + match[0].indexOf(match[1]!),
508
- });
526
+ })
509
527
  }
510
- return calls;
528
+ return calls
511
529
  }
512
530
 
513
531
  function literalSpecifier(raw: string) {
514
- return /^\s*(['"])([^'"]*)\1\s*$/.exec(raw)?.[2] || undefined;
532
+ return /^\s*(['"])([^'"]*)\1\s*$/.exec(raw)?.[2] || undefined
515
533
  }
516
534
 
517
535
  interface AstNode {
518
- type: string;
519
- start: number;
520
- end: number;
521
- [key: string]: unknown;
536
+ type: string
537
+ start: number
538
+ end: number
539
+ [key: string]: unknown
522
540
  }
523
541
 
524
542
  function isNode(value: unknown): value is AstNode {
525
- return typeof value === 'object' && value !== null && typeof (value as AstNode).type === 'string';
543
+ return typeof value === 'object' && value !== null && typeof (value as AstNode).type === 'string'
526
544
  }
527
545
 
528
546
  function child(node: AstNode | undefined, key: string): AstNode | undefined {
529
- const value = node?.[key];
530
- return isNode(value) ? value : undefined;
547
+ const value = node?.[key]
548
+ return isNode(value) ? value : undefined
531
549
  }
532
550
 
533
551
  function collectDynamicCalls(program: AstNode): DynamicCallFact[] {
534
- const calls: DynamicCallFact[] = [];
552
+ const calls: DynamicCallFact[] = []
535
553
  const visit = (value: unknown) => {
536
554
  if (Array.isArray(value)) {
537
- for (const item of value) visit(item);
538
- return;
555
+ for (const item of value) visit(item)
556
+ return
539
557
  }
540
- if (!isNode(value)) return;
558
+ if (!isNode(value)) return
541
559
  if (value.type === 'CallExpression') {
542
- const fact = dynamicCallFact(value);
543
- if (fact) calls.push(fact);
560
+ const fact = dynamicCallFact(value)
561
+ if (fact) calls.push(fact)
544
562
  }
545
563
  for (const key in value) {
546
- if (key === 'type' || key === 'loc' || key === 'range') continue;
547
- const entry = value[key];
548
- if (entry && typeof entry === 'object') visit(entry);
564
+ if (key === 'type' || key === 'loc' || key === 'range') continue
565
+ const entry = value[key]
566
+ if (entry && typeof entry === 'object') visit(entry)
549
567
  }
550
- };
551
- visit(program.body);
552
- return calls.sort((a, b) => a.start - b.start);
568
+ }
569
+ visit(program.body)
570
+ return calls.sort((a, b) => a.start - b.start)
553
571
  }
554
572
 
555
573
  function dynamicCallFact(call: AstNode): DynamicCallFact | undefined {
556
- const callee = child(call, 'callee');
557
- if (callee?.type !== 'Identifier') return undefined;
558
- const args = call.arguments;
559
- if (!Array.isArray(args) || !isNode(args[0])) return undefined;
560
- const loader = args[0];
561
-
562
- let target: { specifier: AstNode; exportName: string } | undefined;
563
- let literal: boolean | undefined;
574
+ const callee = child(call, 'callee')
575
+ if (callee?.type !== 'Identifier') return undefined
576
+ const args = call.arguments
577
+ if (!Array.isArray(args) || !isNode(args[0])) return undefined
578
+ const loader = args[0]
579
+
580
+ let target: { specifier: AstNode; exportName: string } | undefined
581
+ let literal: boolean | undefined
564
582
  if (stringValue(loader) !== undefined) {
565
- target = { specifier: loader, exportName: 'default' };
566
- literal = true;
583
+ target = { specifier: loader, exportName: 'default' }
584
+ literal = true
567
585
  } else if (loader.type === 'ArrowFunctionExpression' || loader.type === 'FunctionExpression') {
568
- target = loaderImportTarget(loader) ?? firstImportTarget(loader);
586
+ target = loaderImportTarget(loader) ?? firstImportTarget(loader)
569
587
  }
570
- if (!target) return undefined;
588
+ if (!target) return undefined
571
589
 
572
- const specifier = stringValue(target.specifier);
573
- if (specifier === undefined) return undefined;
574
- const options = isNode(args[1]) ? args[1] : undefined;
590
+ const specifier = stringValue(target.specifier)
591
+ if (specifier === undefined) return undefined
592
+ const options = isNode(args[1]) ? args[1] : undefined
575
593
  return {
576
594
  name: callee.name as string,
577
595
  start: callee.start,
@@ -583,51 +601,55 @@ function dynamicCallFact(call: AstNode): DynamicCallFact | undefined {
583
601
  ...(literal ? { literal } : {}),
584
602
  loaderEnd: loader.end,
585
603
  ...(options ? { optionsStart: options.start, optionsEnd: options.end } : {}),
586
- };
604
+ }
587
605
  }
588
606
 
589
607
  function stringValue(node: AstNode | undefined): string | undefined {
590
- if (!node) return undefined;
591
- if (node.type !== 'Literal' && node.type !== 'StringLiteral') return undefined;
592
- return typeof node.value === 'string' ? node.value : undefined;
608
+ if (!node) return undefined
609
+ if (node.type !== 'Literal' && node.type !== 'StringLiteral') return undefined
610
+ return typeof node.value === 'string' ? node.value : undefined
593
611
  }
594
612
 
595
613
  /** Past parens, `await`, `as`/`!` and optional-chain wrappers to the loader's real expression. */
596
614
  function unwrapExpression(node: AstNode | undefined): AstNode | undefined {
597
- let current = node;
615
+ let current = node
598
616
  for (;;) {
599
- if (!current) return undefined;
617
+ if (!current) return undefined
600
618
  if (current.type === 'ParenthesizedExpression' || current.type === 'ChainExpression') {
601
- current = child(current, 'expression');
619
+ current = child(current, 'expression')
602
620
  } else if (current.type === 'AwaitExpression') {
603
- current = child(current, 'argument');
604
- } else if (current.type === 'TSAsExpression' || current.type === 'TSNonNullExpression' || current.type === 'TSSatisfiesExpression') {
605
- current = child(current, 'expression');
621
+ current = child(current, 'argument')
622
+ } else if (
623
+ current.type === 'TSAsExpression' ||
624
+ current.type === 'TSNonNullExpression' ||
625
+ current.type === 'TSSatisfiesExpression'
626
+ ) {
627
+ current = child(current, 'expression')
606
628
  } else {
607
- return current;
629
+ return current
608
630
  }
609
631
  }
610
632
  }
611
633
 
612
634
  /** The expression a loader function resolves to: its expression body or first `return`. */
613
635
  function loaderResult(fn: AstNode): AstNode | undefined {
614
- const body = child(fn, 'body');
615
- if (!body) return undefined;
616
- if (body.type !== 'BlockStatement' && body.type !== 'FunctionBody') return unwrapExpression(body);
617
- const statements = body.body;
618
- if (!Array.isArray(statements)) return undefined;
636
+ const body = child(fn, 'body')
637
+ if (!body) return undefined
638
+ if (body.type !== 'BlockStatement' && body.type !== 'FunctionBody') return unwrapExpression(body)
639
+ const statements = body.body
640
+ if (!Array.isArray(statements)) return undefined
619
641
  for (const statement of statements) {
620
642
  if (isNode(statement) && statement.type === 'ReturnStatement') {
621
- return unwrapExpression(child(statement, 'argument'));
643
+ return unwrapExpression(child(statement, 'argument'))
622
644
  }
623
645
  }
624
- return undefined;
646
+ return undefined
625
647
  }
626
648
 
627
649
  function importSource(node: AstNode | undefined): AstNode | undefined {
628
- if (node?.type !== 'ImportExpression') return undefined;
629
- const source = child(node, 'source');
630
- return source && stringValue(source) !== undefined ? source : undefined;
650
+ if (node?.type !== 'ImportExpression') return undefined
651
+ const source = child(node, 'source')
652
+ return source && stringValue(source) !== undefined ? source : undefined
631
653
  }
632
654
 
633
655
  /**
@@ -635,44 +657,44 @@ function importSource(node: AstNode | undefined): AstNode | undefined {
635
657
  * (any param/arrow formatting), or `(await import('x')).X`.
636
658
  */
637
659
  function loaderImportTarget(fn: AstNode): { specifier: AstNode; exportName: string } | undefined {
638
- const result = loaderResult(fn);
639
- if (!result) return undefined;
660
+ const result = loaderResult(fn)
661
+ if (!result) return undefined
640
662
 
641
- const direct = importSource(result);
642
- if (direct) return { specifier: direct, exportName: 'default' };
663
+ const direct = importSource(result)
664
+ if (direct) return { specifier: direct, exportName: 'default' }
643
665
 
644
666
  if (result.type === 'MemberExpression' && result.computed !== true) {
645
- const source = importSource(unwrapExpression(child(result, 'object')));
646
- const property = child(result, 'property');
667
+ const source = importSource(unwrapExpression(child(result, 'object')))
668
+ const property = child(result, 'property')
647
669
  if (source && property?.type === 'Identifier') {
648
- return { specifier: source, exportName: property.name as string };
670
+ return { specifier: source, exportName: property.name as string }
649
671
  }
650
672
  }
651
673
 
652
- if (result.type !== 'CallExpression') return undefined;
653
- const callee = child(result, 'callee');
654
- if (callee?.type !== 'MemberExpression' || callee.computed === true) return undefined;
655
- if (child(callee, 'property')?.name !== 'then') return undefined;
656
- const source = importSource(unwrapExpression(child(callee, 'object')));
657
- if (!source) return undefined;
658
- return { specifier: source, exportName: thenArmExport(result) ?? 'default' };
674
+ if (result.type !== 'CallExpression') return undefined
675
+ const callee = child(result, 'callee')
676
+ if (callee?.type !== 'MemberExpression' || callee.computed === true) return undefined
677
+ if (child(callee, 'property')?.name !== 'then') return undefined
678
+ const source = importSource(unwrapExpression(child(callee, 'object')))
679
+ if (!source) return undefined
680
+ return { specifier: source, exportName: thenArmExport(result) ?? 'default' }
659
681
  }
660
682
 
661
683
  /** `X` of a `.then(m => m.X)` arm; undefined for any other arm shape. */
662
684
  function thenArmExport(thenCall: AstNode): string | undefined {
663
- const args = thenCall.arguments;
664
- if (!Array.isArray(args) || !isNode(args[0])) return undefined;
665
- const arm = args[0];
666
- if (arm.type !== 'ArrowFunctionExpression' && arm.type !== 'FunctionExpression') return undefined;
667
- const params = arm.params;
668
- const param = Array.isArray(params) && isNode(params[0]) ? params[0] : undefined;
669
- if (param?.type !== 'Identifier') return undefined;
670
- const result = loaderResult(arm);
671
- if (result?.type !== 'MemberExpression' || result.computed === true) return undefined;
672
- const object = unwrapExpression(child(result, 'object'));
673
- if (object?.type !== 'Identifier' || object.name !== param.name) return undefined;
674
- const property = child(result, 'property');
675
- return property?.type === 'Identifier' ? (property.name as string) : undefined;
685
+ const args = thenCall.arguments
686
+ if (!Array.isArray(args) || !isNode(args[0])) return undefined
687
+ const arm = args[0]
688
+ if (arm.type !== 'ArrowFunctionExpression' && arm.type !== 'FunctionExpression') return undefined
689
+ const params = arm.params
690
+ const param = Array.isArray(params) && isNode(params[0]) ? params[0] : undefined
691
+ if (param?.type !== 'Identifier') return undefined
692
+ const result = loaderResult(arm)
693
+ if (result?.type !== 'MemberExpression' || result.computed === true) return undefined
694
+ const object = unwrapExpression(child(result, 'object'))
695
+ if (object?.type !== 'Identifier' || object.name !== param.name) return undefined
696
+ const property = child(result, 'property')
697
+ return property?.type === 'Identifier' ? (property.name as string) : undefined
676
698
  }
677
699
 
678
700
  /**
@@ -681,32 +703,32 @@ function thenArmExport(thenCall: AstNode): string | undefined {
681
703
  * textual extraction always did for these.
682
704
  */
683
705
  function firstImportTarget(fn: AstNode): { specifier: AstNode; exportName: string } | undefined {
684
- let found: AstNode | undefined;
706
+ let found: AstNode | undefined
685
707
  const visit = (value: unknown) => {
686
- if (found) return;
708
+ if (found) return
687
709
  if (Array.isArray(value)) {
688
- for (const item of value) visit(item);
689
- return;
710
+ for (const item of value) visit(item)
711
+ return
690
712
  }
691
- if (!isNode(value)) return;
692
- const source = importSource(value);
713
+ if (!isNode(value)) return
714
+ const source = importSource(value)
693
715
  if (source) {
694
- found = source;
695
- return;
716
+ found = source
717
+ return
696
718
  }
697
719
  for (const key in value) {
698
- const entry = value[key];
699
- if (entry && typeof entry === 'object') visit(entry);
720
+ const entry = value[key]
721
+ if (entry && typeof entry === 'object') visit(entry)
700
722
  }
701
- };
702
- visit(fn.body);
703
- return found ? { specifier: found, exportName: 'default' } : undefined;
723
+ }
724
+ visit(fn.body)
725
+ return found ? { specifier: found, exportName: 'default' } : undefined
704
726
  }
705
727
 
706
- type ParserLang = 'ts' | 'tsx';
728
+ type ParserLang = 'ts' | 'tsx'
707
729
 
708
730
  // `.ts` forbids JSX (`<T>value` is a type assertion there); everything else —
709
731
  // including extensionless scan inputs — parses as the tsx superset.
710
732
  function langForFile(file: string): ParserLang {
711
- return /\.[mc]?ts$/.test(file) ? 'ts' : 'tsx';
733
+ return /\.[mc]?ts$/.test(file) ? 'ts' : 'tsx'
712
734
  }