Skip to content

Commit 277140f

Browse files
committed
feat: vite hmr wip
1 parent 62613cb commit 277140f

File tree

10 files changed

+91
-833
lines changed

10 files changed

+91
-833
lines changed

packages/angular/src/lib/application.ts

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as AngularCore from '@angular/core';
12
import { ApplicationRef, EnvironmentProviders, NgModuleRef, NgZone, PlatformRef, Provider } from '@angular/core';
23
import {
34
Application,
@@ -18,6 +19,11 @@ import { NativeScriptLoadingService } from './loading.service';
1819
import { APP_ROOT_VIEW, DISABLE_ROOT_VIEW_HANDLING, NATIVESCRIPT_ROOT_MODULE_ID } from './tokens';
1920
import { 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+
2127
export 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) {

packages/zone-js/dist/connectivity.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

packages/zone-js/dist/core.ts

Lines changed: 0 additions & 59 deletions
This file was deleted.

packages/zone-js/dist/events.ts

Lines changed: 0 additions & 69 deletions
This file was deleted.

packages/zone-js/dist/index.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/zone-js/dist/nativescript-globals.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

packages/zone-js/dist/pre-zone-polyfills.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

packages/zone-js/dist/trace-error.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)