@nativescript/vite 8.0.0-alpha.6 → 8.0.0-alpha.61

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