@nativescript/vite 0.0.1-alpha.7 → 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/{dist/helpers → helpers}/external-configs.js +2 -1
- 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 -3
- 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/{dist/helpers → helpers}/module-runner-patch.d.ts +1 -1
- package/{dist/helpers → helpers}/module-runner-patch.js +10 -12
- 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/{dist/helpers → helpers}/ns-cli-plugins.d.ts +6 -1
- package/{dist/helpers → helpers}/ns-cli-plugins.js +31 -51
- 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 +18 -22
- 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.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 +70 -71
- package/helpers/ts-config-paths.js.map +1 -0
- package/{dist/helpers → helpers}/utils.js +14 -27
- package/helpers/utils.js.map +1 -0
- package/{dist/helpers → helpers}/workers.js +15 -16
- package/helpers/workers.js.map +1 -0
- package/{dist/hmr → hmr/client}/css-handler.js +18 -17
- 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/{dist/hmr/plugins/plugin-vue.js → hmr/server/vite-plugin.js} +13 -15
- 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 -31
- 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/{dist/shims → shims}/node-module.js +3 -2
- 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 -4
- package/dist/configuration/base.js +0 -386
- 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 -20
- package/dist/helpers/main-entry-hmr-includes.d.ts +0 -1
- package/dist/helpers/main-entry-hmr-includes.js +0 -18
- package/dist/helpers/main-entry.d.ts +0 -5
- package/dist/helpers/main-entry.js +0 -82
- package/dist/helpers/package-platform-aliases.d.ts +0 -4
- package/dist/helpers/preserve-imports.js +0 -19
- package/dist/helpers/resolver.d.ts +0 -4
- package/dist/helpers/ts-config-paths.d.ts +0 -4
- package/dist/hmr/client-vue.d.ts +0 -6
- package/dist/hmr/client-vue.js +0 -585
- package/dist/hmr/component-tracker.d.ts +0 -23
- package/dist/hmr/component-tracker.js +0 -193
- package/dist/hmr/message-handler.d.ts +0 -1
- package/dist/hmr/message-handler.js +0 -590
- package/dist/hmr/nsv-hooks.d.ts +0 -2
- package/dist/hmr/nsv-hooks.js +0 -481
- package/dist/hmr/plugins/index.d.ts +0 -1
- package/dist/hmr/plugins/index.js +0 -16
- package/dist/hmr/plugins/plugin-vue.d.ts +0 -2
- package/dist/hmr/plugins/websocket-vue.d.ts +0 -2
- package/dist/hmr/plugins/websocket-vue.js +0 -911
- package/dist/hmr/runtime-vue.d.ts +0 -13
- package/dist/hmr/runtime-vue.js +0 -2306
- package/dist/hmr/types.d.ts +0 -24
- package/dist/hmr/types.js +0 -2
- 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}/external-configs.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}/preserve-imports.d.ts +0 -0
- /package/{dist/helpers → helpers}/project.d.ts +0 -0
- /package/{dist/helpers → helpers}/utils.d.ts +0 -0
- /package/{dist/helpers → helpers}/workers.d.ts +0 -0
- /package/{dist/hmr → hmr/client}/css-handler.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}/node-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
package/dist/hmr/runtime-vue.js
DELETED
|
@@ -1,2306 +0,0 @@
|
|
|
1
|
-
// Vue HMR Runtime Integration for NativeScript
|
|
2
|
-
// Clean implementation replacing corrupted content
|
|
3
|
-
import componentTracker from './component-tracker';
|
|
4
|
-
const VERBOSE = true;
|
|
5
|
-
// Track deferred update attempts per instance to avoid infinite loops
|
|
6
|
-
const __pendingUpdateAttempts = new WeakMap();
|
|
7
|
-
const MAX_DEFER_ATTEMPTS = 8;
|
|
8
|
-
const BASE_DEFER_MS = 16; // ~1 frame
|
|
9
|
-
// Microtask and frame schedulers for consistent timing across runtimes
|
|
10
|
-
function scheduleMicrotask(fn) {
|
|
11
|
-
try {
|
|
12
|
-
if (typeof globalThis.queueMicrotask === 'function')
|
|
13
|
-
return void globalThis.queueMicrotask(fn);
|
|
14
|
-
}
|
|
15
|
-
catch { }
|
|
16
|
-
try {
|
|
17
|
-
Promise.resolve().then(fn);
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
setTimeout(fn, 0);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function scheduleNextFrame(fn) {
|
|
24
|
-
try {
|
|
25
|
-
const raf = globalThis.requestAnimationFrame;
|
|
26
|
-
if (typeof raf === 'function')
|
|
27
|
-
return void raf(() => fn());
|
|
28
|
-
}
|
|
29
|
-
catch { }
|
|
30
|
-
setTimeout(fn, 16);
|
|
31
|
-
}
|
|
32
|
-
function resolveNSView(el) {
|
|
33
|
-
let view = null;
|
|
34
|
-
let nativeView = null;
|
|
35
|
-
try {
|
|
36
|
-
if (el && typeof el === 'object') {
|
|
37
|
-
// Method 1: Direct NativeScript view
|
|
38
|
-
if (el.nativeViewProtected) {
|
|
39
|
-
view = el;
|
|
40
|
-
nativeView = el.nativeViewProtected;
|
|
41
|
-
}
|
|
42
|
-
else if (el.nativeView) {
|
|
43
|
-
nativeView = el.nativeView;
|
|
44
|
-
view = el.view || el; // Use el as view if no separate view property
|
|
45
|
-
}
|
|
46
|
-
// Method 2: NSVElement wrapper
|
|
47
|
-
else if (el.view && el.view.nativeViewProtected) {
|
|
48
|
-
view = el.view;
|
|
49
|
-
nativeView = el.view.nativeViewProtected;
|
|
50
|
-
}
|
|
51
|
-
else if (el.view) {
|
|
52
|
-
view = el.view;
|
|
53
|
-
nativeView = view.nativeViewProtected || view.nativeView || null;
|
|
54
|
-
}
|
|
55
|
-
// Method 3: Check if el itself is a native view that we need to wrap
|
|
56
|
-
else if (el._nativeView || el.__native) {
|
|
57
|
-
nativeView = el._nativeView || el.__native;
|
|
58
|
-
view = el; // el is the wrapper
|
|
59
|
-
}
|
|
60
|
-
// Method 4: Check parent node navigation
|
|
61
|
-
else if (el.parentNode) {
|
|
62
|
-
try {
|
|
63
|
-
const p = el.parentNode;
|
|
64
|
-
if (p) {
|
|
65
|
-
if (p.nativeViewProtected) {
|
|
66
|
-
view = p;
|
|
67
|
-
nativeView = p.nativeViewProtected;
|
|
68
|
-
}
|
|
69
|
-
else if (p.view && p.view.nativeViewProtected) {
|
|
70
|
-
view = p.view;
|
|
71
|
-
nativeView = p.view.nativeViewProtected;
|
|
72
|
-
}
|
|
73
|
-
else if (p.nativeView) {
|
|
74
|
-
nativeView = p.nativeView;
|
|
75
|
-
view = p.view || p;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch { }
|
|
80
|
-
}
|
|
81
|
-
// Method 5: Try to find NativeScript view from iOS/Android native objects
|
|
82
|
-
else if (typeof el.ios !== 'undefined' || typeof el.android !== 'undefined') {
|
|
83
|
-
// el might be a native view directly, try to find the wrapper
|
|
84
|
-
nativeView = el;
|
|
85
|
-
// Look for ViewBase wrapper in parent hierarchy or references
|
|
86
|
-
try {
|
|
87
|
-
if (el._owner) {
|
|
88
|
-
view = el._owner;
|
|
89
|
-
}
|
|
90
|
-
else if (el.__owner) {
|
|
91
|
-
view = el.__owner;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
catch { }
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch { }
|
|
99
|
-
const hasNativeView = !!nativeView;
|
|
100
|
-
let suspendCount;
|
|
101
|
-
let isLoaded;
|
|
102
|
-
try {
|
|
103
|
-
const v = view || el;
|
|
104
|
-
if (v && typeof v === 'object') {
|
|
105
|
-
suspendCount = v._suspendNativeUpdatesCount;
|
|
106
|
-
const field = v._isLoaded;
|
|
107
|
-
const getter = v.isLoaded;
|
|
108
|
-
isLoaded = typeof field === 'boolean' ? field : (typeof getter === 'boolean' ? getter : undefined);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch { }
|
|
112
|
-
const isRootView = !!(view && view.mIsRootView);
|
|
113
|
-
return { el, view, nativeView, hasNativeView, isRootView, suspendCount, isLoaded };
|
|
114
|
-
}
|
|
115
|
-
// Probe multiple likely locations on a component instance to find an NS view quickly after updates
|
|
116
|
-
function findNSViewFromInternal(internal) {
|
|
117
|
-
const candidates = [];
|
|
118
|
-
try {
|
|
119
|
-
const ins = internal || {};
|
|
120
|
-
const vnode = ins.vnode;
|
|
121
|
-
const proxy = ins.proxy;
|
|
122
|
-
const subTree = ins.subTree;
|
|
123
|
-
// Add candidates in order of preference - prioritize NativeScript elements
|
|
124
|
-
if (proxy && proxy.$el) {
|
|
125
|
-
const el = proxy.$el;
|
|
126
|
-
if (el && el.constructor && el.constructor.name === 'NSVElement') {
|
|
127
|
-
candidates.unshift(el); // Prioritize NSVElement
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
candidates.push(el);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (vnode && vnode.el) {
|
|
134
|
-
const el = vnode.el;
|
|
135
|
-
if (el && el.constructor && el.constructor.name === 'NSVElement') {
|
|
136
|
-
candidates.unshift(el); // Prioritize NSVElement
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
candidates.push(el);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (subTree && subTree.el) {
|
|
143
|
-
const el = subTree.el;
|
|
144
|
-
if (el && el.constructor && el.constructor.name === 'NSVElement') {
|
|
145
|
-
candidates.unshift(el); // Prioritize NSVElement
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
candidates.push(el);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
// Check subTree component hierarchy
|
|
152
|
-
if (subTree && subTree.component && subTree.component.vnode) {
|
|
153
|
-
const c = subTree.component;
|
|
154
|
-
if (c.vnode && c.vnode.el) {
|
|
155
|
-
const el = c.vnode.el;
|
|
156
|
-
if (el && el.constructor && el.constructor.name === 'NSVElement') {
|
|
157
|
-
candidates.unshift(el); // Prioritize NSVElement
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
candidates.push(el);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (c.subTree && c.subTree.el) {
|
|
164
|
-
const el = c.subTree.el;
|
|
165
|
-
if (el && el.constructor && el.constructor.name === 'NSVElement') {
|
|
166
|
-
candidates.unshift(el); // Prioritize NSVElement
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
candidates.push(el);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// Also peek one level deeper through children arrays if present
|
|
174
|
-
try {
|
|
175
|
-
const st = subTree;
|
|
176
|
-
const ch = st && (st.children || st.child);
|
|
177
|
-
if (Array.isArray(ch)) {
|
|
178
|
-
for (const it of ch) {
|
|
179
|
-
if (!it || typeof it !== 'object')
|
|
180
|
-
continue;
|
|
181
|
-
try {
|
|
182
|
-
if (it.el) {
|
|
183
|
-
const el = it.el;
|
|
184
|
-
if (el && el.constructor && el.constructor.name === 'NSVElement') {
|
|
185
|
-
candidates.unshift(el); // Prioritize NSVElement
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
candidates.push(el);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
catch { }
|
|
193
|
-
try {
|
|
194
|
-
if (it.component && it.component.vnode && it.component.vnode.el)
|
|
195
|
-
candidates.push(it.component.vnode.el);
|
|
196
|
-
}
|
|
197
|
-
catch { }
|
|
198
|
-
try {
|
|
199
|
-
if (it.component && it.component.subTree && it.component.subTree.el)
|
|
200
|
-
candidates.push(it.component.subTree.el);
|
|
201
|
-
}
|
|
202
|
-
catch { }
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
catch { }
|
|
207
|
-
// Add the internal instance itself as a candidate only if it might be useful
|
|
208
|
-
if (ins && typeof ins === 'object' && !candidates.length) {
|
|
209
|
-
candidates.push(ins);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
catch { }
|
|
213
|
-
if (VERBOSE && candidates.length > 0) {
|
|
214
|
-
console.info('[ns-hmr][vue-runtime] findNSViewFromInternal candidates:', {
|
|
215
|
-
count: candidates.length,
|
|
216
|
-
types: candidates.map(c => c?.constructor?.name || typeof c).slice(0, 5)
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
// Evaluate in order; return first with a nativeView
|
|
220
|
-
for (const el of candidates) {
|
|
221
|
-
try {
|
|
222
|
-
const info = resolveNSView(el);
|
|
223
|
-
if (VERBOSE) {
|
|
224
|
-
console.info('[ns-hmr][vue-runtime] candidate evaluation:', {
|
|
225
|
-
elType: el?.constructor?.name || typeof el,
|
|
226
|
-
hasNativeView: info.hasNativeView,
|
|
227
|
-
hasView: !!info.view,
|
|
228
|
-
viewType: info.view?.constructor?.name
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
if (info && info.hasNativeView) {
|
|
232
|
-
if (VERBOSE)
|
|
233
|
-
console.info('[ns-hmr][vue-runtime] Found valid candidate with native view');
|
|
234
|
-
return { el, info };
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
catch { }
|
|
238
|
-
}
|
|
239
|
-
// Fallback to first candidate if any
|
|
240
|
-
const first = candidates.length ? candidates[0] : null;
|
|
241
|
-
const info = resolveNSView(first);
|
|
242
|
-
if (VERBOSE) {
|
|
243
|
-
console.info('[ns-hmr][vue-runtime] Using fallback candidate:', {
|
|
244
|
-
hasFirst: !!first,
|
|
245
|
-
firstType: first?.constructor?.name || typeof first,
|
|
246
|
-
hasNativeView: info.hasNativeView,
|
|
247
|
-
hasView: !!info.view
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
return { el: first, info };
|
|
251
|
-
}
|
|
252
|
-
function registerExistingComponents(runtime) {
|
|
253
|
-
try {
|
|
254
|
-
if (VERBOSE)
|
|
255
|
-
console.info('[ns-hmr][vue-runtime] Registering existing components with HMR runtime');
|
|
256
|
-
let registeredCount = 0;
|
|
257
|
-
// Method 1: Use component tracker
|
|
258
|
-
const allInstances = componentTracker.getAllInstances();
|
|
259
|
-
for (const [id, instances] of allInstances) {
|
|
260
|
-
try {
|
|
261
|
-
// Create record for this component type if not already recorded
|
|
262
|
-
if (typeof runtime.createRecord === 'function' && typeof runtime.isRecorded === 'function') {
|
|
263
|
-
if (!runtime.isRecorded(id)) {
|
|
264
|
-
// Get component definition from first instance
|
|
265
|
-
const firstInstance = Array.from(instances)[0];
|
|
266
|
-
const componentDef = firstInstance?.$?.type || firstInstance?.type || {};
|
|
267
|
-
runtime.createRecord(id, componentDef);
|
|
268
|
-
if (VERBOSE)
|
|
269
|
-
console.info('[ns-hmr][vue-runtime] Created record for component:', id);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
// Register all instances of this component
|
|
273
|
-
if (typeof runtime.registerInstance === 'function') {
|
|
274
|
-
for (const instance of instances) {
|
|
275
|
-
runtime.registerInstance(id, instance);
|
|
276
|
-
registeredCount++;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
catch (e) {
|
|
281
|
-
if (VERBOSE)
|
|
282
|
-
console.warn('[ns-hmr][vue-runtime] Failed to register component:', id, e?.message);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
// Method 2: Bridge with fallback runtime records (handle the disconnect)
|
|
286
|
-
try {
|
|
287
|
-
const fallbackRuntime = runtime;
|
|
288
|
-
if (fallbackRuntime && fallbackRuntime.map) {
|
|
289
|
-
let fallbackCount = 0;
|
|
290
|
-
const records = fallbackRuntime.map;
|
|
291
|
-
if (records && typeof records.forEach === 'function') {
|
|
292
|
-
// Map object with forEach
|
|
293
|
-
records.forEach((instances, id) => {
|
|
294
|
-
fallbackCount++;
|
|
295
|
-
if (VERBOSE)
|
|
296
|
-
console.info('[ns-hmr][vue-runtime] Found fallback record:', id, 'instances:', instances ? instances.length : 0);
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
else if (records && typeof records === 'object') {
|
|
300
|
-
// Plain object
|
|
301
|
-
for (const [id, instances] of Object.entries(records)) {
|
|
302
|
-
fallbackCount++;
|
|
303
|
-
if (VERBOSE)
|
|
304
|
-
console.info('[ns-hmr][vue-runtime] Found fallback record:', id, 'instances:', instances?.length || 0);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
if (VERBOSE)
|
|
308
|
-
console.info('[ns-hmr][vue-runtime] Fallback runtime has', fallbackCount, 'records');
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
catch (e) {
|
|
312
|
-
if (VERBOSE)
|
|
313
|
-
console.warn('[ns-hmr][vue-runtime] Failed to analyze fallback runtime records:', e?.message);
|
|
314
|
-
}
|
|
315
|
-
if (VERBOSE)
|
|
316
|
-
console.info('[ns-hmr][vue-runtime] Registered existing components:', {
|
|
317
|
-
componentTypes: allInstances.size,
|
|
318
|
-
instanceCount: registeredCount
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
catch (e) {
|
|
322
|
-
if (VERBOSE)
|
|
323
|
-
console.warn('[ns-hmr][vue-runtime] Failed to register existing components:', e?.message);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
function getComponentIdFromInternal(internal) {
|
|
327
|
-
try {
|
|
328
|
-
// Try to get component ID from various locations
|
|
329
|
-
const type = internal?.type || internal?.vnode?.type;
|
|
330
|
-
if (type) {
|
|
331
|
-
// Check for __hmrId (Vue 3 HMR component ID)
|
|
332
|
-
if (type.__hmrId)
|
|
333
|
-
return type.__hmrId;
|
|
334
|
-
// Check for __file (component file path)
|
|
335
|
-
if (type.__file)
|
|
336
|
-
return type.__file;
|
|
337
|
-
// Check for name
|
|
338
|
-
if (type.name)
|
|
339
|
-
return type.name;
|
|
340
|
-
// Check for _name (internal Vue name)
|
|
341
|
-
if (type._name)
|
|
342
|
-
return type._name;
|
|
343
|
-
}
|
|
344
|
-
// Check component instance for name
|
|
345
|
-
if (internal?.proxy?.$options?.name)
|
|
346
|
-
return internal.proxy.$options.name;
|
|
347
|
-
if (internal?.proxy?.$options?.__file)
|
|
348
|
-
return internal.proxy.$options.__file;
|
|
349
|
-
// Fallback to component constructor name
|
|
350
|
-
if (internal?.constructor?.name && internal.constructor.name !== 'Object') {
|
|
351
|
-
return internal.constructor.name;
|
|
352
|
-
}
|
|
353
|
-
return null;
|
|
354
|
-
}
|
|
355
|
-
catch {
|
|
356
|
-
return null;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
function instanceHasFrameOrPage(internal) {
|
|
360
|
-
try {
|
|
361
|
-
const q = [];
|
|
362
|
-
const push = (n) => { if (n && typeof n === 'object')
|
|
363
|
-
q.push(n); };
|
|
364
|
-
push(internal?.subTree || internal?.vnode);
|
|
365
|
-
let seen = 0;
|
|
366
|
-
while (q.length && seen < 50) {
|
|
367
|
-
const n = q.shift();
|
|
368
|
-
seen++;
|
|
369
|
-
try {
|
|
370
|
-
const t = (n && (n.type || n.component?.type)) || null;
|
|
371
|
-
const name = t && ((t.__name || t.name || '').toString().toLowerCase());
|
|
372
|
-
if (name === 'frame' || name === 'page')
|
|
373
|
-
return true;
|
|
374
|
-
}
|
|
375
|
-
catch { }
|
|
376
|
-
try {
|
|
377
|
-
if (n.component)
|
|
378
|
-
push(n.component.subTree);
|
|
379
|
-
}
|
|
380
|
-
catch { }
|
|
381
|
-
try {
|
|
382
|
-
const ch = (n.children || n.child);
|
|
383
|
-
if (Array.isArray(ch))
|
|
384
|
-
for (const c of ch)
|
|
385
|
-
push(c);
|
|
386
|
-
else
|
|
387
|
-
push(ch);
|
|
388
|
-
}
|
|
389
|
-
catch { }
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
catch { }
|
|
393
|
-
return false;
|
|
394
|
-
}
|
|
395
|
-
// Cache resolved views per instance to avoid inconsistent lookups
|
|
396
|
-
const instanceViewCache = new WeakMap();
|
|
397
|
-
// Cache the working instance per component ID to ensure consistency
|
|
398
|
-
const workingInstanceCache = new Map();
|
|
399
|
-
// Global registry to track the current working instance being processed
|
|
400
|
-
let currentWorkingInstance = null;
|
|
401
|
-
let currentComponentId = null;
|
|
402
|
-
function setCurrentWorkingInstance(instance, componentId) {
|
|
403
|
-
currentWorkingInstance = instance;
|
|
404
|
-
currentComponentId = componentId || null;
|
|
405
|
-
if (VERBOSE && componentId) {
|
|
406
|
-
console.info('[ns-hmr][vue-runtime] Set current working instance for:', componentId);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
function getCurrentWorkingInstance() {
|
|
410
|
-
return currentWorkingInstance;
|
|
411
|
-
}
|
|
412
|
-
function isNSViewReady(instance, componentId) {
|
|
413
|
-
try {
|
|
414
|
-
if (VERBOSE) {
|
|
415
|
-
console.info('[ns-hmr][vue-runtime] isNSViewReady called with:', {
|
|
416
|
-
hasInstance: !!instance,
|
|
417
|
-
instanceType: instance?.constructor?.name,
|
|
418
|
-
componentId: componentId || 'none',
|
|
419
|
-
hasCachedWorking: componentId ? workingInstanceCache.has(componentId) : false,
|
|
420
|
-
hasCurrentWorking: !!currentWorkingInstance
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
// Priority 1: If we have a cached working instance for this component, use it
|
|
424
|
-
if (componentId && workingInstanceCache.has(componentId)) {
|
|
425
|
-
const workingInstance = workingInstanceCache.get(componentId);
|
|
426
|
-
if (workingInstance && workingInstance !== instance) {
|
|
427
|
-
if (VERBOSE) {
|
|
428
|
-
console.info('[ns-hmr][vue-runtime] Using cached working instance for component:', componentId);
|
|
429
|
-
}
|
|
430
|
-
instance = workingInstance;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
// Priority 2: If no cached instance but we have a current working instance, try it
|
|
434
|
-
else if (currentWorkingInstance && currentWorkingInstance !== instance) {
|
|
435
|
-
if (VERBOSE) {
|
|
436
|
-
console.info('[ns-hmr][vue-runtime] Trying current working instance as fallback');
|
|
437
|
-
}
|
|
438
|
-
// Test the current working instance first
|
|
439
|
-
const testFound = findNSViewFromInternal(currentWorkingInstance);
|
|
440
|
-
if (testFound.info?.hasNativeView) {
|
|
441
|
-
if (VERBOSE) {
|
|
442
|
-
console.info('[ns-hmr][vue-runtime] Current working instance is valid, using it');
|
|
443
|
-
}
|
|
444
|
-
instance = currentWorkingInstance;
|
|
445
|
-
// Cache it for this component if we have a component ID
|
|
446
|
-
if (componentId) {
|
|
447
|
-
workingInstanceCache.set(componentId, currentWorkingInstance);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
let cached = instanceViewCache.get(instance);
|
|
452
|
-
if (!cached) {
|
|
453
|
-
const found = findNSViewFromInternal(instance);
|
|
454
|
-
if (found.info?.hasNativeView) {
|
|
455
|
-
instanceViewCache.set(instance, found);
|
|
456
|
-
cached = found;
|
|
457
|
-
// Cache this as the working instance for this component
|
|
458
|
-
if (componentId && !workingInstanceCache.has(componentId)) {
|
|
459
|
-
workingInstanceCache.set(componentId, instance);
|
|
460
|
-
if (VERBOSE) {
|
|
461
|
-
console.info('[ns-hmr][vue-runtime] Cached working instance for component:', componentId);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
const hasNativeView = cached?.info?.hasNativeView || false;
|
|
467
|
-
const view = cached?.info?.view;
|
|
468
|
-
if (VERBOSE) {
|
|
469
|
-
console.info('[ns-hmr][vue-runtime] isNSViewReady check:', {
|
|
470
|
-
hasEl: !!cached?.el,
|
|
471
|
-
elType: cached?.el?.constructor?.name,
|
|
472
|
-
hasNativeView,
|
|
473
|
-
suspendCount: cached?.info?.suspendCount,
|
|
474
|
-
isLoaded: cached?.info?.isLoaded,
|
|
475
|
-
view: !!view,
|
|
476
|
-
viewType: view?.constructor?.name,
|
|
477
|
-
fromCache: instanceViewCache.has(instance),
|
|
478
|
-
usingWorkingInstance: componentId && workingInstanceCache.has(componentId),
|
|
479
|
-
componentId: componentId || 'none'
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
if (!hasNativeView) {
|
|
483
|
-
if (VERBOSE)
|
|
484
|
-
console.info('[ns-hmr][vue-runtime] Not ready: no native view');
|
|
485
|
-
return false;
|
|
486
|
-
}
|
|
487
|
-
if (typeof cached?.info?.suspendCount === 'number' && cached.info.suspendCount !== 0) {
|
|
488
|
-
if (VERBOSE)
|
|
489
|
-
console.info('[ns-hmr][vue-runtime] Not ready: suspended', { suspendCount: cached.info.suspendCount });
|
|
490
|
-
return false;
|
|
491
|
-
}
|
|
492
|
-
if (typeof cached?.info?.isLoaded === 'boolean' && cached.info.isLoaded === false) {
|
|
493
|
-
if (VERBOSE)
|
|
494
|
-
console.info('[ns-hmr][vue-runtime] Not ready: not loaded');
|
|
495
|
-
return false;
|
|
496
|
-
}
|
|
497
|
-
if (VERBOSE)
|
|
498
|
-
console.info('[ns-hmr][vue-runtime] View is ready for update');
|
|
499
|
-
}
|
|
500
|
-
catch (e) {
|
|
501
|
-
if (VERBOSE)
|
|
502
|
-
console.warn('[ns-hmr][vue-runtime] isNSViewReady failed:', e?.message);
|
|
503
|
-
return false;
|
|
504
|
-
}
|
|
505
|
-
return true;
|
|
506
|
-
}
|
|
507
|
-
const __postUpdateStabilized = new WeakSet();
|
|
508
|
-
const __postUpdateFollowed = new WeakSet();
|
|
509
|
-
// Cache the last resolved element for an internal instance to help stabilization find it later
|
|
510
|
-
const __lastResolvedEl = new WeakMap();
|
|
511
|
-
// Guard to avoid blasting global layout more than once per instance
|
|
512
|
-
const __globalLayoutRequested = new WeakSet();
|
|
513
|
-
function stabilizeNativeLayout(internal, attempt = 1) {
|
|
514
|
-
try {
|
|
515
|
-
if (!internal || __postUpdateStabilized.has(internal))
|
|
516
|
-
return;
|
|
517
|
-
// Prefer the last-resolved element if we have one; otherwise probe fresh
|
|
518
|
-
let cached = __lastResolvedEl.get(internal) || null;
|
|
519
|
-
let probe = cached || findNSViewFromInternal(internal);
|
|
520
|
-
let el = probe.el;
|
|
521
|
-
let info = probe.info;
|
|
522
|
-
// If still no native view, attempt to walk up a couple of parent components to find a parent view
|
|
523
|
-
let parentInfo = null;
|
|
524
|
-
if (!info?.hasNativeView) {
|
|
525
|
-
try {
|
|
526
|
-
let p = internal.parent;
|
|
527
|
-
let hops = 0;
|
|
528
|
-
while (p && hops < 3 && !(parentInfo && parentInfo.hasNativeView)) {
|
|
529
|
-
try {
|
|
530
|
-
const pp = findNSViewFromInternal(p);
|
|
531
|
-
if (pp && pp.info && pp.info.hasNativeView) {
|
|
532
|
-
parentInfo = pp.info;
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
catch { }
|
|
537
|
-
p = p.parent;
|
|
538
|
-
hops++;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
catch { }
|
|
542
|
-
}
|
|
543
|
-
const v = info.view;
|
|
544
|
-
const nv = info.nativeView;
|
|
545
|
-
// If this instance has a working native view, set it as current working instance
|
|
546
|
-
if (info?.hasNativeView && probe.el) {
|
|
547
|
-
setCurrentWorkingInstance(internal);
|
|
548
|
-
if (VERBOSE) {
|
|
549
|
-
console.info('[ns-hmr][vue-runtime] stabilizeNativeLayout found working instance');
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
if (VERBOSE) {
|
|
553
|
-
try {
|
|
554
|
-
const name = v && v.constructor ? v.constructor.name : undefined;
|
|
555
|
-
const snap = {
|
|
556
|
-
attempt,
|
|
557
|
-
hasView: !!v,
|
|
558
|
-
hasNativeView: !!nv,
|
|
559
|
-
viewType: name,
|
|
560
|
-
hasVNode: !!(internal && internal.vnode),
|
|
561
|
-
hasSubTree: !!(internal && internal.subTree),
|
|
562
|
-
parentHasNativeView: !!(parentInfo && parentInfo.hasNativeView),
|
|
563
|
-
};
|
|
564
|
-
console.info('[ns-hmr][vue-runtime] stabilizeNativeLayout', snap);
|
|
565
|
-
}
|
|
566
|
-
catch { }
|
|
567
|
-
}
|
|
568
|
-
// If not yet attached or wrapper view not yet resolved, retry shortly (up to 5 attempts)
|
|
569
|
-
if ((!nv || !v) && attempt < 5) {
|
|
570
|
-
// On the third attempt, try a remedial internal.update once to nudge vnode attachment
|
|
571
|
-
if (attempt === 3) {
|
|
572
|
-
try {
|
|
573
|
-
typeof internal?.update === 'function' && internal.update();
|
|
574
|
-
}
|
|
575
|
-
catch { }
|
|
576
|
-
}
|
|
577
|
-
// First a microtask, then a frame on subsequent attempts
|
|
578
|
-
if (attempt === 1) {
|
|
579
|
-
return void scheduleMicrotask(() => stabilizeNativeLayout(internal, attempt + 1));
|
|
580
|
-
}
|
|
581
|
-
return void scheduleNextFrame(() => stabilizeNativeLayout(internal, attempt + 1));
|
|
582
|
-
}
|
|
583
|
-
// Light-touch layout refresh
|
|
584
|
-
let did = false;
|
|
585
|
-
try {
|
|
586
|
-
if (v && typeof v.requestLayout === 'function') {
|
|
587
|
-
v.requestLayout();
|
|
588
|
-
did = true;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
catch { }
|
|
592
|
-
if (!did && nv) {
|
|
593
|
-
// Try common NativeScript native view layout methods
|
|
594
|
-
try {
|
|
595
|
-
if (typeof nv.setNeedsLayout === 'function') {
|
|
596
|
-
nv.setNeedsLayout();
|
|
597
|
-
did = true;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
catch { }
|
|
601
|
-
try {
|
|
602
|
-
if (!did && typeof nv.setNeedsDisplay === 'function') {
|
|
603
|
-
nv.setNeedsDisplay();
|
|
604
|
-
did = true;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
catch { }
|
|
608
|
-
try {
|
|
609
|
-
if (!did && typeof nv.requestLayout === 'function') {
|
|
610
|
-
nv.requestLayout();
|
|
611
|
-
did = true;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
catch { }
|
|
615
|
-
try {
|
|
616
|
-
if (!did && typeof nv.invalidate === 'function') {
|
|
617
|
-
nv.invalidate();
|
|
618
|
-
did = true;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
catch { }
|
|
622
|
-
// For iOS views
|
|
623
|
-
try {
|
|
624
|
-
if (!did && typeof nv.setNeedsLayout === 'function') {
|
|
625
|
-
nv.setNeedsLayout();
|
|
626
|
-
did = true;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
catch { }
|
|
630
|
-
try {
|
|
631
|
-
if (!did && typeof nv.layoutIfNeeded === 'function') {
|
|
632
|
-
nv.layoutIfNeeded();
|
|
633
|
-
did = true;
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
catch { }
|
|
637
|
-
}
|
|
638
|
-
// Page-level fallback: request layout on the nearest Page to flush subtree
|
|
639
|
-
if (!did) {
|
|
640
|
-
try {
|
|
641
|
-
const candidateView = v || (parentInfo && parentInfo.view) || null;
|
|
642
|
-
const page = candidateView && (candidateView.page || candidateView._page);
|
|
643
|
-
if (page && typeof page.requestLayout === 'function') {
|
|
644
|
-
page.requestLayout();
|
|
645
|
-
did = true;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
catch { }
|
|
649
|
-
}
|
|
650
|
-
// If we didn't find a child view but a parent has a native view, request layout there
|
|
651
|
-
if (!did && parentInfo && parentInfo.nativeView) {
|
|
652
|
-
try {
|
|
653
|
-
const pnv = parentInfo.nativeView;
|
|
654
|
-
if (typeof pnv.setNeedsLayout === 'function') {
|
|
655
|
-
pnv.setNeedsLayout();
|
|
656
|
-
did = true;
|
|
657
|
-
}
|
|
658
|
-
else if (typeof pnv.requestLayout === 'function') {
|
|
659
|
-
pnv.requestLayout();
|
|
660
|
-
did = true;
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
catch { }
|
|
664
|
-
}
|
|
665
|
-
// Minor CSS state poke if layout wasn’t available
|
|
666
|
-
if (!did) {
|
|
667
|
-
try {
|
|
668
|
-
if (v && typeof v._onCssStateChange === 'function') {
|
|
669
|
-
v._onCssStateChange();
|
|
670
|
-
did = true;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
catch { }
|
|
674
|
-
}
|
|
675
|
-
// As a final fallback before giving up: request layout on topmost Frame or root view once
|
|
676
|
-
if (!did && attempt >= 4 && !__globalLayoutRequested.has(internal)) {
|
|
677
|
-
try {
|
|
678
|
-
const req = globalThis.require;
|
|
679
|
-
const core = req && (() => { try {
|
|
680
|
-
return req('@nativescript/core');
|
|
681
|
-
}
|
|
682
|
-
catch {
|
|
683
|
-
return null;
|
|
684
|
-
} })();
|
|
685
|
-
if (core) {
|
|
686
|
-
let flushed = false;
|
|
687
|
-
try {
|
|
688
|
-
const Frame = core.Frame;
|
|
689
|
-
const top = Frame && (typeof Frame.topmost === 'function' ? Frame.topmost() : null);
|
|
690
|
-
if (top) {
|
|
691
|
-
if (typeof top.requestLayout === 'function') {
|
|
692
|
-
top.requestLayout();
|
|
693
|
-
flushed = true;
|
|
694
|
-
}
|
|
695
|
-
else if (top.nativeViewProtected && typeof top.nativeViewProtected.setNeedsLayout === 'function') {
|
|
696
|
-
top.nativeViewProtected.setNeedsLayout();
|
|
697
|
-
flushed = true;
|
|
698
|
-
}
|
|
699
|
-
else if (top.nativeView && typeof top.nativeView.requestLayout === 'function') {
|
|
700
|
-
top.nativeView.requestLayout();
|
|
701
|
-
flushed = true;
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
catch { }
|
|
706
|
-
if (!flushed) {
|
|
707
|
-
try {
|
|
708
|
-
const App = core.Application || core.app || core.application;
|
|
709
|
-
const root = App && (typeof App.getRootView === 'function' ? App.getRootView() : null);
|
|
710
|
-
if (root) {
|
|
711
|
-
if (typeof root.requestLayout === 'function') {
|
|
712
|
-
root.requestLayout();
|
|
713
|
-
flushed = true;
|
|
714
|
-
}
|
|
715
|
-
else if (root.nativeViewProtected && typeof root.nativeViewProtected.setNeedsLayout === 'function') {
|
|
716
|
-
root.nativeViewProtected.setNeedsLayout();
|
|
717
|
-
flushed = true;
|
|
718
|
-
}
|
|
719
|
-
else if (root.nativeView && typeof root.nativeView.requestLayout === 'function') {
|
|
720
|
-
root.nativeView.requestLayout();
|
|
721
|
-
flushed = true;
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
catch { }
|
|
726
|
-
}
|
|
727
|
-
if (VERBOSE)
|
|
728
|
-
console.info('[ns-hmr][vue-runtime] global layout fallback', { flushed });
|
|
729
|
-
if (flushed)
|
|
730
|
-
did = true;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
catch { }
|
|
734
|
-
try {
|
|
735
|
-
__globalLayoutRequested.add(internal);
|
|
736
|
-
}
|
|
737
|
-
catch { }
|
|
738
|
-
}
|
|
739
|
-
// Only mark stabilized when wrapper view is present or we exhausted retries
|
|
740
|
-
if (did || attempt >= 5) {
|
|
741
|
-
if (v || attempt >= 5) {
|
|
742
|
-
try {
|
|
743
|
-
__postUpdateStabilized.add(internal);
|
|
744
|
-
}
|
|
745
|
-
catch { }
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
// Schedule one final microtask check before giving up
|
|
749
|
-
scheduleMicrotask(() => stabilizeNativeLayout(internal, Math.min(attempt + 1, 5)));
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
catch { }
|
|
754
|
-
}
|
|
755
|
-
function scheduleDeferredUpdate(internal, reason) {
|
|
756
|
-
try {
|
|
757
|
-
const prev = __pendingUpdateAttempts.get(internal) || 0;
|
|
758
|
-
const attempt = prev + 1;
|
|
759
|
-
if (VERBOSE)
|
|
760
|
-
console.info('[ns-hmr][vue-runtime] deferring update', { attempt, reason });
|
|
761
|
-
if (attempt > MAX_DEFER_ATTEMPTS) {
|
|
762
|
-
if (VERBOSE)
|
|
763
|
-
console.warn('[ns-hmr][vue-runtime] max deferral attempts reached; giving up for this instance');
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
__pendingUpdateAttempts.set(internal, attempt);
|
|
767
|
-
const delay = Math.min(BASE_DEFER_MS * attempt, 80);
|
|
768
|
-
// Prefer nextTick when available, then timeout
|
|
769
|
-
try {
|
|
770
|
-
const req = globalThis.require;
|
|
771
|
-
const vueMod = req && (() => { try {
|
|
772
|
-
return req('vue');
|
|
773
|
-
}
|
|
774
|
-
catch {
|
|
775
|
-
return null;
|
|
776
|
-
} })();
|
|
777
|
-
const nsv = req && (() => { try {
|
|
778
|
-
return req('nativescript-vue');
|
|
779
|
-
}
|
|
780
|
-
catch {
|
|
781
|
-
return null;
|
|
782
|
-
} })();
|
|
783
|
-
const nextTick = (vueMod && vueMod.nextTick) || (nsv && nsv.nextTick);
|
|
784
|
-
if (VERBOSE)
|
|
785
|
-
console.info('[ns-hmr][vue-runtime] scheduleDeferredUpdate nextTick found:', typeof nextTick === 'function');
|
|
786
|
-
if (typeof nextTick === 'function') {
|
|
787
|
-
return void nextTick(() => {
|
|
788
|
-
try {
|
|
789
|
-
setTimeout(() => { try {
|
|
790
|
-
internal?.update && internal.update();
|
|
791
|
-
}
|
|
792
|
-
catch { } }, delay);
|
|
793
|
-
}
|
|
794
|
-
catch { }
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
catch { }
|
|
799
|
-
setTimeout(() => { try {
|
|
800
|
-
internal?.update && internal.update();
|
|
801
|
-
}
|
|
802
|
-
catch { } }, delay);
|
|
803
|
-
}
|
|
804
|
-
catch { }
|
|
805
|
-
}
|
|
806
|
-
function dumpRuntime(label, rt) {
|
|
807
|
-
try {
|
|
808
|
-
const g = globalThis;
|
|
809
|
-
const hasRt = !!rt;
|
|
810
|
-
const keys = rt && typeof rt === 'object' ? Object.keys(rt) : [];
|
|
811
|
-
const map = rt && (rt.map || rt.records);
|
|
812
|
-
const recordKeys = map && typeof map.keys === 'function' ? Array.from(map.keys()) : (map && typeof map === 'object' ? Object.keys(map) : []);
|
|
813
|
-
const flags = {
|
|
814
|
-
hasRuntime: hasRt,
|
|
815
|
-
hasRerender: !!(rt && rt.rerender),
|
|
816
|
-
hasReload: !!(rt && rt.reload),
|
|
817
|
-
keys,
|
|
818
|
-
recordCount: recordKeys ? recordKeys.length : 0,
|
|
819
|
-
hooksApplied: !!g.__NS_VUE_HOOKS_APPLIED__,
|
|
820
|
-
hasNSVue: !!(g.require && (() => { try {
|
|
821
|
-
g.require('nativescript-vue');
|
|
822
|
-
return true;
|
|
823
|
-
}
|
|
824
|
-
catch {
|
|
825
|
-
return false;
|
|
826
|
-
} })()),
|
|
827
|
-
hasVue: !!(g.require && (() => { try {
|
|
828
|
-
g.require('vue');
|
|
829
|
-
return true;
|
|
830
|
-
}
|
|
831
|
-
catch {
|
|
832
|
-
return false;
|
|
833
|
-
} })()),
|
|
834
|
-
};
|
|
835
|
-
console.info(`[ns-hmr][vue-runtime] ${label}`, flags);
|
|
836
|
-
}
|
|
837
|
-
catch { }
|
|
838
|
-
}
|
|
839
|
-
export function initializeVueHMRRuntime() {
|
|
840
|
-
return ensureVueHMRRuntimeEnhanced();
|
|
841
|
-
}
|
|
842
|
-
export function ensureVueHMRRuntimeEnhanced() {
|
|
843
|
-
try {
|
|
844
|
-
const g = global;
|
|
845
|
-
let rt = g.__VUE_HMR_RUNTIME__;
|
|
846
|
-
if (!rt) {
|
|
847
|
-
if (VERBOSE)
|
|
848
|
-
console.info('[ns-hmr][vue-runtime] Vue HMR runtime not present yet; attempting lazy init');
|
|
849
|
-
// In ES modules mode, skip require() and use direct global access
|
|
850
|
-
let Vue = null;
|
|
851
|
-
// Try to get Vue from global namespace or require (NativeScript ES modules)
|
|
852
|
-
try {
|
|
853
|
-
Vue = g.Vue || g.__VUE__;
|
|
854
|
-
if (Vue) {
|
|
855
|
-
if (VERBOSE)
|
|
856
|
-
console.info('[ns-hmr][vue-runtime] Vue module loaded via globals:', { hasVue: !!Vue, keys: Vue ? Object.keys(Vue).slice(0, 10) : [] });
|
|
857
|
-
}
|
|
858
|
-
else {
|
|
859
|
-
if (VERBOSE)
|
|
860
|
-
console.info('[ns-hmr][vue-runtime] Vue not found in global namespace, checking require fallback');
|
|
861
|
-
// Only try require() if globals failed and we're sure it's available
|
|
862
|
-
const req = globalThis.require;
|
|
863
|
-
if (req && typeof req === 'function') {
|
|
864
|
-
try {
|
|
865
|
-
Vue = req('vue');
|
|
866
|
-
if (VERBOSE)
|
|
867
|
-
console.info('[ns-hmr][vue-runtime] Vue module loaded via require:', { hasVue: !!Vue, keys: Vue ? Object.keys(Vue).slice(0, 10) : [] });
|
|
868
|
-
}
|
|
869
|
-
catch (e) {
|
|
870
|
-
if (VERBOSE)
|
|
871
|
-
console.warn('[ns-hmr][vue-runtime] Vue require failed:', e.message);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
// Force Vue HMR runtime initialization if not already done
|
|
876
|
-
if (Vue && !g.__VUE_HMR_RUNTIME__) {
|
|
877
|
-
// Check if Vue has HMR functionality
|
|
878
|
-
if (Vue.createApp && !g.__VUE_HMR_RUNTIME__) {
|
|
879
|
-
if (VERBOSE)
|
|
880
|
-
console.info('[ns-hmr][vue-runtime] Manually initializing Vue HMR runtime');
|
|
881
|
-
// Create a minimal HMR runtime that Vue can recognize
|
|
882
|
-
g.__VUE_HMR_RUNTIME__ = {
|
|
883
|
-
createRecord: () => true,
|
|
884
|
-
reload: () => { },
|
|
885
|
-
rerender: () => { },
|
|
886
|
-
updateStyle: () => { },
|
|
887
|
-
isRecorded: () => false,
|
|
888
|
-
map: new Map()
|
|
889
|
-
};
|
|
890
|
-
if (VERBOSE)
|
|
891
|
-
console.info('[ns-hmr][vue-runtime] Created minimal Vue HMR runtime');
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
catch (e) {
|
|
896
|
-
if (VERBOSE)
|
|
897
|
-
console.warn('[ns-hmr][vue-runtime] Vue module loading failed:', e.message || String(e));
|
|
898
|
-
}
|
|
899
|
-
// Also try to require nativescript-vue if available
|
|
900
|
-
try {
|
|
901
|
-
const req = globalThis.require;
|
|
902
|
-
if (req && typeof req === 'function') {
|
|
903
|
-
try {
|
|
904
|
-
req('nativescript-vue');
|
|
905
|
-
}
|
|
906
|
-
catch { }
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
catch { }
|
|
910
|
-
rt = g.__VUE_HMR_RUNTIME__;
|
|
911
|
-
if (!rt) {
|
|
912
|
-
if (VERBOSE) {
|
|
913
|
-
console.info('[ns-hmr][vue-runtime] Vue HMR runtime still unavailable after lazy init');
|
|
914
|
-
dumpRuntime('after-lazy-init', rt);
|
|
915
|
-
console.info('[ns-hmr][vue-runtime] Using minimal fallback Vue HMR runtime (local only)');
|
|
916
|
-
}
|
|
917
|
-
try {
|
|
918
|
-
rt = installFallbackHMRRuntime();
|
|
919
|
-
// In ES modules mode, enhance the fallback with ES modules detection
|
|
920
|
-
if (rt && !g.__VUE_HMR_RUNTIME__) {
|
|
921
|
-
// Set global reference for ES modules compatibility
|
|
922
|
-
g.__VUE_HMR_RUNTIME__ = rt;
|
|
923
|
-
if (VERBOSE)
|
|
924
|
-
console.info('[ns-hmr][vue-runtime] Set global Vue HMR runtime for ES modules compatibility');
|
|
925
|
-
// Try to detect Vue through NativeScript ES modules
|
|
926
|
-
try {
|
|
927
|
-
const detectVueInESModules = () => {
|
|
928
|
-
// In NativeScript ES modules environment, look for Vue in globals
|
|
929
|
-
const possibleVue = g.Vue || g.__VUE__ || g.vue;
|
|
930
|
-
if (possibleVue && possibleVue.createApp) {
|
|
931
|
-
if (VERBOSE)
|
|
932
|
-
console.info('[ns-hmr][vue-runtime] Found Vue in ES modules global space');
|
|
933
|
-
return possibleVue;
|
|
934
|
-
}
|
|
935
|
-
return null;
|
|
936
|
-
};
|
|
937
|
-
const esVue = detectVueInESModules();
|
|
938
|
-
if (esVue) {
|
|
939
|
-
// Enhance runtime with ES modules Vue reference
|
|
940
|
-
rt.__esModulesVue = esVue;
|
|
941
|
-
if (VERBOSE)
|
|
942
|
-
console.info('[ns-hmr][vue-runtime] Enhanced runtime with ES modules Vue reference');
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
catch (esErr) {
|
|
946
|
-
if (VERBOSE)
|
|
947
|
-
console.warn('[ns-hmr][vue-runtime] ES modules Vue detection failed:', esErr);
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
/* IMPORTANT: do NOT assign to global to avoid blocking real runtime later */
|
|
951
|
-
}
|
|
952
|
-
catch (e) {
|
|
953
|
-
console.warn('[ns-hmr][vue-runtime] Failed to create fallback runtime:', e?.message || String(e));
|
|
954
|
-
return null;
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
if (VERBOSE)
|
|
959
|
-
dumpRuntime('before-enhance', rt);
|
|
960
|
-
if (rt.__nsEnhanced)
|
|
961
|
-
return rt;
|
|
962
|
-
const enhanced = enhanceVueHMRRuntime(rt);
|
|
963
|
-
enhanced.__nsEnhanced = true;
|
|
964
|
-
if (VERBOSE)
|
|
965
|
-
dumpRuntime('after-enhance', enhanced);
|
|
966
|
-
// Trigger hook setup now that Vue is available
|
|
967
|
-
try {
|
|
968
|
-
const g = globalThis;
|
|
969
|
-
if (g.__ns_attemptHookSetup) {
|
|
970
|
-
g.__ns_attemptHookSetup();
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
catch { }
|
|
974
|
-
// Register any existing components that were tracked before HMR runtime was available
|
|
975
|
-
try {
|
|
976
|
-
registerExistingComponents(enhanced);
|
|
977
|
-
}
|
|
978
|
-
catch (e) {
|
|
979
|
-
if (VERBOSE)
|
|
980
|
-
console.warn('[ns-hmr][vue-runtime] Failed to register existing components:', e?.message);
|
|
981
|
-
}
|
|
982
|
-
return enhanced;
|
|
983
|
-
}
|
|
984
|
-
catch (error) {
|
|
985
|
-
console.warn('[ns-hmr][vue-runtime] Error ensuring Vue HMR runtime:', error?.message);
|
|
986
|
-
return null;
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
function enhanceVueHMRRuntime(existingRuntime) {
|
|
990
|
-
const enhanced = { ...existingRuntime };
|
|
991
|
-
const originalReload = enhanced.reload;
|
|
992
|
-
const originalRerender = enhanced.rerender;
|
|
993
|
-
enhanced.reload = function (id, newDef) {
|
|
994
|
-
if (VERBOSE)
|
|
995
|
-
console.info('[ns-hmr][vue-runtime] Enhanced reload for:', id);
|
|
996
|
-
try {
|
|
997
|
-
if (originalReload)
|
|
998
|
-
originalReload.call(this, id, newDef);
|
|
999
|
-
handleNativeScriptComponentReload(id, newDef);
|
|
1000
|
-
}
|
|
1001
|
-
catch (error) {
|
|
1002
|
-
console.warn('[ns-hmr][vue-runtime] Enhanced reload failed:', error?.message);
|
|
1003
|
-
if (originalReload)
|
|
1004
|
-
originalReload.call(this, id, newDef);
|
|
1005
|
-
}
|
|
1006
|
-
};
|
|
1007
|
-
enhanced.rerender = function (id, newRender) {
|
|
1008
|
-
if (VERBOSE)
|
|
1009
|
-
console.info('[ns-hmr][vue-runtime] Enhanced rerender for:', id);
|
|
1010
|
-
try {
|
|
1011
|
-
try {
|
|
1012
|
-
globalThis.__NS_LAST_RERENDER_ID__ = id;
|
|
1013
|
-
}
|
|
1014
|
-
catch { }
|
|
1015
|
-
// Set current component ID for working instance tracking
|
|
1016
|
-
currentComponentId = id;
|
|
1017
|
-
if (originalRerender)
|
|
1018
|
-
originalRerender.call(this, id, newRender);
|
|
1019
|
-
try {
|
|
1020
|
-
handleNativeScriptComponentRerender(id, newRender, enhanced);
|
|
1021
|
-
}
|
|
1022
|
-
catch { }
|
|
1023
|
-
}
|
|
1024
|
-
catch (error) {
|
|
1025
|
-
console.warn('[ns-hmr][vue-runtime] Enhanced rerender failed:', error?.message);
|
|
1026
|
-
if (originalRerender)
|
|
1027
|
-
originalRerender.call(this, id, newRender);
|
|
1028
|
-
}
|
|
1029
|
-
finally {
|
|
1030
|
-
// Clear the current component ID after processing
|
|
1031
|
-
currentComponentId = null;
|
|
1032
|
-
}
|
|
1033
|
-
};
|
|
1034
|
-
return enhanced;
|
|
1035
|
-
}
|
|
1036
|
-
function normalizeIdToFile(id) {
|
|
1037
|
-
try {
|
|
1038
|
-
let s = String(id || '');
|
|
1039
|
-
s = s.split('?')[0];
|
|
1040
|
-
s = s.replace(/\\/g, '/');
|
|
1041
|
-
return s;
|
|
1042
|
-
}
|
|
1043
|
-
catch {
|
|
1044
|
-
return id;
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
function installFallbackHMRRuntime() {
|
|
1048
|
-
const records = new Map();
|
|
1049
|
-
const api = {
|
|
1050
|
-
__nsFallback: true,
|
|
1051
|
-
map: records,
|
|
1052
|
-
createRecord(id, initialDef) { const key = String(id); if (records.has(key))
|
|
1053
|
-
return true; records.set(key, { def: initialDef || {}, instances: new Set() }); if (VERBOSE)
|
|
1054
|
-
console.info('[ns-hmr][vue-runtime:fallback] createRecord', key); return true; },
|
|
1055
|
-
isRecorded(id) { return records.has(String(id)); },
|
|
1056
|
-
registerInstance(id, instance) { const key = String(id); if (!records.has(key))
|
|
1057
|
-
this.createRecord(key, (instance && (instance.$?.type || instance.type)) || {}); const rec = records.get(key); rec.instances.add(instance); if (VERBOSE)
|
|
1058
|
-
console.info('[ns-hmr][vue-runtime:fallback] registerInstance', key); },
|
|
1059
|
-
rerender(id, newRender) {
|
|
1060
|
-
const key = String(id);
|
|
1061
|
-
const rec = records.get(key);
|
|
1062
|
-
if (rec && rec.def) {
|
|
1063
|
-
try {
|
|
1064
|
-
rec.def.render = newRender;
|
|
1065
|
-
}
|
|
1066
|
-
catch { }
|
|
1067
|
-
}
|
|
1068
|
-
const targets = [];
|
|
1069
|
-
if (rec)
|
|
1070
|
-
targets.push(...Array.from(rec.instances));
|
|
1071
|
-
try {
|
|
1072
|
-
const file = normalizeIdToFile(key);
|
|
1073
|
-
const more = componentTracker.findInstancesByFile(file);
|
|
1074
|
-
for (const ins of more)
|
|
1075
|
-
targets.push(ins);
|
|
1076
|
-
}
|
|
1077
|
-
catch { }
|
|
1078
|
-
let applied = 0;
|
|
1079
|
-
for (const ins of targets) {
|
|
1080
|
-
try {
|
|
1081
|
-
applyRenderAndTriggerWithId(ins, newRender, key);
|
|
1082
|
-
applied++;
|
|
1083
|
-
}
|
|
1084
|
-
catch { }
|
|
1085
|
-
}
|
|
1086
|
-
if (applied === 0) {
|
|
1087
|
-
try {
|
|
1088
|
-
applied += tryPatchInstancesFromRootByFileSuffix(key, newRender);
|
|
1089
|
-
}
|
|
1090
|
-
catch { }
|
|
1091
|
-
try {
|
|
1092
|
-
applied += tryPatchInstancesFromRootByName(key, newRender, api);
|
|
1093
|
-
}
|
|
1094
|
-
catch { }
|
|
1095
|
-
}
|
|
1096
|
-
if (VERBOSE)
|
|
1097
|
-
console.info('[ns-hmr][vue-runtime:fallback] rerender applied for', key, 'instances:', applied);
|
|
1098
|
-
},
|
|
1099
|
-
reload(id, newDef) { const key = String(id); const rec = records.get(key); if (rec) {
|
|
1100
|
-
try {
|
|
1101
|
-
Object.assign(rec.def || (rec.def = {}), newDef);
|
|
1102
|
-
}
|
|
1103
|
-
catch { }
|
|
1104
|
-
} this.rerender(key, (newDef && newDef.render) ? newDef.render : (() => { })); if (VERBOSE)
|
|
1105
|
-
console.info('[ns-hmr][vue-runtime:fallback] reload applied for', key); },
|
|
1106
|
-
updateStyle() { },
|
|
1107
|
-
};
|
|
1108
|
-
return api;
|
|
1109
|
-
}
|
|
1110
|
-
function handleNativeScriptComponentReload(id, newDef) {
|
|
1111
|
-
try {
|
|
1112
|
-
if (VERBOSE)
|
|
1113
|
-
console.info('[ns-hmr][vue-runtime] NativeScript component reload for:', id);
|
|
1114
|
-
}
|
|
1115
|
-
catch (error) {
|
|
1116
|
-
if (VERBOSE)
|
|
1117
|
-
console.warn('[ns-hmr][vue-runtime] NativeScript component reload failed:', error?.message);
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
function handleNativeScriptComponentRerender(id, newRender, runtime) {
|
|
1121
|
-
try {
|
|
1122
|
-
if (VERBOSE)
|
|
1123
|
-
console.info('[ns-hmr][vue-runtime] NativeScript component rerender for:', id);
|
|
1124
|
-
const map = runtime.map || runtime.records;
|
|
1125
|
-
let record = null;
|
|
1126
|
-
if (map) {
|
|
1127
|
-
if (typeof map.get === 'function')
|
|
1128
|
-
record = map.get(id) || null;
|
|
1129
|
-
else if (map[id])
|
|
1130
|
-
record = map[id];
|
|
1131
|
-
}
|
|
1132
|
-
// Let Vue runtime update instances; we just stabilize the root and any known instances after a tick
|
|
1133
|
-
try {
|
|
1134
|
-
scheduleMicrotask(() => { try {
|
|
1135
|
-
const g = globalThis;
|
|
1136
|
-
const root = g.__NS_VUE_ROOT_INSTANCE__;
|
|
1137
|
-
if (root)
|
|
1138
|
-
stabilizeNativeLayout(root.$ || root, 1);
|
|
1139
|
-
}
|
|
1140
|
-
catch { } });
|
|
1141
|
-
}
|
|
1142
|
-
catch { }
|
|
1143
|
-
}
|
|
1144
|
-
catch (error) {
|
|
1145
|
-
if (VERBOSE)
|
|
1146
|
-
console.warn('[ns-hmr][vue-runtime] NativeScript component rerender failed:', error?.message);
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
function baseFileSuffixesFromId(id) {
|
|
1150
|
-
try {
|
|
1151
|
-
const noQuery = String(id || '').split('?')[0].replace(/\\/g, '/');
|
|
1152
|
-
const base = noQuery.split('/').pop() || '';
|
|
1153
|
-
const relFromSrc = noQuery.replace(/^.*?\/src\//, '/src/');
|
|
1154
|
-
const relNoLead = relFromSrc.replace(/^\//, '');
|
|
1155
|
-
const suffixes = new Set();
|
|
1156
|
-
if (base)
|
|
1157
|
-
suffixes.add('/' + base);
|
|
1158
|
-
if (relFromSrc)
|
|
1159
|
-
suffixes.add(relFromSrc);
|
|
1160
|
-
if (relNoLead)
|
|
1161
|
-
suffixes.add('/' + relNoLead);
|
|
1162
|
-
if (VERBOSE)
|
|
1163
|
-
console.info('[ns-hmr][vue-runtime] baseFileSuffixesFromId', { id, suffixes: Array.from(suffixes) });
|
|
1164
|
-
return Array.from(suffixes);
|
|
1165
|
-
}
|
|
1166
|
-
catch {
|
|
1167
|
-
return [];
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
function getComponentType(obj) { try {
|
|
1171
|
-
return (obj && (obj.$?.type || obj.type)) || null;
|
|
1172
|
-
}
|
|
1173
|
-
catch {
|
|
1174
|
-
return null;
|
|
1175
|
-
} }
|
|
1176
|
-
function getComponentName(obj) { try {
|
|
1177
|
-
const t = getComponentType(obj);
|
|
1178
|
-
const n = (t && (t.__name || t.name)) || '';
|
|
1179
|
-
return String(n || '').trim();
|
|
1180
|
-
}
|
|
1181
|
-
catch {
|
|
1182
|
-
return '';
|
|
1183
|
-
} }
|
|
1184
|
-
function forceUpdateInstance(ins, componentId) {
|
|
1185
|
-
try {
|
|
1186
|
-
const internal = ins.$ || ins;
|
|
1187
|
-
// If the underlying NativeScript view isn't ready (loading/suspended), defer the update
|
|
1188
|
-
try {
|
|
1189
|
-
const probe = findNSViewFromInternal(internal);
|
|
1190
|
-
const el = probe.el;
|
|
1191
|
-
const resolved = probe.info;
|
|
1192
|
-
// If this instance has a working native view, set it as current working instance
|
|
1193
|
-
if (resolved?.hasNativeView && el) {
|
|
1194
|
-
setCurrentWorkingInstance(internal, componentId);
|
|
1195
|
-
if (VERBOSE) {
|
|
1196
|
-
console.info('[ns-hmr][vue-runtime] forceUpdateInstance found working instance');
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
// Cache last resolved element right away for stabilization to use soon after
|
|
1200
|
-
try {
|
|
1201
|
-
__lastResolvedEl.set(internal, { el, info: resolved });
|
|
1202
|
-
}
|
|
1203
|
-
catch { }
|
|
1204
|
-
const suspendCount = resolved.suspendCount;
|
|
1205
|
-
const isLoaded = resolved.isLoaded;
|
|
1206
|
-
const isMounted = typeof internal?.isMounted === 'boolean' ? internal.isMounted : undefined;
|
|
1207
|
-
const isSuspended = typeof suspendCount === 'number' && suspendCount !== 0;
|
|
1208
|
-
// Require loaded when available to avoid re-entrant creation on Frame/Page
|
|
1209
|
-
const elReady = isNSViewReady(el) && (typeof isLoaded === 'boolean' ? isLoaded === true : true);
|
|
1210
|
-
// Decode NativeScript suspend flags for richer logs
|
|
1211
|
-
let flagsInfo = undefined;
|
|
1212
|
-
try {
|
|
1213
|
-
if (typeof suspendCount === 'number') {
|
|
1214
|
-
const LOADED = 1 << 20;
|
|
1215
|
-
const NATIVEVIEW = 1 << 21;
|
|
1216
|
-
const UISETUP = 1 << 22;
|
|
1217
|
-
const FLAGS_MASK = LOADED | NATIVEVIEW | UISETUP;
|
|
1218
|
-
const inc = suspendCount & ~FLAGS_MASK;
|
|
1219
|
-
flagsInfo = {
|
|
1220
|
-
suspendCount,
|
|
1221
|
-
inc,
|
|
1222
|
-
LOADED: (suspendCount & LOADED) !== 0,
|
|
1223
|
-
NATIVEVIEW: (suspendCount & NATIVEVIEW) !== 0,
|
|
1224
|
-
UISETUP: (suspendCount & UISETUP) !== 0,
|
|
1225
|
-
};
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
catch { }
|
|
1229
|
-
const notReady = (isMounted === false) || !elReady || isSuspended;
|
|
1230
|
-
if (VERBOSE) {
|
|
1231
|
-
try {
|
|
1232
|
-
const elType = el && el.constructor ? el.constructor.name : (el ? typeof el : 'null');
|
|
1233
|
-
console.info('[ns-hmr][vue-runtime] update-check', { isMounted, isLoaded, elReady, isSuspended, elType, hasNativeView: resolved.hasNativeView, isRootView: resolved.isRootView, flags: flagsInfo });
|
|
1234
|
-
}
|
|
1235
|
-
catch { }
|
|
1236
|
-
}
|
|
1237
|
-
if (notReady) {
|
|
1238
|
-
if (VERBOSE)
|
|
1239
|
-
console.info('[ns-hmr][vue-runtime] deferring update: NS view not ready', { isMounted, isLoaded, suspendCount, elReady, hasNativeView: resolved.hasNativeView });
|
|
1240
|
-
scheduleDeferredUpdate(internal, 'not-ready');
|
|
1241
|
-
return;
|
|
1242
|
-
}
|
|
1243
|
-
// Clear any previous deferral attempts now that we're ready
|
|
1244
|
-
try {
|
|
1245
|
-
__pendingUpdateAttempts.delete(internal);
|
|
1246
|
-
}
|
|
1247
|
-
catch { }
|
|
1248
|
-
}
|
|
1249
|
-
catch { }
|
|
1250
|
-
// If the component tree includes Frame/Page, avoid immediate updates: schedule on next frame(s)
|
|
1251
|
-
if (instanceHasFrameOrPage(internal)) {
|
|
1252
|
-
if (VERBOSE)
|
|
1253
|
-
console.info('[ns-hmr][vue-runtime] frame/page detected; scheduling via scheduler and next frames');
|
|
1254
|
-
try {
|
|
1255
|
-
const eff = internal.effect;
|
|
1256
|
-
if (eff && typeof eff.scheduler === 'function') {
|
|
1257
|
-
scheduleNextFrame(() => { try {
|
|
1258
|
-
eff.scheduler();
|
|
1259
|
-
}
|
|
1260
|
-
catch { } scheduleNextFrame(() => stabilizeNativeLayout(internal)); });
|
|
1261
|
-
return;
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
catch { }
|
|
1265
|
-
scheduleNextFrame(() => { try {
|
|
1266
|
-
internal?.update && internal.update();
|
|
1267
|
-
}
|
|
1268
|
-
catch { } scheduleNextFrame(() => stabilizeNativeLayout(internal)); });
|
|
1269
|
-
return;
|
|
1270
|
-
}
|
|
1271
|
-
// Prefer scheduler then nextTick before attempting direct update
|
|
1272
|
-
try {
|
|
1273
|
-
const eff = internal.effect;
|
|
1274
|
-
if (eff && typeof eff.scheduler === 'function') {
|
|
1275
|
-
if (VERBOSE) {
|
|
1276
|
-
console.info('[ns-hmr][vue-runtime] About to call effect.scheduler()', {
|
|
1277
|
-
hasEffect: !!eff,
|
|
1278
|
-
effectKeys: eff ? Object.keys(eff).slice(0, 10) : [],
|
|
1279
|
-
schedulerType: typeof eff.scheduler
|
|
1280
|
-
});
|
|
1281
|
-
}
|
|
1282
|
-
try {
|
|
1283
|
-
eff.scheduler();
|
|
1284
|
-
if (VERBOSE)
|
|
1285
|
-
console.info('[ns-hmr][vue-runtime] effect.scheduler() executed successfully');
|
|
1286
|
-
// Also try to force a re-render by marking the effect as dirty
|
|
1287
|
-
if (typeof eff.trigger === 'function') {
|
|
1288
|
-
eff.trigger();
|
|
1289
|
-
if (VERBOSE)
|
|
1290
|
-
console.info('[ns-hmr][vue-runtime] effect.trigger() called');
|
|
1291
|
-
}
|
|
1292
|
-
// Force update the instance as well
|
|
1293
|
-
if (typeof internal.update === 'function') {
|
|
1294
|
-
scheduleMicrotask(() => {
|
|
1295
|
-
try {
|
|
1296
|
-
internal.update();
|
|
1297
|
-
if (VERBOSE)
|
|
1298
|
-
console.info('[ns-hmr][vue-runtime] internal.update() called after scheduler');
|
|
1299
|
-
}
|
|
1300
|
-
catch (e) {
|
|
1301
|
-
if (VERBOSE)
|
|
1302
|
-
console.warn('[ns-hmr][vue-runtime] internal.update() failed:', e?.message);
|
|
1303
|
-
}
|
|
1304
|
-
});
|
|
1305
|
-
}
|
|
1306
|
-
// Force a complete re-render cycle - try internal render method
|
|
1307
|
-
if (typeof internal.render === 'function') {
|
|
1308
|
-
scheduleMicrotask(() => {
|
|
1309
|
-
try {
|
|
1310
|
-
if (VERBOSE)
|
|
1311
|
-
console.info('[ns-hmr][vue-runtime] Triggering internal.render() for complete re-render');
|
|
1312
|
-
// Validate render context before calling render
|
|
1313
|
-
const hasValidContext = internal.ctx || internal.setupState || internal.data;
|
|
1314
|
-
if (!hasValidContext) {
|
|
1315
|
-
if (VERBOSE)
|
|
1316
|
-
console.warn('[ns-hmr][vue-runtime] No valid render context found, skipping internal.render()');
|
|
1317
|
-
return;
|
|
1318
|
-
}
|
|
1319
|
-
// Set up proper render context
|
|
1320
|
-
const originalCtx = internal.ctx;
|
|
1321
|
-
const originalScope = internal.scope;
|
|
1322
|
-
try {
|
|
1323
|
-
const newVNode = internal.render.call(internal, internal.ctx || internal.setupState || internal.data, internal.renderCache || {}, internal.props || {}, internal.setupState || {}, internal.data || {}, internal.$options || {});
|
|
1324
|
-
if (VERBOSE)
|
|
1325
|
-
console.info('[ns-hmr][vue-runtime] internal.render() result:', {
|
|
1326
|
-
hasVNode: !!newVNode,
|
|
1327
|
-
vNodeType: newVNode?.type?.name || newVNode?.type || 'unknown'
|
|
1328
|
-
});
|
|
1329
|
-
// Apply new VNode by replacing subTree and scheduling an update
|
|
1330
|
-
if (newVNode) {
|
|
1331
|
-
if (VERBOSE)
|
|
1332
|
-
console.info('[ns-hmr][vue-runtime] New vNode created, applying via subTree replacement');
|
|
1333
|
-
try {
|
|
1334
|
-
internal.subTree = newVNode;
|
|
1335
|
-
}
|
|
1336
|
-
catch { }
|
|
1337
|
-
if (internal.update && typeof internal.update === 'function') {
|
|
1338
|
-
scheduleMicrotask(() => {
|
|
1339
|
-
try {
|
|
1340
|
-
internal.update();
|
|
1341
|
-
if (VERBOSE)
|
|
1342
|
-
console.info('[ns-hmr][vue-runtime] Triggered component update after subTree replacement');
|
|
1343
|
-
}
|
|
1344
|
-
catch (e) {
|
|
1345
|
-
if (VERBOSE)
|
|
1346
|
-
console.warn('[ns-hmr][vue-runtime] Component update after subTree replacement failed:', e?.message);
|
|
1347
|
-
}
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
finally {
|
|
1353
|
-
// Restore original context
|
|
1354
|
-
if (originalCtx)
|
|
1355
|
-
internal.ctx = originalCtx;
|
|
1356
|
-
if (originalScope)
|
|
1357
|
-
internal.scope = originalScope;
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
catch (e) {
|
|
1361
|
-
if (VERBOSE)
|
|
1362
|
-
console.warn('[ns-hmr][vue-runtime] internal.render() failed:', e?.message, e?.stack);
|
|
1363
|
-
}
|
|
1364
|
-
});
|
|
1365
|
-
}
|
|
1366
|
-
// Enhanced NativeScript-specific component update approach
|
|
1367
|
-
scheduleMicrotask(() => {
|
|
1368
|
-
try {
|
|
1369
|
-
if (VERBOSE)
|
|
1370
|
-
console.info('[ns-hmr][vue-runtime] Starting NativeScript-specific component update');
|
|
1371
|
-
const nsEl = findNSViewFromInternal(internal);
|
|
1372
|
-
if (nsEl && nsEl.info && nsEl.info.view) {
|
|
1373
|
-
const view = nsEl.info.view;
|
|
1374
|
-
const nativeView = nsEl.info.nativeView;
|
|
1375
|
-
if (VERBOSE)
|
|
1376
|
-
console.info('[ns-hmr][vue-runtime] Found NativeScript view for update:', {
|
|
1377
|
-
hasView: !!view,
|
|
1378
|
-
hasNativeView: !!nativeView,
|
|
1379
|
-
viewType: view?.constructor?.name || typeof view
|
|
1380
|
-
});
|
|
1381
|
-
// Step 1: Force Vue component to re-evaluate its render function using Vue 3 compatible methods
|
|
1382
|
-
if (internal.effect) {
|
|
1383
|
-
try {
|
|
1384
|
-
// Use Vue 3's proper effect triggering methods instead of setting readonly 'dirty' property
|
|
1385
|
-
if (typeof internal.effect.trigger === 'function') {
|
|
1386
|
-
internal.effect.trigger();
|
|
1387
|
-
if (VERBOSE)
|
|
1388
|
-
console.info('[ns-hmr][vue-runtime] Triggered Vue effect via trigger()');
|
|
1389
|
-
}
|
|
1390
|
-
else if (typeof internal.effect.run === 'function') {
|
|
1391
|
-
// Force effect to run again
|
|
1392
|
-
internal.effect.run();
|
|
1393
|
-
if (VERBOSE)
|
|
1394
|
-
console.info('[ns-hmr][vue-runtime] Triggered Vue effect via run()');
|
|
1395
|
-
}
|
|
1396
|
-
else {
|
|
1397
|
-
// Fallback: try to schedule the effect
|
|
1398
|
-
if (typeof internal.effect.scheduler === 'function') {
|
|
1399
|
-
internal.effect.scheduler();
|
|
1400
|
-
if (VERBOSE)
|
|
1401
|
-
console.info('[ns-hmr][vue-runtime] Triggered Vue effect via scheduler()');
|
|
1402
|
-
}
|
|
1403
|
-
else {
|
|
1404
|
-
if (VERBOSE)
|
|
1405
|
-
console.warn('[ns-hmr][vue-runtime] No compatible Vue effect trigger method found');
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
catch (e) {
|
|
1410
|
-
if (VERBOSE)
|
|
1411
|
-
console.warn('[ns-hmr][vue-runtime] Vue effect triggering failed:', e?.message);
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
// Step 2: Clear any cached render results
|
|
1415
|
-
if (internal.renderCache) {
|
|
1416
|
-
const cacheKeys = Object.keys(internal.renderCache);
|
|
1417
|
-
internal.renderCache = {};
|
|
1418
|
-
if (VERBOSE)
|
|
1419
|
-
console.info('[ns-hmr][vue-runtime] Cleared render cache:', cacheKeys.length, 'entries');
|
|
1420
|
-
}
|
|
1421
|
-
// Step 3: Force NativeScript view updates
|
|
1422
|
-
if (nativeView) {
|
|
1423
|
-
// Platform-specific layout forcing
|
|
1424
|
-
const isIOS = globalThis.__ios || (nativeView.setNeedsLayout && !nativeView.requestLayout);
|
|
1425
|
-
const isAndroid = globalThis.__android || (nativeView.requestLayout && !nativeView.setNeedsLayout);
|
|
1426
|
-
if (isIOS) {
|
|
1427
|
-
// iOS-specific layout forcing
|
|
1428
|
-
if (nativeView.setNeedsLayout) {
|
|
1429
|
-
nativeView.setNeedsLayout();
|
|
1430
|
-
if (VERBOSE)
|
|
1431
|
-
console.info('[ns-hmr][vue-runtime] Called iOS setNeedsLayout()');
|
|
1432
|
-
}
|
|
1433
|
-
if (nativeView.layoutIfNeeded) {
|
|
1434
|
-
nativeView.layoutIfNeeded();
|
|
1435
|
-
if (VERBOSE)
|
|
1436
|
-
console.info('[ns-hmr][vue-runtime] Called iOS layoutIfNeeded()');
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
else if (isAndroid) {
|
|
1440
|
-
// Android-specific layout forcing
|
|
1441
|
-
if (nativeView.requestLayout) {
|
|
1442
|
-
nativeView.requestLayout();
|
|
1443
|
-
if (VERBOSE)
|
|
1444
|
-
console.info('[ns-hmr][vue-runtime] Called Android requestLayout()');
|
|
1445
|
-
}
|
|
1446
|
-
if (nativeView.invalidate) {
|
|
1447
|
-
nativeView.invalidate();
|
|
1448
|
-
if (VERBOSE)
|
|
1449
|
-
console.info('[ns-hmr][vue-runtime] Called Android invalidate()');
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
else {
|
|
1453
|
-
// Fallback: try both but log appropriately
|
|
1454
|
-
if (nativeView.setNeedsLayout) {
|
|
1455
|
-
nativeView.setNeedsLayout();
|
|
1456
|
-
if (VERBOSE)
|
|
1457
|
-
console.info('[ns-hmr][vue-runtime] Called iOS setNeedsLayout() (fallback)');
|
|
1458
|
-
}
|
|
1459
|
-
if (nativeView.requestLayout) {
|
|
1460
|
-
nativeView.requestLayout();
|
|
1461
|
-
if (VERBOSE)
|
|
1462
|
-
console.info('[ns-hmr][vue-runtime] Called Android requestLayout() (fallback)');
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
// Step 4: Force NativeScript view hierarchy update
|
|
1467
|
-
if (view) {
|
|
1468
|
-
// Try NativeScript's own update mechanisms
|
|
1469
|
-
if (view.requestLayout && typeof view.requestLayout === 'function') {
|
|
1470
|
-
view.requestLayout();
|
|
1471
|
-
if (VERBOSE)
|
|
1472
|
-
console.info('[ns-hmr][vue-runtime] Called NativeScript view requestLayout()');
|
|
1473
|
-
}
|
|
1474
|
-
if (view._onCssStateChange && typeof view._onCssStateChange === 'function') {
|
|
1475
|
-
view._onCssStateChange();
|
|
1476
|
-
if (VERBOSE)
|
|
1477
|
-
console.info('[ns-hmr][vue-runtime] Called view CSS state change');
|
|
1478
|
-
}
|
|
1479
|
-
if (view._redrawNativeBackground && typeof view._redrawNativeBackground === 'function') {
|
|
1480
|
-
view._redrawNativeBackground();
|
|
1481
|
-
if (VERBOSE)
|
|
1482
|
-
console.info('[ns-hmr][vue-runtime] Called view background redraw');
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
// Step 5: Trigger Vue's update cycle in NativeScript-safe way
|
|
1486
|
-
if (internal.update && typeof internal.update === 'function') {
|
|
1487
|
-
// Use setTimeout to break out of current execution context
|
|
1488
|
-
setTimeout(() => {
|
|
1489
|
-
try {
|
|
1490
|
-
internal.update();
|
|
1491
|
-
if (VERBOSE)
|
|
1492
|
-
console.info('[ns-hmr][vue-runtime] Called Vue internal.update() via setTimeout');
|
|
1493
|
-
}
|
|
1494
|
-
catch (e) {
|
|
1495
|
-
if (VERBOSE)
|
|
1496
|
-
console.warn('[ns-hmr][vue-runtime] Vue internal.update() failed:', e?.message);
|
|
1497
|
-
}
|
|
1498
|
-
}, 0);
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
else {
|
|
1502
|
-
if (VERBOSE)
|
|
1503
|
-
console.warn('[ns-hmr][vue-runtime] No NativeScript view found for update');
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
catch (e) {
|
|
1507
|
-
if (VERBOSE)
|
|
1508
|
-
console.warn('[ns-hmr][vue-runtime] NativeScript component update failed:', e?.message);
|
|
1509
|
-
}
|
|
1510
|
-
});
|
|
1511
|
-
// Experimental: Try to force a complete component rebuild
|
|
1512
|
-
scheduleMicrotask(() => {
|
|
1513
|
-
try {
|
|
1514
|
-
if (VERBOSE)
|
|
1515
|
-
console.info('[ns-hmr][vue-runtime] Attempting experimental complete component refresh');
|
|
1516
|
-
// Clear more Vue caches that might be blocking updates
|
|
1517
|
-
if (internal.renderCache) {
|
|
1518
|
-
const oldLen = Object.keys(internal.renderCache).length;
|
|
1519
|
-
internal.renderCache = {};
|
|
1520
|
-
if (VERBOSE)
|
|
1521
|
-
console.info('[ns-hmr][vue-runtime] Cleared renderCache entries:', oldLen);
|
|
1522
|
-
}
|
|
1523
|
-
// Try to force Vue to think the component has changed
|
|
1524
|
-
if (internal.dirtyLevel !== undefined) {
|
|
1525
|
-
internal.dirtyLevel = 3; // Force dirty
|
|
1526
|
-
if (VERBOSE)
|
|
1527
|
-
console.info('[ns-hmr][vue-runtime] Set dirtyLevel to 3');
|
|
1528
|
-
}
|
|
1529
|
-
// Try to force the component's patch
|
|
1530
|
-
if (internal.parent && internal.parent.update) {
|
|
1531
|
-
internal.parent.update();
|
|
1532
|
-
if (VERBOSE)
|
|
1533
|
-
console.info('[ns-hmr][vue-runtime] Called parent.update()');
|
|
1534
|
-
}
|
|
1535
|
-
// Try to force app-level update
|
|
1536
|
-
const app = internal.appContext?.app;
|
|
1537
|
-
if (app && app._instance && app._instance.update) {
|
|
1538
|
-
app._instance.update();
|
|
1539
|
-
if (VERBOSE)
|
|
1540
|
-
console.info('[ns-hmr][vue-runtime] Called app._instance.update()');
|
|
1541
|
-
}
|
|
1542
|
-
// Force re-evaluation of computed properties
|
|
1543
|
-
if (internal.scope && internal.scope.effects) {
|
|
1544
|
-
for (const effect of internal.scope.effects) {
|
|
1545
|
-
if (effect && effect.scheduler) {
|
|
1546
|
-
effect.scheduler();
|
|
1547
|
-
if (VERBOSE)
|
|
1548
|
-
console.info('[ns-hmr][vue-runtime] Triggered scope effect scheduler');
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
catch (e) {
|
|
1554
|
-
if (VERBOSE)
|
|
1555
|
-
console.warn('[ns-hmr][vue-runtime] Experimental refresh failed:', e?.message);
|
|
1556
|
-
}
|
|
1557
|
-
});
|
|
1558
|
-
}
|
|
1559
|
-
catch (e) {
|
|
1560
|
-
if (VERBOSE)
|
|
1561
|
-
console.warn('[ns-hmr][vue-runtime] effect.scheduler() failed:', e?.message);
|
|
1562
|
-
}
|
|
1563
|
-
scheduleMicrotask(() => stabilizeNativeLayout(internal));
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1566
|
-
else {
|
|
1567
|
-
if (VERBOSE) {
|
|
1568
|
-
console.info('[ns-hmr][vue-runtime] No effect.scheduler available', {
|
|
1569
|
-
hasEffect: !!eff,
|
|
1570
|
-
hasScheduler: eff && typeof eff.scheduler === 'function',
|
|
1571
|
-
effectType: eff?.constructor?.name,
|
|
1572
|
-
effectKeys: eff ? Object.keys(eff).slice(0, 10) : []
|
|
1573
|
-
});
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
catch (e) {
|
|
1578
|
-
if (VERBOSE)
|
|
1579
|
-
console.warn('[ns-hmr][vue-runtime] Effect scheduler attempt failed:', e?.message);
|
|
1580
|
-
}
|
|
1581
|
-
// Prefer scheduling on nextTick before attempting immediate update to avoid NS creation timing
|
|
1582
|
-
try {
|
|
1583
|
-
const req = globalThis.require;
|
|
1584
|
-
const vueMod = req && (() => { try {
|
|
1585
|
-
return req('vue');
|
|
1586
|
-
}
|
|
1587
|
-
catch {
|
|
1588
|
-
return null;
|
|
1589
|
-
} })();
|
|
1590
|
-
const nsv = req && (() => { try {
|
|
1591
|
-
return req('nativescript-vue');
|
|
1592
|
-
}
|
|
1593
|
-
catch {
|
|
1594
|
-
return null;
|
|
1595
|
-
} })();
|
|
1596
|
-
const nextTick = (vueMod && vueMod.nextTick) || (nsv && nsv.nextTick);
|
|
1597
|
-
if (VERBOSE)
|
|
1598
|
-
console.info('[ns-hmr][vue-runtime] forceUpdate nextTick found:', typeof nextTick === 'function');
|
|
1599
|
-
if (typeof nextTick === 'function') {
|
|
1600
|
-
if (VERBOSE)
|
|
1601
|
-
console.info('[ns-hmr][vue-runtime] scheduling nextTick update (preferred path)');
|
|
1602
|
-
nextTick(() => {
|
|
1603
|
-
try {
|
|
1604
|
-
internal?.update && internal.update();
|
|
1605
|
-
if (VERBOSE)
|
|
1606
|
-
console.info('[ns-hmr][vue-runtime] nextTick(preferred) internal.update');
|
|
1607
|
-
// After update, schedule stabilization on the next microtask to allow vnode.el to attach
|
|
1608
|
-
try {
|
|
1609
|
-
scheduleMicrotask(() => stabilizeNativeLayout(internal));
|
|
1610
|
-
// And one-time next-frame follow-up update to flush any late vnode attachments
|
|
1611
|
-
if (!__postUpdateFollowed.has(internal)) {
|
|
1612
|
-
__postUpdateFollowed.add(internal);
|
|
1613
|
-
scheduleNextFrame(() => {
|
|
1614
|
-
try {
|
|
1615
|
-
typeof internal?.update === 'function' && internal.update();
|
|
1616
|
-
}
|
|
1617
|
-
catch { }
|
|
1618
|
-
scheduleMicrotask(() => stabilizeNativeLayout(internal));
|
|
1619
|
-
});
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
catch { }
|
|
1623
|
-
}
|
|
1624
|
-
catch (e) {
|
|
1625
|
-
if (VERBOSE)
|
|
1626
|
-
console.warn('[ns-hmr][vue-runtime] nextTick(preferred) update failed:', e?.message);
|
|
1627
|
-
if (e && String(e.message || e).includes('entry.create')) {
|
|
1628
|
-
scheduleDeferredUpdate(internal, 'entry.create');
|
|
1629
|
-
}
|
|
1630
|
-
else {
|
|
1631
|
-
// For non-entry.create errors, try gentle approach
|
|
1632
|
-
scheduleGentleRerender(internal);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
});
|
|
1636
|
-
return;
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
catch { }
|
|
1640
|
-
if (typeof internal?.update === 'function') {
|
|
1641
|
-
try {
|
|
1642
|
-
internal.update();
|
|
1643
|
-
try {
|
|
1644
|
-
__pendingUpdateAttempts.delete(internal);
|
|
1645
|
-
}
|
|
1646
|
-
catch { }
|
|
1647
|
-
if (VERBOSE)
|
|
1648
|
-
console.info('[ns-hmr][vue-runtime] internal.update');
|
|
1649
|
-
try {
|
|
1650
|
-
scheduleMicrotask(() => stabilizeNativeLayout(internal));
|
|
1651
|
-
// And one-time next-frame follow-up update to flush any late vnode attachments
|
|
1652
|
-
if (!__postUpdateFollowed.has(internal)) {
|
|
1653
|
-
__postUpdateFollowed.add(internal);
|
|
1654
|
-
scheduleNextFrame(() => {
|
|
1655
|
-
try {
|
|
1656
|
-
typeof internal?.update === 'function' && internal.update();
|
|
1657
|
-
}
|
|
1658
|
-
catch { }
|
|
1659
|
-
scheduleMicrotask(() => stabilizeNativeLayout(internal));
|
|
1660
|
-
});
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
catch { }
|
|
1664
|
-
return;
|
|
1665
|
-
}
|
|
1666
|
-
catch (e) {
|
|
1667
|
-
if (VERBOSE)
|
|
1668
|
-
console.warn('[ns-hmr][vue-runtime] internal.update failed:', e?.message);
|
|
1669
|
-
// If NativeScript is still creating views, defer and retry
|
|
1670
|
-
if (e && String(e.message || e).includes('entry.create')) {
|
|
1671
|
-
scheduleDeferredUpdate(internal, 'entry.create');
|
|
1672
|
-
return;
|
|
1673
|
-
}
|
|
1674
|
-
else {
|
|
1675
|
-
// For other errors, try gentle approach
|
|
1676
|
-
scheduleGentleRerender(internal);
|
|
1677
|
-
return;
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
try {
|
|
1682
|
-
const eff = internal.effect;
|
|
1683
|
-
if (eff && typeof eff.run === 'function') {
|
|
1684
|
-
eff.run();
|
|
1685
|
-
if (VERBOSE)
|
|
1686
|
-
console.info('[ns-hmr][vue-runtime] effect.run()');
|
|
1687
|
-
return;
|
|
1688
|
-
}
|
|
1689
|
-
if (eff && typeof eff.scheduler === 'function') {
|
|
1690
|
-
eff.scheduler();
|
|
1691
|
-
if (VERBOSE)
|
|
1692
|
-
console.info('[ns-hmr][vue-runtime] effect.scheduler()');
|
|
1693
|
-
return;
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
catch { }
|
|
1697
|
-
try {
|
|
1698
|
-
const vue = globalThis.require && globalThis.require('nativescript-vue');
|
|
1699
|
-
const nextTick = (vue && vue.nextTick) || (globalThis.require && globalThis.require('vue')?.nextTick);
|
|
1700
|
-
if (typeof nextTick === 'function') {
|
|
1701
|
-
nextTick(() => { try {
|
|
1702
|
-
internal?.update && internal.update();
|
|
1703
|
-
if (VERBOSE)
|
|
1704
|
-
console.info('[ns-hmr][vue-runtime] nextTick internal.update');
|
|
1705
|
-
}
|
|
1706
|
-
catch (e) {
|
|
1707
|
-
if (VERBOSE)
|
|
1708
|
-
console.warn('[ns-hmr][vue-runtime] nextTick update failed:', e?.message);
|
|
1709
|
-
} });
|
|
1710
|
-
return;
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
catch { }
|
|
1714
|
-
function attemptReloadForInstance(internal) {
|
|
1715
|
-
try {
|
|
1716
|
-
const g = globalThis;
|
|
1717
|
-
const rt = g.__VUE_HMR_RUNTIME__;
|
|
1718
|
-
if (!rt || typeof rt.reload !== 'function')
|
|
1719
|
-
return;
|
|
1720
|
-
const type = internal?.type || internal?.proxy?.type || internal?.vnode?.type;
|
|
1721
|
-
const file = (type && (type.__file || type.file)) ? String(type.__file || type.file).replace(/\\/g, '/') : '';
|
|
1722
|
-
const recentId = g.__NS_LAST_RERENDER_ID__ ? String(g.__NS_LAST_RERENDER_ID__) : '';
|
|
1723
|
-
const candidates = new Set();
|
|
1724
|
-
if (recentId)
|
|
1725
|
-
candidates.add(recentId);
|
|
1726
|
-
if (file) {
|
|
1727
|
-
const suffixes = baseFileSuffixesFromId(file);
|
|
1728
|
-
// Scan runtime records and match by suffix
|
|
1729
|
-
const map = rt.map || rt.records || {};
|
|
1730
|
-
const keys = map && typeof map.keys === 'function'
|
|
1731
|
-
? Array.from(map.keys())
|
|
1732
|
-
: (map && typeof map === 'object' ? Object.keys(map) : []);
|
|
1733
|
-
for (const k of keys) {
|
|
1734
|
-
for (const s of suffixes) {
|
|
1735
|
-
if (String(k).endsWith(s))
|
|
1736
|
-
candidates.add(String(k));
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
const ids = Array.from(candidates);
|
|
1741
|
-
if (VERBOSE)
|
|
1742
|
-
console.info('[ns-hmr][vue-runtime] Attempting component-local reload', { file, ids });
|
|
1743
|
-
for (const id of ids) {
|
|
1744
|
-
try {
|
|
1745
|
-
rt.reload(id, { /* best-effort */});
|
|
1746
|
-
if (VERBOSE)
|
|
1747
|
-
console.info('[ns-hmr][vue-runtime] Reload triggered for', id);
|
|
1748
|
-
break;
|
|
1749
|
-
}
|
|
1750
|
-
catch (e) {
|
|
1751
|
-
if (VERBOSE)
|
|
1752
|
-
console.warn('[ns-hmr][vue-runtime] Reload failed for', id, e?.message);
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
catch { }
|
|
1757
|
-
}
|
|
1758
|
-
if (VERBOSE) {
|
|
1759
|
-
try {
|
|
1760
|
-
const keys = internal ? Object.keys(internal).slice(0, 30) : [];
|
|
1761
|
-
console.warn('[ns-hmr][vue-runtime] No safe update path found for instance', { hasInternal: !!internal, internalKeys: keys });
|
|
1762
|
-
}
|
|
1763
|
-
catch { }
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
catch { }
|
|
1767
|
-
}
|
|
1768
|
-
export function applyRenderAndTrigger(ins, newRender) {
|
|
1769
|
-
return applyRenderAndTriggerWithId(ins, newRender);
|
|
1770
|
-
}
|
|
1771
|
-
export function applyRenderAndTriggerWithId(ins, newRender, componentId) {
|
|
1772
|
-
try {
|
|
1773
|
-
const internal = ins.$ || ins;
|
|
1774
|
-
const type = internal?.type || (ins && ins.type) || null;
|
|
1775
|
-
if (VERBOSE) {
|
|
1776
|
-
try {
|
|
1777
|
-
const prevTypeRender = type && type.render;
|
|
1778
|
-
const prevVNodeTypeRender = internal?.vnode?.type && internal.vnode.type.render;
|
|
1779
|
-
// Also surface some readiness info for the target instance
|
|
1780
|
-
const vnode = internal?.vnode;
|
|
1781
|
-
const el = vnode && vnode.el;
|
|
1782
|
-
const resolved = resolveNSView(el);
|
|
1783
|
-
const suspendCount = resolved.suspendCount;
|
|
1784
|
-
const hasNativeView = resolved.hasNativeView;
|
|
1785
|
-
const flags = (() => {
|
|
1786
|
-
try {
|
|
1787
|
-
if (typeof suspendCount !== 'number')
|
|
1788
|
-
return undefined;
|
|
1789
|
-
const LOADED = 1 << 20;
|
|
1790
|
-
const NATIVEVIEW = 1 << 21;
|
|
1791
|
-
const UISETUP = 1 << 22;
|
|
1792
|
-
const FLAGS_MASK = LOADED | NATIVEVIEW | UISETUP;
|
|
1793
|
-
const inc = suspendCount & ~FLAGS_MASK;
|
|
1794
|
-
return {
|
|
1795
|
-
suspendCount,
|
|
1796
|
-
inc,
|
|
1797
|
-
LOADED: (suspendCount & LOADED) !== 0,
|
|
1798
|
-
NATIVEVIEW: (suspendCount & NATIVEVIEW) !== 0,
|
|
1799
|
-
UISETUP: (suspendCount & UISETUP) !== 0,
|
|
1800
|
-
};
|
|
1801
|
-
}
|
|
1802
|
-
catch {
|
|
1803
|
-
return undefined;
|
|
1804
|
-
}
|
|
1805
|
-
})();
|
|
1806
|
-
console.info('[ns-hmr][vue-runtime] patching renders (minimal)', {
|
|
1807
|
-
name: (type && (type.__name || type.name)) || undefined,
|
|
1808
|
-
hadTypeRender: typeof prevTypeRender === 'function',
|
|
1809
|
-
hadVNodeTypeRender: typeof prevVNodeTypeRender === 'function',
|
|
1810
|
-
hasNativeView,
|
|
1811
|
-
flags
|
|
1812
|
-
});
|
|
1813
|
-
}
|
|
1814
|
-
catch { }
|
|
1815
|
-
}
|
|
1816
|
-
// IMPORTANT: patch the component type.render, vnode.type.render, and internal.render so next updates use new render
|
|
1817
|
-
try {
|
|
1818
|
-
if (type)
|
|
1819
|
-
type.render = newRender;
|
|
1820
|
-
}
|
|
1821
|
-
catch { }
|
|
1822
|
-
try {
|
|
1823
|
-
if (internal?.vnode?.type)
|
|
1824
|
-
internal.vnode.type.render = newRender;
|
|
1825
|
-
}
|
|
1826
|
-
catch { }
|
|
1827
|
-
try {
|
|
1828
|
-
if (internal)
|
|
1829
|
-
internal.render = newRender;
|
|
1830
|
-
}
|
|
1831
|
-
catch { }
|
|
1832
|
-
// Clear render cache so compiled template changes take effect immediately
|
|
1833
|
-
try {
|
|
1834
|
-
if (internal && Array.isArray(internal.renderCache)) {
|
|
1835
|
-
const len = internal.renderCache.length;
|
|
1836
|
-
internal.renderCache.length = 0;
|
|
1837
|
-
if (VERBOSE)
|
|
1838
|
-
console.info('[ns-hmr][vue-runtime] cleared instance.renderCache', { prevLen: len });
|
|
1839
|
-
}
|
|
1840
|
-
else if (internal && internal.renderCache) {
|
|
1841
|
-
internal.renderCache = [];
|
|
1842
|
-
if (VERBOSE)
|
|
1843
|
-
console.info('[ns-hmr][vue-runtime] reset instance.renderCache to empty array');
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
catch { }
|
|
1847
|
-
if (VERBOSE) {
|
|
1848
|
-
try {
|
|
1849
|
-
const file = (type && type.__file) ? String(type.__file) : undefined;
|
|
1850
|
-
const name = (type && (type.__name || type.name)) ? String(type.__name || type.name) : undefined;
|
|
1851
|
-
console.info('[ns-hmr][vue-runtime] applyRenderAndTrigger', { file, name, hasType: !!type, hasVNodeType: !!(internal?.vnode?.type) });
|
|
1852
|
-
}
|
|
1853
|
-
catch { }
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
catch { }
|
|
1857
|
-
// Check if the instance is ready for update before forcing
|
|
1858
|
-
try {
|
|
1859
|
-
const ready = isNSViewReady(ins, componentId);
|
|
1860
|
-
if (VERBOSE)
|
|
1861
|
-
console.info('[ns-hmr][vue-runtime] applyRenderAndTrigger readiness:', { ready });
|
|
1862
|
-
if (!ready) {
|
|
1863
|
-
if (VERBOSE)
|
|
1864
|
-
console.info('[ns-hmr][vue-runtime] Instance not ready for update, trying progressive approach');
|
|
1865
|
-
// Instead of giving up, try a more progressive approach
|
|
1866
|
-
// First try the gentle approach, but with a fallback to direct update
|
|
1867
|
-
try {
|
|
1868
|
-
scheduleGentleRerender(ins, componentId);
|
|
1869
|
-
// Also schedule a backup direct update after a delay in case gentle approach fails
|
|
1870
|
-
setTimeout(() => {
|
|
1871
|
-
try {
|
|
1872
|
-
if (VERBOSE)
|
|
1873
|
-
console.info('[ns-hmr][vue-runtime] Backup direct update attempt');
|
|
1874
|
-
forceUpdateInstance(ins, componentId);
|
|
1875
|
-
}
|
|
1876
|
-
catch (e) {
|
|
1877
|
-
if (VERBOSE)
|
|
1878
|
-
console.warn('[ns-hmr][vue-runtime] Backup update failed:', e?.message);
|
|
1879
|
-
}
|
|
1880
|
-
}, 100);
|
|
1881
|
-
}
|
|
1882
|
-
catch (e) {
|
|
1883
|
-
if (VERBOSE)
|
|
1884
|
-
console.warn('[ns-hmr][vue-runtime] Progressive approach failed, falling back to direct update:', e?.message);
|
|
1885
|
-
forceUpdateInstance(ins, componentId);
|
|
1886
|
-
}
|
|
1887
|
-
return;
|
|
1888
|
-
}
|
|
1889
|
-
}
|
|
1890
|
-
catch (e) {
|
|
1891
|
-
if (VERBOSE)
|
|
1892
|
-
console.warn('[ns-hmr][vue-runtime] Readiness check failed, proceeding with direct update:', e?.message);
|
|
1893
|
-
}
|
|
1894
|
-
forceUpdateInstance(ins);
|
|
1895
|
-
}
|
|
1896
|
-
function tryPatchInstancesFromRootByFileSuffix(id, newRender) {
|
|
1897
|
-
const g = globalThis;
|
|
1898
|
-
const root = g.__NS_VUE_ROOT_INSTANCE__;
|
|
1899
|
-
if (!root)
|
|
1900
|
-
return 0;
|
|
1901
|
-
const suffixes = baseFileSuffixesFromId(id);
|
|
1902
|
-
let patched = 0;
|
|
1903
|
-
const maybePatch = (ins) => {
|
|
1904
|
-
try {
|
|
1905
|
-
const type = getComponentType(ins);
|
|
1906
|
-
const file = type && type.__file ? String(type.__file).replace(/\\/g, '/') : '';
|
|
1907
|
-
if (file) {
|
|
1908
|
-
for (const suf of suffixes) {
|
|
1909
|
-
if (file.endsWith(suf)) {
|
|
1910
|
-
applyRenderAndTrigger(ins, newRender);
|
|
1911
|
-
patched++;
|
|
1912
|
-
if (VERBOSE)
|
|
1913
|
-
console.info('[ns-hmr][vue-runtime] patched instance via file suffix match', { file, suf, setType: !!type, setVNode: !!(ins?.vnode?.type), setInternal: true });
|
|
1914
|
-
break;
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
}
|
|
1919
|
-
catch { }
|
|
1920
|
-
};
|
|
1921
|
-
const enqueueChildren = (node, q) => {
|
|
1922
|
-
try {
|
|
1923
|
-
if (!node)
|
|
1924
|
-
return;
|
|
1925
|
-
const internal = (node.$ ? node.$ : node);
|
|
1926
|
-
if (internal?.subTree)
|
|
1927
|
-
q.push(internal.subTree);
|
|
1928
|
-
if (node && typeof node === 'object') {
|
|
1929
|
-
try {
|
|
1930
|
-
const comp = node.component;
|
|
1931
|
-
if (comp)
|
|
1932
|
-
q.push(comp);
|
|
1933
|
-
}
|
|
1934
|
-
catch { }
|
|
1935
|
-
const ch = node.children || node.child || null;
|
|
1936
|
-
if (Array.isArray(ch)) {
|
|
1937
|
-
for (const c of ch) {
|
|
1938
|
-
if (c && typeof c === 'object')
|
|
1939
|
-
q.push(c);
|
|
1940
|
-
}
|
|
1941
|
-
}
|
|
1942
|
-
else if (ch && typeof ch === 'object') {
|
|
1943
|
-
q.push(ch);
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
catch { }
|
|
1948
|
-
};
|
|
1949
|
-
const queue = [root];
|
|
1950
|
-
while (queue.length) {
|
|
1951
|
-
const cur = queue.shift();
|
|
1952
|
-
try {
|
|
1953
|
-
maybePatch(cur);
|
|
1954
|
-
}
|
|
1955
|
-
catch { }
|
|
1956
|
-
try {
|
|
1957
|
-
enqueueChildren(cur, queue);
|
|
1958
|
-
}
|
|
1959
|
-
catch { }
|
|
1960
|
-
}
|
|
1961
|
-
return patched;
|
|
1962
|
-
}
|
|
1963
|
-
function baseNameFromId(id) { try {
|
|
1964
|
-
const noQ = String(id || '').split('?')[0].replace(/\\/g, '/');
|
|
1965
|
-
const base = (noQ.split('/').pop() || '').replace(/\.vue$/i, '');
|
|
1966
|
-
return base;
|
|
1967
|
-
}
|
|
1968
|
-
catch {
|
|
1969
|
-
return '';
|
|
1970
|
-
} }
|
|
1971
|
-
function tryPatchInstancesFromRootByName(id, newRender, runtime) {
|
|
1972
|
-
const g = globalThis;
|
|
1973
|
-
const root = g.__NS_VUE_ROOT_INSTANCE__;
|
|
1974
|
-
if (!root)
|
|
1975
|
-
return 0;
|
|
1976
|
-
const target = baseNameFromId(id);
|
|
1977
|
-
if (!target)
|
|
1978
|
-
return 0;
|
|
1979
|
-
const targetLower = target.toLowerCase();
|
|
1980
|
-
let patched = 0;
|
|
1981
|
-
const maybePatch = (ins) => {
|
|
1982
|
-
try {
|
|
1983
|
-
const type = getComponentType(ins);
|
|
1984
|
-
const name = (type && (type.__name || type.name)) ? String(type.__name || type.name) : '';
|
|
1985
|
-
if (name && name.toLowerCase() === targetLower) {
|
|
1986
|
-
applyRenderAndTrigger(ins, newRender);
|
|
1987
|
-
patched++;
|
|
1988
|
-
if (VERBOSE) {
|
|
1989
|
-
try {
|
|
1990
|
-
const vnode = (ins && ins.vnode) || ((ins && ins.$) ? ins.$.vnode : undefined);
|
|
1991
|
-
const el = vnode && vnode.el;
|
|
1992
|
-
const suspendCount = el && typeof el === 'object' ? el._suspendNativeUpdatesCount : undefined;
|
|
1993
|
-
const isLoaded = el && typeof el === 'object' ? el._isLoaded : undefined;
|
|
1994
|
-
const isMounted = typeof ins?.isMounted === 'boolean' ? ins.isMounted : undefined;
|
|
1995
|
-
console.info('[ns-hmr][vue-runtime] patched instance via name match', { name, target: targetLower, setType: !!type, setVNode: !!(ins?.vnode?.type), setInternal: true, isMounted, isLoaded, suspendCount });
|
|
1996
|
-
}
|
|
1997
|
-
catch { }
|
|
1998
|
-
}
|
|
1999
|
-
try {
|
|
2000
|
-
if (runtime && typeof runtime.registerInstance === 'function')
|
|
2001
|
-
runtime.registerInstance(id, ins);
|
|
2002
|
-
}
|
|
2003
|
-
catch { }
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
catch { }
|
|
2007
|
-
};
|
|
2008
|
-
const enqueueChildren = (node, q) => {
|
|
2009
|
-
try {
|
|
2010
|
-
if (!node)
|
|
2011
|
-
return;
|
|
2012
|
-
const internal = (node.$ ? node.$ : node);
|
|
2013
|
-
if (internal && internal.subTree)
|
|
2014
|
-
q.push(internal.subTree);
|
|
2015
|
-
if (node && typeof node === 'object') {
|
|
2016
|
-
try {
|
|
2017
|
-
const comp = node.component;
|
|
2018
|
-
if (comp)
|
|
2019
|
-
q.push(comp);
|
|
2020
|
-
}
|
|
2021
|
-
catch { }
|
|
2022
|
-
const ch = node.children || node.child || null;
|
|
2023
|
-
if (Array.isArray(ch)) {
|
|
2024
|
-
for (const c of ch) {
|
|
2025
|
-
if (c && typeof c === 'object')
|
|
2026
|
-
q.push(c);
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
else if (ch && typeof ch === 'object') {
|
|
2030
|
-
q.push(ch);
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
catch { }
|
|
2035
|
-
};
|
|
2036
|
-
const queue = [root];
|
|
2037
|
-
while (queue.length) {
|
|
2038
|
-
const cur = queue.shift();
|
|
2039
|
-
try {
|
|
2040
|
-
maybePatch(cur);
|
|
2041
|
-
}
|
|
2042
|
-
catch { }
|
|
2043
|
-
try {
|
|
2044
|
-
enqueueChildren(cur, queue);
|
|
2045
|
-
}
|
|
2046
|
-
catch { }
|
|
2047
|
-
}
|
|
2048
|
-
return patched;
|
|
2049
|
-
}
|
|
2050
|
-
// New function to handle gentle re-rendering without forcing component recreation
|
|
2051
|
-
function scheduleGentleRerender(internal, componentId) {
|
|
2052
|
-
try {
|
|
2053
|
-
if (VERBOSE)
|
|
2054
|
-
console.info('[ns-hmr][vue-runtime] scheduleGentleRerender');
|
|
2055
|
-
// First approach: invalidate the render effect using Vue 3 compatible methods
|
|
2056
|
-
try {
|
|
2057
|
-
const renderEffect = internal.renderEffect || internal.effect;
|
|
2058
|
-
if (renderEffect) {
|
|
2059
|
-
// Use Vue 3's proper effect triggering instead of setting readonly 'dirty' property
|
|
2060
|
-
if (typeof renderEffect.trigger === 'function') {
|
|
2061
|
-
renderEffect.trigger();
|
|
2062
|
-
if (VERBOSE)
|
|
2063
|
-
console.info('[ns-hmr][vue-runtime] gentle update: triggered render effect via trigger()');
|
|
2064
|
-
}
|
|
2065
|
-
else if (typeof renderEffect.run === 'function') {
|
|
2066
|
-
renderEffect.run();
|
|
2067
|
-
if (VERBOSE)
|
|
2068
|
-
console.info('[ns-hmr][vue-runtime] gentle update: triggered render effect via run()');
|
|
2069
|
-
}
|
|
2070
|
-
else if (typeof renderEffect.scheduler === 'function') {
|
|
2071
|
-
renderEffect.scheduler();
|
|
2072
|
-
if (VERBOSE)
|
|
2073
|
-
console.info('[ns-hmr][vue-runtime] gentle update: triggered render effect via scheduler()');
|
|
2074
|
-
}
|
|
2075
|
-
else {
|
|
2076
|
-
if (VERBOSE)
|
|
2077
|
-
console.warn('[ns-hmr][vue-runtime] gentle update: no compatible render effect trigger method found');
|
|
2078
|
-
}
|
|
2079
|
-
// Trigger scheduler if available for gentle scheduling
|
|
2080
|
-
if (typeof renderEffect.scheduler === 'function') {
|
|
2081
|
-
const req = globalThis.require;
|
|
2082
|
-
const vueMod = req && (() => { try {
|
|
2083
|
-
return req('vue');
|
|
2084
|
-
}
|
|
2085
|
-
catch {
|
|
2086
|
-
return null;
|
|
2087
|
-
} })();
|
|
2088
|
-
const nextTick = vueMod && vueMod.nextTick;
|
|
2089
|
-
if (typeof nextTick === 'function') {
|
|
2090
|
-
nextTick(() => {
|
|
2091
|
-
try {
|
|
2092
|
-
renderEffect.scheduler();
|
|
2093
|
-
if (VERBOSE)
|
|
2094
|
-
console.info('[ns-hmr][vue-runtime] gentle rerender via scheduler');
|
|
2095
|
-
// Also request layout to ensure visual update
|
|
2096
|
-
try {
|
|
2097
|
-
const { el, info } = findNSViewFromInternal(internal);
|
|
2098
|
-
if (info.view && typeof info.view.requestLayout === 'function') {
|
|
2099
|
-
info.view.requestLayout();
|
|
2100
|
-
}
|
|
2101
|
-
else if (info.nativeView && typeof info.nativeView.setNeedsLayout === 'function') {
|
|
2102
|
-
info.nativeView.setNeedsLayout();
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
catch { }
|
|
2106
|
-
}
|
|
2107
|
-
catch (e) {
|
|
2108
|
-
if (VERBOSE)
|
|
2109
|
-
console.warn('[ns-hmr][vue-runtime] gentle scheduler failed:', e?.message);
|
|
2110
|
-
}
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
|
-
else {
|
|
2114
|
-
renderEffect.scheduler();
|
|
2115
|
-
// Request layout after scheduler
|
|
2116
|
-
setTimeout(() => {
|
|
2117
|
-
try {
|
|
2118
|
-
const { el, info } = findNSViewFromInternal(internal);
|
|
2119
|
-
if (info.view && typeof info.view.requestLayout === 'function') {
|
|
2120
|
-
info.view.requestLayout();
|
|
2121
|
-
}
|
|
2122
|
-
else if (info.nativeView && typeof info.nativeView.setNeedsLayout === 'function') {
|
|
2123
|
-
info.nativeView.setNeedsLayout();
|
|
2124
|
-
}
|
|
2125
|
-
}
|
|
2126
|
-
catch { }
|
|
2127
|
-
}, 0);
|
|
2128
|
-
}
|
|
2129
|
-
return;
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
}
|
|
2133
|
-
catch (e) {
|
|
2134
|
-
if (VERBOSE)
|
|
2135
|
-
console.warn('[ns-hmr][vue-runtime] gentle effect invalidation failed:', e?.message);
|
|
2136
|
-
}
|
|
2137
|
-
// Fallback: schedule a deferred update with longer delay to give view time to stabilize
|
|
2138
|
-
const attempt = (__pendingUpdateAttempts.get(internal) || 0) + 1;
|
|
2139
|
-
__pendingUpdateAttempts.set(internal, attempt);
|
|
2140
|
-
const delay = Math.min(BASE_DEFER_MS * attempt * 2, 200); // Longer delays for gentle approach
|
|
2141
|
-
setTimeout(() => {
|
|
2142
|
-
try {
|
|
2143
|
-
const { el } = findNSViewFromInternal(internal);
|
|
2144
|
-
if (isNSViewReady(internal)) {
|
|
2145
|
-
if (VERBOSE)
|
|
2146
|
-
console.info('[ns-hmr][vue-runtime] gentle deferred update - view ready, applying');
|
|
2147
|
-
try {
|
|
2148
|
-
// Try multiple update approaches for better coverage
|
|
2149
|
-
let updateApplied = false;
|
|
2150
|
-
// Method 1: Use effect scheduler if available
|
|
2151
|
-
const eff = internal.effect;
|
|
2152
|
-
if (eff && typeof eff.scheduler === 'function') {
|
|
2153
|
-
eff.scheduler();
|
|
2154
|
-
updateApplied = true;
|
|
2155
|
-
if (VERBOSE)
|
|
2156
|
-
console.info('[ns-hmr][vue-runtime] gentle update: effect.scheduler() called');
|
|
2157
|
-
}
|
|
2158
|
-
// Method 2: Direct internal update
|
|
2159
|
-
if (internal?.update && typeof internal.update === 'function') {
|
|
2160
|
-
internal.update();
|
|
2161
|
-
updateApplied = true;
|
|
2162
|
-
if (VERBOSE)
|
|
2163
|
-
console.info('[ns-hmr][vue-runtime] gentle update: internal.update() called');
|
|
2164
|
-
}
|
|
2165
|
-
// Method 3: Force component re-render
|
|
2166
|
-
const vnode = internal?.vnode;
|
|
2167
|
-
if (vnode && !updateApplied) {
|
|
2168
|
-
// Try to trigger Vue's re-render mechanisms
|
|
2169
|
-
if (typeof internal.renderCache?.clear === 'function') {
|
|
2170
|
-
internal.renderCache.clear();
|
|
2171
|
-
}
|
|
2172
|
-
if (Array.isArray(internal.renderCache)) {
|
|
2173
|
-
internal.renderCache.length = 0;
|
|
2174
|
-
}
|
|
2175
|
-
if (VERBOSE)
|
|
2176
|
-
console.info('[ns-hmr][vue-runtime] gentle update: cleared render cache');
|
|
2177
|
-
}
|
|
2178
|
-
if (VERBOSE)
|
|
2179
|
-
console.info('[ns-hmr][vue-runtime] gentle update completed, applied:', updateApplied);
|
|
2180
|
-
// If gentle update failed, try proper Vue component lifecycle approach
|
|
2181
|
-
if (!updateApplied) {
|
|
2182
|
-
try {
|
|
2183
|
-
if (VERBOSE)
|
|
2184
|
-
console.info('[ns-hmr][vue-runtime] Gentle update failed, attempting Vue component lifecycle approach');
|
|
2185
|
-
// Get the Vue HMR runtime for proper component updates
|
|
2186
|
-
const vueRuntime = ensureVueHMRRuntimeEnhanced();
|
|
2187
|
-
const componentId = getComponentIdFromInternal(internal);
|
|
2188
|
-
if (vueRuntime && componentId) {
|
|
2189
|
-
// Use Vue's official HMR rerender instead of manual effect manipulation
|
|
2190
|
-
if (typeof vueRuntime.rerender === 'function') {
|
|
2191
|
-
if (VERBOSE)
|
|
2192
|
-
console.info('[ns-hmr][vue-runtime] Using Vue HMR runtime rerender for component:', componentId);
|
|
2193
|
-
// Get the new render function from the component type
|
|
2194
|
-
const componentType = internal.type || internal.vnode?.type;
|
|
2195
|
-
if (componentType && componentType.render) {
|
|
2196
|
-
vueRuntime.rerender(componentId, componentType.render);
|
|
2197
|
-
if (VERBOSE)
|
|
2198
|
-
console.info('[ns-hmr][vue-runtime] Vue HMR rerender called successfully');
|
|
2199
|
-
}
|
|
2200
|
-
else {
|
|
2201
|
-
if (VERBOSE)
|
|
2202
|
-
console.warn('[ns-hmr][vue-runtime] No render function found for Vue HMR rerender');
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
// Also try Vue's reload as backup
|
|
2206
|
-
if (typeof vueRuntime.reload === 'function') {
|
|
2207
|
-
const componentDef = internal.type || internal.vnode?.type;
|
|
2208
|
-
if (componentDef) {
|
|
2209
|
-
vueRuntime.reload(componentId, componentDef);
|
|
2210
|
-
if (VERBOSE)
|
|
2211
|
-
console.info('[ns-hmr][vue-runtime] Vue HMR reload called as backup');
|
|
2212
|
-
}
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
else {
|
|
2216
|
-
if (VERBOSE)
|
|
2217
|
-
console.warn('[ns-hmr][vue-runtime] No Vue HMR runtime or component ID available for lifecycle approach');
|
|
2218
|
-
}
|
|
2219
|
-
// Force component instance update through proper Vue channels
|
|
2220
|
-
if (internal.parent && internal.parent.update) {
|
|
2221
|
-
internal.parent.update();
|
|
2222
|
-
if (VERBOSE)
|
|
2223
|
-
console.info('[ns-hmr][vue-runtime] Triggered parent component update');
|
|
2224
|
-
}
|
|
2225
|
-
// Force root app update if available
|
|
2226
|
-
const g = globalThis;
|
|
2227
|
-
const root = g.__NS_VUE_ROOT_INSTANCE__;
|
|
2228
|
-
if (root && root.$ && typeof root.$.update === 'function') {
|
|
2229
|
-
root.$.update();
|
|
2230
|
-
if (VERBOSE)
|
|
2231
|
-
console.info('[ns-hmr][vue-runtime] Triggered root instance update');
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2234
|
-
catch (e) {
|
|
2235
|
-
if (VERBOSE)
|
|
2236
|
-
console.warn('[ns-hmr][vue-runtime] Vue component lifecycle approach failed:', e?.message);
|
|
2237
|
-
}
|
|
2238
|
-
}
|
|
2239
|
-
// Force native layout updates to ensure visual changes appear
|
|
2240
|
-
try {
|
|
2241
|
-
const probe = findNSViewFromInternal(internal);
|
|
2242
|
-
if (probe.info?.view) {
|
|
2243
|
-
const view = probe.info.view;
|
|
2244
|
-
if (typeof view.requestLayout === 'function') {
|
|
2245
|
-
view.requestLayout();
|
|
2246
|
-
if (VERBOSE)
|
|
2247
|
-
console.info('[ns-hmr][vue-runtime] gentle update: requested layout');
|
|
2248
|
-
}
|
|
2249
|
-
if (probe.info.nativeView && typeof probe.info.nativeView.setNeedsLayout === 'function') {
|
|
2250
|
-
probe.info.nativeView.setNeedsLayout();
|
|
2251
|
-
if (VERBOSE)
|
|
2252
|
-
console.info('[ns-hmr][vue-runtime] gentle update: set needs layout');
|
|
2253
|
-
}
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
catch (e) {
|
|
2257
|
-
if (VERBOSE)
|
|
2258
|
-
console.warn('[ns-hmr][vue-runtime] Layout update failed:', e?.message);
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
catch (e) {
|
|
2262
|
-
if (VERBOSE)
|
|
2263
|
-
console.warn('[ns-hmr][vue-runtime] gentle update failed:', e?.message);
|
|
2264
|
-
}
|
|
2265
|
-
__pendingUpdateAttempts.delete(internal);
|
|
2266
|
-
}
|
|
2267
|
-
else {
|
|
2268
|
-
if (attempt < MAX_DEFER_ATTEMPTS) {
|
|
2269
|
-
if (VERBOSE)
|
|
2270
|
-
console.info('[ns-hmr][vue-runtime] gentle deferred update - view not ready, retrying');
|
|
2271
|
-
scheduleGentleRerender(internal, componentId);
|
|
2272
|
-
}
|
|
2273
|
-
else {
|
|
2274
|
-
if (VERBOSE)
|
|
2275
|
-
console.warn('[ns-hmr][vue-runtime] giving up on gentle rerender after max attempts');
|
|
2276
|
-
// Last resort: force update anyway
|
|
2277
|
-
try {
|
|
2278
|
-
if (VERBOSE)
|
|
2279
|
-
console.info('[ns-hmr][vue-runtime] last resort: forcing update despite view state');
|
|
2280
|
-
internal?.update && internal.update();
|
|
2281
|
-
__pendingUpdateAttempts.delete(internal);
|
|
2282
|
-
}
|
|
2283
|
-
catch (e) {
|
|
2284
|
-
if (VERBOSE)
|
|
2285
|
-
console.warn('[ns-hmr][vue-runtime] last resort update failed:', e?.message);
|
|
2286
|
-
}
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2289
|
-
}
|
|
2290
|
-
catch (e) {
|
|
2291
|
-
if (VERBOSE)
|
|
2292
|
-
console.warn('[ns-hmr][vue-runtime] gentle deferred update failed:', e?.message);
|
|
2293
|
-
if (attempt < MAX_DEFER_ATTEMPTS) {
|
|
2294
|
-
scheduleGentleRerender(internal, componentId);
|
|
2295
|
-
}
|
|
2296
|
-
}
|
|
2297
|
-
}, delay);
|
|
2298
|
-
}
|
|
2299
|
-
catch (e) {
|
|
2300
|
-
if (VERBOSE)
|
|
2301
|
-
console.warn('[ns-hmr][vue-runtime] scheduleGentleRerender failed:', e?.message);
|
|
2302
|
-
}
|
|
2303
|
-
}
|
|
2304
|
-
// Note: Avoid auto-initializing Vue HMR runtime here to prevent fallback
|
|
2305
|
-
// runtime creation and noisy logs at app boot. The webpack5-style handler
|
|
2306
|
-
// manages HMR runtime setup explicitly.
|