Skip to content

Commit c02d53a

Browse files
committed
chore: improve log warnings during hmr sessions with begign NG0912
1 parent bd03ac6 commit c02d53a

1 file changed

Lines changed: 35 additions & 38 deletions

File tree

packages/angular/src/lib/application.ts

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,39 @@ angularHmrGlobal.__NS_REMEMBER_ANGULAR_CORE__ = (core: any) => {
6262
setAngularCoreForHmr(core, angularHmrGlobal);
6363
};
6464

65+
/**
66+
* Suppress benign NG0912 ("Component ID generation collision") warnings in
67+
* dev/HMR. They fire when the same logical component is re-defined under a
68+
* second class identity (a `.ts` edit, or a module evaluated under two
69+
* dev-server URLs) — same name, no real collision. We only suppress when both
70+
* class names in the message match, so genuine collisions still surface.
71+
*
72+
* Installed at module load, not inside `runNativeScriptAngularApp`: that runs
73+
* after `main.ts`'s imports — including the user's components — have already
74+
* defined, so a filter there misses the cold-boot warnings. Same import-order
75+
* guarantee `installAngularHmrComponentRegistrar()` relies on. Idempotent.
76+
*/
77+
function installAngularNg0912HmrWarningFilter(): void {
78+
const w: { __NS_ANGULAR_NG0912_FILTER_INSTALLED__?: boolean } = globalThis as any;
79+
if (w.__NS_ANGULAR_NG0912_FILTER_INSTALLED__) return;
80+
w.__NS_ANGULAR_NG0912_FILTER_INSTALLED__ = true;
81+
const origWarn = console.warn.bind(console);
82+
// Captures the two class names from "Components 'Foo' and 'Bar' with selector …".
83+
const NG0912_NAME_MATCH = /NG0912[\s\S]*?Components '([^']+)' and '([^']+)' with selector/;
84+
console.warn = (...args: any[]) => {
85+
const msg = String(args[0] ?? '');
86+
if (msg.includes('NG0912')) {
87+
const m = NG0912_NAME_MATCH.exec(msg);
88+
if (m && m[1] === m[2]) {
89+
return;
90+
}
91+
}
92+
origWarn(...args);
93+
};
94+
}
95+
// Install before any user component module evaluates its `ɵɵdefineComponent`.
96+
installAngularNg0912HmrWarningFilter();
97+
6598
export interface AppLaunchView extends LayoutBase {
6699
// called when the animation is to begin
67100
startAnimation?: () => void;
@@ -766,44 +799,8 @@ export function runNativeScriptAngularApp<T, K>(options: AppRunOptions<T, K>) {
766799
resetAngularHmrCompiledComponents(getAngularCoreForHmrReset(AngularCore as any, globalThis as any));
767800
};
768801

769-
// Suppress benign HMR-induced NG0912 ("Component ID generation collision")
770-
// warnings. On a `.ts` edit Angular Live Reload's
771-
// `ListenNowComponent_UpdateMetadata` function in the freshly re-imported
772-
// module calls `ɵɵreplaceMetadata` → `ɵɵdefineComponent` → `getComponentId`
773-
// against a class that shares its name with the just-rebooted instance but
774-
// not its identity (one comes from the route-loaded module, the other from
775-
// the dynamically-fetched `/@ng/component?c=…` metadata chunk). The check
776-
// surfaces every component the user touches as a noisy warning even though
777-
// there's no real collision — same logical class, two transient identities
778-
// during the HMR cycle.
779-
//
780-
// Real collisions — different classes that happen to hash to the same id —
781-
// produce a warning where `'X' and 'Y'` (different class names) appear in
782-
// the message. We only filter when both names match, so genuine duplicates
783-
// still reach the user.
784-
//
785-
// Install once per process; the filter self-detaches if the warning text
786-
// changes shape (defensive against future Angular wording tweaks).
787-
(() => {
788-
const w: { __NS_ANGULAR_NG0912_FILTER_INSTALLED__?: boolean } = global as any;
789-
if (w.__NS_ANGULAR_NG0912_FILTER_INSTALLED__) return;
790-
w.__NS_ANGULAR_NG0912_FILTER_INSTALLED__ = true;
791-
const origWarn = console.warn.bind(console);
792-
// Pattern: "Components 'Foo' and 'Bar' with selector 'xyz'" — capture
793-
// both class names and compare. We suppress only when they're identical
794-
// (the HMR pseudo-collision signature).
795-
const NG0912_NAME_MATCH = /NG0912[\s\S]*?Components '([^']+)' and '([^']+)' with selector/;
796-
console.warn = (...args: any[]) => {
797-
const msg = String(args[0] ?? '');
798-
if (msg.includes('NG0912')) {
799-
const m = NG0912_NAME_MATCH.exec(msg);
800-
if (m && m[1] === m[2]) {
801-
return;
802-
}
803-
}
804-
origWarn(...args);
805-
};
806-
})();
802+
// Already installed at module load; this is a no-op safety net.
803+
installAngularNg0912HmrWarningFilter();
807804
global['__reboot_ng_modules__'] = (shouldDisposePlatform: boolean = false) => {
808805
// Bump the global HMR cycle counter so subsequent diagnostic log
809806
// lines (class registry, dialog services) can be cross-referenced

0 commit comments

Comments
 (0)