@nativescript/vite 8.0.0-alpha.2 → 8.0.0-alpha.21
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.
- package/configuration/angular.d.ts +34 -1
- package/configuration/angular.js +380 -34
- package/configuration/angular.js.map +1 -1
- package/configuration/base.js +171 -7
- package/configuration/base.js.map +1 -1
- package/configuration/solid.js +27 -1
- package/configuration/solid.js.map +1 -1
- package/configuration/typescript.js +1 -1
- package/configuration/typescript.js.map +1 -1
- package/helpers/angular/angular-linker.js +3 -12
- package/helpers/angular/angular-linker.js.map +1 -1
- package/helpers/angular/inject-component-hmr-registration.d.ts +112 -0
- package/helpers/angular/inject-component-hmr-registration.js +359 -0
- package/helpers/angular/inject-component-hmr-registration.js.map +1 -0
- package/helpers/angular/inject-hmr-vite-ignore.d.ts +75 -0
- package/helpers/angular/inject-hmr-vite-ignore.js +288 -0
- package/helpers/angular/inject-hmr-vite-ignore.js.map +1 -0
- package/helpers/angular/util.d.ts +1 -0
- package/helpers/angular/util.js +88 -0
- package/helpers/angular/util.js.map +1 -1
- package/helpers/commonjs-plugins.d.ts +5 -2
- package/helpers/commonjs-plugins.js +126 -0
- package/helpers/commonjs-plugins.js.map +1 -1
- package/helpers/config-as-json.js +10 -0
- package/helpers/config-as-json.js.map +1 -1
- package/helpers/dev-host.d.ts +274 -0
- package/helpers/dev-host.js +491 -0
- package/helpers/dev-host.js.map +1 -0
- package/helpers/global-defines.d.ts +51 -0
- package/helpers/global-defines.js +77 -0
- package/helpers/global-defines.js.map +1 -1
- package/helpers/logging.d.ts +1 -0
- package/helpers/logging.js +63 -3
- package/helpers/logging.js.map +1 -1
- package/helpers/main-entry.d.ts +3 -1
- package/helpers/main-entry.js +450 -125
- package/helpers/main-entry.js.map +1 -1
- package/helpers/nativeclass-transformer-plugin.d.ts +9 -2
- package/helpers/nativeclass-transformer-plugin.js +157 -14
- package/helpers/nativeclass-transformer-plugin.js.map +1 -1
- package/helpers/ns-core-url.d.ts +88 -0
- package/helpers/ns-core-url.js +191 -0
- package/helpers/ns-core-url.js.map +1 -0
- package/helpers/prelink-angular.js +1 -4
- package/helpers/prelink-angular.js.map +1 -1
- package/helpers/project.d.ts +35 -0
- package/helpers/project.js +120 -2
- package/helpers/project.js.map +1 -1
- package/helpers/resolver.js +9 -1
- package/helpers/resolver.js.map +1 -1
- package/helpers/solid-jsx-deps.d.ts +15 -0
- package/helpers/solid-jsx-deps.js +178 -0
- package/helpers/solid-jsx-deps.js.map +1 -0
- package/helpers/ts-config-paths.js +50 -2
- package/helpers/ts-config-paths.js.map +1 -1
- package/helpers/workers.d.ts +20 -19
- package/helpers/workers.js +620 -3
- package/helpers/workers.js.map +1 -1
- package/hmr/client/css-handler.d.ts +1 -0
- package/hmr/client/css-handler.js +34 -5
- package/hmr/client/css-handler.js.map +1 -1
- package/hmr/client/css-update-overlay.d.ts +18 -0
- package/hmr/client/css-update-overlay.js +27 -0
- package/hmr/client/css-update-overlay.js.map +1 -0
- package/hmr/client/hmr-pending-overlay.d.ts +27 -0
- package/hmr/client/hmr-pending-overlay.js +50 -0
- package/hmr/client/hmr-pending-overlay.js.map +1 -0
- package/hmr/client/index.js +491 -34
- package/hmr/client/index.js.map +1 -1
- package/hmr/client/utils.d.ts +5 -0
- package/hmr/client/utils.js +283 -12
- package/hmr/client/utils.js.map +1 -1
- package/hmr/client/vue-sfc-update-overlay.d.ts +82 -0
- package/hmr/client/vue-sfc-update-overlay.js +133 -0
- package/hmr/client/vue-sfc-update-overlay.js.map +1 -0
- package/hmr/entry-runtime.d.ts +2 -1
- package/hmr/entry-runtime.js +253 -66
- package/hmr/entry-runtime.js.map +1 -1
- package/hmr/frameworks/angular/client/index.d.ts +3 -1
- package/hmr/frameworks/angular/client/index.js +802 -10
- package/hmr/frameworks/angular/client/index.js.map +1 -1
- package/hmr/frameworks/angular/server/linker.js +1 -4
- package/hmr/frameworks/angular/server/linker.js.map +1 -1
- package/hmr/frameworks/angular/server/strategy.js +30 -6
- package/hmr/frameworks/angular/server/strategy.js.map +1 -1
- package/hmr/frameworks/typescript/server/strategy.js +8 -2
- package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
- package/hmr/frameworks/vue/client/index.js +30 -45
- package/hmr/frameworks/vue/client/index.js.map +1 -1
- package/hmr/helpers/ast-normalizer.js +52 -5
- package/hmr/helpers/ast-normalizer.js.map +1 -1
- package/hmr/helpers/cjs-named-exports.d.ts +23 -0
- package/hmr/helpers/cjs-named-exports.js +152 -0
- package/hmr/helpers/cjs-named-exports.js.map +1 -0
- package/hmr/helpers/package-exports.d.ts +16 -0
- package/hmr/helpers/package-exports.js +396 -0
- package/hmr/helpers/package-exports.js.map +1 -0
- package/hmr/server/constants.js +13 -4
- package/hmr/server/constants.js.map +1 -1
- package/hmr/server/core-sanitize.d.ts +93 -8
- package/hmr/server/core-sanitize.js +222 -49
- package/hmr/server/core-sanitize.js.map +1 -1
- package/hmr/server/import-map.js +80 -22
- package/hmr/server/import-map.js.map +1 -1
- package/hmr/server/index.d.ts +2 -1
- package/hmr/server/index.js.map +1 -1
- package/hmr/server/ns-core-cjs-shape.d.ts +204 -0
- package/hmr/server/ns-core-cjs-shape.js +271 -0
- package/hmr/server/ns-core-cjs-shape.js.map +1 -0
- package/hmr/server/ns-rt-bridge.d.ts +51 -0
- package/hmr/server/ns-rt-bridge.js +131 -0
- package/hmr/server/ns-rt-bridge.js.map +1 -0
- package/hmr/server/perf-instrumentation.d.ts +114 -0
- package/hmr/server/perf-instrumentation.js +195 -0
- package/hmr/server/perf-instrumentation.js.map +1 -0
- package/hmr/server/runtime-graph-filter.d.ts +5 -0
- package/hmr/server/runtime-graph-filter.js +21 -0
- package/hmr/server/runtime-graph-filter.js.map +1 -0
- package/hmr/server/shared-transform-request.d.ts +12 -0
- package/hmr/server/shared-transform-request.js +144 -0
- package/hmr/server/shared-transform-request.js.map +1 -0
- package/hmr/server/vite-plugin.d.ts +21 -1
- package/hmr/server/vite-plugin.js +497 -58
- package/hmr/server/vite-plugin.js.map +1 -1
- package/hmr/server/websocket-angular-entry.d.ts +2 -0
- package/hmr/server/websocket-angular-entry.js +68 -0
- package/hmr/server/websocket-angular-entry.js.map +1 -0
- package/hmr/server/websocket-angular-hot-update.d.ts +78 -0
- package/hmr/server/websocket-angular-hot-update.js +413 -0
- package/hmr/server/websocket-angular-hot-update.js.map +1 -0
- package/hmr/server/websocket-core-bridge.d.ts +58 -0
- package/hmr/server/websocket-core-bridge.js +368 -0
- package/hmr/server/websocket-core-bridge.js.map +1 -0
- package/hmr/server/websocket-css-hot-update.d.ts +33 -0
- package/hmr/server/websocket-css-hot-update.js +65 -0
- package/hmr/server/websocket-css-hot-update.js.map +1 -0
- package/hmr/server/websocket-graph-upsert.d.ts +21 -0
- package/hmr/server/websocket-graph-upsert.js +33 -0
- package/hmr/server/websocket-graph-upsert.js.map +1 -0
- package/hmr/server/websocket-hmr-pending.d.ts +43 -0
- package/hmr/server/websocket-hmr-pending.js +55 -0
- package/hmr/server/websocket-hmr-pending.js.map +1 -0
- package/hmr/server/websocket-module-bindings.d.ts +6 -0
- package/hmr/server/websocket-module-bindings.js +471 -0
- package/hmr/server/websocket-module-bindings.js.map +1 -0
- package/hmr/server/websocket-module-specifiers.d.ts +101 -0
- package/hmr/server/websocket-module-specifiers.js +820 -0
- package/hmr/server/websocket-module-specifiers.js.map +1 -0
- package/hmr/server/websocket-ns-m-finalize.d.ts +22 -0
- package/hmr/server/websocket-ns-m-finalize.js +88 -0
- package/hmr/server/websocket-ns-m-finalize.js.map +1 -0
- package/hmr/server/websocket-ns-m-paths.d.ts +3 -0
- package/hmr/server/websocket-ns-m-paths.js +92 -0
- package/hmr/server/websocket-ns-m-paths.js.map +1 -0
- package/hmr/server/websocket-ns-m-request.d.ts +45 -0
- package/hmr/server/websocket-ns-m-request.js +196 -0
- package/hmr/server/websocket-ns-m-request.js.map +1 -0
- package/hmr/server/websocket-served-module-helpers.d.ts +36 -0
- package/hmr/server/websocket-served-module-helpers.js +644 -0
- package/hmr/server/websocket-served-module-helpers.js.map +1 -0
- package/hmr/server/websocket-txn.d.ts +6 -0
- package/hmr/server/websocket-txn.js +45 -0
- package/hmr/server/websocket-txn.js.map +1 -0
- package/hmr/server/websocket-vendor-unifier.d.ts +10 -0
- package/hmr/server/websocket-vendor-unifier.js +51 -0
- package/hmr/server/websocket-vendor-unifier.js.map +1 -0
- package/hmr/server/websocket-vue-sfc.d.ts +26 -0
- package/hmr/server/websocket-vue-sfc.js +1053 -0
- package/hmr/server/websocket-vue-sfc.js.map +1 -0
- package/hmr/server/websocket.d.ts +58 -75
- package/hmr/server/websocket.js +2232 -1802
- package/hmr/server/websocket.js.map +1 -1
- package/hmr/shared/package-classifier.d.ts +9 -0
- package/hmr/shared/package-classifier.js +58 -0
- package/hmr/shared/package-classifier.js.map +1 -0
- package/hmr/shared/runtime/boot-placeholder-ui.d.ts +69 -0
- package/hmr/shared/runtime/boot-placeholder-ui.js +101 -0
- package/hmr/shared/runtime/boot-placeholder-ui.js.map +1 -0
- package/hmr/shared/runtime/boot-progress.d.ts +40 -0
- package/hmr/shared/runtime/boot-progress.js +128 -0
- package/hmr/shared/runtime/boot-progress.js.map +1 -0
- package/hmr/shared/runtime/boot-timeline.d.ts +18 -0
- package/hmr/shared/runtime/boot-timeline.js +52 -0
- package/hmr/shared/runtime/boot-timeline.js.map +1 -0
- package/hmr/shared/runtime/browser-runtime-contract.d.ts +64 -0
- package/hmr/shared/runtime/browser-runtime-contract.js +54 -0
- package/hmr/shared/runtime/browser-runtime-contract.js.map +1 -0
- package/hmr/shared/runtime/dev-overlay.d.ts +78 -3
- package/hmr/shared/runtime/dev-overlay.js +1094 -26
- package/hmr/shared/runtime/dev-overlay.js.map +1 -1
- package/hmr/shared/runtime/module-provenance.js +1 -4
- package/hmr/shared/runtime/module-provenance.js.map +1 -1
- package/hmr/shared/runtime/root-placeholder.d.ts +1 -0
- package/hmr/shared/runtime/root-placeholder.js +1019 -151
- package/hmr/shared/runtime/root-placeholder.js.map +1 -1
- package/hmr/shared/runtime/session-bootstrap.d.ts +1 -0
- package/hmr/shared/runtime/session-bootstrap.js +309 -0
- package/hmr/shared/runtime/session-bootstrap.js.map +1 -0
- package/hmr/shared/runtime/vendor-bootstrap.js +1 -9
- package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -1
- package/hmr/shared/vendor/manifest.d.ts +32 -0
- package/hmr/shared/vendor/manifest.js +411 -46
- package/hmr/shared/vendor/manifest.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +5 -0
- package/index.js.map +1 -1
- package/package.json +9 -1
- package/runtime/core-aliases-early.js +94 -67
- package/runtime/core-aliases-early.js.map +1 -1
|
@@ -1,3 +1,553 @@
|
|
|
1
|
+
import { BOOT_PLACEHOLDER_MOTION, computeBootProgressFillScale, formatBootDetailLine, formatBootPrimaryLine, getBootPlaceholderPalette } from './boot-placeholder-ui.js';
|
|
2
|
+
import { setHmrBootStage } from './dev-overlay.js';
|
|
3
|
+
function isPlaceholderView(view, placeholderRoot) {
|
|
4
|
+
if (!view) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
if (placeholderRoot && view === placeholderRoot) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
if (view.__ns_dev_placeholder) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
catch { }
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
function getCommittedRootView(application, placeholderRoot) {
|
|
19
|
+
const probe = (app) => {
|
|
20
|
+
try {
|
|
21
|
+
const root = app?.getRootView?.() || null;
|
|
22
|
+
if (!root)
|
|
23
|
+
return null;
|
|
24
|
+
if (!isPlaceholderView(root, placeholderRoot))
|
|
25
|
+
return root;
|
|
26
|
+
const currentPage = root.currentPage || root._currentEntry?.resolvedPage || null;
|
|
27
|
+
if (currentPage && !isPlaceholderView(currentPage, placeholderRoot))
|
|
28
|
+
return root;
|
|
29
|
+
}
|
|
30
|
+
catch { }
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
const primary = probe(application);
|
|
34
|
+
if (primary)
|
|
35
|
+
return primary;
|
|
36
|
+
// Vite HMR realm split: Angular's `Application.resetRootView` may have
|
|
37
|
+
// committed the real root on a different Application instance than the
|
|
38
|
+
// one the placeholder/early hook patched. Scan every Application we
|
|
39
|
+
// know about so we can detect the commit regardless of which twin
|
|
40
|
+
// Angular actually wrote to.
|
|
41
|
+
try {
|
|
42
|
+
const g = globalThis;
|
|
43
|
+
const known = g['__NS_DEV_KNOWN_APPLICATIONS__'] || [];
|
|
44
|
+
for (const app of known) {
|
|
45
|
+
if (!app || app === application)
|
|
46
|
+
continue;
|
|
47
|
+
const r = probe(app);
|
|
48
|
+
if (r)
|
|
49
|
+
return r;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch { }
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
function getPlaceholderWaitDiagnosticSnapshot(g, application, placeholderRoot) {
|
|
56
|
+
const snapshot = {
|
|
57
|
+
bootComplete: !!g.__NS_HMR_BOOT_COMPLETE__,
|
|
58
|
+
hasPlaceholderRoot: !!placeholderRoot,
|
|
59
|
+
hasPlaceholderFlag: !!g.__NS_DEV_PLACEHOLDER_ROOT_EARLY__,
|
|
60
|
+
hasAngularAppRef: !!g.__NS_ANGULAR_APP_REF__,
|
|
61
|
+
hasAngularReboot: typeof g.__reboot_ng_modules__ === 'function',
|
|
62
|
+
};
|
|
63
|
+
try {
|
|
64
|
+
snapshot.applicationType = application?.constructor?.name;
|
|
65
|
+
snapshot.hasLaunched = typeof application?.hasLaunched === 'function' ? !!application.hasLaunched() : undefined;
|
|
66
|
+
snapshot.rootViewType = application?.getRootView?.()?.constructor?.name;
|
|
67
|
+
}
|
|
68
|
+
catch { }
|
|
69
|
+
try {
|
|
70
|
+
const Frame = g.Frame;
|
|
71
|
+
const topmost = Frame?.topmost?.() || null;
|
|
72
|
+
snapshot.topmostFrameType = topmost?.constructor?.name;
|
|
73
|
+
snapshot.topmostPageType = topmost?.currentPage?.constructor?.name || topmost?._currentEntry?.resolvedPage?.constructor?.name;
|
|
74
|
+
}
|
|
75
|
+
catch { }
|
|
76
|
+
return snapshot;
|
|
77
|
+
}
|
|
78
|
+
function restoreOriginalApplicationRun(g) {
|
|
79
|
+
const originalRun = g['__NS_DEV_ORIGINAL_APP_RUN__'];
|
|
80
|
+
if (typeof originalRun !== 'function') {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const application = g['__NS_DEV_PLACEHOLDER_APPLICATION__'] || g.Application;
|
|
84
|
+
try {
|
|
85
|
+
if (application) {
|
|
86
|
+
application.run = originalRun;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
try {
|
|
91
|
+
if (g.Application && g.Application !== application) {
|
|
92
|
+
g.Application.run = originalRun;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch { }
|
|
96
|
+
try {
|
|
97
|
+
const proto = application ? Object.getPrototypeOf(application) : null;
|
|
98
|
+
if (proto && typeof proto.run === 'function' && proto.run !== originalRun) {
|
|
99
|
+
proto.run = originalRun;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch { }
|
|
103
|
+
delete g['__NS_DEV_ORIGINAL_APP_RUN__'];
|
|
104
|
+
}
|
|
105
|
+
function clearPlaceholderGlobals(g) {
|
|
106
|
+
delete g['__NS_DEV_PLACEHOLDER_ROOT_VIEW__'];
|
|
107
|
+
delete g['__NS_DEV_PLACEHOLDER_ROOT_EARLY__'];
|
|
108
|
+
delete g['__NS_DEV_BOOT_STATUS_LABEL__'];
|
|
109
|
+
delete g['__NS_DEV_BOOT_DETAIL_LABEL__'];
|
|
110
|
+
delete g['__NS_DEV_BOOT_PROGRESS_FILL__'];
|
|
111
|
+
delete g['__NS_DEV_BOOT_PROGRESS_LAST_SCALE__'];
|
|
112
|
+
delete g['__NS_DEV_BOOT_ACTIVITY_INDICATOR__'];
|
|
113
|
+
delete g['__NS_DEV_PLACEHOLDER_LAUNCH_HANDLER__'];
|
|
114
|
+
delete g['__NS_DEV_PLACEHOLDER_APPLICATION__'];
|
|
115
|
+
const timer = g['__NS_DEV_PLACEHOLDER_RESTORE_TIMER__'];
|
|
116
|
+
if (timer) {
|
|
117
|
+
try {
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
}
|
|
120
|
+
catch { }
|
|
121
|
+
}
|
|
122
|
+
delete g['__NS_DEV_PLACEHOLDER_RESTORE_TIMER__'];
|
|
123
|
+
}
|
|
124
|
+
// Official NativeScript wordmark, dark slate on transparent. Hosted
|
|
125
|
+
// remotely so we don't have to ship the asset with @nativescript/vite;
|
|
126
|
+
// fetched once per cold boot, NS's Image element handles caching.
|
|
127
|
+
const NATIVESCRIPT_LOGO_URL = 'https://raw.githubusercontent.com/NativeScript/artwork/main/logo/export/NativeScript_Logo_Dark_Transparent.png';
|
|
128
|
+
const BRAND_MARK_SIZE = 44;
|
|
129
|
+
function makeColor(Color, value) {
|
|
130
|
+
if (!Color)
|
|
131
|
+
return value;
|
|
132
|
+
try {
|
|
133
|
+
return new Color(value);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// iOS layer-level shadow. Soft + offset down so the card reads as
|
|
140
|
+
// "slightly lifted off the page" without a heavy, dated drop.
|
|
141
|
+
function applyIosCardShadow(card, shadowHex, ColorCtor) {
|
|
142
|
+
const ios = card.ios;
|
|
143
|
+
const layer = ios?.layer;
|
|
144
|
+
if (!layer)
|
|
145
|
+
return;
|
|
146
|
+
if (ColorCtor) {
|
|
147
|
+
const shadowColor = new ColorCtor(shadowHex);
|
|
148
|
+
const uiColor = shadowColor.ios;
|
|
149
|
+
if (uiColor && typeof uiColor.CGColor !== 'undefined') {
|
|
150
|
+
layer.shadowColor = uiColor.CGColor;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
layer.shadowOpacity = 0.18;
|
|
154
|
+
layer.shadowRadius = 16;
|
|
155
|
+
layer.shadowOffset = { width: 0, height: 6 };
|
|
156
|
+
layer.masksToBounds = false;
|
|
157
|
+
}
|
|
158
|
+
// Pre-load setup: keep the card invisible + slightly down-scaled so
|
|
159
|
+
// it doesn't flash at full opacity before the loaded handler can
|
|
160
|
+
// kick off the entrance animation. Called once at construction.
|
|
161
|
+
function primeCardForEntrance(card) {
|
|
162
|
+
if (!card)
|
|
163
|
+
return;
|
|
164
|
+
try {
|
|
165
|
+
card.opacity = 0;
|
|
166
|
+
card.scaleX = BOOT_PLACEHOLDER_MOTION.entranceFromScale;
|
|
167
|
+
card.scaleY = BOOT_PLACEHOLDER_MOTION.entranceFromScale;
|
|
168
|
+
}
|
|
169
|
+
catch { }
|
|
170
|
+
}
|
|
171
|
+
// One-shot fade + scale on attach. Triggered from `loaded` so we run
|
|
172
|
+
// after the view has been measured and committed to the visual tree.
|
|
173
|
+
// Primed via `primeCardForEntrance` to avoid a pre-animation flash.
|
|
174
|
+
function animateCardIn(card) {
|
|
175
|
+
if (!card || typeof card.animate !== 'function')
|
|
176
|
+
return;
|
|
177
|
+
try {
|
|
178
|
+
card
|
|
179
|
+
.animate({
|
|
180
|
+
opacity: 1,
|
|
181
|
+
scale: { x: 1, y: 1 },
|
|
182
|
+
duration: BOOT_PLACEHOLDER_MOTION.entranceDurationMs,
|
|
183
|
+
curve: 'easeOut',
|
|
184
|
+
})
|
|
185
|
+
.catch(() => {
|
|
186
|
+
try {
|
|
187
|
+
card.opacity = 1;
|
|
188
|
+
card.scaleX = 1;
|
|
189
|
+
card.scaleY = 1;
|
|
190
|
+
}
|
|
191
|
+
catch { }
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
catch { }
|
|
195
|
+
}
|
|
196
|
+
// Slow opacity pulse on the brand mark to give the otherwise-static
|
|
197
|
+
// card a heartbeat. Loops until boot completes (the `__NS_HMR_BOOT_COMPLETE__`
|
|
198
|
+
// gate) or the view is detached (animate rejects and the .catch swallows it).
|
|
199
|
+
function pulseBrandMark(badge) {
|
|
200
|
+
if (!badge || typeof badge.animate !== 'function')
|
|
201
|
+
return;
|
|
202
|
+
const g = globalThis;
|
|
203
|
+
if (g.__NS_HMR_BOOT_COMPLETE__)
|
|
204
|
+
return;
|
|
205
|
+
try {
|
|
206
|
+
badge
|
|
207
|
+
.animate({
|
|
208
|
+
opacity: BOOT_PLACEHOLDER_MOTION.brandPulseMinOpacity,
|
|
209
|
+
duration: BOOT_PLACEHOLDER_MOTION.brandPulseDurationMs,
|
|
210
|
+
curve: 'easeInOut',
|
|
211
|
+
})
|
|
212
|
+
.then(() => badge.animate({
|
|
213
|
+
opacity: 1,
|
|
214
|
+
duration: BOOT_PLACEHOLDER_MOTION.brandPulseDurationMs,
|
|
215
|
+
curve: 'easeInOut',
|
|
216
|
+
}))
|
|
217
|
+
.then(() => pulseBrandMark(badge))
|
|
218
|
+
.catch(() => { });
|
|
219
|
+
}
|
|
220
|
+
catch { }
|
|
221
|
+
}
|
|
222
|
+
function buildPlaceholderPage(ctors) {
|
|
223
|
+
const { Page, Label, ActivityIndicator, StackLayout, GridLayout, ContentView, Image, Color } = ctors;
|
|
224
|
+
const palette = getBootPlaceholderPalette('info');
|
|
225
|
+
const page = new Page();
|
|
226
|
+
page.actionBarHidden = true;
|
|
227
|
+
try {
|
|
228
|
+
page.backgroundColor = makeColor(Color, palette.pageBackground);
|
|
229
|
+
}
|
|
230
|
+
catch { }
|
|
231
|
+
const titleLabel = new Label();
|
|
232
|
+
titleLabel.text = 'NativeScript Vite preparing dev session...';
|
|
233
|
+
titleLabel.textAlignment = 'center';
|
|
234
|
+
titleLabel.textWrap = true;
|
|
235
|
+
titleLabel.fontSize = 18;
|
|
236
|
+
titleLabel.fontWeight = '700';
|
|
237
|
+
try {
|
|
238
|
+
titleLabel.color = makeColor(Color, palette.titleText);
|
|
239
|
+
}
|
|
240
|
+
catch { }
|
|
241
|
+
titleLabel.marginTop = 18;
|
|
242
|
+
const statusLabel = new Label();
|
|
243
|
+
statusLabel.text = 'Preparing the HTTP HMR bootstrap (4%)';
|
|
244
|
+
statusLabel.textAlignment = 'center';
|
|
245
|
+
statusLabel.textWrap = true;
|
|
246
|
+
statusLabel.fontSize = 13;
|
|
247
|
+
try {
|
|
248
|
+
statusLabel.color = makeColor(Color, palette.phaseText);
|
|
249
|
+
}
|
|
250
|
+
catch { }
|
|
251
|
+
statusLabel.marginTop = 10;
|
|
252
|
+
const detailLabel = new Label();
|
|
253
|
+
detailLabel.text = '';
|
|
254
|
+
detailLabel.textAlignment = 'center';
|
|
255
|
+
detailLabel.textWrap = true;
|
|
256
|
+
detailLabel.fontSize = 11;
|
|
257
|
+
try {
|
|
258
|
+
detailLabel.color = makeColor(Color, palette.detailText);
|
|
259
|
+
}
|
|
260
|
+
catch { }
|
|
261
|
+
detailLabel.marginTop = 12;
|
|
262
|
+
const activityIndicator = ActivityIndicator
|
|
263
|
+
? (() => {
|
|
264
|
+
const indicator = new ActivityIndicator();
|
|
265
|
+
indicator.busy = true;
|
|
266
|
+
indicator.marginTop = 14;
|
|
267
|
+
indicator.width = 22;
|
|
268
|
+
indicator.height = 22;
|
|
269
|
+
indicator.horizontalAlignment = 'center';
|
|
270
|
+
try {
|
|
271
|
+
indicator.color = makeColor(Color, palette.activityIndicator);
|
|
272
|
+
}
|
|
273
|
+
catch { }
|
|
274
|
+
return indicator;
|
|
275
|
+
})()
|
|
276
|
+
: null;
|
|
277
|
+
let progressFill = null;
|
|
278
|
+
let progressTrack = null;
|
|
279
|
+
if (GridLayout && ContentView) {
|
|
280
|
+
try {
|
|
281
|
+
progressTrack = new GridLayout();
|
|
282
|
+
progressTrack.height = 6;
|
|
283
|
+
progressTrack.marginTop = 16;
|
|
284
|
+
progressTrack.marginLeft = 4;
|
|
285
|
+
progressTrack.marginRight = 4;
|
|
286
|
+
try {
|
|
287
|
+
progressTrack.backgroundColor = makeColor(Color, palette.progressTrack);
|
|
288
|
+
}
|
|
289
|
+
catch { }
|
|
290
|
+
try {
|
|
291
|
+
progressTrack.borderRadius = 3;
|
|
292
|
+
}
|
|
293
|
+
catch { }
|
|
294
|
+
progressTrack.horizontalAlignment = 'stretch';
|
|
295
|
+
progressFill = new ContentView();
|
|
296
|
+
progressFill.height = 6;
|
|
297
|
+
progressFill.horizontalAlignment = 'stretch';
|
|
298
|
+
progressFill.verticalAlignment = 'middle';
|
|
299
|
+
try {
|
|
300
|
+
progressFill.backgroundColor = makeColor(Color, palette.progressFill);
|
|
301
|
+
}
|
|
302
|
+
catch { }
|
|
303
|
+
try {
|
|
304
|
+
progressFill.borderRadius = 3;
|
|
305
|
+
}
|
|
306
|
+
catch { }
|
|
307
|
+
// Anchor the scale transform at the left edge so the fill
|
|
308
|
+
// grows rightward like a real progress bar. Starting scale
|
|
309
|
+
// matches `computeBootProgressFillScale(0)` = 0.01 — visible
|
|
310
|
+
// sliver of accent that telegraphs "we're starting".
|
|
311
|
+
try {
|
|
312
|
+
progressFill.originX = 0;
|
|
313
|
+
}
|
|
314
|
+
catch { }
|
|
315
|
+
progressFill.scaleX = computeBootProgressFillScale(0);
|
|
316
|
+
progressTrack.addChild(progressFill);
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
progressTrack = null;
|
|
320
|
+
progressFill = null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const brandMark = new Image();
|
|
324
|
+
brandMark.src = NATIVESCRIPT_LOGO_URL;
|
|
325
|
+
brandMark.stretch = 'aspectFit';
|
|
326
|
+
brandMark.width = BRAND_MARK_SIZE;
|
|
327
|
+
brandMark.height = BRAND_MARK_SIZE;
|
|
328
|
+
brandMark.horizontalAlignment = 'center';
|
|
329
|
+
brandMark.on?.('loaded', () => pulseBrandMark(brandMark));
|
|
330
|
+
let card = null;
|
|
331
|
+
if (StackLayout) {
|
|
332
|
+
try {
|
|
333
|
+
card = new StackLayout();
|
|
334
|
+
card.padding = '24 28 22 28';
|
|
335
|
+
try {
|
|
336
|
+
card.backgroundColor = makeColor(Color, palette.cardBackground);
|
|
337
|
+
}
|
|
338
|
+
catch { }
|
|
339
|
+
try {
|
|
340
|
+
card.borderRadius = 18;
|
|
341
|
+
}
|
|
342
|
+
catch { }
|
|
343
|
+
card.width = 320;
|
|
344
|
+
card.horizontalAlignment = 'center';
|
|
345
|
+
if (brandMark)
|
|
346
|
+
card.addChild(brandMark);
|
|
347
|
+
card.addChild(titleLabel);
|
|
348
|
+
card.addChild(statusLabel);
|
|
349
|
+
if (progressTrack)
|
|
350
|
+
card.addChild(progressTrack);
|
|
351
|
+
card.addChild(detailLabel);
|
|
352
|
+
if (activityIndicator)
|
|
353
|
+
card.addChild(activityIndicator);
|
|
354
|
+
primeCardForEntrance(card);
|
|
355
|
+
card.on?.('loaded', () => {
|
|
356
|
+
try {
|
|
357
|
+
const ios = card.ios;
|
|
358
|
+
if (ios && ios.layer) {
|
|
359
|
+
ios.layer.cornerRadius = 18;
|
|
360
|
+
ios.layer.masksToBounds = false;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch { }
|
|
364
|
+
applyIosCardShadow(card, palette.cardShadow, Color);
|
|
365
|
+
animateCardIn(card);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
card = null;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (card && GridLayout) {
|
|
373
|
+
try {
|
|
374
|
+
const root = new GridLayout();
|
|
375
|
+
root.horizontalAlignment = 'stretch';
|
|
376
|
+
root.verticalAlignment = 'stretch';
|
|
377
|
+
try {
|
|
378
|
+
root.backgroundColor = makeColor(Color, palette.pageBackground);
|
|
379
|
+
}
|
|
380
|
+
catch { }
|
|
381
|
+
card.verticalAlignment = 'middle';
|
|
382
|
+
card.horizontalAlignment = 'center';
|
|
383
|
+
root.addChild(card);
|
|
384
|
+
page.content = root;
|
|
385
|
+
}
|
|
386
|
+
catch {
|
|
387
|
+
page.content = card;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else if (card) {
|
|
391
|
+
card.verticalAlignment = 'middle';
|
|
392
|
+
page.content = card;
|
|
393
|
+
}
|
|
394
|
+
else if (StackLayout) {
|
|
395
|
+
// StackLayout exists but card creation failed — fall back to the
|
|
396
|
+
// minimal three-child layout the older placeholder used so the
|
|
397
|
+
// dev-overlay's fallback `findBootStatusLabel` walk still works.
|
|
398
|
+
try {
|
|
399
|
+
const root = new StackLayout();
|
|
400
|
+
root.padding = 24;
|
|
401
|
+
root.verticalAlignment = 'middle';
|
|
402
|
+
root.horizontalAlignment = 'center';
|
|
403
|
+
root.addChild(titleLabel);
|
|
404
|
+
root.addChild(statusLabel);
|
|
405
|
+
if (activityIndicator)
|
|
406
|
+
root.addChild(activityIndicator);
|
|
407
|
+
page.content = root;
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
titleLabel.verticalAlignment = 'middle';
|
|
411
|
+
titleLabel.horizontalAlignment = 'center';
|
|
412
|
+
titleLabel.width = 280;
|
|
413
|
+
titleLabel.padding = 12;
|
|
414
|
+
page.content = titleLabel;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
titleLabel.verticalAlignment = 'middle';
|
|
419
|
+
titleLabel.horizontalAlignment = 'center';
|
|
420
|
+
titleLabel.width = 280;
|
|
421
|
+
titleLabel.padding = 12;
|
|
422
|
+
page.content = titleLabel;
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
page,
|
|
426
|
+
statusLabel,
|
|
427
|
+
detailLabel: card ? detailLabel : null,
|
|
428
|
+
progressFill,
|
|
429
|
+
activityIndicator,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
export function tryFinalizeBootPlaceholder(reason, verbose) {
|
|
433
|
+
const g = globalThis;
|
|
434
|
+
const placeholderRoot = g['__NS_DEV_PLACEHOLDER_ROOT_VIEW__'] || null;
|
|
435
|
+
const hadPlaceholder = !!placeholderRoot || !!g['__NS_DEV_PLACEHOLDER_ROOT_EARLY__'] || !!g['__NS_DEV_BOOT_STATUS_LABEL__'] || !!g['__NS_DEV_BOOT_ACTIVITY_INDICATOR__'];
|
|
436
|
+
const application = g['__NS_DEV_PLACEHOLDER_APPLICATION__'] || g.Application;
|
|
437
|
+
const committedRoot = getCommittedRootView(application, placeholderRoot);
|
|
438
|
+
if (!committedRoot) {
|
|
439
|
+
// Throttled verbose-gated diagnostic. Used to be unconditional
|
|
440
|
+
// (with a `__NS_PLACEHOLDER_DIAG_SILENT__` opt-out) while we
|
|
441
|
+
// were debugging the Android "Waiting for the app root view"
|
|
442
|
+
// stall — now that Layer 1-9 fixes have landed, surface this
|
|
443
|
+
// only when the user opted into `verbose` in their HMR config.
|
|
444
|
+
// Still throttled to 1 Hz to avoid spamming the verbose log on
|
|
445
|
+
// long stalls.
|
|
446
|
+
try {
|
|
447
|
+
if (verbose) {
|
|
448
|
+
const now = Date.now();
|
|
449
|
+
const last = g.__NS_PLACEHOLDER_DIAG_LAST_FINALIZE__ || 0;
|
|
450
|
+
if (now - last > 1000) {
|
|
451
|
+
g.__NS_PLACEHOLDER_DIAG_LAST_FINALIZE__ = now;
|
|
452
|
+
const describe = (app) => {
|
|
453
|
+
try {
|
|
454
|
+
const r = app?.getRootView?.();
|
|
455
|
+
const cp = r?.currentPage || r?._currentEntry?.resolvedPage;
|
|
456
|
+
return {
|
|
457
|
+
appType: app?.constructor?.name || typeof app,
|
|
458
|
+
appIdentity: app === application ? 'primary' : 'alt',
|
|
459
|
+
rootType: r?.constructor?.name || 'null',
|
|
460
|
+
rootIsPlaceholder: !!r && (r === placeholderRoot || r.__ns_dev_placeholder === true),
|
|
461
|
+
currentPageType: cp?.constructor?.name,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
catch {
|
|
465
|
+
return { appType: 'error' };
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
const known = (g['__NS_DEV_KNOWN_APPLICATIONS__'] || []);
|
|
469
|
+
console.warn('[ns-placeholder][diag] tryFinalize: no committed root', {
|
|
470
|
+
reason,
|
|
471
|
+
hadPlaceholder,
|
|
472
|
+
placeholderRootType: placeholderRoot?.constructor?.name,
|
|
473
|
+
primary: describe(application),
|
|
474
|
+
knownApplications: known.length,
|
|
475
|
+
alts: known.filter((a) => a && a !== application).map(describe),
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
catch { }
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
let detachedPlaceholder = false;
|
|
484
|
+
if (hadPlaceholder) {
|
|
485
|
+
try {
|
|
486
|
+
const launchHandler = g['__NS_DEV_PLACEHOLDER_LAUNCH_HANDLER__'];
|
|
487
|
+
if (application && typeof application.off === 'function' && launchHandler) {
|
|
488
|
+
application.off(application.launchEvent, launchHandler);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
catch { }
|
|
492
|
+
restoreOriginalApplicationRun(g);
|
|
493
|
+
clearPlaceholderGlobals(g);
|
|
494
|
+
detachedPlaceholder = true;
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
g.__NS_HMR_BOOT_COMPLETE__ = true;
|
|
498
|
+
}
|
|
499
|
+
catch { }
|
|
500
|
+
if (detachedPlaceholder) {
|
|
501
|
+
setHmrBootStage('app-root-committed', {
|
|
502
|
+
detail: 'The real app root replaced the boot placeholder.',
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
if (verbose) {
|
|
506
|
+
console.info('[ns-placeholder] real app root committed', {
|
|
507
|
+
reason,
|
|
508
|
+
rootType: committedRoot?.constructor?.name || typeof committedRoot,
|
|
509
|
+
detachedPlaceholder,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
514
|
+
function scheduleBootPlaceholderFinalize(reason, verbose) {
|
|
515
|
+
const g = globalThis;
|
|
516
|
+
if (g['__NS_DEV_PLACEHOLDER_RESTORE_TIMER__']) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
const startedAt = Date.now();
|
|
520
|
+
const maxWaitMs = 20000;
|
|
521
|
+
let attempts = 0;
|
|
522
|
+
const tick = () => {
|
|
523
|
+
delete g['__NS_DEV_PLACEHOLDER_RESTORE_TIMER__'];
|
|
524
|
+
if (tryFinalizeBootPlaceholder(reason, verbose)) {
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
attempts += 1;
|
|
528
|
+
if (Date.now() - startedAt >= maxWaitMs) {
|
|
529
|
+
// Verbose-gated — used to be unconditional with a
|
|
530
|
+
// `__NS_PLACEHOLDER_DIAG_SILENT__` opt-out while we were
|
|
531
|
+
// debugging the Android stall. Now that the stall is
|
|
532
|
+
// resolved, users investigating a new stall should enable
|
|
533
|
+
// `verbose` in their HMR config to see this warning.
|
|
534
|
+
try {
|
|
535
|
+
if (verbose) {
|
|
536
|
+
console.warn('[ns-placeholder][diag] waiting for real root commit TIMED OUT', {
|
|
537
|
+
reason,
|
|
538
|
+
attempts,
|
|
539
|
+
waitMs: Date.now() - startedAt,
|
|
540
|
+
state: getPlaceholderWaitDiagnosticSnapshot(g, g['__NS_DEV_PLACEHOLDER_APPLICATION__'] || g.Application, g['__NS_DEV_PLACEHOLDER_ROOT_VIEW__'] || null),
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
catch { }
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
g['__NS_DEV_PLACEHOLDER_RESTORE_TIMER__'] = setTimeout(tick, attempts === 1 ? 0 : 100);
|
|
548
|
+
};
|
|
549
|
+
tick();
|
|
550
|
+
}
|
|
1
551
|
// Root placeholder installer used during dev HMR until HTTP ESM loads.
|
|
2
552
|
//
|
|
3
553
|
// Architecture:
|
|
@@ -14,107 +564,323 @@ export function installRootPlaceholder(verbose) {
|
|
|
14
564
|
if (g['__NS_DEV_PLACEHOLDER_ROOT_EARLY__'])
|
|
15
565
|
return;
|
|
16
566
|
g['__NS_DEV_PLACEHOLDER_ROOT_EARLY__'] = true;
|
|
567
|
+
g['__NS_DEV_RESTORE_PLACEHOLDER__'] = (reason) => {
|
|
568
|
+
if (!tryFinalizeBootPlaceholder(reason, verbose)) {
|
|
569
|
+
scheduleBootPlaceholderFinalize(reason, verbose);
|
|
570
|
+
}
|
|
571
|
+
};
|
|
17
572
|
try {
|
|
573
|
+
const resolveModule = (moduleIds) => {
|
|
574
|
+
for (const moduleId of moduleIds) {
|
|
575
|
+
try {
|
|
576
|
+
if (typeof g.moduleExists === 'function' && g.moduleExists(moduleId) && typeof g.loadModule === 'function') {
|
|
577
|
+
const mod = g.loadModule(moduleId);
|
|
578
|
+
if (mod)
|
|
579
|
+
return { value: (mod.default ?? mod) || mod, via: 'loadModule', moduleId };
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
catch { }
|
|
583
|
+
try {
|
|
584
|
+
const reg = g.__nsVendorRegistry;
|
|
585
|
+
if (reg?.has?.(moduleId)) {
|
|
586
|
+
const mod = reg.get(moduleId);
|
|
587
|
+
if (mod)
|
|
588
|
+
return { value: (mod.default ?? mod) || mod, via: '__nsVendorRegistry', moduleId };
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
catch { }
|
|
592
|
+
try {
|
|
593
|
+
const req = g.__nsVendorRequire || g.__nsRequire || g.require;
|
|
594
|
+
if (typeof req === 'function') {
|
|
595
|
+
const mod = req(moduleId);
|
|
596
|
+
if (mod)
|
|
597
|
+
return { value: (mod.default ?? mod) || mod, via: 'require', moduleId };
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
catch { }
|
|
601
|
+
try {
|
|
602
|
+
const nr = g.__nativeRequire;
|
|
603
|
+
if (typeof nr === 'function') {
|
|
604
|
+
const mod = nr(moduleId, '/');
|
|
605
|
+
if (mod)
|
|
606
|
+
return { value: (mod.default ?? mod) || mod, via: '__nativeRequire', moduleId };
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
catch { }
|
|
610
|
+
}
|
|
611
|
+
return undefined;
|
|
612
|
+
};
|
|
18
613
|
const getCore = (name) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
614
|
+
if (name === 'Application' && g.Application && (typeof g.Application.run === 'function' || typeof g.Application.on === 'function' || typeof g.Application.resetRootView === 'function')) {
|
|
615
|
+
return { value: g.Application, source: 'globalThis.Application' };
|
|
616
|
+
}
|
|
617
|
+
const pickApplicationApi = (candidate, source) => {
|
|
618
|
+
if (!candidate)
|
|
619
|
+
return null;
|
|
620
|
+
const candidates = [
|
|
621
|
+
{ value: candidate, source },
|
|
622
|
+
{ value: candidate.Application, source: `${source}#Application` },
|
|
623
|
+
{ value: candidate.app, source: `${source}#app` },
|
|
624
|
+
{ value: candidate.application, source: `${source}#application` },
|
|
625
|
+
];
|
|
626
|
+
for (const entry of candidates) {
|
|
627
|
+
if (entry.value && (typeof entry.value.run === 'function' || typeof entry.value.on === 'function' || typeof entry.value.resetRootView === 'function')) {
|
|
628
|
+
return entry;
|
|
28
629
|
}
|
|
29
|
-
catch { }
|
|
30
630
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
631
|
+
return null;
|
|
632
|
+
};
|
|
633
|
+
if (name === 'Application') {
|
|
634
|
+
const applicationModule = resolveModule(['@nativescript/core/application']);
|
|
635
|
+
const pickedFromAppModule = pickApplicationApi(applicationModule?.value, applicationModule ? `${applicationModule.via}:${applicationModule.moduleId}` : '@nativescript/core/application');
|
|
636
|
+
if (pickedFromAppModule)
|
|
637
|
+
return pickedFromAppModule;
|
|
36
638
|
}
|
|
37
|
-
|
|
639
|
+
const primary = resolveModule(['@nativescript/core']);
|
|
640
|
+
if (name === 'Application' && primary?.value) {
|
|
641
|
+
const pickedFromPrimary = pickApplicationApi(primary.value, `${primary.via}:${primary.moduleId}`);
|
|
642
|
+
if (pickedFromPrimary)
|
|
643
|
+
return pickedFromPrimary;
|
|
644
|
+
}
|
|
645
|
+
if (primary?.value && primary.value[name])
|
|
646
|
+
return { value: primary.value[name], source: `${primary.via}:${primary.moduleId}` };
|
|
647
|
+
const ui = resolveModule(['@nativescript/core/ui']);
|
|
648
|
+
if (ui?.value && ui.value[name])
|
|
649
|
+
return { value: ui.value[name], source: `${ui.via}:${ui.moduleId}` };
|
|
650
|
+
return { value: undefined, source: 'unresolved' };
|
|
651
|
+
};
|
|
652
|
+
const applicationResolved = getCore('Application');
|
|
653
|
+
const frameResolved = getCore('Frame');
|
|
654
|
+
const pageResolved = getCore('Page');
|
|
655
|
+
const labelResolved = getCore('Label');
|
|
656
|
+
const activityResolved = getCore('ActivityIndicator');
|
|
657
|
+
const Application = applicationResolved.value;
|
|
658
|
+
const Frame = frameResolved.value;
|
|
659
|
+
const Page = pageResolved.value;
|
|
660
|
+
const Label = labelResolved.value;
|
|
661
|
+
const ActivityIndicator = activityResolved.value;
|
|
662
|
+
if (!Application) {
|
|
663
|
+
if (verbose) {
|
|
664
|
+
console.warn('[ns-placeholder] Application unavailable', {
|
|
665
|
+
resolution: {
|
|
666
|
+
Application: applicationResolved.source,
|
|
667
|
+
Frame: frameResolved.source,
|
|
668
|
+
Page: pageResolved.source,
|
|
669
|
+
Label: labelResolved.source,
|
|
670
|
+
},
|
|
671
|
+
moduleApis: {
|
|
672
|
+
moduleExists: typeof g.moduleExists === 'function',
|
|
673
|
+
loadModule: typeof g.loadModule === 'function',
|
|
674
|
+
uiModuleRegistered: typeof g.moduleExists === 'function' ? !!g.moduleExists('@nativescript/core/ui') : false,
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
g['__NS_DEV_PLACEHOLDER_APPLICATION__'] = Application;
|
|
681
|
+
const isAndroid = !!(g.__ANDROID__ || typeof g.android !== 'undefined');
|
|
682
|
+
// Patch `Application.resetRootView` on BOTH platforms so the placeholder
|
|
683
|
+
// finalize callback (`__NS_DEV_RESTORE_PLACEHOLDER__`) fires every time
|
|
684
|
+
// the framework swaps the root view.
|
|
685
|
+
//
|
|
686
|
+
// History: this used to be gated behind `!isAndroid` on the assumption
|
|
687
|
+
// that `core-aliases-early.ts` already installs an Android-specific
|
|
688
|
+
// `resetRootView` wrapper. That early hook is unreliable in HTTP HMR
|
|
689
|
+
// boot — it runs before `@nativescript/core/bundle-entry-points`, so
|
|
690
|
+
// `g.Application` is undefined when it runs and the wrapper is silently
|
|
691
|
+
// skipped. By the time `installRootPlaceholder` reaches this point,
|
|
692
|
+
// `getCore('Application')` has resolved a real Application (the
|
|
693
|
+
// placeholder UI is already showing, which proves it), so wrapping here
|
|
694
|
+
// works on Android too. We also coordinate with the early hook's flag
|
|
695
|
+
// (`__NS_DEV_PATCHED_RESET_ROOT__`) so we never double-wrap if it did
|
|
696
|
+
// install successfully.
|
|
697
|
+
const earlyAndroidWrapped = !!g['__NS_DEV_PATCHED_RESET_ROOT__'];
|
|
698
|
+
// Verbose-gated. Previously this was unconditional with a
|
|
699
|
+
// `__NS_PLACEHOLDER_DIAG_SILENT__` opt-out — needed while we
|
|
700
|
+
// were debugging the Android "Waiting for the app root view"
|
|
701
|
+
// stall. Now that Layer 1-9 fixes have landed, the diag stream
|
|
702
|
+
// (resetRootView wraps, launch-handler entries, placeholder
|
|
703
|
+
// install state) is only useful when investigating a new
|
|
704
|
+
// stall, so it follows the user's `verbose` opt-in.
|
|
705
|
+
const diag = verbose
|
|
706
|
+
? (...args) => {
|
|
707
|
+
try {
|
|
708
|
+
console.warn('[ns-placeholder][diag]', ...args);
|
|
709
|
+
}
|
|
710
|
+
catch { }
|
|
711
|
+
}
|
|
712
|
+
: () => { };
|
|
713
|
+
diag('install entry', {
|
|
714
|
+
platform: isAndroid ? 'android' : 'ios',
|
|
715
|
+
applicationSource: applicationResolved.source,
|
|
716
|
+
applicationType: Application?.constructor?.name,
|
|
717
|
+
hasReset: typeof Application.resetRootView === 'function',
|
|
718
|
+
alreadyPatchedEarly: earlyAndroidWrapped,
|
|
719
|
+
alreadyPatchedView: !!g['__NS_DEV_PATCHED_RESET_ROOT_VIEW__'],
|
|
720
|
+
globalApplicationSame: g.Application === Application,
|
|
721
|
+
vendorApplicationSame: (() => {
|
|
722
|
+
try {
|
|
723
|
+
const v = g.__nsVendorRegistry?.get?.('@nativescript/core');
|
|
724
|
+
return v?.Application === Application || v?.default?.Application === Application;
|
|
725
|
+
}
|
|
726
|
+
catch {
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
})(),
|
|
730
|
+
});
|
|
731
|
+
// Always patch every Application instance we can find. The early
|
|
732
|
+
// Android hook in `core-aliases-early.ts` only patches `g.Application`
|
|
733
|
+
// (the bundled realm's Application) and its prototype — but on Vite
|
|
734
|
+
// HMR there can be a SECOND Application loaded by the HTTP realm
|
|
735
|
+
// (`vendor-registry @nativescript/core`) that Angular's `import { Application }`
|
|
736
|
+
// actually resolves to. If we don't patch that twin too, Angular's
|
|
737
|
+
// `Application.resetRootView({ create: () => doc })` lands on an
|
|
738
|
+
// unpatched object, the placeholder finalize callback is never
|
|
739
|
+
// invoked, and the boot stalls at "Waiting for the app root view".
|
|
740
|
+
const makePatched = (origReset, label) => function __ns_dev_patched_reset_root_view(entry) {
|
|
741
|
+
diag(`patched resetRootView called (${label})`, {
|
|
742
|
+
hasEntry: !!entry,
|
|
743
|
+
entryKind: entry?.create ? 'create-fn' : entry?.moduleName ? 'module-name' : typeof entry,
|
|
744
|
+
});
|
|
745
|
+
const result = origReset(entry);
|
|
746
|
+
try {
|
|
747
|
+
const restore = g['__NS_DEV_RESTORE_PLACEHOLDER__'];
|
|
748
|
+
if (typeof restore === 'function') {
|
|
749
|
+
restore(`Application.resetRootView (${label})`);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
catch (e) {
|
|
753
|
+
diag('patched resetRootView restore threw', String(e && (e.message || e)));
|
|
754
|
+
}
|
|
755
|
+
return result;
|
|
756
|
+
};
|
|
757
|
+
const wrapOnce = (target, label) => {
|
|
38
758
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
759
|
+
if (!target || typeof target.resetRootView !== 'function')
|
|
760
|
+
return false;
|
|
761
|
+
if (target.resetRootView.__ns_dev_placeholder_wrap === true)
|
|
762
|
+
return false;
|
|
763
|
+
const orig = target.resetRootView.bind(target);
|
|
764
|
+
const wrapped = makePatched(orig, label);
|
|
765
|
+
wrapped.__ns_dev_placeholder_wrap = true;
|
|
766
|
+
target.resetRootView = wrapped;
|
|
767
|
+
return true;
|
|
768
|
+
}
|
|
769
|
+
catch {
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
const wrappedLocal = wrapOnce(Application, 'local');
|
|
774
|
+
const wrappedGlobal = g.Application && g.Application !== Application ? wrapOnce(g.Application, 'global') : false;
|
|
775
|
+
const wrappedProto = (() => {
|
|
776
|
+
try {
|
|
777
|
+
const proto = Object.getPrototypeOf(Application);
|
|
778
|
+
return wrapOnce(proto, 'proto');
|
|
779
|
+
}
|
|
780
|
+
catch {
|
|
781
|
+
return false;
|
|
782
|
+
}
|
|
783
|
+
})();
|
|
784
|
+
// Vendor-realm Application coverage. Even when `earlyAndroidWrapped`
|
|
785
|
+
// is true, the early hook only touched `g.Application` + its proto;
|
|
786
|
+
// the vendor's Application is a separate object with its own
|
|
787
|
+
// `resetRootView` that the early hook never sees.
|
|
788
|
+
let wrappedVendor = false;
|
|
789
|
+
let wrappedVendorAppModule = false;
|
|
790
|
+
try {
|
|
791
|
+
const reg = g.__nsVendorRegistry;
|
|
792
|
+
if (reg && typeof reg.get === 'function') {
|
|
793
|
+
const vendorCore = reg.get('@nativescript/core');
|
|
794
|
+
const vendorApp = vendorCore?.Application || vendorCore?.default?.Application;
|
|
795
|
+
if (vendorApp && vendorApp !== Application) {
|
|
796
|
+
wrappedVendor = wrapOnce(vendorApp, 'vendor-core');
|
|
41
797
|
try {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (ns && ns[name])
|
|
47
|
-
return ns[name];
|
|
798
|
+
const vp = Object.getPrototypeOf(vendorApp);
|
|
799
|
+
if (vp && vp !== Object.getPrototypeOf(Application)) {
|
|
800
|
+
wrapOnce(vp, 'vendor-core-proto');
|
|
801
|
+
}
|
|
48
802
|
}
|
|
49
803
|
catch { }
|
|
50
804
|
}
|
|
805
|
+
const vendorAppMod = reg.get('@nativescript/core/application');
|
|
806
|
+
const vendorAppOnly = vendorAppMod?.Application || vendorAppMod?.default?.Application;
|
|
807
|
+
if (vendorAppOnly && vendorAppOnly !== Application && vendorAppOnly !== vendorApp) {
|
|
808
|
+
wrappedVendorAppModule = wrapOnce(vendorAppOnly, 'vendor-application');
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
catch { }
|
|
813
|
+
// Track every Application instance we know about so
|
|
814
|
+
// `tryFinalizeBootPlaceholder` can poll the real root view on the
|
|
815
|
+
// instance Angular actually committed to.
|
|
816
|
+
try {
|
|
817
|
+
const apps = (g['__NS_DEV_KNOWN_APPLICATIONS__'] || (g['__NS_DEV_KNOWN_APPLICATIONS__'] = []));
|
|
818
|
+
const push = (a) => {
|
|
819
|
+
if (a && apps.indexOf(a) === -1)
|
|
820
|
+
apps.push(a);
|
|
821
|
+
};
|
|
822
|
+
push(Application);
|
|
823
|
+
push(g.Application);
|
|
824
|
+
try {
|
|
825
|
+
const reg = g.__nsVendorRegistry;
|
|
826
|
+
if (reg && typeof reg.get === 'function') {
|
|
827
|
+
const vendorCore = reg.get('@nativescript/core');
|
|
828
|
+
push(vendorCore?.Application);
|
|
829
|
+
push(vendorCore?.default?.Application);
|
|
830
|
+
const vendorAppMod = reg.get('@nativescript/core/application');
|
|
831
|
+
push(vendorAppMod?.Application);
|
|
832
|
+
push(vendorAppMod?.default?.Application);
|
|
833
|
+
}
|
|
51
834
|
}
|
|
52
835
|
catch { }
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
836
|
+
}
|
|
837
|
+
catch { }
|
|
838
|
+
g['__NS_DEV_PATCHED_RESET_ROOT_VIEW__'] = true;
|
|
839
|
+
g['__NS_DEV_PATCHED_RESET_ROOT__'] = true;
|
|
840
|
+
diag('patched Application.resetRootView', {
|
|
841
|
+
platform: isAndroid ? 'android' : 'ios',
|
|
842
|
+
wrappedLocal,
|
|
843
|
+
wrappedGlobal,
|
|
844
|
+
wrappedProto,
|
|
845
|
+
wrappedVendor,
|
|
846
|
+
wrappedVendorAppModule,
|
|
847
|
+
knownApplications: (g['__NS_DEV_KNOWN_APPLICATIONS__'] || []).length,
|
|
848
|
+
});
|
|
849
|
+
const canCreatePlaceholderRoot = !!Frame && !!Page && !!Label;
|
|
850
|
+
if (!canCreatePlaceholderRoot && verbose) {
|
|
851
|
+
console.warn('[ns-placeholder] visual placeholder unavailable; starting lifecycle without placeholder root', {
|
|
852
|
+
resolution: {
|
|
853
|
+
Application: applicationResolved.source,
|
|
854
|
+
Frame: frameResolved.source,
|
|
855
|
+
Page: pageResolved.source,
|
|
856
|
+
Label: labelResolved.source,
|
|
857
|
+
ActivityIndicator: activityResolved.source,
|
|
858
|
+
},
|
|
859
|
+
moduleApis: {
|
|
860
|
+
moduleExists: typeof g.moduleExists === 'function',
|
|
861
|
+
loadModule: typeof g.loadModule === 'function',
|
|
862
|
+
uiModuleRegistered: typeof g.moduleExists === 'function' ? !!g.moduleExists('@nativescript/core/ui') : false,
|
|
863
|
+
},
|
|
864
|
+
});
|
|
64
865
|
}
|
|
65
866
|
let handlerFired = false;
|
|
66
867
|
// launchEvent handler: provides a placeholder root, then patches Application.run
|
|
67
868
|
const __ns_launch_handler = (args) => {
|
|
869
|
+
diag('launch handler fired', {
|
|
870
|
+
hasArgs: !!args,
|
|
871
|
+
hasExistingRoot: !!args?.root,
|
|
872
|
+
existingRootType: args?.root?.constructor?.name,
|
|
873
|
+
hasLaunched: typeof Application.hasLaunched === 'function' ? !!Application.hasLaunched() : undefined,
|
|
874
|
+
started: !!Application.started,
|
|
875
|
+
});
|
|
68
876
|
try {
|
|
69
877
|
const prev = args?.root;
|
|
70
|
-
if (!prev && Frame && Page && Label) {
|
|
71
|
-
const
|
|
72
|
-
const page =
|
|
73
|
-
page.actionBarHidden = true;
|
|
74
|
-
const titleLabel = new Label();
|
|
75
|
-
titleLabel.text = 'Starting NativeScript + Vite dev server…';
|
|
76
|
-
titleLabel.textAlignment = 'center';
|
|
77
|
-
titleLabel.textWrap = true;
|
|
78
|
-
titleLabel.fontSize = 20;
|
|
79
|
-
const statusLabel = new Label();
|
|
80
|
-
statusLabel.text = 'Preparing the HTTP HMR bootstrap (4%)';
|
|
81
|
-
statusLabel.textAlignment = 'center';
|
|
82
|
-
statusLabel.textWrap = true;
|
|
83
|
-
statusLabel.fontSize = 14;
|
|
84
|
-
statusLabel.marginTop = 12;
|
|
85
|
-
const activityIndicator = ActivityIndicator
|
|
86
|
-
? (() => {
|
|
87
|
-
const indicator = new ActivityIndicator();
|
|
88
|
-
indicator.busy = true;
|
|
89
|
-
indicator.marginTop = 16;
|
|
90
|
-
indicator.width = 28;
|
|
91
|
-
indicator.height = 28;
|
|
92
|
-
indicator.horizontalAlignment = 'center';
|
|
93
|
-
return indicator;
|
|
94
|
-
})()
|
|
95
|
-
: null;
|
|
96
|
-
if (StackLayout) {
|
|
97
|
-
const root = new StackLayout();
|
|
98
|
-
root.padding = 24;
|
|
99
|
-
root.verticalAlignment = 'middle';
|
|
100
|
-
root.horizontalAlignment = 'center';
|
|
101
|
-
root.addChild(titleLabel);
|
|
102
|
-
root.addChild(statusLabel);
|
|
103
|
-
if (activityIndicator) {
|
|
104
|
-
root.addChild(activityIndicator);
|
|
105
|
-
}
|
|
106
|
-
page.content = root;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
// Fallback: just show the title label centered
|
|
110
|
-
titleLabel.verticalAlignment = 'middle';
|
|
111
|
-
titleLabel.horizontalAlignment = 'center';
|
|
112
|
-
titleLabel.width = 280;
|
|
113
|
-
titleLabel.padding = 12;
|
|
114
|
-
page.content = titleLabel;
|
|
115
|
-
}
|
|
116
|
-
// Store refs so the overlay API can update the status label
|
|
878
|
+
if (!prev && canCreatePlaceholderRoot && Frame && Page && Label) {
|
|
879
|
+
const built = buildPlaceholderPage({ Page, Label, ActivityIndicator, StackLayout: getCore('StackLayout').value, GridLayout: getCore('GridLayout').value, ContentView: getCore('ContentView').value, Image: getCore('Image').value, Color: getCore('Color').value, verbose });
|
|
880
|
+
const { page, statusLabel, detailLabel, progressFill, activityIndicator } = built;
|
|
117
881
|
g['__NS_DEV_BOOT_STATUS_LABEL__'] = statusLabel;
|
|
882
|
+
g['__NS_DEV_BOOT_DETAIL_LABEL__'] = detailLabel;
|
|
883
|
+
g['__NS_DEV_BOOT_PROGRESS_FILL__'] = progressFill;
|
|
118
884
|
g['__NS_DEV_BOOT_ACTIVITY_INDICATOR__'] = activityIndicator;
|
|
119
885
|
const frame = new Frame();
|
|
120
886
|
frame.navigate({ create: () => page, clearHistory: true, animated: false });
|
|
@@ -124,6 +890,14 @@ export function installRootPlaceholder(verbose) {
|
|
|
124
890
|
g['__NS_DEV_PLACEHOLDER_ROOT_VIEW__'] = frame;
|
|
125
891
|
}
|
|
126
892
|
catch { }
|
|
893
|
+
if (verbose) {
|
|
894
|
+
console.info('[ns-placeholder] assigned placeholder root', {
|
|
895
|
+
frameType: frame?.constructor?.name,
|
|
896
|
+
pageType: page?.constructor?.name,
|
|
897
|
+
hasProgressFill: !!progressFill,
|
|
898
|
+
hasActivityIndicator: !!activityIndicator,
|
|
899
|
+
});
|
|
900
|
+
}
|
|
127
901
|
if (args)
|
|
128
902
|
args.root = frame;
|
|
129
903
|
}
|
|
@@ -144,76 +918,121 @@ export function installRootPlaceholder(verbose) {
|
|
|
144
918
|
if (Application && typeof Application.run === 'function') {
|
|
145
919
|
const _originalRun = Application.run.bind(Application);
|
|
146
920
|
g['__NS_DEV_ORIGINAL_APP_RUN__'] = _originalRun;
|
|
921
|
+
// HMR ordering invariant: the patched `Application.run` MUST yield
|
|
922
|
+
// back to the synchronous caller before any iOS view-lifecycle event
|
|
923
|
+
// fires on the new root view.
|
|
924
|
+
//
|
|
925
|
+
// Concrete bug this guards against: nativescript-vue's `app.start()` is
|
|
926
|
+
// const componentInstance = app.mount(createAppRoot(), false, false);
|
|
927
|
+
// startApp(componentInstance); // → Application.run({ create: … })
|
|
928
|
+
// setRootApp(app); // — sets the module-private `rootApp`
|
|
929
|
+
// In a non-HMR build `Application.run` is `UIApplicationMain`, which
|
|
930
|
+
// returns control to the iOS runloop and lets `setRootApp(app)` execute
|
|
931
|
+
// before any `loaded`/`traitCollectionDidChange` callbacks fire. Under
|
|
932
|
+
// HMR `Application.run` is replaced with synchronous `resetRootView`,
|
|
933
|
+
// which attaches the root to the window *inside* this call — iOS then
|
|
934
|
+
// synchronously fires `loaded` on the new view tree, a TabView handler
|
|
935
|
+
// calls `nativescript-vue`'s `createNativeView`, that reads
|
|
936
|
+
// `rootApp._context`, and crashes with
|
|
937
|
+
// TypeError: Cannot read properties of null (reading '_context')
|
|
938
|
+
// because `setRootApp(app)` hasn't run yet.
|
|
939
|
+
//
|
|
940
|
+
// `setRootApp` is module-private inside the vendor bundle, so the bridge
|
|
941
|
+
// cannot call it directly. Deferring the synchronous root attachment to a
|
|
942
|
+
// microtask restores the production timing: every consumer that called
|
|
943
|
+
// `Application.run(entry)` completes its tail (including private state
|
|
944
|
+
// setters like `setRootApp`) before iOS triggers lifecycle on the new
|
|
945
|
+
// root. The microtask runs before any I/O or DOM-tick boundary, so the UI
|
|
946
|
+
// still appears in the same iOS runloop turn — no user-visible delay.
|
|
147
947
|
const __ns_dev_patched_run = function __ns_dev_patched_run(entry) {
|
|
948
|
+
diag('patched Application.run called', {
|
|
949
|
+
hasEntry: !!entry,
|
|
950
|
+
entryKind: entry?.create ? 'create-fn' : entry?.moduleName ? 'module-name' : typeof entry,
|
|
951
|
+
});
|
|
952
|
+
// Detach the launch handler synchronously: by the time the caller
|
|
953
|
+
// returned from `Application.run()`, the framework owns root-view
|
|
954
|
+
// management, and we must not re-enter the placeholder path on a
|
|
955
|
+
// subsequent launch tick.
|
|
148
956
|
try {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (Application && Application.off) {
|
|
152
|
-
Application.off(Application.launchEvent, __ns_launch_handler);
|
|
153
|
-
}
|
|
957
|
+
if (Application && Application.off) {
|
|
958
|
+
Application.off(Application.launchEvent, __ns_launch_handler);
|
|
154
959
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
960
|
+
}
|
|
961
|
+
catch { }
|
|
962
|
+
// Frameworks (notably Angular) call `Application.run()` with no
|
|
963
|
+
// entry — they own the root via launch events and `resetRootView()`
|
|
964
|
+
// directly. Bailing here keeps `resetRootView(undefined)` from
|
|
965
|
+
// throwing "Main entry is missing".
|
|
966
|
+
if (!entry) {
|
|
967
|
+
diag('patched run() called with no entry; framework manages root view');
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
// Snapshot for the deferred body so a later mutation by the caller
|
|
971
|
+
// can't observe a half-finished closure.
|
|
972
|
+
const __ns_deferred_entry = entry;
|
|
973
|
+
const __ns_deferred_reset = () => {
|
|
974
|
+
try {
|
|
975
|
+
const isModuleNameEntry = __ns_deferred_entry && __ns_deferred_entry.moduleName && !__ns_deferred_entry.create;
|
|
976
|
+
if (isModuleNameEntry) {
|
|
977
|
+
if (typeof Application.resetRootView === 'function') {
|
|
978
|
+
Application.resetRootView(__ns_deferred_entry);
|
|
979
|
+
}
|
|
170
980
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
981
|
+
else {
|
|
982
|
+
// Framework path: two-phase boot with dominative document
|
|
983
|
+
Application._rootView = null;
|
|
984
|
+
try {
|
|
985
|
+
const domModule = g.__nsVendorRegistry?.get?.('dominative') ||
|
|
986
|
+
(typeof require === 'function'
|
|
987
|
+
? (() => {
|
|
988
|
+
try {
|
|
989
|
+
return require('dominative');
|
|
990
|
+
}
|
|
991
|
+
catch {
|
|
992
|
+
return null;
|
|
993
|
+
}
|
|
994
|
+
})()
|
|
995
|
+
: null);
|
|
996
|
+
const doc = domModule?.document;
|
|
997
|
+
if (doc && typeof Application.resetRootView === 'function') {
|
|
998
|
+
Application.resetRootView({ create: () => doc });
|
|
999
|
+
if (__ns_deferred_entry && typeof __ns_deferred_entry.create === 'function') {
|
|
1000
|
+
__ns_deferred_entry.create();
|
|
1001
|
+
}
|
|
192
1002
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
1003
|
+
else {
|
|
1004
|
+
if (typeof Application.resetRootView === 'function') {
|
|
1005
|
+
Application.resetRootView(__ns_deferred_entry);
|
|
1006
|
+
}
|
|
197
1007
|
}
|
|
198
1008
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
1009
|
+
catch (e2) {
|
|
1010
|
+
if (verbose)
|
|
1011
|
+
console.warn('[ns-placeholder] two-phase boot failed:', e2?.message || e2);
|
|
1012
|
+
try {
|
|
1013
|
+
if (typeof Application.resetRootView === 'function') {
|
|
1014
|
+
Application.resetRootView(__ns_deferred_entry);
|
|
1015
|
+
}
|
|
206
1016
|
}
|
|
1017
|
+
catch { }
|
|
207
1018
|
}
|
|
208
|
-
catch { }
|
|
209
1019
|
}
|
|
210
1020
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
1021
|
+
catch (e) {
|
|
1022
|
+
console.warn('[ns-placeholder] deferred patched run() error:', e);
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
// Microtask-defer. `Promise.resolve().then(...)` lands the callback
|
|
1026
|
+
// in the same iOS runloop turn — no perceptible delay — but only
|
|
1027
|
+
// after the synchronous call stack that invoked `Application.run`
|
|
1028
|
+
// has fully unwound, so `nativescript-vue`'s post-`startApp` code
|
|
1029
|
+
// (`setRootApp(app);`) has executed before any view lifecycle fires.
|
|
1030
|
+
Promise.resolve().then(__ns_deferred_reset);
|
|
215
1031
|
};
|
|
216
1032
|
Application.run = __ns_dev_patched_run;
|
|
1033
|
+
if (verbose) {
|
|
1034
|
+
console.info('[ns-placeholder] patched Application.run');
|
|
1035
|
+
}
|
|
217
1036
|
if (g.Application && g.Application !== Application) {
|
|
218
1037
|
g.Application.run = __ns_dev_patched_run;
|
|
219
1038
|
}
|
|
@@ -229,6 +1048,7 @@ export function installRootPlaceholder(verbose) {
|
|
|
229
1048
|
catch { }
|
|
230
1049
|
}
|
|
231
1050
|
};
|
|
1051
|
+
g['__NS_DEV_PLACEHOLDER_LAUNCH_HANDLER__'] = __ns_launch_handler;
|
|
232
1052
|
try {
|
|
233
1053
|
if (Application && Application.on) {
|
|
234
1054
|
Application.on(Application.launchEvent, __ns_launch_handler);
|
|
@@ -237,20 +1057,68 @@ export function installRootPlaceholder(verbose) {
|
|
|
237
1057
|
catch { }
|
|
238
1058
|
// Determine boot path
|
|
239
1059
|
try {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
1060
|
+
const appAny = Application;
|
|
1061
|
+
const methodState = {
|
|
1062
|
+
hasRun: typeof appAny?.run === 'function',
|
|
1063
|
+
hasOn: typeof appAny?.on === 'function',
|
|
1064
|
+
hasOff: typeof appAny?.off === 'function',
|
|
1065
|
+
hasHasLaunched: typeof appAny?.hasLaunched === 'function',
|
|
1066
|
+
hasGetRootView: typeof appAny?.getRootView === 'function',
|
|
1067
|
+
hasResetRootView: typeof appAny?.resetRootView === 'function',
|
|
1068
|
+
hasRunAsMainApp: typeof appAny?.runAsMainApp === 'function',
|
|
1069
|
+
type: appAny?.constructor?.name,
|
|
1070
|
+
};
|
|
1071
|
+
if (verbose) {
|
|
1072
|
+
console.info('[ns-placeholder] application methods', methodState);
|
|
1073
|
+
console.info('[ns-placeholder] application source', applicationResolved.source);
|
|
1074
|
+
}
|
|
1075
|
+
if (!appAny || typeof appAny.run !== 'function') {
|
|
1076
|
+
console.warn('[ns-placeholder] Application.run unavailable', {
|
|
1077
|
+
...methodState,
|
|
1078
|
+
source: applicationResolved.source,
|
|
1079
|
+
});
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
const hasLaunched = typeof appAny.hasLaunched === 'function' ? !!appAny.hasLaunched() : false;
|
|
1083
|
+
const hasRootView = typeof appAny.getRootView === 'function' ? !!appAny.getRootView() : false;
|
|
1084
|
+
const started = !!appAny.started;
|
|
1085
|
+
const nativeApp = appAny.nativeApp;
|
|
1086
|
+
const iosNativeApp = appAny.ios?.nativeApp;
|
|
1087
|
+
const canRunAsMainApp = typeof appAny.runAsMainApp === 'function';
|
|
1088
|
+
if (verbose) {
|
|
1089
|
+
console.info('[ns-placeholder] boot state', {
|
|
1090
|
+
hasLaunched,
|
|
1091
|
+
hasRootView,
|
|
1092
|
+
started,
|
|
1093
|
+
nativeApp: !!nativeApp,
|
|
1094
|
+
iosNativeApp: !!iosNativeApp,
|
|
1095
|
+
canRunAsMainApp,
|
|
1096
|
+
hasResetRootView: typeof appAny.resetRootView === 'function',
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
if (hasLaunched || hasRootView) {
|
|
1100
|
+
// App lifecycle is already active. Skip starting it again and only install
|
|
1101
|
+
// the placeholder root/patching behavior for the existing instance.
|
|
1102
|
+
if (verbose) {
|
|
1103
|
+
console.info('[ns-placeholder] boot branch: existing lifecycle');
|
|
1104
|
+
}
|
|
1105
|
+
try {
|
|
1106
|
+
__ns_launch_handler();
|
|
250
1107
|
}
|
|
251
|
-
|
|
252
|
-
|
|
1108
|
+
catch { }
|
|
1109
|
+
}
|
|
1110
|
+
else if (canRunAsMainApp) {
|
|
1111
|
+
if (verbose) {
|
|
1112
|
+
console.info('[ns-placeholder] boot branch: runAsMainApp');
|
|
1113
|
+
}
|
|
1114
|
+
appAny.started = true;
|
|
1115
|
+
appAny.runAsMainApp();
|
|
1116
|
+
}
|
|
1117
|
+
else {
|
|
1118
|
+
if (verbose) {
|
|
1119
|
+
console.info('[ns-placeholder] boot branch: Application.run');
|
|
253
1120
|
}
|
|
1121
|
+
appAny.run();
|
|
254
1122
|
}
|
|
255
1123
|
}
|
|
256
1124
|
catch (e) {
|