Skip to content

Commit 228eb3d

Browse files
committed
feat: hmr logs gated by hmrTraceCategory
1 parent e1ec30d commit 228eb3d

5 files changed

Lines changed: 125 additions & 86 deletions

File tree

packages/angular/src/lib/application.ts

Lines changed: 102 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,9 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
272272
cleared > 0 ||
273273
(clearedLocation && (clearedLocation.outlets > 0 || clearedLocation.states > 0 || clearedLocation.callbacks > 0 || clearedLocation.hadUrlTree))
274274
) {
275-
console.log('[ng-hmr] cleared Angular route caches before reboot:', {
276-
detachedViews: clearedDetached,
277-
locationState: clearedLocation,
278-
routeFields: cleared,
279-
});
275+
if (NativeScriptDebug.isLogEnabled()) {
276+
NativeScriptDebug.hmrLog(`cleared Angular route caches before reboot: detachedViews=${clearedDetached} routeFields=${cleared} locationState=${JSON.stringify(clearedLocation)}`);
277+
}
280278
}
281279
} catch {}
282280
};
@@ -305,29 +303,38 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
305303
}, 0);
306304
};
307305
const setRootView = (ref: NgModuleRef<T | K> | ApplicationRef | View) => {
308-
console.log('[ng-hmr] setRootView called, bootstrapId:', bootstrapId, 'ref type:', ref?.constructor?.name);
306+
const traceEnabled = NativeScriptDebug.isLogEnabled();
307+
if (traceEnabled) {
308+
NativeScriptDebug.hmrLog(`setRootView called bootstrapId=${bootstrapId} refType=${ref?.constructor?.name}`);
309+
}
309310
if (bootstrapId === -1) {
310-
// treat edge cases
311-
console.log('[ng-hmr] setRootView: bootstrapId is -1, returning early');
311+
// edge case: a stale ref racing with a teardown
312+
if (traceEnabled) {
313+
NativeScriptDebug.hmrLog('setRootView: bootstrapId is -1, returning early');
314+
}
312315
return;
313316
}
314317
if (ref instanceof NgModuleRef || ref instanceof ApplicationRef) {
315318
if (ref.injector.get(DISABLE_ROOT_VIEW_HANDLING, false)) {
316-
console.log('[ng-hmr] setRootView: DISABLE_ROOT_VIEW_HANDLING is true, returning');
319+
if (traceEnabled) {
320+
NativeScriptDebug.hmrLog('setRootView: DISABLE_ROOT_VIEW_HANDLING is true, returning');
321+
}
317322
return;
318323
}
319324
} else {
320325
if (ref['__disable_root_view_handling']) {
321-
console.log('[ng-hmr] setRootView: __disable_root_view_handling is true, returning');
326+
if (traceEnabled) {
327+
NativeScriptDebug.hmrLog('setRootView: __disable_root_view_handling is true, returning');
328+
}
322329
return;
323330
}
324331
}
325332
Application.getRootView()?._closeAllModalViewsInternal(); // cleanup old rootview
326333
NativeScriptDebug.bootstrapLog(`Setting RootView ${launchEventDone ? 'outside of' : 'during'} launch event`);
327334
// TODO: check for leaks when root view isn't properly destroyed
328335
if (ref instanceof View) {
329-
console.log('[ng-hmr] setRootView: ref is View, launchEventDone:', launchEventDone);
330-
if (NativeScriptDebug.isLogEnabled()) {
336+
if (traceEnabled) {
337+
NativeScriptDebug.hmrLog(`setRootView: ref is View, launchEventDone=${launchEventDone}`);
331338
NativeScriptDebug.bootstrapLog(`Setting RootView to ${ref}`);
332339
}
333340
if (currentOptions.embedded) {
@@ -342,41 +349,36 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
342349
}
343350
const view = ref.injector.get(APP_ROOT_VIEW) as AppHostView | View;
344351
const newRoot = view instanceof AppHostView ? view.content : view;
345-
console.log(
346-
'[ng-hmr] setRootView: view from injector:',
347-
view?.constructor?.name,
348-
'newRoot:',
349-
newRoot?.constructor?.name,
350-
);
351-
console.log('[ng-hmr] setRootView: launchEventDone:', launchEventDone, 'embedded:', currentOptions.embedded);
352-
if (NativeScriptDebug.isLogEnabled()) {
352+
if (traceEnabled) {
353+
NativeScriptDebug.hmrLog(`setRootView: view=${view?.constructor?.name} newRoot=${newRoot?.constructor?.name} launchEventDone=${launchEventDone} embedded=${!!currentOptions.embedded}`);
353354
NativeScriptDebug.bootstrapLog(`Setting RootView to ${newRoot}`);
354355
}
355356
if (currentOptions.embedded) {
356-
console.log('[ng-hmr] setRootView: calling Application.run (embedded)');
357+
if (traceEnabled) {
358+
NativeScriptDebug.hmrLog('setRootView: calling Application.run (embedded)');
359+
}
357360
Application.run({ create: () => newRoot });
358361
} else if (launchEventDone) {
359-
console.log('[ng-hmr] setRootView: calling Application.resetRootView');
360-
console.log('[ng-hmr] setRootView: newRoot details:', {
361-
type: newRoot?.constructor?.name,
362-
nativeView: !!newRoot?.nativeView,
363-
parent: newRoot?.parent?.constructor?.name,
364-
childCount: (newRoot as any)?.getChildrenCount?.() ?? 'N/A',
365-
});
362+
if (traceEnabled) {
363+
NativeScriptDebug.hmrLog(
364+
`setRootView: calling Application.resetRootView newRoot type=${newRoot?.constructor?.name} hasNativeView=${!!newRoot?.nativeView} parent=${newRoot?.parent?.constructor?.name} childCount=${(newRoot as any)?.getChildrenCount?.() ?? 'N/A'}`,
365+
);
366+
}
366367
rootTransitionGuard.runApplicationResetRootView(Application, () => newRoot, newRoot?.constructor?.name || 'View');
367368
refreshRootViewCss(newRoot);
368-
console.log('[ng-hmr] setRootView: Application.resetRootView returned');
369-
// Check root view after reset
370-
setTimeout(() => {
371-
const currentRoot = Application.getRootView();
372-
console.log('[ng-hmr] setRootView: after reset, getRootView:', {
373-
type: currentRoot?.constructor?.name,
374-
nativeView: !!currentRoot?.nativeView,
375-
childCount: (currentRoot as any)?.getChildrenCount?.() ?? 'N/A',
376-
});
377-
}, 100);
369+
if (traceEnabled) {
370+
NativeScriptDebug.hmrLog('setRootView: Application.resetRootView returned');
371+
setTimeout(() => {
372+
const currentRoot = Application.getRootView();
373+
NativeScriptDebug.hmrLog(
374+
`setRootView: post-reset getRootView type=${currentRoot?.constructor?.name} hasNativeView=${!!currentRoot?.nativeView} childCount=${(currentRoot as any)?.getChildrenCount?.() ?? 'N/A'}`,
375+
);
376+
}, 100);
377+
}
378378
} else {
379-
console.log('[ng-hmr] setRootView: setting targetRootView (launch in progress)');
379+
if (traceEnabled) {
380+
NativeScriptDebug.hmrLog('setRootView: setting targetRootView (launch in progress)');
381+
}
380382
targetRootView = newRoot;
381383
}
382384
};
@@ -388,14 +390,18 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
388390
setRootView(errorTextBox);
389391
};
390392
const bootstrapRoot = (reason: NgModuleReason) => {
391-
console.log('[ng-hmr] bootstrapRoot called, reason:', reason);
393+
if (NativeScriptDebug.isLogEnabled()) {
394+
NativeScriptDebug.hmrLog(`bootstrapRoot called reason=${reason}`);
395+
}
392396
try {
393397
if (reason === 'hotreload') {
394398
resetAngularHmrCompiledComponents(getAngularCoreForHmrReset(AngularCore as any, globalThis as any));
395399
}
396400

397401
bootstrapId = Date.now();
398-
console.log('[ng-hmr] bootstrapRoot: new bootstrapId:', bootstrapId);
402+
if (NativeScriptDebug.isLogEnabled()) {
403+
NativeScriptDebug.hmrLog(`bootstrapRoot: new bootstrapId=${bootstrapId}`);
404+
}
399405
const currentBootstrapId = bootstrapId;
400406
let bootstrapped = false;
401407
let onMainBootstrap = () => {
@@ -405,12 +411,19 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
405411
() =>
406412
currentOptions.appModuleBootstrap(reason).then(
407413
(ref) => {
408-
console.log('[ng-hmr] appModuleBootstrap resolved, ref:', ref?.constructor?.name);
409-
console.log('[ng-hmr] currentBootstrapId:', currentBootstrapId, 'bootstrapId:', bootstrapId);
414+
if (NativeScriptDebug.isLogEnabled()) {
415+
NativeScriptDebug.hmrLog(
416+
`appModuleBootstrap resolved ref=${ref?.constructor?.name} currentBootstrapId=${currentBootstrapId} bootstrapId=${bootstrapId}`,
417+
);
418+
}
410419
if (currentBootstrapId !== bootstrapId) {
411-
// this module is old and not needed anymore
412-
// this may happen when developer uses async app initializer and the user exits the app before this bootstraps
413-
console.log('[ng-hmr] bootstrap ID mismatch, destroying ref');
420+
// The pending bootstrap resolved AFTER another reboot bumped
421+
// bootstrapId. This typically happens when a developer ships
422+
// an async APP_INITIALIZER and the user exits/re-enters the
423+
// app while it's still resolving. Drop this ref.
424+
if (NativeScriptDebug.isLogEnabled()) {
425+
NativeScriptDebug.hmrLog('bootstrap ID mismatch, destroying ref');
426+
}
414427
ref.destroy();
415428
return;
416429
}
@@ -433,50 +446,55 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
433446
runInZone(() => {
434447
mainModuleRef = ref;
435448

436-
// Expose ApplicationRef for HMR to trigger change detection
437-
// Check for ApplicationRef by duck-typing since instanceof can fail across module realms
449+
// Expose ApplicationRef for HMR to trigger change detection.
450+
// Check by duck-typing because `instanceof` can fail across
451+
// module realms during HMR — we may be holding a fresh
452+
// ApplicationRef class while `ref` was constructed by an
453+
// earlier (now-evicted) realm copy.
438454
const refAny = ref as any;
439455
const isAppRef = refAny && typeof refAny.tick === 'function' && Array.isArray(refAny.components);
440-
console.log(
441-
'[ng-hmr] ref type check: isAppRef=',
442-
isAppRef,
443-
'has tick=',
444-
typeof refAny?.tick === 'function',
445-
'has components=',
446-
Array.isArray(refAny?.components),
447-
);
456+
if (NativeScriptDebug.isLogEnabled()) {
457+
NativeScriptDebug.hmrLog(
458+
`ref type check isAppRef=${isAppRef} hasTick=${typeof refAny?.tick === 'function'} hasComponents=${Array.isArray(refAny?.components)}`,
459+
);
460+
}
448461

449462
if (isAppRef) {
450463
global['__NS_ANGULAR_APP_REF__'] = ref;
451-
// Mark boot complete for the HMR system
452464
global['__NS_HMR_BOOT_COMPLETE__'] = true;
453465

454-
// Register bootstrapped components for HMR lookup
455466
if (!global['__NS_ANGULAR_COMPONENTS__']) {
456467
global['__NS_ANGULAR_COMPONENTS__'] = {};
457468
}
458-
// Get the component class from the first bootstrapped component
459-
console.log('[ng-hmr] ApplicationRef components count:', refAny.components?.length);
469+
if (NativeScriptDebug.isLogEnabled()) {
470+
NativeScriptDebug.hmrLog(`ApplicationRef components count=${refAny.components?.length ?? 0}`);
471+
}
460472
if (refAny.components && refAny.components.length > 0) {
461473
const componentRef = refAny.components[0];
462-
console.log('[ng-hmr] componentRef:', componentRef?.constructor?.name);
463-
console.log('[ng-hmr] componentRef.componentType:', componentRef?.componentType?.name);
474+
if (NativeScriptDebug.isLogEnabled()) {
475+
NativeScriptDebug.hmrLog(
476+
`componentRef=${componentRef?.constructor?.name} componentType=${componentRef?.componentType?.name}`,
477+
);
478+
}
464479

465-
// For Angular 17+ standalone components, the component type is on componentRef.componentType
466-
// For older Angular, try componentRef.instance.constructor
480+
// Angular 17+ standalone: the component class is on
481+
// `componentRef.componentType`. Older Angular keeps it on
482+
// `componentRef.instance.constructor`.
467483
let componentType = componentRef?.componentType;
468484
if (!componentType && componentRef?.instance) {
469485
componentType = componentRef.instance.constructor;
470486
}
471487

472488
if (componentType && componentType.name) {
473489
global['__NS_ANGULAR_COMPONENTS__'][componentType.name] = componentType;
474-
console.log('[ng-hmr] Registered component for HMR:', componentType.name);
475-
} else {
476-
console.log('[ng-hmr] Could not get componentType name');
490+
if (NativeScriptDebug.isLogEnabled()) {
491+
NativeScriptDebug.hmrLog(`registered component for HMR: ${componentType.name}`);
492+
}
493+
} else if (NativeScriptDebug.isLogEnabled()) {
494+
NativeScriptDebug.hmrLog('could not resolve componentType name');
477495
}
478-
} else {
479-
console.log('[ng-hmr] No components in ApplicationRef');
496+
} else if (NativeScriptDebug.isLogEnabled()) {
497+
NativeScriptDebug.hmrLog('no components in ApplicationRef');
480498
}
481499
} else {
482500
const appRef = ref.injector.get(ApplicationRef, null);
@@ -672,19 +690,29 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
672690
disposePlatform('hotreload');
673691
};
674692
global['__reboot_ng_modules__'] = (shouldDisposePlatform: boolean = false) => {
675-
console.log('[ng-hmr] __reboot_ng_modules__ called, shouldDisposePlatform:', shouldDisposePlatform);
676-
console.log('[ng-hmr] current bootstrapId:', bootstrapId, 'mainModuleRef:', !!mainModuleRef);
693+
const traceEnabled = NativeScriptDebug.isLogEnabled();
694+
if (traceEnabled) {
695+
NativeScriptDebug.hmrLog(
696+
`__reboot_ng_modules__ called shouldDisposePlatform=${shouldDisposePlatform} bootstrapId=${bootstrapId} hasMainModuleRef=${!!mainModuleRef}`,
697+
);
698+
}
677699
try {
678700
global['__NS_CAPTURE_ANGULAR_HMR_ROUTE__']?.();
679701
} catch {}
680702
disposeLastModules('hotreload');
681-
console.log('[ng-hmr] after disposeLastModules, bootstrapId:', bootstrapId);
703+
if (traceEnabled) {
704+
NativeScriptDebug.hmrLog(`after disposeLastModules bootstrapId=${bootstrapId}`);
705+
}
682706
if (shouldDisposePlatform) {
683707
disposePlatform('hotreload');
684708
}
685-
console.log('[ng-hmr] calling bootstrapRoot...');
709+
if (traceEnabled) {
710+
NativeScriptDebug.hmrLog('calling bootstrapRoot');
711+
}
686712
bootstrapRoot('hotreload');
687-
console.log('[ng-hmr] bootstrapRoot returned, new bootstrapId:', bootstrapId);
713+
if (traceEnabled) {
714+
NativeScriptDebug.hmrLog(`bootstrapRoot returned bootstrapId=${bootstrapId}`);
715+
}
688716
};
689717

690718
if (isWebpackHot) {

packages/angular/src/lib/platform-nativescript.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export interface AppOptions {
207207
* @deprecated use runNativeScriptAngularApp instead
208208
*/
209209
export const platformNativeScriptDynamic = function (options?: AppOptions, extraProviders?: StaticProvider[]) {
210-
console.log('platformNativeScriptDynamic is deprecated, use runNativeScriptAngularApp instead');
210+
console.warn('platformNativeScriptDynamic is deprecated, use runNativeScriptAngularApp instead');
211211
options = options || {};
212212
extraProviders = extraProviders || [];
213213

packages/angular/src/lib/router/platform-location.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ export class NativescriptPlatformLocation extends PlatformLocation {
1010
constructor(@Inject(START_PATH) private startPath: any) {
1111
super();
1212
if (NativeScriptDebug.enabled) {
13-
NativeScriptDebug.routerLog('NativescriptPlatformLocation.constructor');
13+
NativeScriptDebug.routerLog(`NativescriptPlatformLocation.constructor startPath=${startPath}`);
1414
}
15-
console.log(startPath);
1615
if (this.startPath) {
1716
if (this.startPath instanceof Promise) {
1817
this.startPath.then((v) => (this._pathname = this._pathname === undefined ? v : this._pathname));
@@ -68,7 +67,9 @@ export class NativescriptPlatformLocation extends PlatformLocation {
6867
if (this._pathname === undefined) {
6968
this._pathname = '';
7069
}
71-
console.log('pathname', this._pathname);
70+
if (NativeScriptDebug.enabled) {
71+
NativeScriptDebug.routerLog(`NativescriptPlatformLocation.pathname ${this._pathname}`);
72+
}
7273
return this._pathname;
7374
}
7475
get search(): string {

packages/angular/src/lib/trace.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export class NativeScriptDebug {
88
static readonly routeReuseStrategyTraceCategory = 'ns-route-reuse-strategy';
99
static readonly listViewTraceCategory = 'ns-list-view';
1010
static readonly bootstrapCategory = 'bootstrap';
11+
static readonly hmrTraceCategory = 'ns-ng-hmr';
1112
// TODO: migrate all usage to this - avoids extraneous method executions
1213
static readonly enabled = Trace.isEnabled();
1314

@@ -62,4 +63,12 @@ export class NativeScriptDebug {
6263
static bootstrapLogError(message: string): void {
6364
Trace.write(message, NativeScriptDebug.bootstrapCategory, Trace.messageType.error);
6465
}
66+
67+
static hmrLog(message: string): void {
68+
Trace.write(message, NativeScriptDebug.hmrTraceCategory);
69+
}
70+
71+
static hmrLogError(message: string): void {
72+
Trace.write(message, NativeScriptDebug.hmrTraceCategory, Trace.messageType.error);
73+
}
6574
}

packages/angular/src/lib/view-util.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ function printNgTree(view: NgView) {
3636
}
3737
function printChildrenRecurse(parent: NgView) {
3838
const children = parent.firstChild ? [parent.firstChild, ...getChildrenSiblings(parent.firstChild).nextSiblings] : [];
39-
console.log(
40-
`parent: ${parent}, firstChild: ${parent.firstChild}, lastChild: ${parent.lastChild} children: ${children}`,
41-
);
42-
if (parent.firstChild) {
43-
console.log(`----- start ${parent}`);
39+
if (NativeScriptDebug.isLogEnabled()) {
40+
NativeScriptDebug.viewUtilLog(`parent: ${parent}, firstChild: ${parent.firstChild}, lastChild: ${parent.lastChild} children: ${children}`);
41+
if (parent.firstChild) {
42+
NativeScriptDebug.viewUtilLog(`----- start ${parent}`);
43+
}
4444
}
4545
children.forEach((c) => printChildrenRecurse(c));
46-
if (parent.firstChild) {
47-
console.log(`----- end ${parent}`);
46+
if (parent.firstChild && NativeScriptDebug.isLogEnabled()) {
47+
NativeScriptDebug.viewUtilLog(`----- end ${parent}`);
4848
}
4949
}
5050

@@ -68,8 +68,9 @@ function getChildrenSiblings(view: NgView) {
6868
}
6969

7070
function printSiblingsTree(view: NgView) {
71+
if (!NativeScriptDebug.isLogEnabled()) return;
7172
const { previousSiblings, nextSiblings } = getChildrenSiblings(view);
72-
console.log(`${view} previousSiblings: ${previousSiblings} nextSiblings: ${nextSiblings}`);
73+
NativeScriptDebug.viewUtilLog(`${view} previousSiblings: ${previousSiblings} nextSiblings: ${nextSiblings}`);
7374
}
7475

7576
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type

0 commit comments

Comments
 (0)