@nativescript/vite 0.0.1 → 0.0.2
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/LICENSE +19 -0
- package/README.md +44 -0
- package/{dist/configuration → configuration}/angular.d.ts +1 -1
- package/configuration/angular.js +480 -0
- package/configuration/angular.js.map +1 -0
- package/configuration/base.d.ts +5 -0
- package/configuration/base.js +494 -0
- package/configuration/base.js.map +1 -0
- package/configuration/javascript.d.ts +4 -0
- package/configuration/javascript.js +151 -0
- package/configuration/javascript.js.map +1 -0
- package/{dist/configuration → configuration}/react.d.ts +1 -1
- package/{dist/configuration → configuration}/react.js +18 -17
- package/configuration/react.js.map +1 -0
- package/{dist/configuration → configuration}/solid.d.ts +1 -1
- package/{dist/configuration → configuration}/solid.js +17 -16
- package/configuration/solid.js.map +1 -0
- package/configuration/typescript.d.ts +4 -0
- package/configuration/typescript.js +175 -0
- package/configuration/typescript.js.map +1 -0
- package/{dist/configuration → configuration}/vue.d.ts +1 -1
- package/configuration/vue.js +163 -0
- package/configuration/vue.js.map +1 -0
- package/helpers/angular-linker.d.ts +13 -0
- package/helpers/angular-linker.js +181 -0
- package/helpers/angular-linker.js.map +1 -0
- package/helpers/cli-flags.d.ts +1 -0
- package/helpers/cli-flags.js +15 -0
- package/helpers/cli-flags.js.map +1 -0
- package/{dist/helpers → helpers}/commonjs-plugins.js +14 -13
- package/helpers/commonjs-plugins.js.map +1 -0
- package/{dist/helpers → helpers}/config-as-json.d.ts +1 -1
- package/{dist/helpers → helpers}/config-as-json.js +7 -6
- package/helpers/config-as-json.js.map +1 -0
- package/helpers/css-platform-plugin.d.ts +10 -0
- package/helpers/css-platform-plugin.js +76 -0
- package/helpers/css-platform-plugin.js.map +1 -0
- package/helpers/css-tree.js +22 -0
- package/helpers/css-tree.js.map +1 -0
- package/{dist/helpers → helpers}/dynamic-import-plugin.js +8 -7
- package/helpers/dynamic-import-plugin.js.map +1 -0
- package/helpers/esbuild-platform-resolver.d.ts +14 -0
- package/helpers/esbuild-platform-resolver.js +93 -0
- package/helpers/esbuild-platform-resolver.js.map +1 -0
- package/helpers/external-configs.d.ts +6 -0
- package/helpers/external-configs.js +34 -0
- package/helpers/external-configs.js.map +1 -0
- package/{dist/helpers → helpers}/flavor.d.ts +1 -0
- package/helpers/flavor.js +51 -0
- package/helpers/flavor.js.map +1 -0
- package/{dist/helpers → helpers}/global-defines.d.ts +11 -2
- package/helpers/global-defines.js +24 -0
- package/helpers/global-defines.js.map +1 -0
- package/helpers/logging.d.ts +13 -0
- package/helpers/logging.js +111 -0
- package/helpers/logging.js.map +1 -0
- package/helpers/main-entry.d.ts +10 -0
- package/helpers/main-entry.js +215 -0
- package/helpers/main-entry.js.map +1 -0
- package/{dist/helpers → helpers}/module-resolution.js +4 -3
- package/helpers/module-resolution.js.map +1 -0
- package/helpers/module-runner-patch.d.ts +3 -0
- package/helpers/module-runner-patch.js +63 -0
- package/helpers/module-runner-patch.js.map +1 -0
- package/helpers/nativeclass-transform.d.ts +7 -0
- package/helpers/nativeclass-transform.js +158 -0
- package/helpers/nativeclass-transform.js.map +1 -0
- package/helpers/nativeclass-transformer-plugin.d.ts +5 -0
- package/helpers/nativeclass-transformer-plugin.js +23 -0
- package/helpers/nativeclass-transformer-plugin.js.map +1 -0
- package/{dist/helpers → helpers}/nativescript-package-resolver.js +18 -17
- package/helpers/nativescript-package-resolver.js.map +1 -0
- package/helpers/ns-cli-plugins.d.ts +14 -0
- package/helpers/ns-cli-plugins.js +165 -0
- package/helpers/ns-cli-plugins.js.map +1 -0
- package/helpers/package-platform-aliases.d.ts +10 -0
- package/{dist/helpers → helpers}/package-platform-aliases.js +19 -23
- package/helpers/package-platform-aliases.js.map +1 -0
- package/helpers/postcss-platform-config.d.ts +13 -0
- package/helpers/postcss-platform-config.js +97 -0
- package/helpers/postcss-platform-config.js.map +1 -0
- package/helpers/prelink-angular.d.ts +2 -0
- package/helpers/prelink-angular.js +117 -0
- package/helpers/prelink-angular.js.map +1 -0
- package/helpers/preserve-imports.d.ts +2 -0
- package/helpers/preserve-imports.js +38 -0
- package/helpers/preserve-imports.js.map +1 -0
- package/{dist/helpers → helpers}/project.js +2 -4
- package/helpers/project.js.map +1 -0
- package/helpers/resolver.d.ts +4 -0
- package/{dist/helpers → helpers}/resolver.js +7 -6
- package/helpers/resolver.js.map +1 -0
- package/helpers/theme-core-plugins.d.ts +14 -0
- package/helpers/theme-core-plugins.js +121 -0
- package/helpers/theme-core-plugins.js.map +1 -0
- package/helpers/ts-config-paths.d.ts +10 -0
- package/{dist/helpers → helpers}/ts-config-paths.js +73 -72
- package/helpers/ts-config-paths.js.map +1 -0
- package/{dist/helpers → helpers}/utils.d.ts +6 -0
- package/{dist/helpers → helpers}/utils.js +28 -34
- package/helpers/utils.js.map +1 -0
- package/{dist/helpers → helpers}/workers.js +15 -16
- package/helpers/workers.js.map +1 -0
- package/hmr/client/css-handler.d.ts +4 -0
- package/hmr/client/css-handler.js +78 -0
- package/hmr/client/css-handler.js.map +1 -0
- package/hmr/client/index.d.ts +13 -0
- package/hmr/client/index.js +1550 -0
- package/hmr/client/index.js.map +1 -0
- package/hmr/client/utils.d.ts +38 -0
- package/hmr/client/utils.js +426 -0
- package/hmr/client/utils.js.map +1 -0
- package/hmr/entry-runtime.d.ts +8 -0
- package/hmr/entry-runtime.js +135 -0
- package/hmr/entry-runtime.js.map +1 -0
- package/hmr/frameworks/angular/server/strategy.d.ts +2 -0
- package/hmr/frameworks/angular/server/strategy.js +101 -0
- package/hmr/frameworks/angular/server/strategy.js.map +1 -0
- package/hmr/frameworks/vue/client/index.d.ts +22 -0
- package/hmr/frameworks/vue/client/index.js +1537 -0
- package/hmr/frameworks/vue/client/index.js.map +1 -0
- package/hmr/frameworks/vue/server/compiler.d.ts +11 -0
- package/hmr/frameworks/vue/server/compiler.js +26 -0
- package/hmr/frameworks/vue/server/compiler.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-transforms.d.ts +14 -0
- package/hmr/frameworks/vue/server/sfc-transforms.js +282 -0
- package/hmr/frameworks/vue/server/sfc-transforms.js.map +1 -0
- package/hmr/frameworks/vue/server/strategy.d.ts +2 -0
- package/hmr/frameworks/vue/server/strategy.js +273 -0
- package/hmr/frameworks/vue/server/strategy.js.map +1 -0
- package/hmr/helpers/ast-extract.d.ts +6 -0
- package/hmr/helpers/ast-extract.js +72 -0
- package/hmr/helpers/ast-extract.js.map +1 -0
- package/hmr/helpers/ast-normalizer.d.ts +7 -0
- package/hmr/helpers/ast-normalizer.js +772 -0
- package/hmr/helpers/ast-normalizer.js.map +1 -0
- package/hmr/helpers/babel.d.ts +3 -0
- package/hmr/helpers/babel.js +17 -0
- package/hmr/helpers/babel.js.map +1 -0
- package/hmr/helpers/sanitize.d.ts +6 -0
- package/hmr/helpers/sanitize.js +55 -0
- package/hmr/helpers/sanitize.js.map +1 -0
- package/hmr/helpers/vendor-rewrite.d.ts +1 -0
- package/hmr/helpers/vendor-rewrite.js +35 -0
- package/hmr/helpers/vendor-rewrite.js.map +1 -0
- package/hmr/server/compiler.d.ts +2 -0
- package/hmr/server/compiler.js +75 -0
- package/hmr/server/compiler.js.map +1 -0
- package/hmr/server/constants.d.ts +14 -0
- package/hmr/server/constants.js +23 -0
- package/hmr/server/constants.js.map +1 -0
- package/hmr/server/core-sanitize.d.ts +32 -0
- package/hmr/server/core-sanitize.js +134 -0
- package/hmr/server/core-sanitize.js.map +1 -0
- package/hmr/server/framework-strategy.d.ts +68 -0
- package/hmr/server/framework-strategy.js +2 -0
- package/hmr/server/framework-strategy.js.map +1 -0
- package/hmr/server/index.d.ts +5 -0
- package/hmr/server/index.js +19 -0
- package/hmr/server/index.js.map +1 -0
- package/hmr/server/vite-plugin.d.ts +5 -0
- package/hmr/server/vite-plugin.js +44 -0
- package/hmr/server/vite-plugin.js.map +1 -0
- package/hmr/server/websocket.d.ts +15 -0
- package/hmr/server/websocket.js +5528 -0
- package/hmr/server/websocket.js.map +1 -0
- package/hmr/shared/runtime/http-only-boot.d.ts +1 -0
- package/hmr/shared/runtime/http-only-boot.js +107 -0
- package/hmr/shared/runtime/http-only-boot.js.map +1 -0
- package/hmr/shared/runtime/root-placeholder.d.ts +1 -0
- package/hmr/shared/runtime/root-placeholder.js +142 -0
- package/hmr/shared/runtime/root-placeholder.js.map +1 -0
- package/hmr/shared/runtime/vendor-bootstrap.d.ts +1 -0
- package/hmr/shared/runtime/vendor-bootstrap.js +134 -0
- package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -0
- package/hmr/shared/vendor/manifest-loader.d.ts +9 -0
- package/hmr/shared/vendor/manifest-loader.js +38 -0
- package/hmr/shared/vendor/manifest-loader.js.map +1 -0
- package/hmr/shared/vendor/manifest.d.ts +34 -0
- package/hmr/shared/vendor/manifest.js +787 -0
- package/hmr/shared/vendor/manifest.js.map +1 -0
- package/hmr/shared/vendor/registry.d.ts +9 -0
- package/hmr/shared/vendor/registry.js +62 -0
- package/hmr/shared/vendor/registry.js.map +1 -0
- package/hmr/vendor-bootstrap.d.ts +3 -0
- package/hmr/vendor-bootstrap.js +32 -0
- package/hmr/vendor-bootstrap.js.map +1 -0
- package/{dist/index.d.ts → index.d.ts} +2 -0
- package/{dist/index.js → index.js} +3 -0
- package/index.js.map +1 -0
- package/package.json +39 -30
- package/{dist/polyfills → polyfills}/mdn-data-at-rules.js +1 -0
- package/polyfills/mdn-data-at-rules.js.map +1 -0
- package/{dist/polyfills → polyfills}/mdn-data-properties.js +1 -0
- package/polyfills/mdn-data-properties.js.map +1 -0
- package/{dist/polyfills → polyfills}/mdn-data-syntaxes.js +1 -0
- package/polyfills/mdn-data-syntaxes.js.map +1 -0
- package/{dist/polyfills → polyfills}/module.js +1 -0
- package/polyfills/module.js.map +1 -0
- package/runtime/core-aliases-early.d.ts +1 -0
- package/runtime/core-aliases-early.js +334 -0
- package/runtime/core-aliases-early.js.map +1 -0
- package/shims/angular-animations-stub.d.ts +8 -0
- package/shims/angular-animations-stub.js +14 -0
- package/shims/angular-animations-stub.js.map +1 -0
- package/shims/node-module.d.ts +5 -0
- package/shims/node-module.js +13 -0
- package/shims/node-module.js.map +1 -0
- package/{dist/shims → shims}/react-reconciler-constants.js +2 -1
- package/shims/react-reconciler-constants.js.map +1 -0
- package/{dist/shims → shims}/react-reconciler.js +1 -0
- package/shims/react-reconciler.js.map +1 -0
- package/{dist/shims → shims}/set-value.js +5 -1
- package/shims/set-value.js.map +1 -0
- package/transformers/NativeClass/index.d.ts +2 -0
- package/transformers/NativeClass/index.js +222 -0
- package/transformers/NativeClass/index.js.map +1 -0
- package/dist/configuration/angular.js +0 -30
- package/dist/configuration/base.d.ts +0 -13
- package/dist/configuration/base.js +0 -228
- package/dist/configuration/old-without-merge-base.d.ts +0 -13
- package/dist/configuration/old-without-merge-base.js +0 -249
- package/dist/configuration/vue.js +0 -45
- package/dist/helpers/css-tree.js +0 -21
- package/dist/helpers/flavor.js +0 -40
- package/dist/helpers/global-defines.js +0 -18
- package/dist/helpers/main-entry.d.ts +0 -5
- package/dist/helpers/main-entry.js +0 -75
- package/dist/helpers/ns-cli-plugins.d.ts +0 -17
- package/dist/helpers/ns-cli-plugins.js +0 -128
- package/dist/helpers/package-platform-aliases.d.ts +0 -4
- package/dist/helpers/resolver.d.ts +0 -4
- package/dist/helpers/ts-config-paths.d.ts +0 -4
- package/dist/hmr/hmr-angular.d.ts +0 -1
- package/dist/hmr/hmr-angular.js +0 -34
- package/dist/hmr/hmr-bridge.d.ts +0 -18
- package/dist/hmr/hmr-bridge.js +0 -154
- package/dist/hmr/hmr-client.d.ts +0 -5
- package/dist/hmr/hmr-client.js +0 -93
- package/dist/hmr/hmr-server.d.ts +0 -20
- package/dist/hmr/hmr-server.js +0 -179
- package/dist/transformers/NativeClass/index.d.ts +0 -5
- package/dist/transformers/NativeClass/index.js +0 -46
- /package/{dist/helpers → helpers}/commonjs-plugins.d.ts +0 -0
- /package/{dist/helpers → helpers}/css-tree.d.ts +0 -0
- /package/{dist/helpers → helpers}/dynamic-import-plugin.d.ts +0 -0
- /package/{dist/helpers → helpers}/module-resolution.d.ts +0 -0
- /package/{dist/helpers → helpers}/nativescript-package-resolver.d.ts +0 -0
- /package/{dist/helpers → helpers}/project.d.ts +0 -0
- /package/{dist/helpers → helpers}/workers.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/mdn-data-at-rules.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/mdn-data-properties.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/mdn-data-syntaxes.d.ts +0 -0
- /package/{dist/polyfills → polyfills}/module.d.ts +0 -0
- /package/{dist/shims → shims}/react-reconciler-constants.d.ts +0 -0
- /package/{dist/shims → shims}/react-reconciler.d.ts +0 -0
- /package/{dist/shims → shims}/set-value.d.ts +0 -0
|
@@ -0,0 +1,1550 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Robust HMR client for NativeScript.
|
|
3
|
+
*
|
|
4
|
+
* Avoid importing from '@nativescript/core' and other framework modules here to prevent creating a second module realm via HTTP ESM.
|
|
5
|
+
* Always resolve core classes and Application from the vendor realm or globalThis at runtime.
|
|
6
|
+
* The HMR client is evaluated via HTTP ESM on device; static imports would create secondary instances.
|
|
7
|
+
*/
|
|
8
|
+
import { setHMRWsUrl, getHMRWsUrl, pendingModuleFetches, deriveHttpOrigin, setHttpOriginForVite, moduleFetchCache, requestModuleFromServer, getHttpOriginForVite, normalizeSpec, hmrMetrics, graph, setGraphVersion, getGraphVersion, getCurrentApp, getRootFrame, setCurrentApp, setRootFrame, getCore, attachDiagnosticsToFrame, logUiSnapshot } from './utils.js';
|
|
9
|
+
import { handleCssUpdates } from './css-handler.js';
|
|
10
|
+
const VERBOSE = typeof __NS_ENV_VERBOSE__ !== 'undefined' && __NS_ENV_VERBOSE__;
|
|
11
|
+
// Policy: by default, let the app's own main entry mount initially; HMR client handles updates/remounts only.
|
|
12
|
+
// Flip this to true via global __NS_HMR_ALLOW_INITIAL_MOUNT__ if you need the client to perform the first mount.
|
|
13
|
+
const ALLOW_INITIAL_MOUNT = !!globalThis.__NS_HMR_ALLOW_INITIAL_MOUNT__;
|
|
14
|
+
// When verbose mode is enabled, also enable runtime nav diagnostics so /ns/rt logs are visible
|
|
15
|
+
try {
|
|
16
|
+
if (VERBOSE) {
|
|
17
|
+
globalThis.__NS_DEV_LOGS__ = true;
|
|
18
|
+
globalThis.__NS_VERBOSE_RT_NAV__ = true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch { }
|
|
22
|
+
// Ensure core aliases are present on globalThis early so that /ns/rt exports resolve to functions
|
|
23
|
+
// before any SFCs are evaluated during HTTP-only dev boot.
|
|
24
|
+
function ensureCoreAliasesOnGlobalThis() {
|
|
25
|
+
const g = globalThis;
|
|
26
|
+
try {
|
|
27
|
+
const F = getCore('Frame') || g.Frame;
|
|
28
|
+
const A = getCore('Application') || g.Application;
|
|
29
|
+
const P = getCore('Page') || g.Page;
|
|
30
|
+
// Publish to globalThis if missing
|
|
31
|
+
try {
|
|
32
|
+
if (F && !g.Frame)
|
|
33
|
+
g.Frame = F;
|
|
34
|
+
}
|
|
35
|
+
catch { }
|
|
36
|
+
try {
|
|
37
|
+
if (A && !g.Application)
|
|
38
|
+
g.Application = A;
|
|
39
|
+
}
|
|
40
|
+
catch { }
|
|
41
|
+
try {
|
|
42
|
+
if (P && !g.Page)
|
|
43
|
+
g.Page = P;
|
|
44
|
+
}
|
|
45
|
+
catch { }
|
|
46
|
+
// Optional diagnostics: compare with vendor realm if available
|
|
47
|
+
if (VERBOSE) {
|
|
48
|
+
let vF, vA, vP;
|
|
49
|
+
try {
|
|
50
|
+
const reg = g.__nsVendorRegistry;
|
|
51
|
+
const vmod = reg?.get ? reg.get('@nativescript/core') : undefined;
|
|
52
|
+
const vns = (vmod && (vmod.default || vmod)) || vmod;
|
|
53
|
+
vF = vns?.Frame;
|
|
54
|
+
vA = vns?.Application;
|
|
55
|
+
vP = vns?.Page;
|
|
56
|
+
}
|
|
57
|
+
catch { }
|
|
58
|
+
try {
|
|
59
|
+
console.log('[hmr-client] core alias status', {
|
|
60
|
+
globalHas: { Frame: !!F, Application: !!A, Page: !!P },
|
|
61
|
+
globalMethods: {
|
|
62
|
+
FrameTopmost: typeof F?.topmost === 'function',
|
|
63
|
+
AppResetRoot: typeof A?.resetRootView === 'function',
|
|
64
|
+
},
|
|
65
|
+
sameRef: {
|
|
66
|
+
Frame: F && vF ? F === vF : undefined,
|
|
67
|
+
Application: A && vA ? A === vA : undefined,
|
|
68
|
+
Page: P && vP ? P === vP : undefined,
|
|
69
|
+
},
|
|
70
|
+
ctorNames: {
|
|
71
|
+
Frame: F?.name || F?.constructor?.name,
|
|
72
|
+
Application: A?.name || A?.constructor?.name,
|
|
73
|
+
Page: P?.name || P?.constructor?.name,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch { }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch { }
|
|
81
|
+
}
|
|
82
|
+
// Apply once on module evaluation
|
|
83
|
+
ensureCoreAliasesOnGlobalThis();
|
|
84
|
+
// Install low-level diagnostics for navigation and root replacement to trace duplicates and state
|
|
85
|
+
installDeepDiagnostics();
|
|
86
|
+
/**
|
|
87
|
+
* Flavor hooks
|
|
88
|
+
*/
|
|
89
|
+
import { installNsVueDevShims, ensureBackWrapperInstalled, getRootForVue, loadSfcComponent, ensureVueGlobals, ensurePiniaOnApp, addSfcMapping, recordVuePayloadChanges, handleVueSfcRegistry, handleVueSfcRegistryUpdate } from '../frameworks/vue/client/index.js';
|
|
90
|
+
switch (__NS_TARGET_FLAVOR__) {
|
|
91
|
+
case 'vue':
|
|
92
|
+
if (VERBOSE) {
|
|
93
|
+
console.log('[hmr-client] installing nativescript-vue dev shims');
|
|
94
|
+
}
|
|
95
|
+
installNsVueDevShims();
|
|
96
|
+
break;
|
|
97
|
+
case 'angular':
|
|
98
|
+
if (VERBOSE) {
|
|
99
|
+
try {
|
|
100
|
+
console.log('[hmr-client] Initializing Angular HMR shims');
|
|
101
|
+
}
|
|
102
|
+
catch { }
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
// Global frame diagnostics: instrument Frame.navigate and Frame.topmost to detect
|
|
107
|
+
// navigation against non-authoritative frames across the app (helps gray-screen cases)
|
|
108
|
+
try {
|
|
109
|
+
const g = globalThis;
|
|
110
|
+
const F = getCore('Frame') || g.Frame;
|
|
111
|
+
if (F && F.prototype && !g.__NS_DEV_GLOBAL_FRAME_PATCHED__) {
|
|
112
|
+
const tag = (fr) => {
|
|
113
|
+
try {
|
|
114
|
+
if (!fr)
|
|
115
|
+
return;
|
|
116
|
+
if (!fr.__ns_tag)
|
|
117
|
+
fr.__ns_tag = Math.random().toString(36).slice(2);
|
|
118
|
+
}
|
|
119
|
+
catch { }
|
|
120
|
+
};
|
|
121
|
+
const proto = F.prototype;
|
|
122
|
+
const origNav = proto.navigate;
|
|
123
|
+
if (typeof origNav === 'function') {
|
|
124
|
+
proto.navigate = function __ns_diag_nav(entry) {
|
|
125
|
+
try {
|
|
126
|
+
tag(this);
|
|
127
|
+
console.log('[diag][global][frame.navigate]', {
|
|
128
|
+
tag: this.__ns_tag,
|
|
129
|
+
type: this?.constructor?.name,
|
|
130
|
+
hasCreate: !!entry?.create,
|
|
131
|
+
clearHistory: !!entry?.clearHistory,
|
|
132
|
+
animated: !!entry?.animated,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch { }
|
|
136
|
+
return origNav.apply(this, arguments);
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const origTop = typeof F.topmost === 'function' ? F.topmost.bind(F) : null;
|
|
140
|
+
if (origTop) {
|
|
141
|
+
F.topmost = function __ns_diag_topmost() {
|
|
142
|
+
const fr = origTop();
|
|
143
|
+
try {
|
|
144
|
+
tag(fr);
|
|
145
|
+
console.log('[diag][global][Frame.topmost]', {
|
|
146
|
+
tag: fr?.__ns_tag,
|
|
147
|
+
type: fr?.constructor?.name,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
catch { }
|
|
151
|
+
return fr;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
g.__NS_DEV_GLOBAL_FRAME_PATCHED__ = true;
|
|
156
|
+
}
|
|
157
|
+
catch { }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch { }
|
|
161
|
+
// --- Diagnostics helpers ----------------------------------------------------
|
|
162
|
+
function summarizeNavEntry(entry) {
|
|
163
|
+
try {
|
|
164
|
+
if (!entry)
|
|
165
|
+
return { kind: 'empty' };
|
|
166
|
+
if (typeof entry === 'string')
|
|
167
|
+
return { kind: 'string', moduleName: entry };
|
|
168
|
+
const hasCreate = typeof entry.create === 'function';
|
|
169
|
+
const moduleName = entry.moduleName;
|
|
170
|
+
const clearHistory = !!entry.clearHistory;
|
|
171
|
+
const animated = entry.animated;
|
|
172
|
+
const backstackVisible = entry.backstackVisible;
|
|
173
|
+
const contextKeys = Object.keys(entry.context || {});
|
|
174
|
+
return {
|
|
175
|
+
kind: 'entry',
|
|
176
|
+
hasCreate,
|
|
177
|
+
moduleName,
|
|
178
|
+
clearHistory,
|
|
179
|
+
animated,
|
|
180
|
+
backstackVisible,
|
|
181
|
+
contextKeys,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return { kind: 'unknown' };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function classifyResetArg(arg) {
|
|
189
|
+
try {
|
|
190
|
+
const ctorName = String(arg?.constructor?.name || '').replace(/^_+/, '');
|
|
191
|
+
const keys = Object.keys(arg || {});
|
|
192
|
+
const hasCreate = typeof arg?.create === 'function';
|
|
193
|
+
const hasModuleName = typeof arg?.moduleName === 'string';
|
|
194
|
+
const isFrameLike = !!arg && (ctorName === 'Frame' || /^Frame(\$\d+)?$/.test(ctorName) || (typeof arg?.navigate === 'function' && typeof arg?.addChild === 'function'));
|
|
195
|
+
const isPageLike = !!arg && (ctorName === 'Page' || /^Page(\$\d+)?$/.test(ctorName) || (typeof arg?.content !== 'undefined' && typeof arg?.addChild === 'function'));
|
|
196
|
+
return {
|
|
197
|
+
ctorName,
|
|
198
|
+
keys,
|
|
199
|
+
hasCreate,
|
|
200
|
+
hasModuleName,
|
|
201
|
+
isFrameLike,
|
|
202
|
+
isPageLike,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return { ctorName: 'unknown' };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function installDeepDiagnostics() {
|
|
210
|
+
if (!VERBOSE)
|
|
211
|
+
return;
|
|
212
|
+
const g = globalThis;
|
|
213
|
+
try {
|
|
214
|
+
// Patch Frame.navigate to log calls and a short stack
|
|
215
|
+
const F = getCore('Frame') || g.Frame;
|
|
216
|
+
if (F?.prototype && !F.prototype.__ns_diag_nav__) {
|
|
217
|
+
const orig = F.prototype.navigate;
|
|
218
|
+
if (typeof orig === 'function') {
|
|
219
|
+
F.prototype.__ns_diag_nav__ = true;
|
|
220
|
+
// Simple duplicate navigation suppression in dev: if the same target is navigated twice within a short window, ignore the 2nd.
|
|
221
|
+
F.prototype.navigate = function (...args) {
|
|
222
|
+
try {
|
|
223
|
+
const entry = args[0];
|
|
224
|
+
const summary = summarizeNavEntry(entry);
|
|
225
|
+
const stack = (new Error().stack || '').split('\n').slice(2, 8).join('\n');
|
|
226
|
+
console.log('[diag][Frame.navigate]', {
|
|
227
|
+
frameCtor: this?.constructor?.name,
|
|
228
|
+
summary,
|
|
229
|
+
stack,
|
|
230
|
+
});
|
|
231
|
+
try {
|
|
232
|
+
const gAny = globalThis;
|
|
233
|
+
const key = JSON.stringify({
|
|
234
|
+
k: 'nav',
|
|
235
|
+
m: summary.moduleName || '',
|
|
236
|
+
c: !!summary.hasCreate,
|
|
237
|
+
ch: !!summary.clearHistory,
|
|
238
|
+
a: !!summary.animated,
|
|
239
|
+
});
|
|
240
|
+
const now = Date.now();
|
|
241
|
+
const last = gAny.__NS_DIAG_LAST_NAV__;
|
|
242
|
+
if (last && last.key === key && now - last.t < 300) {
|
|
243
|
+
console.warn('[diag][Frame.navigate] duplicate nav suppressed (dev)', { withinMs: now - last.t, key });
|
|
244
|
+
return; // suppress duplicate
|
|
245
|
+
}
|
|
246
|
+
gAny.__NS_DIAG_LAST_NAV__ = { key, t: now };
|
|
247
|
+
}
|
|
248
|
+
catch { }
|
|
249
|
+
}
|
|
250
|
+
catch { }
|
|
251
|
+
return orig.apply(this, args);
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch { }
|
|
257
|
+
try {
|
|
258
|
+
// Wrap Application.resetRootView to log argument classification and stack
|
|
259
|
+
const App = getCore('Application') || g.Application;
|
|
260
|
+
const proto = App && Object.getPrototypeOf(App);
|
|
261
|
+
const orig = (App && App.resetRootView) || (proto && proto.resetRootView);
|
|
262
|
+
if (typeof orig === 'function' && !g.__NS_DIAG_RESET_WRAPPED__) {
|
|
263
|
+
const wrapped = function __ns_diag_resetRootView(entry) {
|
|
264
|
+
try {
|
|
265
|
+
const classification = classifyResetArg(entry);
|
|
266
|
+
const stack = (new Error().stack || '').split('\n').slice(2, 8).join('\n');
|
|
267
|
+
console.log('[diag][Application.resetRootView]', {
|
|
268
|
+
classification,
|
|
269
|
+
stack,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
catch { }
|
|
273
|
+
return orig.call(this, entry);
|
|
274
|
+
};
|
|
275
|
+
try {
|
|
276
|
+
App.resetRootView = wrapped;
|
|
277
|
+
}
|
|
278
|
+
catch { }
|
|
279
|
+
try {
|
|
280
|
+
if (proto && typeof proto === 'object')
|
|
281
|
+
proto.resetRootView = wrapped;
|
|
282
|
+
}
|
|
283
|
+
catch { }
|
|
284
|
+
try {
|
|
285
|
+
g.__NS_DIAG_RESET_WRAPPED__ = true;
|
|
286
|
+
}
|
|
287
|
+
catch { }
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
catch { }
|
|
291
|
+
}
|
|
292
|
+
// Track whether we've mounted an initial app root yet in HTTP-only boot
|
|
293
|
+
let initialMounted = !!globalThis.__NS_HMR_BOOT_COMPLETE__;
|
|
294
|
+
// Prevent duplicate initial-mount scheduling across rapid full-graph broadcasts and re-evaluations
|
|
295
|
+
let initialMounting = !!globalThis.__NS_HMR_INITIAL_MOUNT_IN_PROGRESS__;
|
|
296
|
+
const changedQueue = [];
|
|
297
|
+
let processingQueue = false;
|
|
298
|
+
// Detect whether the early placeholder root is still active on screen
|
|
299
|
+
function isPlaceholderActive() {
|
|
300
|
+
try {
|
|
301
|
+
const g = globalThis;
|
|
302
|
+
if (g.__NS_DEV_PLACEHOLDER_ROOT_VIEW__)
|
|
303
|
+
return true;
|
|
304
|
+
if (g.__NS_DEV_PLACEHOLDER_ROOT_EARLY__)
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
catch { }
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
// Navigation queue removed: we navigate immediately or throw with a clear error
|
|
311
|
+
// Robust navigation fallback: create a sub-app and mount it on a new Page, then navigate there.
|
|
312
|
+
// __nsNavigateWithSubApp removed: no navigation fallbacks are used
|
|
313
|
+
function applyFullGraph(payload) {
|
|
314
|
+
if (typeof payload.version !== 'number' || !Array.isArray(payload.modules))
|
|
315
|
+
return;
|
|
316
|
+
graph.clear();
|
|
317
|
+
payload.modules.forEach((m) => {
|
|
318
|
+
if (m && m.id)
|
|
319
|
+
graph.set(m.id, { id: m.id, deps: m.deps || [], hash: m.hash || '' });
|
|
320
|
+
});
|
|
321
|
+
setGraphVersion(payload.version);
|
|
322
|
+
if (VERBOSE)
|
|
323
|
+
console.log('[hmr][graph] full graph applied version', getGraphVersion(), 'modules=', graph.size);
|
|
324
|
+
// Guarded initial mount rescue: if app hasn't replaced the placeholder shortly after graph arrives,
|
|
325
|
+
// perform a one-time mount. This waits briefly to let /src/app.ts start() run first to avoid double mounts.
|
|
326
|
+
try {
|
|
327
|
+
const g = globalThis;
|
|
328
|
+
const bootDone = !!g.__NS_HMR_BOOT_COMPLETE__;
|
|
329
|
+
if (!bootDone && !initialMounted && !initialMounting && !g.__NS_HMR_RESCUE_SCHEDULED__) {
|
|
330
|
+
// simple snapshot helpers
|
|
331
|
+
const getTopmost = () => {
|
|
332
|
+
try {
|
|
333
|
+
const F = getCore('Frame') || g.Frame;
|
|
334
|
+
return F?.topmost?.() || null;
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
const isPlaceholderView = (v) => {
|
|
341
|
+
try {
|
|
342
|
+
if (!v)
|
|
343
|
+
return false;
|
|
344
|
+
if (v === (g.__NS_DEV_PLACEHOLDER_ROOT_VIEW__ || null))
|
|
345
|
+
return true;
|
|
346
|
+
return !!v.__ns_dev_placeholder;
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const hasRealRoot = () => {
|
|
353
|
+
try {
|
|
354
|
+
const fr = getTopmost();
|
|
355
|
+
if (!fr)
|
|
356
|
+
return false;
|
|
357
|
+
if (isPlaceholderView(fr))
|
|
358
|
+
return false;
|
|
359
|
+
const pg = fr.currentPage || fr._currentEntry?.resolvedPage;
|
|
360
|
+
if (!pg)
|
|
361
|
+
return false;
|
|
362
|
+
if (isPlaceholderView(pg))
|
|
363
|
+
return false;
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
try {
|
|
371
|
+
g.__NS_HMR_RESCUE_SCHEDULED__ = true;
|
|
372
|
+
}
|
|
373
|
+
catch { }
|
|
374
|
+
setTimeout(() => {
|
|
375
|
+
try {
|
|
376
|
+
if (g.__NS_HMR_BOOT_COMPLETE__)
|
|
377
|
+
return; // app already mounted
|
|
378
|
+
if (hasRealRoot()) {
|
|
379
|
+
try {
|
|
380
|
+
g.__NS_HMR_BOOT_COMPLETE__ = true;
|
|
381
|
+
}
|
|
382
|
+
catch { }
|
|
383
|
+
if (VERBOSE)
|
|
384
|
+
console.log('[hmr][init] detected real root after delay; skipping client initial mount');
|
|
385
|
+
// Detach placeholder handler if still present
|
|
386
|
+
try {
|
|
387
|
+
const restore = g.__NS_DEV_RESTORE_PLACEHOLDER__;
|
|
388
|
+
if (typeof restore === 'function')
|
|
389
|
+
restore();
|
|
390
|
+
}
|
|
391
|
+
catch { }
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
// If placeholder still active and no real root, try a one-time gentle initial mount
|
|
395
|
+
const placeholderActive = isPlaceholderActive();
|
|
396
|
+
if (!placeholderActive)
|
|
397
|
+
return;
|
|
398
|
+
if (VERBOSE)
|
|
399
|
+
console.log('[hmr][init] placeholder persists after delay; performing one-time initial mount');
|
|
400
|
+
// Prefer first .vue under /src/app.ts deps, else first .vue in graph
|
|
401
|
+
let candidate = null;
|
|
402
|
+
const appEntry = graph.get('/src/app.ts');
|
|
403
|
+
if (appEntry && Array.isArray(appEntry.deps)) {
|
|
404
|
+
const vueDep = appEntry.deps.find((d) => typeof d === 'string' && /\.vue$/i.test(d));
|
|
405
|
+
if (vueDep)
|
|
406
|
+
candidate = vueDep;
|
|
407
|
+
}
|
|
408
|
+
if (!candidate) {
|
|
409
|
+
for (const id of graph.keys()) {
|
|
410
|
+
if (/\.vue$/i.test(id)) {
|
|
411
|
+
candidate = id;
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (!candidate)
|
|
417
|
+
return;
|
|
418
|
+
initialMounting = true;
|
|
419
|
+
try {
|
|
420
|
+
g.__NS_HMR_INITIAL_MOUNT_IN_PROGRESS__ = true;
|
|
421
|
+
}
|
|
422
|
+
catch { }
|
|
423
|
+
(async () => {
|
|
424
|
+
try {
|
|
425
|
+
let comp = null;
|
|
426
|
+
switch (__NS_TARGET_FLAVOR__) {
|
|
427
|
+
case 'vue':
|
|
428
|
+
comp = await loadSfcComponent(candidate, 'initial_mount_rescue');
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
if (!comp)
|
|
432
|
+
return;
|
|
433
|
+
const ok = await performResetRoot(comp);
|
|
434
|
+
if (ok) {
|
|
435
|
+
initialMounted = true;
|
|
436
|
+
try {
|
|
437
|
+
g.__NS_HMR_BOOT_COMPLETE__ = true;
|
|
438
|
+
}
|
|
439
|
+
catch { }
|
|
440
|
+
if (VERBOSE)
|
|
441
|
+
console.log('[hmr][init] initial mount (rescue) complete');
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
catch (e) {
|
|
445
|
+
console.warn('[hmr][init] initial mount (rescue) error', e);
|
|
446
|
+
}
|
|
447
|
+
finally {
|
|
448
|
+
initialMounting = false;
|
|
449
|
+
try {
|
|
450
|
+
g.__NS_HMR_INITIAL_MOUNT_IN_PROGRESS__ = false;
|
|
451
|
+
}
|
|
452
|
+
catch { }
|
|
453
|
+
}
|
|
454
|
+
})();
|
|
455
|
+
}
|
|
456
|
+
catch { }
|
|
457
|
+
}, 450);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
catch { }
|
|
461
|
+
// On first full graph, if we have not mounted yet, attempt an initial mount
|
|
462
|
+
// by choosing a likely Vue root component and performing a resetRootView with it.
|
|
463
|
+
try {
|
|
464
|
+
// Short-circuit if boot is complete or an initial mount is already underway (across realms/evals)
|
|
465
|
+
const bootDone = !!globalThis.__NS_HMR_BOOT_COMPLETE__;
|
|
466
|
+
const bootInProgress = !!globalThis.__NS_HMR_INITIAL_MOUNT_IN_PROGRESS__ || initialMounting;
|
|
467
|
+
// Only allow initial mount when explicitly enabled. Rely on the app's own /src/app.ts start() for the first mount
|
|
468
|
+
// to avoid double-mount races that can cause duplicate navigation logs.
|
|
469
|
+
if (ALLOW_INITIAL_MOUNT && !initialMounted && !bootDone && !bootInProgress && !getCurrentApp() && !getRootFrame()) {
|
|
470
|
+
// Prefer the first .vue dependency of /src/app.ts, else first .vue in graph
|
|
471
|
+
let candidate = null;
|
|
472
|
+
const appEntry = graph.get('/src/app.ts');
|
|
473
|
+
if (appEntry && Array.isArray(appEntry.deps)) {
|
|
474
|
+
const vueDep = appEntry.deps.find((d) => typeof d === 'string' && /\.vue$/i.test(d));
|
|
475
|
+
if (vueDep)
|
|
476
|
+
candidate = vueDep;
|
|
477
|
+
}
|
|
478
|
+
if (!candidate) {
|
|
479
|
+
for (const id of graph.keys()) {
|
|
480
|
+
if (/\.vue$/i.test(id)) {
|
|
481
|
+
candidate = id;
|
|
482
|
+
break;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if (candidate) {
|
|
487
|
+
// Mark initial-mount in progress (both module-local and global) BEFORE scheduling async work
|
|
488
|
+
initialMounting = true;
|
|
489
|
+
try {
|
|
490
|
+
globalThis.__NS_HMR_INITIAL_MOUNT_IN_PROGRESS__ = true;
|
|
491
|
+
}
|
|
492
|
+
catch { }
|
|
493
|
+
(async () => {
|
|
494
|
+
try {
|
|
495
|
+
if (VERBOSE)
|
|
496
|
+
console.log('[hmr][init] mounting initial Vue root from', candidate);
|
|
497
|
+
// Android-only: avoid racing entry-runtime reset and Activity bring-up
|
|
498
|
+
try {
|
|
499
|
+
const g = globalThis;
|
|
500
|
+
const App = getCore('Application') || g.Application;
|
|
501
|
+
const isAndroid = !!(App && App.android !== undefined);
|
|
502
|
+
if (isAndroid) {
|
|
503
|
+
const ready = async (ms = 8000, step = 60) => {
|
|
504
|
+
const start = Date.now();
|
|
505
|
+
const ok = () => {
|
|
506
|
+
try {
|
|
507
|
+
const a = App.android;
|
|
508
|
+
const act = a && (a.foregroundActivity || a.startActivity);
|
|
509
|
+
const inProg = !!g.__NS_DEV_RESET_IN_PROGRESS__;
|
|
510
|
+
return !!act && !inProg;
|
|
511
|
+
}
|
|
512
|
+
catch {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
while (Date.now() - start < ms) {
|
|
517
|
+
if (ok())
|
|
518
|
+
return true;
|
|
519
|
+
await new Promise((r) => setTimeout(r, step));
|
|
520
|
+
}
|
|
521
|
+
return ok();
|
|
522
|
+
};
|
|
523
|
+
const ok = await ready(8000, 60);
|
|
524
|
+
if (!ok && VERBOSE)
|
|
525
|
+
console.warn('[hmr][init] proceeding without explicit boot-ready signal (timeout)');
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
catch { }
|
|
529
|
+
const comp = await loadSfcComponent(candidate, 'initial_mount');
|
|
530
|
+
if (comp) {
|
|
531
|
+
const ok = await performResetRoot(comp);
|
|
532
|
+
if (ok) {
|
|
533
|
+
initialMounted = true;
|
|
534
|
+
try {
|
|
535
|
+
globalThis.__NS_HMR_BOOT_COMPLETE__ = true;
|
|
536
|
+
}
|
|
537
|
+
catch { }
|
|
538
|
+
if (VERBOSE)
|
|
539
|
+
console.log('[hmr][init] initial mount complete');
|
|
540
|
+
}
|
|
541
|
+
else if (VERBOSE) {
|
|
542
|
+
console.warn('[hmr][init] initial mount did not verify; will rely on subsequent retries');
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
else if (VERBOSE) {
|
|
546
|
+
console.warn('[hmr][init] failed to load initial component from', candidate);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
catch (e) {
|
|
550
|
+
console.warn('[hmr][init] initial mount error', e);
|
|
551
|
+
}
|
|
552
|
+
finally {
|
|
553
|
+
// Clear in-progress flag regardless of outcome to allow future retries if needed
|
|
554
|
+
initialMounting = false;
|
|
555
|
+
try {
|
|
556
|
+
globalThis.__NS_HMR_INITIAL_MOUNT_IN_PROGRESS__ = false;
|
|
557
|
+
}
|
|
558
|
+
catch { }
|
|
559
|
+
}
|
|
560
|
+
})();
|
|
561
|
+
}
|
|
562
|
+
else if (VERBOSE) {
|
|
563
|
+
console.warn('[hmr][init] no Vue component found in graph to mount initially');
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
catch { }
|
|
568
|
+
}
|
|
569
|
+
function applyDelta(payload) {
|
|
570
|
+
if (payload.baseVersion !== getGraphVersion()) {
|
|
571
|
+
if (VERBOSE)
|
|
572
|
+
console.warn('[hmr][graph] version mismatch requesting resync', payload.baseVersion, getGraphVersion());
|
|
573
|
+
// Request resync (simple ping) – server will resend full graph (protocol extension placeholder)
|
|
574
|
+
hmrSocket?.send(JSON.stringify({ type: 'ns:hmr-resync-request' }));
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
setGraphVersion(payload.newVersion);
|
|
578
|
+
const changed = payload.changed || [];
|
|
579
|
+
switch (__NS_TARGET_FLAVOR__) {
|
|
580
|
+
case 'vue':
|
|
581
|
+
recordVuePayloadChanges(changed, getGraphVersion());
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
(payload.changed || []).forEach((m) => {
|
|
585
|
+
if (m && m.id)
|
|
586
|
+
graph.set(m.id, { id: m.id, deps: m.deps || [], hash: m.hash || '' });
|
|
587
|
+
});
|
|
588
|
+
(payload.removed || []).forEach((r) => {
|
|
589
|
+
graph.delete(r);
|
|
590
|
+
});
|
|
591
|
+
if (VERBOSE)
|
|
592
|
+
console.log('[hmr][graph] delta applied newVersion', getGraphVersion(), 'changed=', (payload.changed || []).length, 'removed=', (payload.removed || []).length);
|
|
593
|
+
// Queue evaluation of changed modules (placeholder pipeline)
|
|
594
|
+
if (payload.changed?.length) {
|
|
595
|
+
// HARD SUPPRESS: the very first delta (baseVersion 0) commonly includes /src/app.ts which is already evaluated during bootstrap.
|
|
596
|
+
// Importing it again with a cache-bust often produces a spurious module-not-found (timestamp param treated as distinct file).
|
|
597
|
+
const isInitial = payload.baseVersion === 0;
|
|
598
|
+
// Filter out virtual helper ids (e.g. '\0plugin-vue:export-helper') which we do not evaluate directly
|
|
599
|
+
const realIds = payload.changed.map((c) => c.id).filter((id) => !/^\0|^\/\0|plugin-vue:export-helper/.test(id));
|
|
600
|
+
// Proactively prefetch core/src deps for any changed .vue SFCs (before registry update triggers reset)
|
|
601
|
+
try {
|
|
602
|
+
for (const entry of payload.changed || []) {
|
|
603
|
+
if (!entry || !/\.vue$/i.test(entry.id))
|
|
604
|
+
continue;
|
|
605
|
+
const deps = Array.isArray(entry.deps) ? entry.deps : [];
|
|
606
|
+
const prefetchTargets = deps.filter((d) => /^\//.test(d) && !/node_modules/.test(d) && !/\.vue$/i.test(d));
|
|
607
|
+
if (prefetchTargets.length && VERBOSE)
|
|
608
|
+
console.log('[hmr][prefetch] SFC deps', entry.id, '->', prefetchTargets);
|
|
609
|
+
for (const dep of prefetchTargets) {
|
|
610
|
+
const norm = normalizeSpec(dep);
|
|
611
|
+
// Skip if we already wrote it (basic heuristic: moduleFetchCache has it or path exists in Documents/_ns_hmr)
|
|
612
|
+
if (moduleFetchCache.has(norm))
|
|
613
|
+
continue;
|
|
614
|
+
// Fire and forget; ensure rejection does not break HMR pipeline
|
|
615
|
+
requestModuleFromServer(norm).catch(() => { });
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
catch (e) {
|
|
620
|
+
if (VERBOSE)
|
|
621
|
+
console.warn('[hmr][prefetch] failed', e);
|
|
622
|
+
}
|
|
623
|
+
for (const id of realIds) {
|
|
624
|
+
// We now rely on SFC registry update events to trigger root resets for .vue files directly
|
|
625
|
+
if (/\.vue$/i.test(id)) {
|
|
626
|
+
if (VERBOSE)
|
|
627
|
+
console.log('[hmr][delta] skipping queue for .vue id; will handle on registry update', id);
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
if (isInitial && /\/src\/app\.ts$/.test(id)) {
|
|
631
|
+
if (VERBOSE)
|
|
632
|
+
console.log('[hmr][delta] suppressing initial /src/app.ts evaluation');
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
if (/\/src\/app\.ts$/.test(id)) {
|
|
636
|
+
try {
|
|
637
|
+
const exists = globalThis.require?.(id) || globalThis.__nsGetModuleExports?.(id);
|
|
638
|
+
if (!exists && VERBOSE)
|
|
639
|
+
console.log('[hmr][delta] skipping unresolved /src/app.ts change');
|
|
640
|
+
if (!exists)
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
catch {
|
|
644
|
+
/* ignore */
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
changedQueue.push(id);
|
|
648
|
+
}
|
|
649
|
+
if (changedQueue.length)
|
|
650
|
+
processQueue();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
// Deterministic navigation using the current Vue app instance rather than vendor-held rootApp
|
|
654
|
+
function __nsNavigateUsingApp(comp, opts = {}) {
|
|
655
|
+
const g = globalThis;
|
|
656
|
+
switch (__NS_TARGET_FLAVOR__) {
|
|
657
|
+
case 'vue':
|
|
658
|
+
ensureVueGlobals();
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
const AppFactory = g.createApp;
|
|
662
|
+
const RootCtor = g.NSVRoot;
|
|
663
|
+
if (typeof AppFactory !== 'function' || typeof RootCtor !== 'function') {
|
|
664
|
+
throw new Error('Vue runtime not initialized');
|
|
665
|
+
}
|
|
666
|
+
try {
|
|
667
|
+
const top = (g.Frame && g.Frame.topmost && g.Frame.topmost()) || null;
|
|
668
|
+
const ctor = top && top.constructor && top.constructor.name;
|
|
669
|
+
if (VERBOSE)
|
|
670
|
+
console.log('[app-nav] begin', {
|
|
671
|
+
hmrRealm: g.__NS_HMR_REALM__ || 'unknown',
|
|
672
|
+
rtRealm: g.__NS_RT_REALM__ || 'unknown',
|
|
673
|
+
topCtor: ctor,
|
|
674
|
+
hasTop: !!top,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
catch { }
|
|
678
|
+
// Build a fresh Page each time the factory is invoked to avoid reusing a Page instance
|
|
679
|
+
// across fragment recreations (Android) or multiple frame attachments.
|
|
680
|
+
const buildTarget = () => {
|
|
681
|
+
const existingApp = getCurrentApp();
|
|
682
|
+
const baseProvides = (existingApp && existingApp._context && existingApp._context.provides) || {};
|
|
683
|
+
const app = AppFactory(normalizeComponent(comp, comp && (comp.__name || comp.name)));
|
|
684
|
+
switch (__NS_TARGET_FLAVOR__) {
|
|
685
|
+
case 'vue':
|
|
686
|
+
ensurePiniaOnApp(app);
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
try {
|
|
690
|
+
const registry = g.__nsVendorRegistry;
|
|
691
|
+
const req = registry?.get ? g.__nsVendorRequire || g.__nsRequire || g.require : g.__nsRequire || g.require;
|
|
692
|
+
let rh = null;
|
|
693
|
+
if (registry && registry.has('nativescript-vue/dist/runtimeHelpers'))
|
|
694
|
+
rh = registry.get('nativescript-vue/dist/runtimeHelpers');
|
|
695
|
+
if (!rh && typeof req === 'function') {
|
|
696
|
+
try {
|
|
697
|
+
rh = req('nativescript-vue/dist/runtimeHelpers');
|
|
698
|
+
}
|
|
699
|
+
catch { }
|
|
700
|
+
}
|
|
701
|
+
const setRootApp = rh && (rh.setRootApp || rh.default?.setRootApp);
|
|
702
|
+
if (typeof setRootApp === 'function')
|
|
703
|
+
setRootApp(app);
|
|
704
|
+
}
|
|
705
|
+
catch { }
|
|
706
|
+
try {
|
|
707
|
+
const ctx = app?._context;
|
|
708
|
+
if (ctx) {
|
|
709
|
+
const prov = (ctx.provides || (ctx.provides = {}));
|
|
710
|
+
Object.getOwnPropertyNames(baseProvides).forEach((k) => {
|
|
711
|
+
if (!Object.prototype.hasOwnProperty.call(prov, k))
|
|
712
|
+
prov[k] = baseProvides[k];
|
|
713
|
+
});
|
|
714
|
+
Object.getOwnPropertySymbols(baseProvides).forEach((s) => {
|
|
715
|
+
if (!Object.prototype.hasOwnProperty.call(prov, s))
|
|
716
|
+
prov[s] = baseProvides[s];
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
catch { }
|
|
721
|
+
const root = new RootCtor();
|
|
722
|
+
const vm = typeof app.runWithContext === 'function' ? app.runWithContext(() => app.mount(root)) : app.mount(root);
|
|
723
|
+
setCurrentApp(app);
|
|
724
|
+
const el = vm?.$el;
|
|
725
|
+
const nativeView = el?.nativeView;
|
|
726
|
+
if (!nativeView)
|
|
727
|
+
throw new Error('navigation mount did not yield a nativeView');
|
|
728
|
+
const P = getCore('Page');
|
|
729
|
+
const ctorName = String(nativeView?.constructor?.name || '').replace(/^_+/, '');
|
|
730
|
+
if (ctorName === 'Page' || /^Page(\$\d+)?$/.test(ctorName)) {
|
|
731
|
+
return nativeView;
|
|
732
|
+
}
|
|
733
|
+
if (typeof P === 'function') {
|
|
734
|
+
const pg = new P();
|
|
735
|
+
pg.content = nativeView;
|
|
736
|
+
// Hide default ActionBar for wrapped views to avoid double bars
|
|
737
|
+
try {
|
|
738
|
+
pg.actionBarHidden = true;
|
|
739
|
+
}
|
|
740
|
+
catch { }
|
|
741
|
+
return pg;
|
|
742
|
+
}
|
|
743
|
+
return nativeView; // fallback
|
|
744
|
+
};
|
|
745
|
+
let frame = opts && opts.frame ? opts.frame : getRootFrame();
|
|
746
|
+
if (!frame) {
|
|
747
|
+
const F = getCore('Frame');
|
|
748
|
+
frame = F && typeof F.topmost === 'function' ? F.topmost() : null;
|
|
749
|
+
}
|
|
750
|
+
if (!frame) {
|
|
751
|
+
const GApp = getCore('Application') || g.Application;
|
|
752
|
+
const F = getCore('Frame');
|
|
753
|
+
if (typeof GApp?.resetRootView === 'function' && typeof F === 'function') {
|
|
754
|
+
GApp.resetRootView({
|
|
755
|
+
create: () => {
|
|
756
|
+
var _a;
|
|
757
|
+
const fr = new F();
|
|
758
|
+
const navEntry = {
|
|
759
|
+
create: () => buildTarget(),
|
|
760
|
+
clearHistory: true,
|
|
761
|
+
animated: false,
|
|
762
|
+
};
|
|
763
|
+
try {
|
|
764
|
+
fr.navigate(navEntry);
|
|
765
|
+
}
|
|
766
|
+
catch { }
|
|
767
|
+
try {
|
|
768
|
+
attachDiagnosticsToFrame(fr);
|
|
769
|
+
}
|
|
770
|
+
catch { }
|
|
771
|
+
setRootFrame(fr);
|
|
772
|
+
try {
|
|
773
|
+
(_a = getRootFrame()).__ns_tag || (_a.__ns_tag = Math.random().toString(36).slice(2));
|
|
774
|
+
console.log('[diag][root] ROOT_FRAME set (app-nav)', {
|
|
775
|
+
tag: getRootFrame()?.__ns_tag,
|
|
776
|
+
type: getRootFrame()?.constructor?.name,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
catch { }
|
|
780
|
+
return fr;
|
|
781
|
+
},
|
|
782
|
+
});
|
|
783
|
+
return undefined;
|
|
784
|
+
}
|
|
785
|
+
throw new Error('Application.resetRootView unavailable');
|
|
786
|
+
}
|
|
787
|
+
try {
|
|
788
|
+
attachDiagnosticsToFrame(frame);
|
|
789
|
+
}
|
|
790
|
+
catch { }
|
|
791
|
+
const navEntry = { create: () => buildTarget(), ...(opts || {}) };
|
|
792
|
+
try {
|
|
793
|
+
const summary = summarizeNavEntry(navEntry);
|
|
794
|
+
if (VERBOSE)
|
|
795
|
+
console.log('[app-nav] navigate entry', summary);
|
|
796
|
+
}
|
|
797
|
+
catch { }
|
|
798
|
+
frame.navigate(navEntry);
|
|
799
|
+
try {
|
|
800
|
+
const top2 = (g.Frame && g.Frame.topmost && g.Frame.topmost()) || null;
|
|
801
|
+
const ctor2 = top2 && top2.constructor && top2.constructor.name;
|
|
802
|
+
if (VERBOSE)
|
|
803
|
+
console.log('[app-nav] after navigate', {
|
|
804
|
+
topCtor: ctor2,
|
|
805
|
+
hasTop: !!top2,
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
catch { }
|
|
809
|
+
return undefined;
|
|
810
|
+
}
|
|
811
|
+
// Expose deterministic app navigation globally so /ns/rt can guarantee single-path navigation
|
|
812
|
+
try {
|
|
813
|
+
globalThis.__nsNavigateUsingApp = __nsNavigateUsingApp;
|
|
814
|
+
}
|
|
815
|
+
catch { }
|
|
816
|
+
async function processQueue() {
|
|
817
|
+
if (!globalThis.__NS_HMR_BOOT_COMPLETE__) {
|
|
818
|
+
if (VERBOSE)
|
|
819
|
+
console.log('[hmr][gate] deferring HMR eval until boot complete');
|
|
820
|
+
setTimeout(() => {
|
|
821
|
+
try {
|
|
822
|
+
processQueue();
|
|
823
|
+
}
|
|
824
|
+
catch { }
|
|
825
|
+
}, 150);
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
if (processingQueue)
|
|
829
|
+
return;
|
|
830
|
+
processingQueue = true;
|
|
831
|
+
// ...existing code...
|
|
832
|
+
processingQueue = false;
|
|
833
|
+
}
|
|
834
|
+
let hmrSocket = null;
|
|
835
|
+
// Track server-announced batches for each version so we can import in-order client-side
|
|
836
|
+
const txnClientBatches = new Map();
|
|
837
|
+
// Public hook for NativeScript runtime to call from ImportModuleDynamicallyCallback later.
|
|
838
|
+
globalThis.__nsHmrRequestModule = async function (spec) {
|
|
839
|
+
let normalized = normalizeSpec(spec);
|
|
840
|
+
// Remove extension for transform lookup variants (server will try .ts/.js/.mjs)
|
|
841
|
+
normalized = normalized.replace(/\.(ts|js|tsx|jsx|mjs)$/i, '');
|
|
842
|
+
if (!normalized.startsWith('/'))
|
|
843
|
+
normalized = '/' + normalized;
|
|
844
|
+
if (normalized === '@') {
|
|
845
|
+
// Soft-handle instead of throwing to avoid breaking evaluation paths: return a safe empty module stub.
|
|
846
|
+
try {
|
|
847
|
+
const err = new Error('[hmr-fetch] anomalous @ spec');
|
|
848
|
+
const stack = err.stack || '';
|
|
849
|
+
hmrMetrics.invalidAtSpec = (hmrMetrics.invalidAtSpec || 0) + 1;
|
|
850
|
+
console.warn('[hmr-fetch] refusing to fetch bare @ spec; returning stub; original=', spec, 'stack=\n' + stack);
|
|
851
|
+
}
|
|
852
|
+
catch { }
|
|
853
|
+
return '/__invalid_at__.mjs';
|
|
854
|
+
}
|
|
855
|
+
const url = await requestModuleFromServer(normalized);
|
|
856
|
+
return url;
|
|
857
|
+
};
|
|
858
|
+
function connectHmr() {
|
|
859
|
+
if (hmrSocket?.readyState === WebSocket.OPEN)
|
|
860
|
+
return;
|
|
861
|
+
if (hmrSocket?.readyState === WebSocket.CONNECTING) {
|
|
862
|
+
if (__NS_ENV_VERBOSE__)
|
|
863
|
+
console.log('[hmr-client] Already connecting to HMR WebSocket, skipping');
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
const baseUrl = getHMRWsUrl() || 'ws://localhost:5173/ns-hmr';
|
|
867
|
+
const buildCandidates = (url) => {
|
|
868
|
+
let candidates = [];
|
|
869
|
+
try {
|
|
870
|
+
const u = new URL(url);
|
|
871
|
+
const proto = u.protocol === 'wss:' ? ['wss'] : ['ws'];
|
|
872
|
+
const defaultPort = u.port || '5173';
|
|
873
|
+
// Build ordered host candidates with preference to the active HTTP origin
|
|
874
|
+
const orderedHosts = [];
|
|
875
|
+
try {
|
|
876
|
+
const g = globalThis;
|
|
877
|
+
const httpOrigin = g && typeof g.__NS_HTTP_ORIGIN__ === 'string' ? g.__NS_HTTP_ORIGIN__ : undefined;
|
|
878
|
+
if (httpOrigin) {
|
|
879
|
+
try {
|
|
880
|
+
const ho = new URL(httpOrigin);
|
|
881
|
+
orderedHosts.push({
|
|
882
|
+
host: ho.hostname,
|
|
883
|
+
port: ho.port || defaultPort,
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
catch { }
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
catch { }
|
|
890
|
+
// From provided URL
|
|
891
|
+
orderedHosts.push({ host: u.hostname, port: defaultPort });
|
|
892
|
+
// Explicit override
|
|
893
|
+
try {
|
|
894
|
+
const h = globalThis.__NS_HMR_HOST;
|
|
895
|
+
if (h)
|
|
896
|
+
orderedHosts.push({ host: String(h), port: defaultPort });
|
|
897
|
+
}
|
|
898
|
+
catch { }
|
|
899
|
+
// Common fallbacks
|
|
900
|
+
orderedHosts.push({ host: '10.0.2.2', port: defaultPort });
|
|
901
|
+
orderedHosts.push({ host: 'localhost', port: defaultPort });
|
|
902
|
+
const seen = new Set();
|
|
903
|
+
for (const p of proto) {
|
|
904
|
+
for (const { host, port } of orderedHosts) {
|
|
905
|
+
const key = `${host}:${port}`;
|
|
906
|
+
if (seen.has(key))
|
|
907
|
+
continue;
|
|
908
|
+
seen.add(key);
|
|
909
|
+
const cand = `${p}://${host}:${port}${u.pathname || '/ns-hmr'}`;
|
|
910
|
+
candidates.push(cand);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
catch {
|
|
915
|
+
candidates.push(url);
|
|
916
|
+
}
|
|
917
|
+
// Deduplicate while preserving order
|
|
918
|
+
const seen = new Set();
|
|
919
|
+
return candidates.filter((c) => (seen.has(c) ? false : (seen.add(c), true)));
|
|
920
|
+
};
|
|
921
|
+
const candidates = buildCandidates(baseUrl);
|
|
922
|
+
let idx = 0;
|
|
923
|
+
const tryNext = () => {
|
|
924
|
+
if (idx >= candidates.length) {
|
|
925
|
+
console.warn('[hmr-client] All WS candidates failed:', candidates.join(', '));
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
const url = candidates[idx++];
|
|
929
|
+
try {
|
|
930
|
+
if (__NS_ENV_VERBOSE__)
|
|
931
|
+
console.log('[hmr-client] Connecting to HMR WebSocket:', url);
|
|
932
|
+
const sock = new WebSocket(url);
|
|
933
|
+
hmrSocket = sock;
|
|
934
|
+
setHttpOriginForVite(deriveHttpOrigin(url));
|
|
935
|
+
let opened = false;
|
|
936
|
+
const timeout = setTimeout(() => {
|
|
937
|
+
if (!opened && sock.readyState !== WebSocket.OPEN) {
|
|
938
|
+
try {
|
|
939
|
+
sock.close();
|
|
940
|
+
}
|
|
941
|
+
catch { }
|
|
942
|
+
if (VERBOSE)
|
|
943
|
+
console.warn('[hmr-client] WS connect timeout, trying next…');
|
|
944
|
+
tryNext();
|
|
945
|
+
}
|
|
946
|
+
}, 3500);
|
|
947
|
+
sock.onopen = () => {
|
|
948
|
+
opened = true;
|
|
949
|
+
clearTimeout(timeout);
|
|
950
|
+
VERBOSE && console.log('[hmr-client] Connected to HMR WebSocket');
|
|
951
|
+
};
|
|
952
|
+
sock.onmessage = handleHmrMessage;
|
|
953
|
+
sock.onerror = (error) => {
|
|
954
|
+
clearTimeout(timeout);
|
|
955
|
+
console.warn('[hmr-client] WebSocket error:', (error && (error.message || error)) || error);
|
|
956
|
+
};
|
|
957
|
+
sock.onclose = (ev) => {
|
|
958
|
+
clearTimeout(timeout);
|
|
959
|
+
if (!opened) {
|
|
960
|
+
// immediate failure during connect → try another candidate
|
|
961
|
+
if (VERBOSE)
|
|
962
|
+
console.warn('[hmr-client] WS close before open (code', ev?.code, '), trying next…');
|
|
963
|
+
tryNext();
|
|
964
|
+
}
|
|
965
|
+
else {
|
|
966
|
+
if (VERBOSE)
|
|
967
|
+
console.log('[hmr-client] WebSocket closed (code', ev?.code, '), will reconnect…');
|
|
968
|
+
// try to reconnect with full candidate list again
|
|
969
|
+
setTimeout(connectHmr, 1000);
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
catch (e) {
|
|
974
|
+
console.warn('[hmr-client] Failed to connect WebSocket', e);
|
|
975
|
+
tryNext();
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
tryNext();
|
|
979
|
+
}
|
|
980
|
+
async function handleHmrMessage(ev) {
|
|
981
|
+
let msg;
|
|
982
|
+
try {
|
|
983
|
+
msg = JSON.parse(ev.data);
|
|
984
|
+
}
|
|
985
|
+
catch {
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
if (VERBOSE)
|
|
989
|
+
console.log('[hmr-client] msg', msg);
|
|
990
|
+
if (msg) {
|
|
991
|
+
if (msg.type === 'ns:hmr-full-graph') {
|
|
992
|
+
setGraphVersion(Number(msg.version || getGraphVersion() || 0));
|
|
993
|
+
applyFullGraph(msg);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
if (msg.type === 'ns:hmr-delta') {
|
|
997
|
+
setGraphVersion(Number(msg.newVersion || getGraphVersion() || 0));
|
|
998
|
+
try {
|
|
999
|
+
const ids = Array.isArray(msg.changed) ? msg.changed.map((c) => c?.id).filter(Boolean) : [];
|
|
1000
|
+
if (ids.length)
|
|
1001
|
+
txnClientBatches.set(getGraphVersion(), ids);
|
|
1002
|
+
}
|
|
1003
|
+
catch { }
|
|
1004
|
+
applyDelta(msg);
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
else if (msg.type === 'ns:angular-update') {
|
|
1008
|
+
try {
|
|
1009
|
+
if (VERBOSE)
|
|
1010
|
+
console.log('[hmr-client][angular] update', msg);
|
|
1011
|
+
// Minimal safe policy for Angular today: if the app provides a bootstrap
|
|
1012
|
+
// factory via globalThis.__NS_ANGULAR_BOOTSTRAP__, perform a full root
|
|
1013
|
+
// replacement. Otherwise, log a guidance message.
|
|
1014
|
+
const g = globalThis;
|
|
1015
|
+
const App = getCore('Application') || g.Application;
|
|
1016
|
+
const bootstrap = g.__NS_ANGULAR_BOOTSTRAP__;
|
|
1017
|
+
if (typeof App?.resetRootView === 'function' && typeof bootstrap === 'function') {
|
|
1018
|
+
if (VERBOSE)
|
|
1019
|
+
console.log('[hmr-client][angular] resetRootView via bootstrap factory');
|
|
1020
|
+
try {
|
|
1021
|
+
g.__NS_DEV_RESET_IN_PROGRESS__ = true;
|
|
1022
|
+
}
|
|
1023
|
+
catch { }
|
|
1024
|
+
App.resetRootView({ create: () => bootstrap() });
|
|
1025
|
+
setTimeout(() => {
|
|
1026
|
+
try {
|
|
1027
|
+
g.__NS_DEV_RESET_IN_PROGRESS__ = false;
|
|
1028
|
+
}
|
|
1029
|
+
catch { }
|
|
1030
|
+
}, 0);
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
if (VERBOSE)
|
|
1034
|
+
console.warn('[hmr-client][angular] No __NS_ANGULAR_BOOTSTRAP__ factory found; consider exposing one from main.ts');
|
|
1035
|
+
}
|
|
1036
|
+
catch (e) {
|
|
1037
|
+
try {
|
|
1038
|
+
console.warn('[hmr-client][angular] failed to handle update', e && (e.message || e));
|
|
1039
|
+
}
|
|
1040
|
+
catch { }
|
|
1041
|
+
}
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
// On-demand module fetch response (Option A)
|
|
1046
|
+
if (msg.type === 'ns:module-response' && typeof msg.requestId === 'number') {
|
|
1047
|
+
const pending = pendingModuleFetches.get(msg.requestId);
|
|
1048
|
+
if (pending) {
|
|
1049
|
+
pendingModuleFetches.delete(msg.requestId);
|
|
1050
|
+
if (msg.error) {
|
|
1051
|
+
if (VERBOSE)
|
|
1052
|
+
console.warn('[hmr-fetch] error', msg.error, 'spec=', pending.spec, 'id=', msg.requestId);
|
|
1053
|
+
pending.reject(new Error(`[hmr-fetch] ${msg.error} for ${pending.spec}`));
|
|
1054
|
+
}
|
|
1055
|
+
else {
|
|
1056
|
+
try {
|
|
1057
|
+
const origin = getHttpOriginForVite() || deriveHttpOrigin(getHMRWsUrl());
|
|
1058
|
+
if (!origin)
|
|
1059
|
+
throw new Error('no-http-origin');
|
|
1060
|
+
const url = origin + '/ns/m' + (String(pending.spec).startsWith('/') ? pending.spec : '/' + pending.spec);
|
|
1061
|
+
moduleFetchCache.set(pending.spec, url);
|
|
1062
|
+
if (VERBOSE)
|
|
1063
|
+
console.log('[hmr-fetch] resolved via URL', pending.spec, '->', url, 'id=', msg.requestId);
|
|
1064
|
+
pending.resolve(url);
|
|
1065
|
+
}
|
|
1066
|
+
catch (e) {
|
|
1067
|
+
pending.reject(e);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
if (msg.type === 'ns:css-updates' && Array.isArray(msg.updates)) {
|
|
1074
|
+
try {
|
|
1075
|
+
const origin = msg.origin || getHttpOriginForVite() || deriveHttpOrigin(getHMRWsUrl());
|
|
1076
|
+
await handleCssUpdates(msg.updates, origin);
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
catch (e) {
|
|
1080
|
+
console.warn('[hmr-client] CSS updates handling failed:', e);
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
if (msg.type === 'ns:vue-sfc-registry') {
|
|
1085
|
+
handleVueSfcRegistry(msg);
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
if (msg.type === 'ns:vue-sfc-registry-update') {
|
|
1089
|
+
if (typeof msg.version === 'number')
|
|
1090
|
+
setGraphVersion(msg.version);
|
|
1091
|
+
const comp = await handleVueSfcRegistryUpdate(msg, getGraphVersion());
|
|
1092
|
+
if (comp) {
|
|
1093
|
+
await performResetRoot(comp);
|
|
1094
|
+
}
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
function normalizeComponent(input, nameHint) {
|
|
1099
|
+
try {
|
|
1100
|
+
if (!input)
|
|
1101
|
+
return null;
|
|
1102
|
+
// Unwrap module namespace with default
|
|
1103
|
+
if (input && typeof input === 'object' && 'default' in input) {
|
|
1104
|
+
const d = input.default;
|
|
1105
|
+
if (d)
|
|
1106
|
+
return normalizeComponent(d, nameHint);
|
|
1107
|
+
}
|
|
1108
|
+
// If already a component-like object with render/setup/template, return as-is
|
|
1109
|
+
if (typeof input === 'object' && (input.render || input.setup || input.template || input.__isVue)) {
|
|
1110
|
+
return input;
|
|
1111
|
+
}
|
|
1112
|
+
// If provided a render function, wrap with defineComponent
|
|
1113
|
+
if (typeof input === 'function') {
|
|
1114
|
+
ensureVueGlobals();
|
|
1115
|
+
const comp = globalThis.defineComponent
|
|
1116
|
+
? globalThis.defineComponent({
|
|
1117
|
+
name: nameHint || input.name || 'AnonymousSFC',
|
|
1118
|
+
render: input,
|
|
1119
|
+
})
|
|
1120
|
+
: { name: nameHint || input.name || 'AnonymousSFC', render: input };
|
|
1121
|
+
return comp;
|
|
1122
|
+
}
|
|
1123
|
+
// If object has a render function property
|
|
1124
|
+
if (input?.render && typeof input.render === 'function') {
|
|
1125
|
+
ensureVueGlobals();
|
|
1126
|
+
const comp = globalThis.defineComponent
|
|
1127
|
+
? globalThis.defineComponent({
|
|
1128
|
+
name: nameHint || input.name || 'AnonymousSFC',
|
|
1129
|
+
render: input.render,
|
|
1130
|
+
})
|
|
1131
|
+
: {
|
|
1132
|
+
name: nameHint || input.name || 'AnonymousSFC',
|
|
1133
|
+
render: input.render,
|
|
1134
|
+
};
|
|
1135
|
+
return comp;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
catch { }
|
|
1139
|
+
return input;
|
|
1140
|
+
}
|
|
1141
|
+
async function performResetRoot(newComponent) {
|
|
1142
|
+
const tStart = Date.now();
|
|
1143
|
+
// Guard against re-entrant or rapid successive resets
|
|
1144
|
+
try {
|
|
1145
|
+
globalThis.__NS_DEV_RESET_IN_PROGRESS__ = true;
|
|
1146
|
+
}
|
|
1147
|
+
catch { }
|
|
1148
|
+
try {
|
|
1149
|
+
ensureCoreAliasesOnGlobalThis();
|
|
1150
|
+
}
|
|
1151
|
+
catch { }
|
|
1152
|
+
try {
|
|
1153
|
+
if (VERBOSE)
|
|
1154
|
+
logUiSnapshot('pre-performResetRoot');
|
|
1155
|
+
}
|
|
1156
|
+
catch { }
|
|
1157
|
+
if (VERBOSE) {
|
|
1158
|
+
try {
|
|
1159
|
+
const g = globalThis;
|
|
1160
|
+
const vF = getCore('Frame');
|
|
1161
|
+
console.log('[hmr-client] alias check before remount', {
|
|
1162
|
+
globalFrameHasTopmost: typeof g?.Frame?.topmost === 'function',
|
|
1163
|
+
vendorFrameHasTopmost: typeof vF?.topmost === 'function',
|
|
1164
|
+
sameFrameRef: vF === g?.Frame,
|
|
1165
|
+
appHasReset: typeof g?.Application?.resetRootView === 'function',
|
|
1166
|
+
pageIsCtor: typeof g?.Page === 'function',
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
catch { }
|
|
1170
|
+
}
|
|
1171
|
+
if (VERBOSE) {
|
|
1172
|
+
console.log('[hmr-client] Single-path: replace current root Page');
|
|
1173
|
+
console.log('[hmr-client] Component details:', {
|
|
1174
|
+
componentName: newComponent?.__name,
|
|
1175
|
+
componentFile: newComponent?.__file,
|
|
1176
|
+
hasRender: !!newComponent?.render,
|
|
1177
|
+
hasSetup: !!newComponent?.setup,
|
|
1178
|
+
componentKeys: Object.keys(newComponent || {}),
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
function createRootFactory() {
|
|
1182
|
+
let rootKind = 'page';
|
|
1183
|
+
let cachedRoot = undefined;
|
|
1184
|
+
const state = {
|
|
1185
|
+
getRootKind: () => rootKind,
|
|
1186
|
+
setRootKind: (k) => {
|
|
1187
|
+
rootKind = k;
|
|
1188
|
+
},
|
|
1189
|
+
getCachedRoot: () => cachedRoot,
|
|
1190
|
+
setCachedRoot: (r) => {
|
|
1191
|
+
cachedRoot = r;
|
|
1192
|
+
},
|
|
1193
|
+
};
|
|
1194
|
+
const factory = {
|
|
1195
|
+
get kind() {
|
|
1196
|
+
return rootKind;
|
|
1197
|
+
},
|
|
1198
|
+
create: () => {
|
|
1199
|
+
if (cachedRoot)
|
|
1200
|
+
return cachedRoot;
|
|
1201
|
+
try {
|
|
1202
|
+
switch (__NS_TARGET_FLAVOR__) {
|
|
1203
|
+
case 'vue':
|
|
1204
|
+
cachedRoot = getRootForVue(newComponent, state);
|
|
1205
|
+
break;
|
|
1206
|
+
}
|
|
1207
|
+
return cachedRoot;
|
|
1208
|
+
}
|
|
1209
|
+
catch (e) {
|
|
1210
|
+
console.warn('[hmr-client] createRootFactory failed', e);
|
|
1211
|
+
if (VERBOSE)
|
|
1212
|
+
console.warn('[hmr-client] [createRoot] stack', e?.stack);
|
|
1213
|
+
const GPage = getCore('Page');
|
|
1214
|
+
rootKind = 'page';
|
|
1215
|
+
cachedRoot = GPage ? new GPage() : {};
|
|
1216
|
+
return cachedRoot;
|
|
1217
|
+
}
|
|
1218
|
+
},
|
|
1219
|
+
};
|
|
1220
|
+
return factory;
|
|
1221
|
+
}
|
|
1222
|
+
// Android readiness before any root changes
|
|
1223
|
+
const App = getCore('Application') || globalThis.Application;
|
|
1224
|
+
const isAndroid = !!(App && App.android !== undefined);
|
|
1225
|
+
if (isAndroid) {
|
|
1226
|
+
const isReady = () => {
|
|
1227
|
+
try {
|
|
1228
|
+
const a = App.android;
|
|
1229
|
+
const act = a && (a.foregroundActivity || a.startActivity);
|
|
1230
|
+
return !!act;
|
|
1231
|
+
}
|
|
1232
|
+
catch {
|
|
1233
|
+
return false;
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
const waitFor = async (pred, ms = 6000, step = 60) => {
|
|
1237
|
+
const start = Date.now();
|
|
1238
|
+
while (Date.now() - start < ms) {
|
|
1239
|
+
if (pred())
|
|
1240
|
+
return true;
|
|
1241
|
+
await new Promise((r) => setTimeout(r, step));
|
|
1242
|
+
}
|
|
1243
|
+
return pred();
|
|
1244
|
+
};
|
|
1245
|
+
const withEvents = async (ms = 6000) => {
|
|
1246
|
+
try {
|
|
1247
|
+
const a = App.android;
|
|
1248
|
+
if (!a || typeof a.on !== 'function' || typeof a.off !== 'function') {
|
|
1249
|
+
if (VERBOSE)
|
|
1250
|
+
console.log('[hmr-client] [android] events API not available; polling');
|
|
1251
|
+
return await waitFor(isReady, ms, 60);
|
|
1252
|
+
}
|
|
1253
|
+
if (isReady()) {
|
|
1254
|
+
if (VERBOSE)
|
|
1255
|
+
console.log('[hmr-client] [android] activity already ready');
|
|
1256
|
+
return true;
|
|
1257
|
+
}
|
|
1258
|
+
return await new Promise((resolve) => {
|
|
1259
|
+
let done = false;
|
|
1260
|
+
const tWait = Date.now();
|
|
1261
|
+
const finish = (ok) => {
|
|
1262
|
+
if (done)
|
|
1263
|
+
return;
|
|
1264
|
+
done = true;
|
|
1265
|
+
try {
|
|
1266
|
+
a.off(a.activityStartedEvent || 'activityStarted', onAny);
|
|
1267
|
+
a.off(a.activityResumedEvent || 'activityResumed', onAny);
|
|
1268
|
+
}
|
|
1269
|
+
catch { }
|
|
1270
|
+
if (VERBOSE)
|
|
1271
|
+
console.log('[hmr-client] [android] readiness result', {
|
|
1272
|
+
ok,
|
|
1273
|
+
elapsedMs: Date.now() - tWait,
|
|
1274
|
+
});
|
|
1275
|
+
resolve(ok);
|
|
1276
|
+
};
|
|
1277
|
+
const onAny = (evt) => {
|
|
1278
|
+
if (VERBOSE)
|
|
1279
|
+
console.log('[hmr-client] [android] activity event', {
|
|
1280
|
+
type: evt?.eventName || 'unknown',
|
|
1281
|
+
});
|
|
1282
|
+
if (isReady())
|
|
1283
|
+
finish(true);
|
|
1284
|
+
};
|
|
1285
|
+
try {
|
|
1286
|
+
a.on(a.activityStartedEvent || 'activityStarted', onAny);
|
|
1287
|
+
a.on(a.activityResumedEvent || 'activityResumed', onAny);
|
|
1288
|
+
if (VERBOSE)
|
|
1289
|
+
console.log('[hmr-client] [android] waiting for activity events…');
|
|
1290
|
+
}
|
|
1291
|
+
catch {
|
|
1292
|
+
return resolve(waitFor(isReady, ms, 60));
|
|
1293
|
+
}
|
|
1294
|
+
setTimeout(() => finish(isReady()), ms);
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
catch {
|
|
1298
|
+
return await waitFor(isReady, ms, 60);
|
|
1299
|
+
}
|
|
1300
|
+
};
|
|
1301
|
+
const ok = await withEvents(6000);
|
|
1302
|
+
if (!ok && VERBOSE)
|
|
1303
|
+
console.warn('[hmr-client] [android] activity not ready; proceeding with best-effort');
|
|
1304
|
+
}
|
|
1305
|
+
// Create the new root first to determine whether it is a Page or a Frame
|
|
1306
|
+
const rootFactory = createRootFactory();
|
|
1307
|
+
const preparedRoot = rootFactory.create();
|
|
1308
|
+
const isFrameRoot = (() => {
|
|
1309
|
+
try {
|
|
1310
|
+
const name = String(preparedRoot?.constructor?.name || '').replace(/^_+/, '');
|
|
1311
|
+
return /^Frame(\$\d+)?$/.test(name);
|
|
1312
|
+
}
|
|
1313
|
+
catch {
|
|
1314
|
+
return false;
|
|
1315
|
+
}
|
|
1316
|
+
})();
|
|
1317
|
+
// Prefer resetRootView on initial boot (placeholder present) or on iOS to avoid early createRootView races
|
|
1318
|
+
let hadPlaceholder = false;
|
|
1319
|
+
let isIOS = false;
|
|
1320
|
+
try {
|
|
1321
|
+
hadPlaceholder = !!globalThis.__NS_DEV_PLACEHOLDER_ROOT_EARLY__;
|
|
1322
|
+
}
|
|
1323
|
+
catch { }
|
|
1324
|
+
try {
|
|
1325
|
+
const AppAny = getCore('Application') || globalThis.Application;
|
|
1326
|
+
isIOS = !!(AppAny && AppAny.ios !== undefined);
|
|
1327
|
+
}
|
|
1328
|
+
catch { }
|
|
1329
|
+
// Preferred policy:
|
|
1330
|
+
// - If this is the very first mount (placeholder present), or if the new root is a Frame,
|
|
1331
|
+
// perform a full root replacement via resetRootView so we never couple with the placeholder.
|
|
1332
|
+
// - Otherwise (subsequent HMR updates with an authoritative Frame already in place), re-use the
|
|
1333
|
+
// current app Frame and navigate to the new Page. This avoids a brief flash that can occur
|
|
1334
|
+
// when swapping the entire root view on Android. The placeholder is never involved here.
|
|
1335
|
+
const gAnyForPolicy = globalThis;
|
|
1336
|
+
const placeholderFrame = (() => {
|
|
1337
|
+
try {
|
|
1338
|
+
return gAnyForPolicy.__NS_DEV_PLACEHOLDER_ROOT_VIEW__ || null;
|
|
1339
|
+
}
|
|
1340
|
+
catch {
|
|
1341
|
+
return null;
|
|
1342
|
+
}
|
|
1343
|
+
})();
|
|
1344
|
+
let existingAppFrame = null;
|
|
1345
|
+
try {
|
|
1346
|
+
existingAppFrame = getRootFrame() || getCore('Frame')?.topmost?.() || null;
|
|
1347
|
+
}
|
|
1348
|
+
catch { }
|
|
1349
|
+
const isAuthoritativeFrame = !!existingAppFrame && existingAppFrame !== placeholderFrame;
|
|
1350
|
+
if (!hadPlaceholder && !isFrameRoot && isAuthoritativeFrame && typeof existingAppFrame.navigate === 'function') {
|
|
1351
|
+
try {
|
|
1352
|
+
if (VERBOSE)
|
|
1353
|
+
console.log('[hmr-client] navigating authoritative app Frame to new Page (no placeholder, smooth swap)');
|
|
1354
|
+
try {
|
|
1355
|
+
attachDiagnosticsToFrame(existingAppFrame);
|
|
1356
|
+
}
|
|
1357
|
+
catch { }
|
|
1358
|
+
const navEntry = {
|
|
1359
|
+
create: () => preparedRoot,
|
|
1360
|
+
clearHistory: true,
|
|
1361
|
+
animated: false,
|
|
1362
|
+
};
|
|
1363
|
+
existingAppFrame.navigate(navEntry);
|
|
1364
|
+
setRootFrame(existingAppFrame);
|
|
1365
|
+
return true;
|
|
1366
|
+
}
|
|
1367
|
+
catch (e) {
|
|
1368
|
+
console.warn('[hmr-client] authoritative navigate fallback to resetRootView due to error', e);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
if (VERBOSE)
|
|
1372
|
+
console.log('[hmr-client] full root replacement via resetRootView (placeholder will be discarded)', { isFrameRoot, isIOS, hadPlaceholder });
|
|
1373
|
+
// Fallback or preferred path: resetRootView with a creator that builds a fresh Frame and navigates to the new Page
|
|
1374
|
+
try {
|
|
1375
|
+
const App2 = getCore('Application') || globalThis.Application;
|
|
1376
|
+
if (!App2 || typeof App2.resetRootView !== 'function') {
|
|
1377
|
+
console.warn('[hmr-client] Application.resetRootView unavailable');
|
|
1378
|
+
return false;
|
|
1379
|
+
}
|
|
1380
|
+
// iOS-specific: if the cached window was left in an invalid state (boolean false), clear it so
|
|
1381
|
+
// setWindowContent can recreate a proper UIWindow. This can occur in rare early-boot races.
|
|
1382
|
+
try {
|
|
1383
|
+
const isIos = !!(App2 && App2.ios !== undefined);
|
|
1384
|
+
if (isIos) {
|
|
1385
|
+
let win = undefined;
|
|
1386
|
+
try {
|
|
1387
|
+
win = App2.window;
|
|
1388
|
+
}
|
|
1389
|
+
catch { }
|
|
1390
|
+
if (win === false) {
|
|
1391
|
+
if (VERBOSE)
|
|
1392
|
+
console.warn('[hmr-client] iOS Application.window is boolean false; attempting to clear cached window');
|
|
1393
|
+
try {
|
|
1394
|
+
const g = globalThis;
|
|
1395
|
+
const reg = g.__nsVendorRegistry;
|
|
1396
|
+
const req = reg?.get ? g.__nsVendorRequire || g.__nsRequire || g.require : g.__nsRequire || g.require;
|
|
1397
|
+
let helpers = null;
|
|
1398
|
+
// Try vendor registry first
|
|
1399
|
+
if (reg && reg.has('@nativescript/core/application/helpers-common')) {
|
|
1400
|
+
helpers = reg.get('@nativescript/core/application/helpers-common');
|
|
1401
|
+
}
|
|
1402
|
+
// Fallback to device require
|
|
1403
|
+
if (!helpers && typeof req === 'function') {
|
|
1404
|
+
try {
|
|
1405
|
+
helpers = req('@nativescript/core/application/helpers-common');
|
|
1406
|
+
}
|
|
1407
|
+
catch { }
|
|
1408
|
+
}
|
|
1409
|
+
const setter = helpers && (helpers.setiOSWindow || helpers.default?.setiOSWindow);
|
|
1410
|
+
if (typeof setter === 'function') {
|
|
1411
|
+
try {
|
|
1412
|
+
setter(undefined);
|
|
1413
|
+
if (VERBOSE)
|
|
1414
|
+
console.log('[hmr-client] cleared cached iOS window via helpers-common');
|
|
1415
|
+
}
|
|
1416
|
+
catch { }
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
catch { }
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
catch { }
|
|
1424
|
+
// Use the previously created preparedRoot
|
|
1425
|
+
const entry = {
|
|
1426
|
+
create: () => {
|
|
1427
|
+
var _a, _b;
|
|
1428
|
+
if (!isFrameRoot) {
|
|
1429
|
+
const F = getCore('Frame');
|
|
1430
|
+
const fr = new F();
|
|
1431
|
+
if (VERBOSE)
|
|
1432
|
+
console.log('[hmr-client] resetRootView:create new Frame', {
|
|
1433
|
+
type: fr?.constructor?.name,
|
|
1434
|
+
});
|
|
1435
|
+
const navEntry = {
|
|
1436
|
+
create: () => preparedRoot,
|
|
1437
|
+
clearHistory: true,
|
|
1438
|
+
animated: false,
|
|
1439
|
+
};
|
|
1440
|
+
try {
|
|
1441
|
+
fr.navigate(navEntry);
|
|
1442
|
+
if (VERBOSE)
|
|
1443
|
+
console.log('[hmr-client] resetRootView:create navigated Frame');
|
|
1444
|
+
}
|
|
1445
|
+
catch (e) {
|
|
1446
|
+
console.warn('[hmr-client] resetRootView:create navigate failed', e);
|
|
1447
|
+
}
|
|
1448
|
+
try {
|
|
1449
|
+
attachDiagnosticsToFrame(fr);
|
|
1450
|
+
}
|
|
1451
|
+
catch { }
|
|
1452
|
+
setRootFrame(fr);
|
|
1453
|
+
try {
|
|
1454
|
+
(_a = getRootFrame()).__ns_tag || (_a.__ns_tag = Math.random().toString(36).slice(2));
|
|
1455
|
+
console.log('[diag][root] ROOT_FRAME set (new)', {
|
|
1456
|
+
tag: getRootFrame()?.__ns_tag,
|
|
1457
|
+
type: getRootFrame()?.constructor?.name,
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
catch { }
|
|
1461
|
+
return fr;
|
|
1462
|
+
}
|
|
1463
|
+
else {
|
|
1464
|
+
const fr = preparedRoot;
|
|
1465
|
+
if (VERBOSE)
|
|
1466
|
+
console.log('[hmr-client] resetRootView:create using provided Frame', { type: fr?.constructor?.name });
|
|
1467
|
+
try {
|
|
1468
|
+
attachDiagnosticsToFrame(fr);
|
|
1469
|
+
}
|
|
1470
|
+
catch { }
|
|
1471
|
+
setRootFrame(fr);
|
|
1472
|
+
try {
|
|
1473
|
+
(_b = getRootFrame()).__ns_tag || (_b.__ns_tag = Math.random().toString(36).slice(2));
|
|
1474
|
+
console.log('[diag][root] ROOT_FRAME set (provided)', {
|
|
1475
|
+
tag: getRootFrame()?.__ns_tag,
|
|
1476
|
+
type: getRootFrame()?.constructor?.name,
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
catch { }
|
|
1480
|
+
return fr;
|
|
1481
|
+
}
|
|
1482
|
+
},
|
|
1483
|
+
};
|
|
1484
|
+
if (VERBOSE)
|
|
1485
|
+
console.log('[hmr-client] invoking Application.resetRootView with entry (always)', { isFrameRoot, hadPlaceholder, isIOS });
|
|
1486
|
+
// Always use an entry with a create() function to avoid cross‑realm instanceof checks on Android.
|
|
1487
|
+
App2.resetRootView(entry);
|
|
1488
|
+
// After authoritative reset, it's safe to detach the early placeholder launch handler
|
|
1489
|
+
try {
|
|
1490
|
+
const restore = globalThis.__NS_DEV_RESTORE_PLACEHOLDER__;
|
|
1491
|
+
if (typeof restore === 'function') {
|
|
1492
|
+
if (VERBOSE)
|
|
1493
|
+
console.log('[hmr-client] restoring: detach early placeholder launch handler');
|
|
1494
|
+
restore();
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
catch { }
|
|
1498
|
+
if (VERBOSE) {
|
|
1499
|
+
logUiSnapshot('post-resetRootView');
|
|
1500
|
+
console.log('[hmr-client] performResetRoot completed', {
|
|
1501
|
+
elapsedMs: Date.now() - tStart,
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1504
|
+
return true;
|
|
1505
|
+
}
|
|
1506
|
+
catch (e) {
|
|
1507
|
+
console.warn('[hmr-client] resetRootView failed', e);
|
|
1508
|
+
try {
|
|
1509
|
+
if (VERBOSE)
|
|
1510
|
+
console.warn('[hmr-client] resetRootView stack', e?.stack);
|
|
1511
|
+
}
|
|
1512
|
+
catch { }
|
|
1513
|
+
return false;
|
|
1514
|
+
}
|
|
1515
|
+
finally {
|
|
1516
|
+
try {
|
|
1517
|
+
globalThis.__NS_DEV_RESET_IN_PROGRESS__ = false;
|
|
1518
|
+
}
|
|
1519
|
+
catch { }
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
export function initHmrClient(opts) {
|
|
1523
|
+
if (opts?.wsUrl) {
|
|
1524
|
+
setHMRWsUrl(opts.wsUrl);
|
|
1525
|
+
}
|
|
1526
|
+
if (VERBOSE)
|
|
1527
|
+
console.log('[hmr-client] Initializing Vue HMR client', getHMRWsUrl() ? `(ws: ${getHMRWsUrl()})` : '');
|
|
1528
|
+
// Prevent duplicate client initialization across re-evaluations
|
|
1529
|
+
const g = globalThis;
|
|
1530
|
+
if (g.__NS_HMR_CLIENT_ACTIVE__) {
|
|
1531
|
+
if (VERBOSE)
|
|
1532
|
+
console.log('[hmr-client] HMR client already active; skipping duplicate init');
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
g.__NS_HMR_CLIENT_ACTIVE__ = true;
|
|
1536
|
+
ensureCoreAliasesOnGlobalThis();
|
|
1537
|
+
connectHmr();
|
|
1538
|
+
// Best-effort: install back wrapper even before first remount; original root may be captured later
|
|
1539
|
+
switch (__NS_TARGET_FLAVOR__) {
|
|
1540
|
+
case 'vue':
|
|
1541
|
+
ensureBackWrapperInstalled(performResetRoot, getCore);
|
|
1542
|
+
break;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
export default function startViteHMR(opts) {
|
|
1546
|
+
if (VERBOSE)
|
|
1547
|
+
console.log('[hmr-client] Starting HMR client', opts);
|
|
1548
|
+
initHmrClient(opts);
|
|
1549
|
+
}
|
|
1550
|
+
//# sourceMappingURL=index.js.map
|