@nativescript/vite 8.0.0-alpha.9 → 8.0.0-dev.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 (554) hide show
  1. package/README.md +89 -14
  2. package/bin/cli.cjs +8 -14
  3. package/configuration/angular.d.ts +34 -1
  4. package/configuration/angular.js +196 -217
  5. package/configuration/angular.js.map +1 -1
  6. package/configuration/base.js +152 -104
  7. package/configuration/base.js.map +1 -1
  8. package/configuration/javascript.js +14 -93
  9. package/configuration/javascript.js.map +1 -1
  10. package/configuration/react.js +41 -73
  11. package/configuration/react.js.map +1 -1
  12. package/configuration/solid.js +51 -6
  13. package/configuration/solid.js.map +1 -1
  14. package/configuration/typescript.js +11 -92
  15. package/configuration/typescript.js.map +1 -1
  16. package/framework.d.ts +22 -0
  17. package/framework.js +18 -0
  18. package/framework.js.map +1 -0
  19. package/helpers/app-components.d.ts +2 -1
  20. package/helpers/app-components.js.map +1 -1
  21. package/helpers/app-css-refresh.d.ts +31 -0
  22. package/helpers/app-css-refresh.js +43 -0
  23. package/helpers/app-css-refresh.js.map +1 -0
  24. package/helpers/app-css-state.d.ts +17 -0
  25. package/helpers/app-css-state.js +51 -0
  26. package/helpers/app-css-state.js.map +1 -0
  27. package/helpers/bundler-context.d.ts +11 -0
  28. package/helpers/bundler-context.js +71 -0
  29. package/helpers/bundler-context.js.map +1 -0
  30. package/helpers/cli-flags.d.ts +12 -0
  31. package/helpers/cli-flags.js +34 -0
  32. package/helpers/cli-flags.js.map +1 -1
  33. package/helpers/css-platform-plugin.d.ts +14 -0
  34. package/helpers/css-platform-plugin.js +43 -25
  35. package/helpers/css-platform-plugin.js.map +1 -1
  36. package/helpers/dev-host.d.ts +360 -0
  37. package/helpers/dev-host.js +694 -0
  38. package/helpers/dev-host.js.map +1 -0
  39. package/helpers/dynamic-import-plugin.d.ts +2 -1
  40. package/helpers/dynamic-import-plugin.js +59 -53
  41. package/helpers/dynamic-import-plugin.js.map +1 -1
  42. package/helpers/esbuild-platform-resolver.js +4 -1
  43. package/helpers/esbuild-platform-resolver.js.map +1 -1
  44. package/helpers/external-configs.d.ts +10 -12
  45. package/helpers/external-configs.js +58 -35
  46. package/helpers/external-configs.js.map +1 -1
  47. package/helpers/flavor.d.ts +31 -0
  48. package/helpers/flavor.js +53 -2
  49. package/helpers/flavor.js.map +1 -1
  50. package/helpers/global-defines.d.ts +100 -33
  51. package/helpers/global-defines.js +192 -66
  52. package/helpers/global-defines.js.map +1 -1
  53. package/helpers/hmr-scope.d.ts +26 -0
  54. package/helpers/hmr-scope.js +67 -0
  55. package/helpers/hmr-scope.js.map +1 -0
  56. package/helpers/init.js +24 -26
  57. package/helpers/init.js.map +1 -1
  58. package/helpers/logging.d.ts +11 -1
  59. package/helpers/logging.js +45 -2
  60. package/helpers/logging.js.map +1 -1
  61. package/helpers/main-entry.d.ts +4 -1
  62. package/helpers/main-entry.js +293 -40
  63. package/helpers/main-entry.js.map +1 -1
  64. package/helpers/nativeclass-esbuild-plugin.d.ts +2 -1
  65. package/helpers/nativeclass-esbuild-plugin.js +6 -1
  66. package/helpers/nativeclass-esbuild-plugin.js.map +1 -1
  67. package/helpers/nativeclass-transform.d.ts +13 -0
  68. package/helpers/nativeclass-transform.js +37 -7
  69. package/helpers/nativeclass-transform.js.map +1 -1
  70. package/helpers/nativeclass-transformer-plugin.js +8 -3
  71. package/helpers/nativeclass-transformer-plugin.js.map +1 -1
  72. package/helpers/nativescript-package-resolver.js +10 -62
  73. package/helpers/nativescript-package-resolver.js.map +1 -1
  74. package/helpers/normalize-id.d.ts +42 -0
  75. package/helpers/normalize-id.js +60 -0
  76. package/helpers/normalize-id.js.map +1 -0
  77. package/helpers/ns-core-external-urls.d.ts +32 -0
  78. package/helpers/ns-core-external-urls.js +107 -0
  79. package/helpers/ns-core-external-urls.js.map +1 -0
  80. package/helpers/ns-core-url.d.ts +26 -3
  81. package/helpers/ns-core-url.js +66 -8
  82. package/helpers/ns-core-url.js.map +1 -1
  83. package/helpers/optimize-deps.d.ts +16 -0
  84. package/helpers/optimize-deps.js +17 -0
  85. package/helpers/optimize-deps.js.map +1 -0
  86. package/helpers/package-platform-aliases.js +34 -49
  87. package/helpers/package-platform-aliases.js.map +1 -1
  88. package/helpers/platform-types.d.ts +2 -0
  89. package/helpers/platform-types.js +2 -0
  90. package/helpers/platform-types.js.map +1 -0
  91. package/helpers/postcss-platform-config.d.ts +17 -1
  92. package/helpers/postcss-platform-config.js +20 -37
  93. package/helpers/postcss-platform-config.js.map +1 -1
  94. package/helpers/resolve-main-field-platform.d.ts +20 -0
  95. package/helpers/resolve-main-field-platform.js +49 -0
  96. package/helpers/resolve-main-field-platform.js.map +1 -0
  97. package/helpers/resolver.js +17 -2
  98. package/helpers/resolver.js.map +1 -1
  99. package/helpers/theme-core-plugins.js +1 -1
  100. package/helpers/theme-core-plugins.js.map +1 -1
  101. package/helpers/ts-config-paths.d.ts +32 -0
  102. package/helpers/ts-config-paths.js +143 -62
  103. package/helpers/ts-config-paths.js.map +1 -1
  104. package/helpers/typescript-check.d.ts +3 -3
  105. package/helpers/typescript-check.js +4 -4
  106. package/helpers/typescript-check.js.map +1 -1
  107. package/helpers/ui-registration.d.ts +21 -0
  108. package/helpers/ui-registration.js +156 -0
  109. package/helpers/ui-registration.js.map +1 -0
  110. package/helpers/utils.d.ts +9 -0
  111. package/helpers/utils.js +22 -2
  112. package/helpers/utils.js.map +1 -1
  113. package/helpers/vite-package-version.d.ts +7 -0
  114. package/helpers/vite-package-version.js +44 -0
  115. package/helpers/vite-package-version.js.map +1 -0
  116. package/helpers/workers.d.ts +33 -0
  117. package/helpers/workers.js +237 -10
  118. package/helpers/workers.js.map +1 -1
  119. package/hmr/client/css-handler.d.ts +2 -1
  120. package/hmr/client/css-handler.js +63 -32
  121. package/hmr/client/css-handler.js.map +1 -1
  122. package/hmr/client/css-update-overlay.d.ts +18 -0
  123. package/hmr/client/css-update-overlay.js +27 -0
  124. package/hmr/client/css-update-overlay.js.map +1 -0
  125. package/hmr/client/framework-client-strategy.d.ts +117 -0
  126. package/hmr/client/framework-client-strategy.js +18 -0
  127. package/hmr/client/framework-client-strategy.js.map +1 -0
  128. package/hmr/client/framework.d.ts +31 -0
  129. package/hmr/client/framework.js +17 -0
  130. package/hmr/client/framework.js.map +1 -0
  131. package/hmr/client/hmr-pending-overlay.d.ts +0 -14
  132. package/hmr/client/hmr-pending-overlay.js +2 -11
  133. package/hmr/client/hmr-pending-overlay.js.map +1 -1
  134. package/hmr/client/hot-context.d.ts +89 -0
  135. package/hmr/client/hot-context.js +404 -0
  136. package/hmr/client/hot-context.js.map +1 -0
  137. package/hmr/client/index.d.ts +9 -1
  138. package/hmr/client/index.js +70 -1970
  139. package/hmr/client/index.js.map +1 -1
  140. package/hmr/client/overlay-driver.d.ts +10 -0
  141. package/hmr/client/overlay-driver.js +33 -0
  142. package/hmr/client/overlay-driver.js.map +1 -0
  143. package/hmr/client/protocol-dispatch.d.ts +8 -0
  144. package/hmr/client/protocol-dispatch.js +308 -0
  145. package/hmr/client/protocol-dispatch.js.map +1 -0
  146. package/hmr/client/root-reset.d.ts +15 -0
  147. package/hmr/client/root-reset.js +358 -0
  148. package/hmr/client/root-reset.js.map +1 -0
  149. package/hmr/client/strategy-loader.d.ts +24 -0
  150. package/hmr/client/strategy-loader.js +136 -0
  151. package/hmr/client/strategy-loader.js.map +1 -0
  152. package/hmr/client/update-pipeline.d.ts +27 -0
  153. package/hmr/client/update-pipeline.js +489 -0
  154. package/hmr/client/update-pipeline.js.map +1 -0
  155. package/hmr/client/utils.d.ts +9 -1
  156. package/hmr/client/utils.js +117 -97
  157. package/hmr/client/utils.js.map +1 -1
  158. package/hmr/client/ws-transport.d.ts +21 -0
  159. package/hmr/client/ws-transport.js +323 -0
  160. package/hmr/client/ws-transport.js.map +1 -0
  161. package/hmr/entry-runtime.d.ts +2 -1
  162. package/hmr/entry-runtime.js +279 -44
  163. package/hmr/entry-runtime.js.map +1 -1
  164. package/hmr/framework-flavors.d.ts +59 -0
  165. package/hmr/framework-flavors.js +108 -0
  166. package/hmr/framework-flavors.js.map +1 -0
  167. package/hmr/frameworks/angular/build/angular-linker.d.ts +12 -0
  168. package/hmr/frameworks/angular/build/angular-linker.js +113 -0
  169. package/hmr/frameworks/angular/build/angular-linker.js.map +1 -0
  170. package/{helpers/angular → hmr/frameworks/angular/build}/inject-component-hmr-registration.js +2 -70
  171. package/hmr/frameworks/angular/build/inject-component-hmr-registration.js.map +1 -0
  172. package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.d.ts +75 -0
  173. package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.js +221 -0
  174. package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.js.map +1 -0
  175. package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.js +1 -170
  176. package/hmr/frameworks/angular/build/inline-decorator-component-templates.js.map +1 -0
  177. package/hmr/frameworks/angular/build/js-lexer.d.ts +4 -0
  178. package/{helpers/angular/synthesize-decorator-ctor-parameters.js → hmr/frameworks/angular/build/js-lexer.js} +22 -96
  179. package/hmr/frameworks/angular/build/js-lexer.js.map +1 -0
  180. package/hmr/frameworks/angular/build/linker-stats.d.ts +18 -0
  181. package/hmr/frameworks/angular/build/linker-stats.js +29 -0
  182. package/hmr/frameworks/angular/build/linker-stats.js.map +1 -0
  183. package/hmr/frameworks/angular/build/shared-linker.d.ts +39 -0
  184. package/hmr/frameworks/angular/build/shared-linker.js +128 -0
  185. package/hmr/frameworks/angular/build/shared-linker.js.map +1 -0
  186. package/hmr/frameworks/angular/build/synthesize-decorator-ctor-parameters.js +88 -0
  187. package/hmr/frameworks/angular/build/synthesize-decorator-ctor-parameters.js.map +1 -0
  188. package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.js +1 -174
  189. package/hmr/frameworks/angular/build/synthesize-injectable-factories.js.map +1 -0
  190. package/hmr/frameworks/angular/build/ts-fallback-transform.d.ts +5 -0
  191. package/hmr/frameworks/angular/build/ts-fallback-transform.js +138 -0
  192. package/hmr/frameworks/angular/build/ts-fallback-transform.js.map +1 -0
  193. package/hmr/frameworks/angular/build/util.js.map +1 -0
  194. package/hmr/frameworks/angular/build/worker-url-preserve.d.ts +5 -0
  195. package/hmr/frameworks/angular/build/worker-url-preserve.js +140 -0
  196. package/hmr/frameworks/angular/build/worker-url-preserve.js.map +1 -0
  197. package/hmr/frameworks/angular/client/index.d.ts +0 -1
  198. package/hmr/frameworks/angular/client/index.js +360 -194
  199. package/hmr/frameworks/angular/client/index.js.map +1 -1
  200. package/hmr/frameworks/angular/client/strategy.d.ts +9 -0
  201. package/hmr/frameworks/angular/client/strategy.js +19 -0
  202. package/hmr/frameworks/angular/client/strategy.js.map +1 -0
  203. package/hmr/frameworks/angular/server/angular-root-component.d.ts +79 -0
  204. package/hmr/frameworks/angular/server/angular-root-component.js +149 -0
  205. package/hmr/frameworks/angular/server/angular-root-component.js.map +1 -0
  206. package/hmr/frameworks/angular/server/ng-component-route.d.ts +43 -0
  207. package/hmr/frameworks/angular/server/ng-component-route.js +113 -0
  208. package/hmr/frameworks/angular/server/ng-component-route.js.map +1 -0
  209. package/hmr/frameworks/angular/server/strategy.js +668 -13
  210. package/hmr/frameworks/angular/server/strategy.js.map +1 -1
  211. package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.js +2 -2
  212. package/hmr/frameworks/angular/server/websocket-angular-entry.js.map +1 -0
  213. package/hmr/{server → frameworks/angular/server}/websocket-angular-hot-update.d.ts +27 -11
  214. package/hmr/{server → frameworks/angular/server}/websocket-angular-hot-update.js +179 -107
  215. package/hmr/frameworks/angular/server/websocket-angular-hot-update.js.map +1 -0
  216. package/hmr/frameworks/react/client/strategy.d.ts +12 -0
  217. package/hmr/frameworks/react/client/strategy.js +27 -0
  218. package/hmr/frameworks/react/client/strategy.js.map +1 -0
  219. package/hmr/frameworks/react/server/strategy.d.ts +2 -0
  220. package/hmr/frameworks/react/server/strategy.js +230 -0
  221. package/hmr/frameworks/react/server/strategy.js.map +1 -0
  222. package/hmr/frameworks/solid/build/solid-jsx-deps.d.ts +15 -0
  223. package/hmr/frameworks/solid/build/solid-jsx-deps.js +178 -0
  224. package/hmr/frameworks/solid/build/solid-jsx-deps.js.map +1 -0
  225. package/hmr/frameworks/solid/client/app-runtime.d.ts +68 -0
  226. package/hmr/frameworks/solid/client/app-runtime.js +252 -0
  227. package/hmr/frameworks/solid/client/app-runtime.js.map +1 -0
  228. package/hmr/frameworks/solid/client/strategy.d.ts +7 -0
  229. package/hmr/frameworks/solid/client/strategy.js +391 -0
  230. package/hmr/frameworks/solid/client/strategy.js.map +1 -0
  231. package/hmr/frameworks/solid/server/strategy.js +293 -16
  232. package/hmr/frameworks/solid/server/strategy.js.map +1 -1
  233. package/hmr/frameworks/typescript/client/strategy.d.ts +7 -0
  234. package/hmr/frameworks/typescript/client/strategy.js +418 -0
  235. package/hmr/frameworks/typescript/client/strategy.js.map +1 -0
  236. package/hmr/frameworks/typescript/server/strategy.js +40 -14
  237. package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
  238. package/hmr/frameworks/vue/client/dep-propagation.d.ts +44 -0
  239. package/hmr/frameworks/vue/client/dep-propagation.js +148 -0
  240. package/hmr/frameworks/vue/client/dep-propagation.js.map +1 -0
  241. package/hmr/frameworks/vue/client/index.d.ts +10 -1
  242. package/hmr/frameworks/vue/client/index.js +270 -521
  243. package/hmr/frameworks/vue/client/index.js.map +1 -1
  244. package/hmr/frameworks/vue/client/navigate-app.d.ts +3 -0
  245. package/hmr/frameworks/vue/client/navigate-app.js +178 -0
  246. package/hmr/frameworks/vue/client/navigate-app.js.map +1 -0
  247. package/hmr/frameworks/vue/client/strategy.d.ts +33 -0
  248. package/hmr/frameworks/vue/client/strategy.js +152 -0
  249. package/hmr/frameworks/vue/client/strategy.js.map +1 -0
  250. package/hmr/frameworks/vue/client/vue-sfc-update-overlay.d.ts +49 -0
  251. package/hmr/frameworks/vue/client/vue-sfc-update-overlay.js +124 -0
  252. package/hmr/frameworks/vue/client/vue-sfc-update-overlay.js.map +1 -0
  253. package/hmr/frameworks/vue/server/compiler.d.ts +3 -1
  254. package/hmr/frameworks/vue/server/compiler.js +3 -1
  255. package/hmr/frameworks/vue/server/compiler.js.map +1 -1
  256. package/hmr/frameworks/vue/server/sfc-route-assemble.d.ts +7 -0
  257. package/hmr/frameworks/vue/server/sfc-route-assemble.js +823 -0
  258. package/hmr/frameworks/vue/server/sfc-route-assemble.js.map +1 -0
  259. package/hmr/frameworks/vue/server/sfc-route-meta.d.ts +7 -0
  260. package/hmr/frameworks/vue/server/sfc-route-meta.js +80 -0
  261. package/hmr/frameworks/vue/server/sfc-route-meta.js.map +1 -0
  262. package/hmr/frameworks/vue/server/sfc-route-serve.d.ts +8 -0
  263. package/hmr/frameworks/vue/server/sfc-route-serve.js +462 -0
  264. package/hmr/frameworks/vue/server/sfc-route-serve.js.map +1 -0
  265. package/hmr/frameworks/vue/server/sfc-route-shared.d.ts +45 -0
  266. package/hmr/frameworks/vue/server/sfc-route-shared.js +105 -0
  267. package/hmr/frameworks/vue/server/sfc-route-shared.js.map +1 -0
  268. package/hmr/frameworks/vue/server/strategy.d.ts +35 -0
  269. package/hmr/frameworks/vue/server/strategy.js +291 -7
  270. package/hmr/frameworks/vue/server/strategy.js.map +1 -1
  271. package/hmr/frameworks/vue/server/websocket-sfc.d.ts +15 -0
  272. package/hmr/frameworks/vue/server/websocket-sfc.js +20 -0
  273. package/hmr/frameworks/vue/server/websocket-sfc.js.map +1 -0
  274. package/hmr/helpers/ast-normalizer.d.ts +3 -1
  275. package/hmr/helpers/ast-normalizer.js +109 -14
  276. package/hmr/helpers/ast-normalizer.js.map +1 -1
  277. package/hmr/helpers/package-exports.d.ts +16 -0
  278. package/hmr/helpers/package-exports.js +396 -0
  279. package/hmr/helpers/package-exports.js.map +1 -0
  280. package/hmr/helpers/vendor-rewrite.d.ts +1 -1
  281. package/hmr/helpers/vendor-rewrite.js +5 -3
  282. package/hmr/helpers/vendor-rewrite.js.map +1 -1
  283. package/hmr/server/boot-recording.d.ts +51 -0
  284. package/hmr/server/boot-recording.js +214 -0
  285. package/hmr/server/boot-recording.js.map +1 -0
  286. package/hmr/server/constants.js +7 -1
  287. package/hmr/server/constants.js.map +1 -1
  288. package/hmr/server/content-css-update.d.ts +54 -0
  289. package/hmr/server/content-css-update.js +78 -0
  290. package/hmr/server/content-css-update.js.map +1 -0
  291. package/hmr/server/core-bundle.d.ts +140 -0
  292. package/hmr/server/core-bundle.js +614 -0
  293. package/hmr/server/core-bundle.js.map +1 -0
  294. package/hmr/server/core-sanitize.d.ts +86 -7
  295. package/hmr/server/core-sanitize.js +155 -37
  296. package/hmr/server/core-sanitize.js.map +1 -1
  297. package/hmr/server/css-connect-sync.d.ts +28 -0
  298. package/hmr/server/css-connect-sync.js +59 -0
  299. package/hmr/server/css-connect-sync.js.map +1 -0
  300. package/hmr/server/css-device-module.d.ts +28 -0
  301. package/hmr/server/css-device-module.js +44 -0
  302. package/hmr/server/css-device-module.js.map +1 -0
  303. package/hmr/server/css-update-message.d.ts +23 -0
  304. package/hmr/server/css-update-message.js +41 -0
  305. package/hmr/server/css-update-message.js.map +1 -0
  306. package/hmr/server/deps-bundle.d.ts +233 -0
  307. package/hmr/server/deps-bundle.js +1022 -0
  308. package/hmr/server/deps-bundle.js.map +1 -0
  309. package/hmr/server/device-transform-helpers.d.ts +24 -0
  310. package/hmr/server/device-transform-helpers.js +408 -0
  311. package/hmr/server/device-transform-helpers.js.map +1 -0
  312. package/hmr/server/framework-strategy.d.ts +182 -11
  313. package/hmr/server/hmr-module-graph.d.ts +37 -0
  314. package/hmr/server/hmr-module-graph.js +215 -0
  315. package/hmr/server/hmr-module-graph.js.map +1 -0
  316. package/hmr/server/import-map.d.ts +57 -23
  317. package/hmr/server/import-map.js +142 -70
  318. package/hmr/server/import-map.js.map +1 -1
  319. package/hmr/server/index.js +7 -16
  320. package/hmr/server/index.js.map +1 -1
  321. package/hmr/server/node-builtins-route.d.ts +12 -0
  322. package/hmr/server/node-builtins-route.js +86 -0
  323. package/hmr/server/node-builtins-route.js.map +1 -0
  324. package/hmr/server/ns-m-response-memo.d.ts +10 -0
  325. package/hmr/server/ns-m-response-memo.js +33 -0
  326. package/hmr/server/ns-m-response-memo.js.map +1 -0
  327. package/hmr/server/ns-rt-bridge.d.ts +51 -0
  328. package/hmr/server/ns-rt-bridge.js +131 -0
  329. package/hmr/server/ns-rt-bridge.js.map +1 -0
  330. package/hmr/server/ns-rt-route.d.ts +5 -0
  331. package/hmr/server/ns-rt-route.js +39 -0
  332. package/hmr/server/ns-rt-route.js.map +1 -0
  333. package/hmr/server/perf-instrumentation.d.ts +1 -1
  334. package/hmr/server/perf-instrumentation.js +3 -1
  335. package/hmr/server/perf-instrumentation.js.map +1 -1
  336. package/hmr/server/process-code-for-device.d.ts +54 -0
  337. package/hmr/server/process-code-for-device.js +832 -0
  338. package/hmr/server/process-code-for-device.js.map +1 -0
  339. package/hmr/server/require-guard.d.ts +1 -0
  340. package/hmr/server/require-guard.js +12 -0
  341. package/hmr/server/require-guard.js.map +1 -0
  342. package/hmr/server/rewrite-imports.d.ts +2 -0
  343. package/hmr/server/rewrite-imports.js +631 -0
  344. package/hmr/server/rewrite-imports.js.map +1 -0
  345. package/hmr/server/route-helpers.d.ts +7 -0
  346. package/hmr/server/route-helpers.js +13 -0
  347. package/hmr/server/route-helpers.js.map +1 -0
  348. package/hmr/server/runtime-graph-filter.js +8 -1
  349. package/hmr/server/runtime-graph-filter.js.map +1 -1
  350. package/hmr/server/server-origin.d.ts +2 -0
  351. package/hmr/server/server-origin.js +88 -0
  352. package/hmr/server/server-origin.js.map +1 -0
  353. package/hmr/server/shared-transform-request.js +1 -2
  354. package/hmr/server/shared-transform-request.js.map +1 -1
  355. package/hmr/server/socket-utils.d.ts +10 -0
  356. package/hmr/server/socket-utils.js +14 -0
  357. package/hmr/server/socket-utils.js.map +1 -0
  358. package/hmr/server/transform-cache-invalidation.d.ts +37 -0
  359. package/hmr/server/transform-cache-invalidation.js +156 -0
  360. package/hmr/server/transform-cache-invalidation.js.map +1 -0
  361. package/hmr/server/vendor-bare-module-shims.d.ts +4 -0
  362. package/hmr/server/vendor-bare-module-shims.js +80 -0
  363. package/hmr/server/vendor-bare-module-shims.js.map +1 -0
  364. package/hmr/server/vite-plugin.d.ts +1 -0
  365. package/hmr/server/vite-plugin.js +211 -53
  366. package/hmr/server/vite-plugin.js.map +1 -1
  367. package/hmr/server/websocket-core-bridge.d.ts +51 -4
  368. package/hmr/server/websocket-core-bridge.js +62 -49
  369. package/hmr/server/websocket-core-bridge.js.map +1 -1
  370. package/hmr/server/websocket-device-transform.d.ts +3 -0
  371. package/hmr/server/websocket-device-transform.js +7 -0
  372. package/hmr/server/websocket-device-transform.js.map +1 -0
  373. package/hmr/server/websocket-hmr-pending.d.ts +2 -16
  374. package/hmr/server/websocket-hmr-pending.js +0 -22
  375. package/hmr/server/websocket-hmr-pending.js.map +1 -1
  376. package/hmr/server/websocket-hot-update.d.ts +80 -0
  377. package/hmr/server/websocket-hot-update.js +299 -0
  378. package/hmr/server/websocket-hot-update.js.map +1 -0
  379. package/hmr/server/websocket-import-map-route.d.ts +15 -0
  380. package/hmr/server/websocket-import-map-route.js +51 -0
  381. package/hmr/server/websocket-import-map-route.js.map +1 -0
  382. package/hmr/server/websocket-module-bindings.d.ts +15 -0
  383. package/hmr/server/websocket-module-bindings.js +36 -3
  384. package/hmr/server/websocket-module-bindings.js.map +1 -1
  385. package/hmr/server/websocket-module-specifiers.d.ts +2 -5
  386. package/hmr/server/websocket-module-specifiers.js +42 -30
  387. package/hmr/server/websocket-module-specifiers.js.map +1 -1
  388. package/hmr/server/websocket-ns-core.d.ts +34 -0
  389. package/hmr/server/websocket-ns-core.js +414 -0
  390. package/hmr/server/websocket-ns-core.js.map +1 -0
  391. package/hmr/server/websocket-ns-entry.d.ts +21 -0
  392. package/hmr/server/websocket-ns-entry.js +163 -0
  393. package/hmr/server/websocket-ns-entry.js.map +1 -0
  394. package/hmr/server/websocket-ns-m-paths.d.ts +19 -3
  395. package/hmr/server/websocket-ns-m-paths.js +98 -75
  396. package/hmr/server/websocket-ns-m-paths.js.map +1 -1
  397. package/hmr/server/websocket-ns-m-request.d.ts +2 -1
  398. package/hmr/server/websocket-ns-m-request.js +3 -2
  399. package/hmr/server/websocket-ns-m-request.js.map +1 -1
  400. package/hmr/server/websocket-ns-m.d.ts +52 -0
  401. package/hmr/server/websocket-ns-m.js +592 -0
  402. package/hmr/server/websocket-ns-m.js.map +1 -0
  403. package/hmr/server/websocket-served-module-helpers.d.ts +65 -3
  404. package/hmr/server/websocket-served-module-helpers.js +457 -140
  405. package/hmr/server/websocket-served-module-helpers.js.map +1 -1
  406. package/hmr/server/websocket-txn.js +6 -9
  407. package/hmr/server/websocket-txn.js.map +1 -1
  408. package/hmr/server/websocket-vendor-unifier.d.ts +0 -1
  409. package/hmr/server/websocket-vendor-unifier.js +4 -9
  410. package/hmr/server/websocket-vendor-unifier.js.map +1 -1
  411. package/hmr/server/websocket.d.ts +6 -40
  412. package/hmr/server/websocket.js +661 -6751
  413. package/hmr/server/websocket.js.map +1 -1
  414. package/hmr/shared/ns-globals.d.ts +108 -0
  415. package/hmr/shared/ns-globals.js +29 -0
  416. package/hmr/shared/ns-globals.js.map +1 -0
  417. package/hmr/shared/protocol.d.ts +157 -0
  418. package/hmr/shared/protocol.js +28 -0
  419. package/hmr/shared/protocol.js.map +1 -0
  420. package/hmr/shared/runtime/boot-complete.d.ts +14 -0
  421. package/hmr/shared/runtime/boot-complete.js +32 -0
  422. package/hmr/shared/runtime/boot-complete.js.map +1 -0
  423. package/hmr/shared/runtime/boot-placeholder-ui.d.ts +69 -0
  424. package/hmr/shared/runtime/boot-placeholder-ui.js +101 -0
  425. package/hmr/shared/runtime/boot-placeholder-ui.js.map +1 -0
  426. package/hmr/shared/runtime/boot-progress.d.ts +44 -0
  427. package/hmr/shared/runtime/boot-progress.js +134 -0
  428. package/hmr/shared/runtime/boot-progress.js.map +1 -0
  429. package/hmr/shared/runtime/boot-timeline.d.ts +1 -1
  430. package/hmr/shared/runtime/boot-timeline.js +8 -19
  431. package/hmr/shared/runtime/boot-timeline.js.map +1 -1
  432. package/hmr/shared/runtime/browser-runtime-contract.d.ts +58 -25
  433. package/hmr/shared/runtime/browser-runtime-contract.js +21 -9
  434. package/hmr/shared/runtime/browser-runtime-contract.js.map +1 -1
  435. package/hmr/shared/runtime/dev-overlay-ios.d.ts +87 -0
  436. package/hmr/shared/runtime/dev-overlay-ios.js +521 -0
  437. package/hmr/shared/runtime/dev-overlay-ios.js.map +1 -0
  438. package/hmr/shared/runtime/dev-overlay-shared.d.ts +58 -0
  439. package/hmr/shared/runtime/dev-overlay-shared.js +116 -0
  440. package/hmr/shared/runtime/dev-overlay-shared.js.map +1 -0
  441. package/hmr/shared/runtime/dev-overlay-snapshots.d.ts +31 -0
  442. package/hmr/shared/runtime/dev-overlay-snapshots.js +324 -0
  443. package/hmr/shared/runtime/dev-overlay-snapshots.js.map +1 -0
  444. package/hmr/shared/runtime/dev-overlay-tree.d.ts +59 -0
  445. package/hmr/shared/runtime/dev-overlay-tree.js +712 -0
  446. package/hmr/shared/runtime/dev-overlay-tree.js.map +1 -0
  447. package/hmr/shared/runtime/dev-overlay.d.ts +23 -69
  448. package/hmr/shared/runtime/dev-overlay.js +67 -1011
  449. package/hmr/shared/runtime/dev-overlay.js.map +1 -1
  450. package/hmr/shared/runtime/global-scope.d.ts +18 -0
  451. package/hmr/shared/runtime/global-scope.js +21 -0
  452. package/hmr/shared/runtime/global-scope.js.map +1 -0
  453. package/hmr/shared/runtime/hooks.js +2 -1
  454. package/hmr/shared/runtime/hooks.js.map +1 -1
  455. package/hmr/shared/runtime/launch-bridge.d.ts +9 -0
  456. package/hmr/shared/runtime/launch-bridge.js +98 -0
  457. package/hmr/shared/runtime/launch-bridge.js.map +1 -0
  458. package/hmr/shared/runtime/module-provenance.js +3 -2
  459. package/hmr/shared/runtime/module-provenance.js.map +1 -1
  460. package/hmr/shared/runtime/ns-runtime-test-double.d.ts +21 -0
  461. package/hmr/shared/runtime/ns-runtime-test-double.js +20 -0
  462. package/hmr/shared/runtime/ns-runtime-test-double.js.map +1 -0
  463. package/hmr/shared/runtime/overlay-flag.d.ts +9 -0
  464. package/hmr/shared/runtime/overlay-flag.js +34 -0
  465. package/hmr/shared/runtime/overlay-flag.js.map +1 -0
  466. package/hmr/shared/runtime/root-placeholder-view.d.ts +19 -0
  467. package/hmr/shared/runtime/root-placeholder-view.js +311 -0
  468. package/hmr/shared/runtime/root-placeholder-view.js.map +1 -0
  469. package/hmr/shared/runtime/root-placeholder.js +382 -157
  470. package/hmr/shared/runtime/root-placeholder.js.map +1 -1
  471. package/hmr/shared/runtime/session-bootstrap.js +209 -54
  472. package/hmr/shared/runtime/session-bootstrap.js.map +1 -1
  473. package/hmr/shared/runtime/vendor-bootstrap.js +2 -1
  474. package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -1
  475. package/hmr/shared/runtime/vendor-resolve.d.ts +22 -0
  476. package/hmr/shared/runtime/vendor-resolve.js +45 -0
  477. package/hmr/shared/runtime/vendor-resolve.js.map +1 -0
  478. package/hmr/shared/runtime/worker-tracking.d.ts +28 -0
  479. package/hmr/shared/runtime/worker-tracking.js +114 -0
  480. package/hmr/shared/runtime/worker-tracking.js.map +1 -0
  481. package/hmr/shared/vendor/manifest-collect.d.ts +4 -0
  482. package/hmr/shared/vendor/manifest-collect.js +909 -0
  483. package/hmr/shared/vendor/manifest-collect.js.map +1 -0
  484. package/hmr/shared/vendor/manifest-loader.d.ts +2 -1
  485. package/hmr/shared/vendor/manifest-loader.js +5 -3
  486. package/hmr/shared/vendor/manifest-loader.js.map +1 -1
  487. package/hmr/shared/vendor/manifest.d.ts +10 -35
  488. package/hmr/shared/vendor/manifest.js +154 -978
  489. package/hmr/shared/vendor/manifest.js.map +1 -1
  490. package/hmr/shared/vendor/registry.d.ts +2 -0
  491. package/hmr/shared/vendor/registry.js +14 -0
  492. package/hmr/shared/vendor/registry.js.map +1 -1
  493. package/hmr/shared/vendor/vendor-device-shim.d.ts +1 -0
  494. package/hmr/shared/vendor/vendor-device-shim.js +208 -0
  495. package/hmr/shared/vendor/vendor-device-shim.js.map +1 -0
  496. package/hmr/shared/vendor/vendor-esbuild-plugins.d.ts +107 -0
  497. package/hmr/shared/vendor/vendor-esbuild-plugins.js +540 -0
  498. package/hmr/shared/vendor/vendor-esbuild-plugins.js.map +1 -0
  499. package/package.json +70 -13
  500. package/runtime/core-aliases-early.js +11 -16
  501. package/runtime/core-aliases-early.js.map +1 -1
  502. package/shims/react-jsx-runtime.d.ts +4 -0
  503. package/shims/react-jsx-runtime.js +61 -0
  504. package/shims/react-jsx-runtime.js.map +1 -0
  505. package/helpers/angular/angular-linker.d.ts +0 -13
  506. package/helpers/angular/angular-linker.js +0 -185
  507. package/helpers/angular/angular-linker.js.map +0 -1
  508. package/helpers/angular/inject-component-hmr-registration.js.map +0 -1
  509. package/helpers/angular/inline-decorator-component-templates.js.map +0 -1
  510. package/helpers/angular/shared-linker.d.ts +0 -11
  511. package/helpers/angular/shared-linker.js +0 -75
  512. package/helpers/angular/shared-linker.js.map +0 -1
  513. package/helpers/angular/synthesize-decorator-ctor-parameters.js.map +0 -1
  514. package/helpers/angular/synthesize-injectable-factories.js.map +0 -1
  515. package/helpers/angular/util.js.map +0 -1
  516. package/helpers/module-runner-patch.d.ts +0 -3
  517. package/helpers/module-runner-patch.js +0 -63
  518. package/helpers/module-runner-patch.js.map +0 -1
  519. package/helpers/prelink-angular.d.ts +0 -2
  520. package/helpers/prelink-angular.js +0 -114
  521. package/helpers/prelink-angular.js.map +0 -1
  522. package/hmr/server/websocket-angular-entry.js.map +0 -1
  523. package/hmr/server/websocket-angular-hot-update.js.map +0 -1
  524. package/hmr/server/websocket-ns-m-finalize.d.ts +0 -22
  525. package/hmr/server/websocket-ns-m-finalize.js +0 -88
  526. package/hmr/server/websocket-ns-m-finalize.js.map +0 -1
  527. package/hmr/server/websocket-runtime-compat.d.ts +0 -19
  528. package/hmr/server/websocket-runtime-compat.js +0 -287
  529. package/hmr/server/websocket-runtime-compat.js.map +0 -1
  530. package/hmr/server/websocket-vue-sfc.d.ts +0 -27
  531. package/hmr/server/websocket-vue-sfc.js +0 -1069
  532. package/hmr/server/websocket-vue-sfc.js.map +0 -1
  533. package/hmr/shared/runtime/http-only-boot.d.ts +0 -2
  534. package/hmr/shared/runtime/http-only-boot.js +0 -171
  535. package/hmr/shared/runtime/http-only-boot.js.map +0 -1
  536. package/hmr/vendor-bootstrap.d.ts +0 -3
  537. package/hmr/vendor-bootstrap.js +0 -32
  538. package/hmr/vendor-bootstrap.js.map +0 -1
  539. package/shims/react-reconciler-constants.d.ts +0 -14
  540. package/shims/react-reconciler-constants.js +0 -21
  541. package/shims/react-reconciler-constants.js.map +0 -1
  542. package/shims/react-reconciler.d.ts +0 -8
  543. package/shims/react-reconciler.js +0 -15
  544. package/shims/react-reconciler.js.map +0 -1
  545. package/transformers/NativeClass/index.d.ts +0 -2
  546. package/transformers/NativeClass/index.js +0 -222
  547. package/transformers/NativeClass/index.js.map +0 -1
  548. /package/{helpers/angular → hmr/frameworks/angular/build}/inject-component-hmr-registration.d.ts +0 -0
  549. /package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.d.ts +0 -0
  550. /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-decorator-ctor-parameters.d.ts +0 -0
  551. /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.d.ts +0 -0
  552. /package/{helpers/angular → hmr/frameworks/angular/build}/util.d.ts +0 -0
  553. /package/{helpers/angular → hmr/frameworks/angular/build}/util.js +0 -0
  554. /package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.d.ts +0 -0
@@ -1,44 +1,24 @@
1
- // Opt-out flag for the apply-progress overlay (default: enabled).
2
- // Driven by `NS_VITE_PROGRESS_OVERLAY=0` (or `false`/`off`/`no`) on the
3
- // dev server; baked into the bundle via
4
- // `__NS_HMR_PROGRESS_OVERLAY_ENABLED__` at build time. We collapse the
5
- // build-time constant into a runtime boolean once so each call-site is
6
- // a single property check rather than a try/typeof. Tests that re-run
7
- // the angular client (via vitest) see `undefined` and default to
8
- // enabled — matching the production dev-server experience.
9
- const overlayEnabled = (() => {
10
- try {
11
- return typeof __NS_HMR_PROGRESS_OVERLAY_ENABLED__ === 'boolean' ? __NS_HMR_PROGRESS_OVERLAY_ENABLED__ : true;
12
- }
13
- catch {
14
- return true;
15
- }
16
- })();
17
- function getHmrOverlayApi() {
18
- if (!overlayEnabled)
19
- return null;
20
- try {
21
- return globalThis.__NS_HMR_DEV_OVERLAY__ || null;
22
- }
23
- catch { }
24
- return null;
25
- }
1
+ import { getGlobalScope } from '../../../shared/runtime/global-scope.js';
2
+ import { getNsHotRegistry } from '../../../client/hot-context.js';
3
+ import { getOverlayApi, resolveOverlayEnabled, setUpdateStage } from '../../../client/overlay-driver.js';
4
+ import { handleCssUpdates } from '../../../client/css-handler.js';
5
+ import { resolveHmrHttpOrigin } from '../../../client/utils.js';
6
+ import { readNsRuntimeDevHostApi } from '../../../shared/runtime/browser-runtime-contract.js';
7
+ import { sweepTrackedWorkers } from '../../../shared/runtime/worker-tracking.js';
8
+ // HMR-applying progress overlay, driven through `client/overlay-driver.ts`.
9
+ // The opt-out gate is collapsed into a runtime boolean once at module load so
10
+ // each call-site is a single property check rather than a try/typeof chain.
11
+ const overlayEnabled = resolveOverlayEnabled();
26
12
  function setUpdateOverlayStage(stage, info) {
27
13
  if (!overlayEnabled)
28
14
  return;
29
- try {
30
- const api = getHmrOverlayApi();
31
- if (api && typeof api.setUpdateStage === 'function') {
32
- api.setUpdateStage(stage, info);
33
- }
34
- }
35
- catch { }
15
+ setUpdateStage(stage, info);
36
16
  }
37
17
  function hideUpdateOverlay() {
38
18
  if (!overlayEnabled)
39
19
  return;
40
20
  try {
41
- const api = getHmrOverlayApi();
21
+ const api = getOverlayApi();
42
22
  if (api && typeof api.hide === 'function') {
43
23
  api.hide('hmr-applied');
44
24
  }
@@ -79,12 +59,25 @@ export function installAngularHmrClientHooks() {
79
59
  }
80
60
  catch { }
81
61
  }
62
+ async function applyDeferredCssUpdates(msg) {
63
+ const updates = Array.isArray(msg?.cssUpdates) ? msg.cssUpdates : [];
64
+ if (!updates.length)
65
+ return;
66
+ try {
67
+ await handleCssUpdates(updates, resolveHmrHttpOrigin(msg?.origin));
68
+ }
69
+ catch (error) {
70
+ // The Angular module refresh is still viable. Surface the CSS failure, but
71
+ // continue with the reboot so one fetch cannot strand the old application.
72
+ console.warn('[ns-hmr][angular] deferred app.css update failed:', error?.message || error);
73
+ }
74
+ }
82
75
  // HMR cycle serialization mutex.
83
76
  //
84
77
  // A back-to-back save (e.g., the user holds Cmd+S, or `runOnSave`
85
78
  // saves a file twice during one tick) could overlap two HMR cycles:
86
79
  // the first cycle's `import(entry)` would still be resolving when the
87
- // second cycle's `__nsInvalidateModules` ran, leaving the registry in
80
+ // second cycle's `invalidateModules` (ns:module) ran, leaving the registry in
88
81
  // a half-evicted state and producing flaky "module already evaluated"
89
82
  // errors.
90
83
  //
@@ -98,128 +91,193 @@ export function installAngularHmrClientHooks() {
98
91
  let inFlightHmrCycle = null;
99
92
  // Explicit module eviction.
100
93
  //
101
- // `__nsInvalidateModules` is a runtime-installed global that takes an
102
- // array of canonical /ns/m/<rel> URLs and removes each one from V8's
103
- // module registry (`g_moduleRegistry`). The runtime canonicalizer
104
- // strips legacy `__ns_hmr__/<tag>/` and `__ns_boot__/b1/` segments
105
- // before lookup, so the same URL evicts every cache entry historically
106
- // created for that module — even if a stale tagged URL is still around.
94
+ // `invalidateModules` is an ns:module builtin member that takes an
95
+ // array of canonical /ns/m/<rel> URLs, removes each one from V8's
96
+ // module registry (`g_moduleRegistry`) and the prefetch cache, and
97
+ // marks the keys "bust next fetch" so the runtime's next HTTP fetch
98
+ // for them defeats OS-level caches with a one-shot query nonce.
107
99
  //
108
- // Soft-fails on older runtimes that don't expose the function. In that
109
- // case we fall through to the legacy URL-versioning path and emit a
110
- // one-time warning so the user knows the eviction protocol is
111
- // unavailable.
112
- function invalidateModules(urls, verbose) {
113
- if (!urls || !urls.length)
114
- return false;
115
- const g = globalThis;
116
- const fn = g.__nsInvalidateModules;
117
- if (typeof fn !== 'function') {
118
- console.warn(`[ns-hmr-diag][client] runtime missing __nsInvalidateModules; falling back to legacy URL versioning. evict=${urls.length}`);
119
- return false;
100
+ // Soft-fails (with a loud warning) if the runtime is missing the
101
+ // function — the eviction protocol is a required part of the runtime
102
+ // contract, so that indicates a runtime/vite version mismatch.
103
+ // Dispatch one of Vite's standard HMR lifecycle events through the JS
104
+ // hot registry (`hot-context.ts`). The registry owns the listener map
105
+ // that `import.meta.hot.on(event, cb)` populates; this function is the
106
+ // producer side that lets the Angular HMR client emit the canonical
107
+ // Vite events (`vite:beforeUpdate`, `vite:afterUpdate`,
108
+ // `vite:beforeFullReload`, `vite:invalidate`, `vite:error`) at the
109
+ // right moments. User code that does
110
+ // `import.meta.hot.on('vite:beforeUpdate', cb)` only fires when this is
111
+ // called.
112
+ //
113
+ // The registry is a `globalThis.__NS_HOT_REGISTRY__` singleton, so this
114
+ // works even if this module and the served app modules were evaluated
115
+ // from different URLs. Per-listener failures are swallowed inside the
116
+ // registry, so a single bad listener can't break the HMR cycle.
117
+ function dispatchHotEvent(_g, event, payload) {
118
+ try {
119
+ getNsHotRegistry().dispatchHotEvent(event, payload);
120
120
  }
121
+ catch (err) {
122
+ // Defensive safety net for registry regressions. Log only under
123
+ // verbose to avoid noisy dev logs.
124
+ if (envVerbose) {
125
+ console.warn(`[ns-hmr][client] dispatchHotEvent('${event}') threw:`, err?.message ?? err);
126
+ }
127
+ }
128
+ }
129
+ // Trigger a JS-driven full app reload, dispatching `vite:beforeFullReload`
130
+ // first so user-code listeners can react. The registry's full-reload path
131
+ // evicts every loaded app module (ns:module `getLoadedModuleUrls` →
132
+ // `invalidateModules`) and re-imports the dev entry; the
133
+ // `Application.run` patch in root-placeholder converts re-entry into
134
+ // `resetRootView`. Returns `true` if the reload was triggered. Used both
135
+ // by `import.meta.hot.invalidate()` (handled inside the registry) AND by
136
+ // the declined-module check below (where the JS layer makes the decision
137
+ // and asks for the reload).
138
+ function triggerFullReload(_g, message) {
139
+ dispatchHotEvent(_g, 'vite:beforeFullReload', { message });
121
140
  try {
122
- if (verbose && envVerbose) {
123
- console.info(`[ns-hmr-diag][client] invalidateModules calling __nsInvalidateModules urls=${urls.length}`);
141
+ // Fire-and-forget — the reload path is async, but we don't await
142
+ // it here because the module graph is about to be torn down. The
143
+ // HMR cycle's caller treats this as terminal and short-circuits
144
+ // the rest of the cycle.
145
+ getNsHotRegistry().requestFullReload(message);
146
+ }
147
+ catch (err) {
148
+ if (envVerbose) {
149
+ console.warn('[ns-hmr][client] requestFullReload threw:', err?.message ?? err);
124
150
  }
125
- fn.call(null, urls);
126
- if (verbose && envVerbose) {
127
- console.info(`[ns-hmr-diag][client] invalidateModules OK urls=${urls.length}`);
151
+ return false;
152
+ }
153
+ return true;
154
+ }
155
+ // Check if any module being touched by this HMR update has called
156
+ // `import.meta.hot.decline()`. If so, per Vite spec we MUST do a full
157
+ // reload instead of a hot-update — declining means "I refuse to be
158
+ // hot-updated". Returns `true` if a full reload was triggered (caller
159
+ // should short-circuit the rest of the cycle).
160
+ function checkDeclinedAndReload(g, msg, options) {
161
+ // `evictPaths` is the eviction set the dev server computed for this
162
+ // HMR cycle — every module that needs to be re-evaluated. If ANY of
163
+ // those modules declined HMR, the whole cycle has to convert to a
164
+ // full reload. Pass them through verbatim; the registry canonicalizes
165
+ // internally when matching against its declined set.
166
+ const evictPaths = Array.isArray(msg?.evictPaths) ? msg.evictPaths : [];
167
+ let declined = false;
168
+ try {
169
+ declined = getNsHotRegistry().hasDeclined(evictPaths);
170
+ }
171
+ catch (err) {
172
+ if (options.verbose && envVerbose) {
173
+ console.warn('[ns-hmr][client] hasDeclined threw:', err?.message ?? err);
128
174
  }
129
- return true;
175
+ return false;
130
176
  }
131
- catch (error) {
132
- // Real exception path — the runtime hook itself threw. Always
133
- // surfaced for the same reason as the missing-hook warn above.
134
- console.warn('[ns-hmr-diag][client] __nsInvalidateModules threw', error?.message || error);
177
+ if (!declined)
135
178
  return false;
179
+ const filePath = typeof msg?.path === 'string' ? msg.path : '<unknown>';
180
+ const message = `module declined HMR (file=${filePath}, evictPaths=${evictPaths.length})`;
181
+ console.info(`[ns-hmr][decline] ${message} — falling back to full reload`);
182
+ const reloaded = triggerFullReload(g, message);
183
+ if (!reloaded && options.verbose && envVerbose) {
184
+ console.warn('[ns-hmr][client] declined module detected but full reload unavailable; HMR will proceed');
136
185
  }
186
+ return reloaded;
137
187
  }
138
- // Eviction-set size cap for the kickstart.
139
- //
140
- // `__NS_HMR_KICKSTART_MAX_URLS__` is a build-time literal injected
141
- // by `helpers/global-defines.ts` (default 32). It is a pure
142
- // performance gate: the kickstart never affects correctness, so
143
- // skipping it for large fan-out edits simply reverts the runtime to
144
- // sequential `HttpFetchText`. See the doc comment on
145
- // `resolveHmrKickstartMaxUrls` (in global-defines.ts) for the
146
- // rationale and the empirical numbers behind the default.
188
+ // Drain `import.meta.hot.dispose(cb)` callbacks via the JS hot
189
+ // registry before Angular's reboot.
147
190
  //
148
- // The constant is read once at module load (the same pattern used
149
- // for `overlayEnabled`) so each call site is a single inequality
150
- // check rather than a try/typeof. Tests that re-import this module
151
- // see `undefined` and fall back to the default.
152
- const KICKSTART_DEFAULT_MAX_URLS = 32;
153
- const kickstartMaxUrls = (() => {
191
+ // The registry (`hot-context.ts`) owns the dispose map — every call to
192
+ // `import.meta.hot.dispose(cb)` from user code lands there. We pass NO
193
+ // key argument so the registry drains every registered callback across
194
+ // every module, which matches the wholesale-reboot semantics of
195
+ // `__reboot_ng_modules__`: when Angular tears down its component tree
196
+ // and re-bootstraps, every module's accumulated side effects are
197
+ // conceptually being thrown away. (A future per-module HMR client could
198
+ // pass an explicit key list to limit the drain.)
199
+ function runHmrDisposeCallbacks(_g, options) {
200
+ let executed = null;
154
201
  try {
155
- const raw = __NS_HMR_KICKSTART_MAX_URLS__;
156
- if (typeof raw !== 'number')
157
- return KICKSTART_DEFAULT_MAX_URLS;
158
- if (!Number.isFinite(raw))
159
- return Number.POSITIVE_INFINITY;
160
- if (raw < 0)
161
- return KICKSTART_DEFAULT_MAX_URLS;
162
- return Math.floor(raw);
202
+ const result = getNsHotRegistry().runDispose();
203
+ executed = typeof result === 'number' ? result : 0;
163
204
  }
164
- catch {
165
- return KICKSTART_DEFAULT_MAX_URLS;
205
+ catch (err) {
206
+ // Per-callback failures are swallowed inside the registry. If
207
+ // the registry itself throws we MUST NOT take down the HMR cycle.
208
+ if (options.verbose && envVerbose) {
209
+ console.warn('[ns-hmr][client] runDispose threw:', err?.message ?? err);
210
+ }
211
+ return;
166
212
  }
167
- })();
168
- // Decide whether to run the kickstart for a given eviction set.
169
- // Exported for unit testing — callers in this module use the inline
170
- // `evictPaths.length` comparison below for a slightly cheaper
171
- // hot-path.
213
+ // Surface ONE concise log per HMR cycle that actually had disposers
214
+ // to run — verbose-only, like every other client log.
215
+ if (executed && executed > 0 && options.verbose && envVerbose) {
216
+ console.info(`[ns-hmr][dispose] ran ${executed} import.meta.hot.dispose callback${executed === 1 ? '' : 's'} before reboot`);
217
+ }
218
+ }
219
+ // Terminate every live worker before Angular's reboot — fully userland.
172
220
  //
173
- // Semantics:
174
- // - `0` urls → no work to do; skip (returns false).
175
- // - `urls.length <= cap` → kickstart eligible (returns true).
176
- // - `urls.length > cap` → skip kickstart (returns false). V8 falls
177
- // back to per-module synchronous fetches inside its module walk.
178
- // - `cap === 0` → kickstart disabled regardless of size.
179
- // - `cap === Infinity` → kickstart always eligible (no cap).
180
- export function shouldRunKickstart(urlCount, maxUrls = kickstartMaxUrls) {
181
- if (!Number.isFinite(urlCount) || urlCount <= 0)
182
- return false;
183
- if (!Number.isFinite(maxUrls))
184
- return maxUrls > 0;
185
- if (maxUrls <= 0)
186
- return false;
187
- return urlCount <= maxUrls;
221
+ // Drains `globalThis.__NS_HMR_WORKERS__`, the session-wide tracked set fed
222
+ // by the global `Worker` constructor interception the session bootstrap
223
+ // installs before any app/framework/vendor code evaluates
224
+ // (`shared/runtime/worker-tracking.ts`). Because the interception sits on
225
+ // the sole birth path for main-realm workers, the set covers every spawn —
226
+ // `new Worker(new URL(...))`, raw `Worker('~/x.js')`, dynamic-import- and
227
+ // plugin-spawned workers alike. Nested workers are reclaimed transitively:
228
+ // the runtime cascades `worker.terminate()` through each worker's children.
229
+ //
230
+ // Tolerant of:
231
+ // * Missing global — non-worker apps have no Set; we no-op.
232
+ // * `terminate()` throwing — the runtime can throw on already-dead
233
+ // workers; the sweep counts per-entry failures so subsequent
234
+ // terminations and the reboot itself still proceed.
235
+ //
236
+ // The Set is always cleared after the sweep so producer-side bookkeeping
237
+ // doesn't grow unbounded across HMR cycles.
238
+ function terminateTrackedWorkers(g, options) {
239
+ const { terminated, failed, total } = sweepTrackedWorkers(g);
240
+ // Surface ONE concise log per HMR cycle when there was actually work
241
+ // to do — verbose-only, like every other client log: the dev terminal
242
+ // stays quiet by default.
243
+ if ((terminated > 0 || failed > 0) && options.verbose && envVerbose) {
244
+ console.info(`[ns-hmr][workers] terminated ${terminated}/${total} tracked worker${total === 1 ? '' : 's'} before reboot`);
245
+ }
188
246
  }
189
- function kickstartHmrPrefetch(urls, verbose) {
247
+ // Narrow an unknown eviction-list entry to a fetchable http(s) URL. Shared by
248
+ // the reboot path (refreshAngularBootstrapOptions) and the leaf re-import
249
+ // fallback so the two stay in lockstep on what counts as a valid evict URL.
250
+ const isHttpUrl = (u) => typeof u === 'string' && /^https?:\/\//.test(u);
251
+ function invalidateModules(urls, verbose) {
190
252
  if (!urls || !urls.length)
191
- return null;
192
- const g = globalThis;
193
- const fn = g.__nsKickstartHmrPrefetch;
253
+ return false;
254
+ const fn = readNsRuntimeDevHostApi(globalThis).invalidateModules;
194
255
  if (typeof fn !== 'function') {
195
- if (verbose && envVerbose) {
196
- console.info(`[hmr-angular] runtime missing __nsKickstartHmrPrefetch; serial fetches will be used. urls=${urls.length}`);
197
- }
198
- return null;
256
+ console.warn(`[ns-hmr][client] runtime missing ns:module invalidateModules (runtime/vite version mismatch?); update cannot apply. evict=${urls.length}`);
257
+ return false;
199
258
  }
200
259
  try {
201
- // Concurrency cap of 16 matches the runtime's documented
202
- // default for the kickstart BFS. Timeout at 10s tracks the
203
- // runtime's `HttpFetchText` retry envelope so we don't
204
- // hold the JS thread forever on a stalled dev server.
205
- const result = fn.call(null, urls.slice(), { maxConcurrent: 16, timeoutMs: 10000 });
206
- if (result && typeof result === 'object') {
207
- const ok = !!result.ok;
208
- const fetched = typeof result.fetched === 'number' ? result.fetched : 0;
209
- const ms = typeof result.ms === 'number' ? result.ms : 0;
210
- return { ok, fetched, ms };
260
+ if (verbose && envVerbose) {
261
+ console.info(`[ns-hmr][client] invalidateModules calling ns:module invalidateModules urls=${urls.length}`);
211
262
  }
212
- return null;
213
- }
214
- catch (error) {
263
+ fn.call(null, urls.slice());
215
264
  if (verbose && envVerbose) {
216
- console.warn('[hmr-angular] __nsKickstartHmrPrefetch threw', error?.message || error);
265
+ console.info(`[ns-hmr][client] invalidateModules OK urls=${urls.length}`);
217
266
  }
218
- return null;
267
+ return true;
268
+ }
269
+ catch (error) {
270
+ // Real exception path — the runtime hook itself threw. Always
271
+ // surfaced for the same reason as the missing-hook warn above.
272
+ console.warn('[ns-hmr][client] ns:module invalidateModules threw', error?.message || error);
273
+ return false;
219
274
  }
220
275
  }
221
276
  function getAngularBootstrapEntryCandidates(msg) {
222
- const root = typeof __NS_APP_ROOT_VIRTUAL__ === 'string' && __NS_APP_ROOT_VIRTUAL__ ? __NS_APP_ROOT_VIRTUAL__ : '/src';
277
+ // Define substitution does not reach this raw-served file; prefer the
278
+ // globalThis seed from the entry's defines-seed module ('app/'-rooted
279
+ // projects would otherwise get the wrong '/src' default).
280
+ const root = (typeof __NS_APP_ROOT_VIRTUAL__ === 'string' && __NS_APP_ROOT_VIRTUAL__) || (typeof getGlobalScope().__NS_APP_ROOT_VIRTUAL__ === 'string' && getGlobalScope().__NS_APP_ROOT_VIRTUAL__) || '/src';
223
281
  // Server announces the canonical bootstrap entry as
224
282
  // `importerEntry`, computed from `package.json#main`. Fall back to
225
283
  // the legacy `entryCandidates` array (for older servers) and finally
@@ -267,7 +325,7 @@ export async function refreshAngularBootstrapOptions(msg, options) {
267
325
  // `g_moduleRegistry` so V8's subsequent `import(entry)` walks the
268
326
  // dep graph and re-fetches ONLY those modules. Everything else stays
269
327
  // hot in the cache.
270
- const evictPaths = Array.isArray(msg?.evictPaths) ? msg.evictPaths.filter((u) => typeof u === 'string' && /^https?:\/\//.test(u)) : [];
328
+ const evictPaths = Array.isArray(msg?.evictPaths) ? msg.evictPaths.filter(isHttpUrl) : [];
271
329
  // Diagnostic: log eviction set client-side so we can verify what
272
330
  // the runtime is being asked to drop. Up to 32 entries are sampled
273
331
  // so large constants edits don't swamp the console. Gated behind
@@ -275,12 +333,12 @@ export async function refreshAngularBootstrapOptions(msg, options) {
275
333
  // so the lines stay silent on normal saves.
276
334
  if (options.verbose && envVerbose) {
277
335
  const _path = typeof msg?.path === 'string' ? msg.path : '(unknown)';
278
- console.info(`[ns-hmr-diag][client] received ns:angular-update path=${_path} evictPaths.length=${evictPaths.length} importerEntry=${msg?.importerEntry ?? '(none)'}`);
336
+ console.info(`[ns-hmr][client] received ns:angular-update path=${_path} evictPaths.length=${evictPaths.length} importerEntry=${msg?.importerEntry ?? '(none)'}`);
279
337
  if (evictPaths.length) {
280
338
  const sample = evictPaths.slice(0, 32);
281
- console.info(`[ns-hmr-diag][client] evictPaths firstN=`, sample);
339
+ console.info(`[ns-hmr][client] evictPaths firstN=`, sample);
282
340
  if (evictPaths.length > sample.length) {
283
- console.info(`[ns-hmr-diag][client] evictPaths hidden=${evictPaths.length - sample.length}`);
341
+ console.info(`[ns-hmr][client] evictPaths hidden=${evictPaths.length - sample.length}`);
284
342
  }
285
343
  }
286
344
  }
@@ -295,61 +353,19 @@ export async function refreshAngularBootstrapOptions(msg, options) {
295
353
  });
296
354
  const evicted = invalidateModules(evictPaths, options.verbose);
297
355
  if (options.verbose && envVerbose) {
298
- console.info(`[ns-hmr-diag][client] evict count=${evictPaths.length} ok=${evicted ? 'yes' : 'no'}`);
356
+ console.info(`[ns-hmr][client] evict count=${evictPaths.length} ok=${evicted ? 'yes' : 'no'}`);
299
357
  }
300
- // Parallel HTTP prefetch for the freshly-evicted modules.
301
- //
302
- // Order matters here: the kickstart MUST run after the eviction so
303
- // that it actually re-populates `g_prefetchCache` for the modules
304
- // V8 will ask for. If we kickstarted before the eviction, every URL
305
- // would skip on the "already cached" check (the walk consumes
306
- // destructively but the prior non-evicted modules sit in V8's
307
- // `g_moduleRegistry`, not the prefetch cache).
308
- //
309
- // We only kickstart when the eviction succeeded, because the
310
- // fallback path (legacy URL-versioning, see `useStableUrls = evicted`
311
- // below) doesn't go through canonical /ns/m URLs and the runtime
312
- // would not match its prefetch cache lookups against the version-
313
- // prefixed forms V8 will end up requesting. Better to skip the
314
- // optimization than risk a confusing partial cache hit.
315
- //
316
- // `shouldRunKickstart` gates large eviction sets out of the
317
- // parallel wave. A `.ts` file with deep inverse-dep fan-in
318
- // (constants files, design-system enums) can produce a
319
- // 200–300-URL closure that overwhelms Vite's single-threaded
320
- // transform pipeline. The kickstart fan-out then makes the cycle
321
- // 5–8× slower than letting V8 fetch sequentially as it walks the
322
- // real forward path. The cap (default 32, override with
323
- // `NS_VITE_KICKSTART_MAX_URLS`) keeps component-shaped closures
324
- // (typically 5–30 URLs) on the fast path. Correctness is
325
- // unaffected — V8's per-module synchronous fetch is the same fall-
326
- // back code path the runtime has always used.
327
- if (evicted && evictPaths.length > 0) {
328
- if (shouldRunKickstart(evictPaths.length)) {
329
- const result = kickstartHmrPrefetch(evictPaths, options.verbose);
330
- if (options.verbose && envVerbose && result) {
331
- console.info(`[ns-hmr][angular] kickstart urls=${evictPaths.length} fetched=${result.fetched} ok=${result.ok ? 'yes' : 'no'} ms=${result.ms}`);
332
- }
333
- }
334
- else if (options.verbose && envVerbose) {
335
- console.info(`[ns-hmr][angular] kickstart skipped urls=${evictPaths.length} cap=${Number.isFinite(kickstartMaxUrls) ? kickstartMaxUrls : 'Infinity'} (eviction set too large; falling back to sequential fetch)`);
336
- }
337
- }
338
- // URL strategy:
339
- //
340
- // * `evicted=true` → modern runtime accepted the eviction; we
341
- // re-import the entry under its STABLE canonical URL. V8's
342
- // registry no longer holds the evicted modules so the import
343
- // triggers fresh fetches for them; the rest of the graph is a
344
- // cache hit.
345
- // * `evicted=false` → either we have no eviction set (older server)
346
- // or the runtime lacks `__nsInvalidateModules` (older runtime).
347
- // Fall back to the legacy `__ns_hmr__/v<version>/` URL pattern so
348
- // V8 sees a fresh URL and re-fetches the entry. The runtime
349
- // canonicalizer collapses the path back to the stable key, which
350
- // keeps cache identity consistent across saves.
351
- const versionRaw = typeof msg?.version === 'number' ? msg.version : 0;
352
- const useStableUrls = evicted;
358
+ // No client-side prefetch is needed after the eviction: the runtime's
359
+ // async module-graph walk fetches the evicted modules concurrently on
360
+ // background threads when the re-import below triggers it.
361
+ // URL strategy: always the STABLE canonical URL. The eviction removed
362
+ // the changed modules from V8's registry (and armed the runtime's
363
+ // bust-next-fetch nonce), so re-importing the entry under its
364
+ // canonical URL triggers fresh fetches for exactly the evicted
365
+ // modules; the rest of the graph is a cache hit. Never version or
366
+ // tag the URL — the runtime treats the literal URL as module
367
+ // identity, so a tagged re-import would mint a second module
368
+ // identity instead of refreshing the first.
353
369
  let lastError;
354
370
  // 'reimporting' is the entry point for the long tail of an HMR
355
371
  // cycle: V8 walks the freshly-evicted graph and the iOS runtime
@@ -360,7 +376,7 @@ export async function refreshAngularBootstrapOptions(msg, options) {
360
376
  detail: 'Re-importing Angular bootstrap entry',
361
377
  });
362
378
  for (const entry of getAngularBootstrapEntryCandidates(msg)) {
363
- const url = useStableUrls ? `${origin}/ns/m${entry}` : versionRaw ? `${origin}/ns/m/__ns_hmr__/v${versionRaw}${entry}` : `${origin}/ns/m${entry}`;
379
+ const url = `${origin}/ns/m${entry}`;
364
380
  try {
365
381
  g.__NS_ANGULAR_HMR_REGISTER_ONLY__ = true;
366
382
  await importAngularBootstrapEntry(url);
@@ -425,6 +441,31 @@ export async function handleAngularHotUpdateMessage(msg, options) {
425
441
  setUpdateOverlayStage('received', { detail: overlayDetail });
426
442
  try {
427
443
  const g = globalThis;
444
+ // Vite-spec entry: `vite:beforeUpdate` fires as soon as the
445
+ // client receives an update message, BEFORE any work begins
446
+ // (refresh, dispose, reboot). User listeners can use this to
447
+ // pause animations, cancel in-flight requests, etc. Payload
448
+ // matches Vite's `Update[]` shape loosely — `path` is the
449
+ // canonical changed file, `evictPaths` is the eviction
450
+ // closure the server already computed.
451
+ const updatePayload = {
452
+ type: 'js-update',
453
+ path: typeof msg?.path === 'string' ? msg.path : null,
454
+ evictPaths: Array.isArray(msg?.evictPaths) ? msg.evictPaths : [],
455
+ timestamp: t0,
456
+ };
457
+ dispatchHotEvent(g, 'vite:beforeUpdate', { updates: [updatePayload] });
458
+ // Declined-module short-circuit. If any updated module called
459
+ // `import.meta.hot.decline()`, we MUST do a full reload per
460
+ // Vite spec rather than the hot-update path. `triggerFullReload`
461
+ // also dispatches `vite:beforeFullReload`. The reload tears the
462
+ // JS realm down so we don't need to do any further bookkeeping
463
+ // here — return early.
464
+ if (checkDeclinedAndReload(g, msg, options)) {
465
+ tEnd = Date.now();
466
+ emitTiming(true);
467
+ return true;
468
+ }
428
469
  // Prefer __reboot_ng_modules__ — it properly disposes existing modules,
429
470
  // re-bootstraps Angular inside NgZone, and sets the root view internally.
430
471
  // __NS_ANGULAR_BOOTSTRAP__ is exposed as a secondary signal that the
@@ -433,8 +474,23 @@ export async function handleAngularHotUpdateMessage(msg, options) {
433
474
  const reboot = g.__reboot_ng_modules__;
434
475
  if (typeof reboot === 'function') {
435
476
  if (options.verbose && envVerbose) {
436
- console.info('[ns-hmr-diag][client] calling __reboot_ng_modules__');
477
+ console.info('[ns-hmr][client] calling __reboot_ng_modules__');
478
+ }
479
+ // Pre-import reset: clear Angular's `GENERATED_COMP_IDS` map BEFORE
480
+ // the changed component modules are re-imported. If we don't, every
481
+ // touched component's `ɵɵdefineComponent` call hashes to the same
482
+ // id as its predecessor (selectors + className haven't changed),
483
+ // hits a "previousCompDefType !== componentDef.type" collision, and
484
+ // surfaces NG0912 "Component ID generation collision detected".
485
+ // The map is cleared again post-reboot as a safety net, but doing
486
+ // it once here suppresses the warning at the source.
487
+ try {
488
+ const preResetCompiled = g.__reset_ng_compiled_components__;
489
+ if (typeof preResetCompiled === 'function') {
490
+ preResetCompiled();
491
+ }
437
492
  }
493
+ catch { }
438
494
  await refreshAngularBootstrapOptions(msg, options);
439
495
  tAfterRefresh = Date.now();
440
496
  try {
@@ -445,6 +501,40 @@ export async function handleAngularHotUpdateMessage(msg, options) {
445
501
  g.__NS_DEV_RESET_IN_PROGRESS__ = true;
446
502
  }
447
503
  catch { }
504
+ // Two-step pre-reboot cleanup. Order matters: dispose runs
505
+ // FIRST so user-code disposers see a still-live runtime
506
+ // (sockets, workers, etc.) and can issue graceful "I'm
507
+ // going away" messages; then we hard-terminate any worker
508
+ // the user didn't manually clean up.
509
+ //
510
+ // Step 1 — `import.meta.hot.dispose(cb)` callbacks
511
+ // ────────────────────────────────────────────────
512
+ // The JS hot registry (`hot-context.ts`) walks its
513
+ // per-module dispose map — populated by
514
+ // `import.meta.hot.dispose(cb)` — and invokes every
515
+ // callback with that module's `hot.data` object, matching
516
+ // the Vite spec.
517
+ //
518
+ // This is the standards-compliant cleanup hook every Vite
519
+ // user already knows. Apps register their intervals,
520
+ // listeners, sockets, store subscriptions, etc. via
521
+ // `import.meta.hot.dispose(...)` and they're guaranteed to
522
+ // fire before the next Angular reboot — no NS-specific
523
+ // knowledge required.
524
+ runHmrDisposeCallbacks(g, options);
525
+ // Step 2 — worker auto-terminate (defence in depth)
526
+ // ───────────────────────────────────────────────────
527
+ // Even with perfect dispose() coverage, workers spawned
528
+ // from constructors that re-run on Angular reboot (e.g.
529
+ // `new Worker(...)` inside `AppComponent`'s constructor)
530
+ // don't fire dispose for `app.component.ts` when only
531
+ // `login.component.html` changes — `app.component.ts`
532
+ // isn't being replaced, so its disposers don't run per
533
+ // Vite spec. The session-wide tracked set doesn't care
534
+ // about module boundaries: the `Worker` constructor
535
+ // interception recorded every spawn, and this sweep
536
+ // terminates them all.
537
+ terminateTrackedWorkers(g, options);
448
538
  // 'rebooting' marks the long tail of the cycle: NgZone
449
539
  // teardown, module re-instantiation, and resetRootView.
450
540
  // The detail line shows refresh-so-far ms so a user can
@@ -452,6 +542,12 @@ export async function handleAngularHotUpdateMessage(msg, options) {
452
542
  setUpdateOverlayStage('rebooting', {
453
543
  detail: `Re-bootstrapping Angular (refresh ${Math.max(0, tAfterRefresh - t0)}ms)`,
454
544
  });
545
+ // Tailwind content CSS belongs to this same save. Fetch and install it
546
+ // inside the serialized Angular cycle, immediately before constructing
547
+ // the replacement tree. This prevents a standalone CSS message from
548
+ // racing teardown, while allowing the new views to resolve both existing
549
+ // bindings and newly generated utility selectors during construction.
550
+ await applyDeferredCssUpdates(msg);
455
551
  try {
456
552
  reboot(true);
457
553
  }
@@ -463,6 +559,12 @@ export async function handleAngularHotUpdateMessage(msg, options) {
463
559
  }
464
560
  tEnd = Date.now();
465
561
  emitTiming(true);
562
+ // Vite-spec exit: `vite:afterUpdate` fires after the update
563
+ // has been successfully applied. User code can re-attach
564
+ // any state torn down by `vite:beforeUpdate` (resume
565
+ // animations, re-fetch, etc.). Same payload shape as
566
+ // `vite:beforeUpdate` so listeners can correlate.
567
+ dispatchHotEvent(g, 'vite:afterUpdate', { updates: [updatePayload] });
466
568
  // 'complete' surfaces the wall-clock total so a user gets a
467
569
  // single-glance confirmation matching the [ns-hmr][angular]
468
570
  // log line in the terminal. The overlay auto-hides shortly
@@ -472,13 +574,65 @@ export async function handleAngularHotUpdateMessage(msg, options) {
472
574
  });
473
575
  return true;
474
576
  }
577
+ // Reached only when the NgModule reboot path above was skipped — i.e.
578
+ // `g.__reboot_ng_modules__` was not a function at the time this update
579
+ // arrived, so no full re-bootstrap ran. (That handler is installed by
580
+ // `runNativeScriptAngularApp()`, so this is NOT about how the app boots;
581
+ // it covers the window where the handler isn't registered yet, or any
582
+ // update that never wires one up.) Fall back to the standard Vite
583
+ // leaf-module path: evict + re-import the changed module(s) so their
584
+ // top-level side-effects and `import.meta.hot.accept` callbacks re-run
585
+ // WITHOUT a full reboot. The server narrows leaf edits (no @Component/
586
+ // @Directive/@Pipe/@Injectable/@NgModule decorator) to just the changed
587
+ // file, so this is cheap. This is what makes self-accepting utility
588
+ // modules (e.g. a live-tuning module that posts values to native on
589
+ // evaluation) hot-reload at all — without it they were silently dropped
590
+ // here.
591
+ try {
592
+ const origin = (typeof g.__NS_HTTP_ORIGIN__ === 'string' ? g.__NS_HTTP_ORIGIN__ : '').replace(/\/$/, '');
593
+ let urls = Array.isArray(msg?.evictPaths) ? msg.evictPaths.filter(isHttpUrl) : [];
594
+ // Derive the canonical /ns/m/<rel> URL from msg.path when the server
595
+ // sent no evictPaths (V8 keys app modules by their extensionless URL).
596
+ if (!urls.length && typeof msg?.path === 'string' && origin) {
597
+ const rel = msg.path.replace(/^\//, '').replace(/\.(?:[mc]?[jt]sx?)$/i, '');
598
+ urls = [`${origin}/ns/m/${rel}`];
599
+ }
600
+ if (urls.length) {
601
+ setUpdateOverlayStage('reimporting', { detail: `Re-importing ${urls.length} module${urls.length === 1 ? '' : 's'}` });
602
+ invalidateModules(urls, options.verbose);
603
+ const nonce = (typeof g.__NS_HMR_IMPORT_NONCE__ === 'number' ? g.__NS_HMR_IMPORT_NONCE__ : 0) + 1;
604
+ g.__NS_HMR_IMPORT_NONCE__ = nonce;
605
+ let reimported = 0;
606
+ for (const u of urls) {
607
+ try {
608
+ await importAngularBootstrapEntry(`${u}${u.includes('?') ? '&' : '?'}hmr=${nonce}`);
609
+ reimported++;
610
+ }
611
+ catch (e) {
612
+ if (options.verbose) {
613
+ console.warn('[ns-hmr][leaf] re-import failed', u, (e && e.message) || e);
614
+ }
615
+ }
616
+ }
617
+ const ok = reimported > 0;
618
+ tEnd = Date.now();
619
+ emitTiming(ok, ok ? 'leaf-reimport' : 'leaf-reimport-failed');
620
+ hideUpdateOverlay();
621
+ return ok;
622
+ }
623
+ }
624
+ catch (e) {
625
+ if (options.verbose) {
626
+ console.warn('[ns-hmr][leaf] fallback threw', (e && e.message) || e);
627
+ }
628
+ }
475
629
  if (options.verbose && envVerbose) {
476
630
  console.warn('[hmr-angular] No Angular HMR handler found. Ensure runNativeScriptAngularApp() has been called.');
477
631
  }
478
632
  tEnd = Date.now();
479
633
  emitTiming(false, 'no-reboot-handler');
480
- // No reboot handler → we can't apply the update; hide the
481
- // overlay rather than leaving stale progress on screen.
634
+ // No reboot handler and nothing to re-import → hide the overlay rather
635
+ // than leaving stale progress on screen.
482
636
  hideUpdateOverlay();
483
637
  }
484
638
  catch (error) {
@@ -486,7 +640,19 @@ export async function handleAngularHotUpdateMessage(msg, options) {
486
640
  console.warn('[hmr-angular] failed to handle update', (error && error.message) || error);
487
641
  }
488
642
  tEnd = Date.now();
489
- emitTiming(false, (error && error.message) || String(error));
643
+ const errorMessage = (error && error.message) || String(error);
644
+ emitTiming(false, errorMessage);
645
+ // Vite-spec error event — fires on any HMR cycle that throws.
646
+ // Payload shape mirrors Vite's `ErrorPayload`: `err: { message,
647
+ // stack? }` plus optional `path`. Soft-fails if no listeners.
648
+ dispatchHotEvent(globalThis, 'vite:error', {
649
+ type: 'error',
650
+ err: {
651
+ message: errorMessage,
652
+ stack: (error && error.stack) || undefined,
653
+ },
654
+ path: typeof msg?.path === 'string' ? msg.path : undefined,
655
+ });
490
656
  // Errors → drop the overlay so the user isn't left looking
491
657
  // at indefinite progress; the underlying error is already
492
658
  // logged above (and surfaced via Vite's standard error