@nativescript/angular 21.0.1-alpha.8 → 21.0.1-alpha.9
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.
|
@@ -2534,6 +2534,61 @@ function runNativeScriptAngularApp(options) {
|
|
|
2534
2534
|
disposeLastModules('hotreload');
|
|
2535
2535
|
disposePlatform('hotreload');
|
|
2536
2536
|
};
|
|
2537
|
+
// Pre-import hook for HMR runtimes. Must be called BEFORE the changed
|
|
2538
|
+
// component modules are re-imported, otherwise their ɵɵdefineComponent
|
|
2539
|
+
// calls fire against the OLD `GENERATED_COMP_IDS` map and Angular emits
|
|
2540
|
+
// a benign-but-noisy NG0912 "Component ID generation collision" warning
|
|
2541
|
+
// for every component the user has touched. Calling
|
|
2542
|
+
// `ɵresetCompiledComponents` here clears the map (and the related
|
|
2543
|
+
// ownerNgModule / verifiedNgModule WeakMaps) so the fresh defs register
|
|
2544
|
+
// into an empty table.
|
|
2545
|
+
//
|
|
2546
|
+
// The post-reboot call inside `bootstrapRoot('hotreload')` remains in
|
|
2547
|
+
// place as a safety net: a project that doesn't wire its HMR runtime to
|
|
2548
|
+
// this hook still gets the reset (just one cycle late, after the warning
|
|
2549
|
+
// has already surfaced).
|
|
2550
|
+
global['__reset_ng_compiled_components__'] = () => {
|
|
2551
|
+
resetAngularHmrCompiledComponents(getAngularCoreForHmrReset(i0, globalThis));
|
|
2552
|
+
};
|
|
2553
|
+
// Suppress benign HMR-induced NG0912 ("Component ID generation collision")
|
|
2554
|
+
// warnings. On a `.ts` edit Angular Live Reload's
|
|
2555
|
+
// `ListenNowComponent_UpdateMetadata` function in the freshly re-imported
|
|
2556
|
+
// module calls `ɵɵreplaceMetadata` → `ɵɵdefineComponent` → `getComponentId`
|
|
2557
|
+
// against a class that shares its name with the just-rebooted instance but
|
|
2558
|
+
// not its identity (one comes from the route-loaded module, the other from
|
|
2559
|
+
// the dynamically-fetched `/@ng/component?c=…` metadata chunk). The check
|
|
2560
|
+
// surfaces every component the user touches as a noisy warning even though
|
|
2561
|
+
// there's no real collision — same logical class, two transient identities
|
|
2562
|
+
// during the HMR cycle.
|
|
2563
|
+
//
|
|
2564
|
+
// Real collisions — different classes that happen to hash to the same id —
|
|
2565
|
+
// produce a warning where `'X' and 'Y'` (different class names) appear in
|
|
2566
|
+
// the message. We only filter when both names match, so genuine duplicates
|
|
2567
|
+
// still reach the user.
|
|
2568
|
+
//
|
|
2569
|
+
// Install once per process; the filter self-detaches if the warning text
|
|
2570
|
+
// changes shape (defensive against future Angular wording tweaks).
|
|
2571
|
+
(() => {
|
|
2572
|
+
const w = global;
|
|
2573
|
+
if (w.__NS_ANGULAR_NG0912_FILTER_INSTALLED__)
|
|
2574
|
+
return;
|
|
2575
|
+
w.__NS_ANGULAR_NG0912_FILTER_INSTALLED__ = true;
|
|
2576
|
+
const origWarn = console.warn.bind(console);
|
|
2577
|
+
// Pattern: "Components 'Foo' and 'Bar' with selector 'xyz'" — capture
|
|
2578
|
+
// both class names and compare. We suppress only when they're identical
|
|
2579
|
+
// (the HMR pseudo-collision signature).
|
|
2580
|
+
const NG0912_NAME_MATCH = /NG0912[\s\S]*?Components '([^']+)' and '([^']+)' with selector/;
|
|
2581
|
+
console.warn = (...args) => {
|
|
2582
|
+
const msg = String(args[0] ?? '');
|
|
2583
|
+
if (msg.includes('NG0912')) {
|
|
2584
|
+
const m = NG0912_NAME_MATCH.exec(msg);
|
|
2585
|
+
if (m && m[1] === m[2]) {
|
|
2586
|
+
return;
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
origWarn(...args);
|
|
2590
|
+
};
|
|
2591
|
+
})();
|
|
2537
2592
|
global['__reboot_ng_modules__'] = (shouldDisposePlatform = false) => {
|
|
2538
2593
|
// Bump the global HMR cycle counter so subsequent diagnostic log
|
|
2539
2594
|
// lines (class registry, dialog services) can be cross-referenced
|
|
@@ -9912,29 +9967,65 @@ function writeAngularHmrRouteState(value, options) {
|
|
|
9912
9967
|
function captureAngularHmrPendingStartPath(value, source = 'hmr-reboot') {
|
|
9913
9968
|
return writeAngularHmrRouteState(value, { pending: true, source });
|
|
9914
9969
|
}
|
|
9970
|
+
/**
|
|
9971
|
+
* Match Angular Router's named-outlet syntax in a serialized URL.
|
|
9972
|
+
*
|
|
9973
|
+
* The router emits named outlets as `(outletName:segments[//otherName:segments])`
|
|
9974
|
+
* — see `DefaultUrlSerializer`. Any URL the captures match `/\(\w+:`
|
|
9975
|
+
* contains at least one named-outlet segment.
|
|
9976
|
+
*
|
|
9977
|
+
* Used to gate the start-path deferral below: when a captured URL has named
|
|
9978
|
+
* outlets it CANNOT be used as the initial-navigation path on the next boot
|
|
9979
|
+
* (the outlet directives are inside child components that don't exist yet at
|
|
9980
|
+
* `router.initialNavigation()` time, so `PageRouterOutlet.activateWith`
|
|
9981
|
+
* returns early with "No outlet found relative to activated route" and the
|
|
9982
|
+
* app renders a white screen).
|
|
9983
|
+
*/
|
|
9984
|
+
function hasNamedOutletsInUrl(url) {
|
|
9985
|
+
if (typeof url !== 'string') {
|
|
9986
|
+
return false;
|
|
9987
|
+
}
|
|
9988
|
+
return /\([A-Za-z0-9_-]+:/.test(url);
|
|
9989
|
+
}
|
|
9915
9990
|
function readAngularHmrPendingStartPath() {
|
|
9916
|
-
//
|
|
9917
|
-
//
|
|
9918
|
-
//
|
|
9919
|
-
//
|
|
9991
|
+
// HMR-DX policy: restore only the user's CURRENT URL. NativeScript Frames
|
|
9992
|
+
// own the back-stack, not the URL, so walking captured history URLs forward
|
|
9993
|
+
// doesn't reconstruct the page stack — it just causes visible re-navigation
|
|
9994
|
+
// sequences (especially with tab-based named outlets) that the user has to
|
|
9995
|
+
// sit through after every save. We pick the last captured URL as the
|
|
9996
|
+
// restoration target and bail on the history walk entirely. The
|
|
9997
|
+
// `forward-navigations` reader returns at most one URL (the deferred
|
|
9998
|
+
// named-outlet case), so the replay service performs zero or one
|
|
9999
|
+
// post-bootstrap navigation, not N.
|
|
9920
10000
|
const pendingHistory = readHistoryArray(PENDING_HISTORY_KEY);
|
|
9921
10001
|
if (pendingHistory.length > 0) {
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
//
|
|
9925
|
-
//
|
|
9926
|
-
//
|
|
9927
|
-
//
|
|
9928
|
-
|
|
9929
|
-
|
|
10002
|
+
const target = pendingHistory[pendingHistory.length - 1];
|
|
10003
|
+
beginAngularHmrRouteRestore(target);
|
|
10004
|
+
// Named-outlet URLs cannot be served as the initial navigation URL.
|
|
10005
|
+
// The outlet directives (e.g. `<page-router-outlet name="listenNowTab">`)
|
|
10006
|
+
// live inside child components that only render AFTER the primary
|
|
10007
|
+
// outlet activates. On `router.initialNavigation()` with a URL like
|
|
10008
|
+
// `/(listenNowTab:listen-now)`, Angular tries to activate `listenNowTab`
|
|
10009
|
+
// immediately and `PageRouterOutlet.activateWith` returns early because
|
|
10010
|
+
// no outlet is registered yet — white screen. Defer to a single forward
|
|
10011
|
+
// navigation that fires AFTER the first NavigationEnd, by which time the
|
|
10012
|
+
// outlet directives have registered.
|
|
10013
|
+
if (hasNamedOutletsInUrl(target)) {
|
|
10014
|
+
return '/';
|
|
10015
|
+
}
|
|
10016
|
+
return target;
|
|
9930
10017
|
}
|
|
9931
10018
|
const g = getGlobalState();
|
|
9932
10019
|
const fallback = normalizeAngularHmrRouteUrl(g[PENDING_START_PATH_KEY]?.url ?? g[PENDING_START_PATH_KEY]) || '';
|
|
9933
10020
|
if (fallback) {
|
|
9934
|
-
//
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
10021
|
+
// Same deferral as above for the legacy single-URL slot.
|
|
10022
|
+
if (hasNamedOutletsInUrl(fallback)) {
|
|
10023
|
+
beginAngularHmrRouteRestore(fallback);
|
|
10024
|
+
// Stash the deferred URL so the forward-navigations reader picks it
|
|
10025
|
+
// up after the initial '/' navigation lands.
|
|
10026
|
+
writeHistoryArray(PENDING_HISTORY_KEY, [fallback]);
|
|
10027
|
+
return '/';
|
|
10028
|
+
}
|
|
9938
10029
|
beginAngularHmrRouteRestore(fallback);
|
|
9939
10030
|
}
|
|
9940
10031
|
return fallback;
|
|
@@ -10087,15 +10178,29 @@ function readAngularHmrPendingRouteHistory() {
|
|
|
10087
10178
|
}
|
|
10088
10179
|
/**
|
|
10089
10180
|
* Read URLs to navigate forward through after the initial navigation finishes.
|
|
10090
|
-
*
|
|
10091
|
-
*
|
|
10181
|
+
*
|
|
10182
|
+
* HMR-DX policy: at most one post-bootstrap navigation. We only need a forward
|
|
10183
|
+
* navigation when `readAngularHmrPendingStartPath` had to return '/' because
|
|
10184
|
+
* the user's current URL contains named outlets (the outlet directives don't
|
|
10185
|
+
* exist yet at initial-navigation time, so we defer to a single nav after the
|
|
10186
|
+
* primary outlet has registered them). For URLs with no named outlets the
|
|
10187
|
+
* start path IS the user's current URL and no forward step is needed.
|
|
10188
|
+
*
|
|
10189
|
+
* We intentionally do NOT walk the captured back-stack of intermediate URLs —
|
|
10190
|
+
* NativeScript Frames own the page stack, not the URL serializer, so URL
|
|
10191
|
+
* replay never reconstructs the Frame stack anyway and only creates visible
|
|
10192
|
+
* mid-save re-navigations.
|
|
10092
10193
|
*/
|
|
10093
10194
|
function readAngularHmrPendingForwardNavigations() {
|
|
10094
10195
|
const pending = readHistoryArray(PENDING_HISTORY_KEY);
|
|
10095
|
-
if (pending.length
|
|
10196
|
+
if (pending.length === 0) {
|
|
10096
10197
|
return [];
|
|
10097
10198
|
}
|
|
10098
|
-
|
|
10199
|
+
const target = pending[pending.length - 1];
|
|
10200
|
+
if (hasNamedOutletsInUrl(target)) {
|
|
10201
|
+
return [target];
|
|
10202
|
+
}
|
|
10203
|
+
return [];
|
|
10099
10204
|
}
|
|
10100
10205
|
/**
|
|
10101
10206
|
* Clear the pending snapshot. The router replay calls this once it finishes
|
|
@@ -10189,14 +10294,18 @@ function endAngularHmrRouteRestore() {
|
|
|
10189
10294
|
*/
|
|
10190
10295
|
const REPLAY_COMPLETED_GRACE_MS = 1000;
|
|
10191
10296
|
/**
|
|
10192
|
-
*
|
|
10193
|
-
*
|
|
10194
|
-
*
|
|
10195
|
-
* back
|
|
10297
|
+
* Restores the user's CURRENT URL after an HMR reboot.
|
|
10298
|
+
*
|
|
10299
|
+
* HMR-DX policy: at most one post-bootstrap navigation. The framework no
|
|
10300
|
+
* longer walks the captured back-stack (`stack[1..n]`) — NativeScript Frames
|
|
10301
|
+
* own the page stack, not the URL serializer, so the URL walk never rebuilt
|
|
10302
|
+
* the Frame stack anyway, it only created visible mid-save re-navigation
|
|
10303
|
+
* sequences (especially with tab-based named outlets) that the user had to
|
|
10304
|
+
* sit through. Now `readAngularHmrPendingForwardNavigations()` returns at
|
|
10305
|
+
* most one URL — the deferred named-outlet case — and we replay only that.
|
|
10196
10306
|
*
|
|
10197
|
-
*
|
|
10198
|
-
*
|
|
10199
|
-
* — the user keeps whichever subset of the stack we successfully re-pushed.
|
|
10307
|
+
* Any failure (cancelled navigation, unrouteable URL) closes the restoring
|
|
10308
|
+
* window with `replay-aborted` so default navigations can resume.
|
|
10200
10309
|
*/
|
|
10201
10310
|
class NativeScriptAngularHmrRouteReplay {
|
|
10202
10311
|
constructor(router) {
|