@nativescript/vite 8.0.0-alpha.7 → 8.0.0-alpha.71

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