1+ import * as AngularCore from '@angular/core' ;
12import { ApplicationRef , EnvironmentProviders , NgModuleRef , NgZone , PlatformRef , Provider } from '@angular/core' ;
23import {
34 Application ,
@@ -18,6 +19,11 @@ import { NativeScriptLoadingService } from './loading.service';
1819import { APP_ROOT_VIEW , DISABLE_ROOT_VIEW_HANDLING , NATIVESCRIPT_ROOT_MODULE_ID } from './tokens' ;
1920import { NativeScriptDebug } from './trace' ;
2021
22+ // Store the original @angular /core module for HMR
23+ // This is crucial because HMR imports a fresh @angular /core with empty LView tracking
24+ // We need to use the original one that has the registered LViews
25+ ( globalThis as any ) . __NS_ANGULAR_CORE__ = AngularCore ;
26+
2127export interface AppLaunchView extends LayoutBase {
2228 // called when the animation is to begin
2329 startAnimation ?: ( ) => void ;
@@ -236,23 +242,28 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
236242 let launchEventDone = true ;
237243 let targetRootView : View = null ;
238244 const setRootView = ( ref : NgModuleRef < T | K > | ApplicationRef | View ) => {
245+ console . log ( '[ng-hmr] setRootView called, bootstrapId:' , bootstrapId , 'ref type:' , ref ?. constructor ?. name ) ;
239246 if ( bootstrapId === - 1 ) {
240247 // treat edge cases
248+ console . log ( '[ng-hmr] setRootView: bootstrapId is -1, returning early' ) ;
241249 return ;
242250 }
243251 if ( ref instanceof NgModuleRef || ref instanceof ApplicationRef ) {
244252 if ( ref . injector . get ( DISABLE_ROOT_VIEW_HANDLING , false ) ) {
253+ console . log ( '[ng-hmr] setRootView: DISABLE_ROOT_VIEW_HANDLING is true, returning' ) ;
245254 return ;
246255 }
247256 } else {
248257 if ( ref [ '__disable_root_view_handling' ] ) {
258+ console . log ( '[ng-hmr] setRootView: __disable_root_view_handling is true, returning' ) ;
249259 return ;
250260 }
251261 }
252262 Application . getRootView ( ) ?. _closeAllModalViewsInternal ( ) ; // cleanup old rootview
253263 NativeScriptDebug . bootstrapLog ( `Setting RootView ${ launchEventDone ? 'outside of' : 'during' } launch event` ) ;
254264 // TODO: check for leaks when root view isn't properly destroyed
255265 if ( ref instanceof View ) {
266+ console . log ( '[ng-hmr] setRootView: ref is View, launchEventDone:' , launchEventDone ) ;
256267 if ( NativeScriptDebug . isLogEnabled ( ) ) {
257268 NativeScriptDebug . bootstrapLog ( `Setting RootView to ${ ref } ` ) ;
258269 }
@@ -267,14 +278,35 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
267278 }
268279 const view = ref . injector . get ( APP_ROOT_VIEW ) as AppHostView | View ;
269280 const newRoot = view instanceof AppHostView ? view . content : view ;
281+ console . log ( '[ng-hmr] setRootView: view from injector:' , view ?. constructor ?. name , 'newRoot:' , newRoot ?. constructor ?. name ) ;
282+ console . log ( '[ng-hmr] setRootView: launchEventDone:' , launchEventDone , 'embedded:' , options . embedded ) ;
270283 if ( NativeScriptDebug . isLogEnabled ( ) ) {
271284 NativeScriptDebug . bootstrapLog ( `Setting RootView to ${ newRoot } ` ) ;
272285 }
273286 if ( options . embedded ) {
287+ console . log ( '[ng-hmr] setRootView: calling Application.run (embedded)' ) ;
274288 Application . run ( { create : ( ) => newRoot } ) ;
275289 } else if ( launchEventDone ) {
290+ console . log ( '[ng-hmr] setRootView: calling Application.resetRootView' ) ;
291+ console . log ( '[ng-hmr] setRootView: newRoot details:' , {
292+ type : newRoot ?. constructor ?. name ,
293+ nativeView : ! ! newRoot ?. nativeView ,
294+ parent : newRoot ?. parent ?. constructor ?. name ,
295+ childCount : ( newRoot as any ) ?. getChildrenCount ?.( ) ?? 'N/A' ,
296+ } ) ;
276297 Application . resetRootView ( { create : ( ) => newRoot } ) ;
298+ console . log ( '[ng-hmr] setRootView: Application.resetRootView returned' ) ;
299+ // Check root view after reset
300+ setTimeout ( ( ) => {
301+ const currentRoot = Application . getRootView ( ) ;
302+ console . log ( '[ng-hmr] setRootView: after reset, getRootView:' , {
303+ type : currentRoot ?. constructor ?. name ,
304+ nativeView : ! ! currentRoot ?. nativeView ,
305+ childCount : ( currentRoot as any ) ?. getChildrenCount ?.( ) ?? 'N/A' ,
306+ } ) ;
307+ } , 100 ) ;
277308 } else {
309+ console . log ( '[ng-hmr] setRootView: setting targetRootView (launch in progress)' ) ;
278310 targetRootView = newRoot ;
279311 }
280312 } ;
@@ -286,8 +318,10 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
286318 setRootView ( errorTextBox ) ;
287319 } ;
288320 const bootstrapRoot = ( reason : NgModuleReason ) => {
321+ console . log ( '[ng-hmr] bootstrapRoot called, reason:' , reason ) ;
289322 try {
290323 bootstrapId = Date . now ( ) ;
324+ console . log ( '[ng-hmr] bootstrapRoot: new bootstrapId:' , bootstrapId ) ;
291325 const currentBootstrapId = bootstrapId ;
292326 let bootstrapped = false ;
293327 let onMainBootstrap = ( ) => {
@@ -297,20 +331,70 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
297331 ( ) =>
298332 options . appModuleBootstrap ( reason ) . then (
299333 ( ref ) => {
334+ console . log ( '[ng-hmr] appModuleBootstrap resolved, ref:' , ref ?. constructor ?. name ) ;
335+ console . log ( '[ng-hmr] currentBootstrapId:' , currentBootstrapId , 'bootstrapId:' , bootstrapId ) ;
300336 if ( currentBootstrapId !== bootstrapId ) {
301337 // this module is old and not needed anymore
302338 // this may happen when developer uses async app initializer and the user exits the app before this bootstraps
339+ console . log ( '[ng-hmr] bootstrap ID mismatch, destroying ref' ) ;
303340 ref . destroy ( ) ;
304341 return ;
305342 }
306343 mainModuleRef = ref ;
344+
345+ // Expose ApplicationRef for HMR to trigger change detection
346+ // Check for ApplicationRef by duck-typing since instanceof can fail across module realms
347+ const refAny = ref as any ;
348+ const isAppRef = refAny && typeof refAny . tick === 'function' && Array . isArray ( refAny . components ) ;
349+ console . log ( '[ng-hmr] ref type check: isAppRef=' , isAppRef , 'has tick=' , typeof refAny ?. tick === 'function' , 'has components=' , Array . isArray ( refAny ?. components ) ) ;
350+
351+ if ( isAppRef ) {
352+ global [ '__NS_ANGULAR_APP_REF__' ] = ref ;
353+ // Mark boot complete for the HMR system
354+ global [ '__NS_HMR_BOOT_COMPLETE__' ] = true ;
355+
356+ // Register bootstrapped components for HMR lookup
357+ if ( ! global [ '__NS_ANGULAR_COMPONENTS__' ] ) {
358+ global [ '__NS_ANGULAR_COMPONENTS__' ] = { } ;
359+ }
360+ // Get the component class from the first bootstrapped component
361+ console . log ( '[ng-hmr] ApplicationRef components count:' , refAny . components ?. length ) ;
362+ if ( refAny . components && refAny . components . length > 0 ) {
363+ const componentRef = refAny . components [ 0 ] ;
364+ console . log ( '[ng-hmr] componentRef:' , componentRef ?. constructor ?. name ) ;
365+ console . log ( '[ng-hmr] componentRef.componentType:' , componentRef ?. componentType ?. name ) ;
366+
367+ // For Angular 17+ standalone components, the component type is on componentRef.componentType
368+ // For older Angular, try componentRef.instance.constructor
369+ let componentType = componentRef ?. componentType ;
370+ if ( ! componentType && componentRef ?. instance ) {
371+ componentType = componentRef . instance . constructor ;
372+ }
373+
374+ if ( componentType && componentType . name ) {
375+ global [ '__NS_ANGULAR_COMPONENTS__' ] [ componentType . name ] = componentType ;
376+ console . log ( '[ng-hmr] Registered component for HMR:' , componentType . name ) ;
377+ } else {
378+ console . log ( '[ng-hmr] Could not get componentType name' ) ;
379+ }
380+ } else {
381+ console . log ( '[ng-hmr] No components in ApplicationRef' ) ;
382+ }
383+ } else {
384+ const appRef = ref . injector . get ( ApplicationRef , null ) ;
385+ if ( appRef ) {
386+ global [ '__NS_ANGULAR_APP_REF__' ] = appRef ;
387+ // Mark boot complete for the HMR system
388+ global [ '__NS_HMR_BOOT_COMPLETE__' ] = true ;
389+ }
390+ }
307391
308- ( ref instanceof ApplicationRef ? ref . components [ 0 ] : ref ) . onDestroy (
392+ ( isAppRef ? refAny . components [ 0 ] : ref ) . onDestroy (
309393 ( ) => ( mainModuleRef = mainModuleRef === ref ? null : mainModuleRef ) ,
310394 ) ;
311395 updatePlatformRef ( ref , reason ) ;
312396 const styleTag = ref . injector . get ( NATIVESCRIPT_ROOT_MODULE_ID ) ;
313- ( ref instanceof ApplicationRef ? ref . components [ 0 ] : ref ) . onDestroy ( ( ) => {
397+ ( isAppRef ? refAny . components [ 0 ] : ref ) . onDestroy ( ( ) => {
314398 removeTaggedAdditionalCSS ( styleTag ) ;
315399 } ) ;
316400 bootstrapped = true ;
@@ -481,11 +565,16 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
481565 disposePlatform ( 'hotreload' ) ;
482566 } ;
483567 global [ '__reboot_ng_modules__' ] = ( shouldDisposePlatform : boolean = false ) => {
568+ console . log ( '[ng-hmr] __reboot_ng_modules__ called, shouldDisposePlatform:' , shouldDisposePlatform ) ;
569+ console . log ( '[ng-hmr] current bootstrapId:' , bootstrapId , 'mainModuleRef:' , ! ! mainModuleRef ) ;
484570 disposeLastModules ( 'hotreload' ) ;
571+ console . log ( '[ng-hmr] after disposeLastModules, bootstrapId:' , bootstrapId ) ;
485572 if ( shouldDisposePlatform ) {
486573 disposePlatform ( 'hotreload' ) ;
487574 }
575+ console . log ( '[ng-hmr] calling bootstrapRoot...' ) ;
488576 bootstrapRoot ( 'hotreload' ) ;
577+ console . log ( '[ng-hmr] bootstrapRoot returned, new bootstrapId:' , bootstrapId ) ;
489578 } ;
490579
491580 if ( isWebpackHot ) {
0 commit comments