@nativescript/vite 8.0.0-alpha.30 → 8.0.0-alpha.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configuration/angular.js +8 -8
- package/configuration/angular.js.map +1 -1
- package/configuration/solid.js +2 -2
- package/configuration/solid.js.map +1 -1
- package/hmr/client/framework-client-strategy.d.ts +73 -0
- package/hmr/client/framework-client-strategy.js +19 -0
- package/hmr/client/framework-client-strategy.js.map +1 -0
- package/hmr/client/index.js +77 -186
- package/hmr/client/index.js.map +1 -1
- package/hmr/client/utils.js.map +1 -1
- package/hmr/entry-runtime.js.map +1 -1
- package/hmr/frameworks/angular/build/angular-linker.js.map +1 -0
- package/hmr/frameworks/angular/build/inject-component-hmr-registration.js.map +1 -0
- package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.js.map +1 -0
- package/hmr/frameworks/angular/build/inline-decorator-component-templates.js.map +1 -0
- package/hmr/frameworks/angular/build/js-lexer.js.map +1 -0
- package/hmr/frameworks/angular/build/shared-linker.js.map +1 -0
- package/hmr/frameworks/angular/build/synthesize-decorator-ctor-parameters.js.map +1 -0
- package/hmr/frameworks/angular/build/synthesize-injectable-factories.js.map +1 -0
- package/hmr/frameworks/angular/build/util.js.map +1 -0
- package/hmr/frameworks/angular/client/index.js.map +1 -1
- package/hmr/frameworks/angular/client/strategy.d.ts +9 -0
- package/hmr/frameworks/angular/client/strategy.js +19 -0
- package/hmr/frameworks/angular/client/strategy.js.map +1 -0
- package/hmr/frameworks/angular/server/angular-root-component.js.map +1 -0
- package/hmr/frameworks/angular/server/strategy.js +440 -2
- package/hmr/frameworks/angular/server/strategy.js.map +1 -1
- package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.js +2 -2
- package/hmr/frameworks/angular/server/websocket-angular-entry.js.map +1 -0
- package/hmr/{server → frameworks/angular/server}/websocket-angular-hot-update.d.ts +0 -11
- package/hmr/{server → frameworks/angular/server}/websocket-angular-hot-update.js +3 -80
- package/hmr/frameworks/angular/server/websocket-angular-hot-update.js.map +1 -0
- package/hmr/frameworks/solid/build/solid-jsx-deps.js.map +1 -0
- package/hmr/frameworks/solid/server/strategy.js +360 -1
- package/hmr/frameworks/solid/server/strategy.js.map +1 -1
- package/hmr/frameworks/typescript/server/strategy.js +27 -0
- package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
- package/hmr/frameworks/vue/client/index.js.map +1 -1
- package/hmr/frameworks/vue/client/strategy.d.ts +7 -0
- package/hmr/frameworks/vue/client/strategy.js +83 -0
- package/hmr/frameworks/vue/client/strategy.js.map +1 -0
- package/hmr/frameworks/vue/client/vue-sfc-update-overlay.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-route-assemble.d.ts +7 -0
- package/hmr/{server/websocket-sfc.js → frameworks/vue/server/sfc-route-assemble.js} +19 -536
- package/hmr/frameworks/vue/server/sfc-route-assemble.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-route-meta.d.ts +7 -0
- package/hmr/frameworks/vue/server/sfc-route-meta.js +80 -0
- package/hmr/frameworks/vue/server/sfc-route-meta.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-route-serve.d.ts +8 -0
- package/hmr/frameworks/vue/server/sfc-route-serve.js +457 -0
- package/hmr/frameworks/vue/server/sfc-route-serve.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-route-shared.d.ts +19 -0
- package/hmr/frameworks/vue/server/sfc-route-shared.js +14 -0
- package/hmr/frameworks/vue/server/sfc-route-shared.js.map +1 -0
- package/hmr/frameworks/vue/server/strategy.js +244 -0
- package/hmr/frameworks/vue/server/strategy.js.map +1 -1
- package/hmr/frameworks/vue/server/websocket-sfc.d.ts +15 -0
- package/hmr/frameworks/vue/server/websocket-sfc.js +20 -0
- package/hmr/frameworks/vue/server/websocket-sfc.js.map +1 -0
- package/hmr/server/device-transform-helpers.d.ts +24 -0
- package/hmr/server/device-transform-helpers.js +327 -0
- package/hmr/server/device-transform-helpers.js.map +1 -0
- package/hmr/server/framework-strategy.d.ts +95 -1
- package/hmr/server/hmr-module-graph.js.map +1 -1
- package/hmr/server/import-map.d.ts +11 -2
- package/hmr/server/import-map.js +21 -54
- package/hmr/server/import-map.js.map +1 -1
- package/hmr/server/index.js +7 -17
- package/hmr/server/index.js.map +1 -1
- package/hmr/server/process-code-for-device.d.ts +15 -0
- package/hmr/server/process-code-for-device.js +654 -0
- package/hmr/server/process-code-for-device.js.map +1 -0
- package/hmr/server/rewrite-imports.d.ts +2 -0
- package/hmr/server/rewrite-imports.js +604 -0
- package/hmr/server/rewrite-imports.js.map +1 -0
- package/hmr/server/transform-cache-invalidation.d.ts +11 -0
- package/hmr/server/transform-cache-invalidation.js +84 -0
- package/hmr/server/transform-cache-invalidation.js.map +1 -0
- package/hmr/server/websocket-device-transform.d.ts +3 -21
- package/hmr/server/websocket-device-transform.js +6 -1569
- package/hmr/server/websocket-device-transform.js.map +1 -1
- package/hmr/server/websocket-hmr-pending.d.ts +2 -8
- package/hmr/server/websocket-hmr-pending.js.map +1 -1
- package/hmr/server/websocket-hot-update.d.ts +40 -14
- package/hmr/server/websocket-hot-update.js +24 -854
- package/hmr/server/websocket-hot-update.js.map +1 -1
- package/hmr/server/websocket-import-map-route.js +3 -1
- package/hmr/server/websocket-import-map-route.js.map +1 -1
- package/hmr/server/websocket-ns-core.d.ts +4 -4
- package/hmr/server/websocket-ns-core.js +3 -2
- package/hmr/server/websocket-ns-core.js.map +1 -1
- package/hmr/server/websocket-ns-entry.d.ts +0 -1
- package/hmr/server/websocket-ns-entry.js +1 -1
- package/hmr/server/websocket-ns-entry.js.map +1 -1
- package/hmr/server/websocket-ns-m.d.ts +0 -1
- package/hmr/server/websocket-ns-m.js +24 -129
- package/hmr/server/websocket-ns-m.js.map +1 -1
- package/hmr/server/websocket-vendor-unifier.d.ts +0 -1
- package/hmr/server/websocket-vendor-unifier.js +2 -1
- package/hmr/server/websocket-vendor-unifier.js.map +1 -1
- package/hmr/server/websocket.d.ts +11 -12
- package/hmr/server/websocket.js +25 -33
- package/hmr/server/websocket.js.map +1 -1
- package/hmr/shared/ns-globals.d.ts +118 -0
- package/hmr/shared/ns-globals.js +27 -0
- package/hmr/shared/ns-globals.js.map +1 -0
- package/hmr/shared/protocol.d.ts +136 -0
- package/hmr/shared/protocol.js +28 -0
- package/hmr/shared/protocol.js.map +1 -0
- package/hmr/shared/vendor/manifest-collect.d.ts +0 -28
- package/hmr/shared/vendor/manifest-collect.js +2 -2
- package/hmr/shared/vendor/manifest-collect.js.map +1 -1
- package/hmr/shared/vendor/manifest.d.ts +1 -3
- package/hmr/shared/vendor/manifest.js +1 -3
- package/hmr/shared/vendor/manifest.js.map +1 -1
- package/hmr/shared/vendor/vendor-esbuild-plugins.js +1 -1
- package/hmr/shared/vendor/vendor-esbuild-plugins.js.map +1 -1
- package/package.json +1 -1
- package/helpers/angular/angular-linker.js.map +0 -1
- package/helpers/angular/inject-component-hmr-registration.js.map +0 -1
- package/helpers/angular/inject-hmr-vite-ignore.js.map +0 -1
- package/helpers/angular/inline-decorator-component-templates.js.map +0 -1
- package/helpers/angular/js-lexer.js.map +0 -1
- package/helpers/angular/shared-linker.js.map +0 -1
- package/helpers/angular/synthesize-decorator-ctor-parameters.js.map +0 -1
- package/helpers/angular/synthesize-injectable-factories.js.map +0 -1
- package/helpers/angular/util.js.map +0 -1
- package/helpers/prelink-angular.d.ts +0 -2
- package/helpers/prelink-angular.js +0 -96
- package/helpers/prelink-angular.js.map +0 -1
- package/helpers/solid-jsx-deps.js.map +0 -1
- package/hmr/client/vue-sfc-update-overlay.js.map +0 -1
- package/hmr/server/angular-root-component.js.map +0 -1
- package/hmr/server/websocket-angular-entry.js.map +0 -1
- package/hmr/server/websocket-angular-hot-update.js.map +0 -1
- package/hmr/server/websocket-sfc.d.ts +0 -24
- package/hmr/server/websocket-sfc.js.map +0 -1
- /package/{helpers/angular → hmr/frameworks/angular/build}/angular-linker.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/angular-linker.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/inject-component-hmr-registration.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/inject-component-hmr-registration.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/inject-hmr-vite-ignore.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/inject-hmr-vite-ignore.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/js-lexer.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/js-lexer.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/shared-linker.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/shared-linker.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-decorator-ctor-parameters.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-decorator-ctor-parameters.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.js +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/util.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/util.js +0 -0
- /package/hmr/{server → frameworks/angular/server}/angular-root-component.d.ts +0 -0
- /package/hmr/{server → frameworks/angular/server}/angular-root-component.js +0 -0
- /package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.d.ts +0 -0
- /package/{helpers → hmr/frameworks/solid/build}/solid-jsx-deps.d.ts +0 -0
- /package/{helpers → hmr/frameworks/solid/build}/solid-jsx-deps.js +0 -0
- /package/hmr/{client → frameworks/vue/client}/vue-sfc-update-overlay.d.ts +0 -0
- /package/hmr/{client → frameworks/vue/client}/vue-sfc-update-overlay.js +0 -0
package/hmr/client/index.js
CHANGED
|
@@ -172,7 +172,6 @@ catch (err) {
|
|
|
172
172
|
// vitest, etc.) or when the user opted out via
|
|
173
173
|
// `__NS_HMR_PROGRESS_OVERLAY_ENABLED__ === false`.
|
|
174
174
|
import { applyHmrPendingFrame } from './hmr-pending-overlay.js';
|
|
175
|
-
import { driveVueSfcUpdateOverlay } from './vue-sfc-update-overlay.js';
|
|
176
175
|
function setHmrPendingOverlay(filePath) {
|
|
177
176
|
applyHmrPendingFrame(filePath, { getOverlay: getHmrOverlayApi });
|
|
178
177
|
}
|
|
@@ -217,19 +216,19 @@ function markHmrConnectionHealthy() {
|
|
|
217
216
|
hideConnectionOverlay();
|
|
218
217
|
}
|
|
219
218
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
219
|
+
let CLIENT_STRATEGY;
|
|
220
|
+
const CLIENT_STRATEGY_READY = TARGET_FLAVOR === 'vue' || TARGET_FLAVOR === 'angular'
|
|
221
|
+
? import(`../frameworks/${TARGET_FLAVOR}/client/strategy.js`)
|
|
222
|
+
.then((mod) => {
|
|
223
|
+
CLIENT_STRATEGY = mod && (mod[`${TARGET_FLAVOR}ClientStrategy`] ?? mod.default);
|
|
224
|
+
if (VERBOSE)
|
|
225
|
+
console.log('[hmr-client] client strategy loaded for flavor:', TARGET_FLAVOR);
|
|
226
|
+
CLIENT_STRATEGY?.install();
|
|
227
|
+
})
|
|
228
|
+
.catch((err) => {
|
|
229
|
+
console.warn('[hmr-client] failed to load client strategy for', TARGET_FLAVOR, err);
|
|
230
|
+
})
|
|
231
|
+
: Promise.resolve();
|
|
233
232
|
// Track whether we've mounted an initial app root yet in HTTP-only boot
|
|
234
233
|
let initialMounted = !!globalThis.__NS_HMR_BOOT_COMPLETE__;
|
|
235
234
|
// Prevent duplicate initial-mount scheduling across rapid full-graph broadcasts and re-evaluations
|
|
@@ -392,39 +391,7 @@ function applyFullGraph(payload) {
|
|
|
392
391
|
}
|
|
393
392
|
return;
|
|
394
393
|
}
|
|
395
|
-
|
|
396
|
-
switch (TARGET_FLAVOR) {
|
|
397
|
-
case 'vue': {
|
|
398
|
-
const appEntry = graph.get(APP_MAIN_ENTRY_SPEC);
|
|
399
|
-
if (appEntry && Array.isArray(appEntry.deps)) {
|
|
400
|
-
const vueDep = appEntry.deps.find((d) => typeof d === 'string' && /\.vue$/i.test(d));
|
|
401
|
-
if (vueDep)
|
|
402
|
-
candidate = vueDep;
|
|
403
|
-
}
|
|
404
|
-
if (!candidate) {
|
|
405
|
-
for (const id of graph.keys()) {
|
|
406
|
-
if (/\.vue$/i.test(id)) {
|
|
407
|
-
candidate = id;
|
|
408
|
-
break;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
// Fallback: when the module graph is empty (Vite 7+ may not populate it
|
|
413
|
-
// before the first full-graph broadcast), check the SFC artifact registry
|
|
414
|
-
// which is populated from the ns:vue-sfc-registry message.
|
|
415
|
-
if (!candidate && sfcArtifactMap.size > 0) {
|
|
416
|
-
for (const id of sfcArtifactMap.keys()) {
|
|
417
|
-
if (/\.vue$/i.test(id)) {
|
|
418
|
-
candidate = id;
|
|
419
|
-
if (VERBOSE)
|
|
420
|
-
console.log('[hmr][init] rescue candidate from SFC registry:', id);
|
|
421
|
-
break;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
break;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
394
|
+
const candidate = CLIENT_STRATEGY?.selectMountCandidate?.({ graph, appMainEntrySpec: APP_MAIN_ENTRY_SPEC }) ?? null;
|
|
428
395
|
if (!candidate)
|
|
429
396
|
return;
|
|
430
397
|
initialMounting = true;
|
|
@@ -435,10 +402,8 @@ function applyFullGraph(payload) {
|
|
|
435
402
|
(async () => {
|
|
436
403
|
try {
|
|
437
404
|
let comp = null;
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
comp = await loadSfcComponent(candidate, 'initial_mount_rescue');
|
|
441
|
-
break;
|
|
405
|
+
if (CLIENT_STRATEGY?.loadComponentForMount) {
|
|
406
|
+
comp = await CLIENT_STRATEGY.loadComponentForMount(candidate, 'initial_mount_rescue');
|
|
442
407
|
}
|
|
443
408
|
if (!comp)
|
|
444
409
|
return;
|
|
@@ -479,41 +444,11 @@ function applyFullGraph(payload) {
|
|
|
479
444
|
// Only allow initial mount when explicitly enabled. Rely on the app's own main entry start() for the first mount
|
|
480
445
|
// to avoid double-mount races that can cause duplicate navigation logs.
|
|
481
446
|
if (ALLOW_INITIAL_MOUNT && !initialMounted && !bootDone && !bootInProgress && !getCurrentApp() && !getRootFrame()) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
const appEntry = graph.get(APP_MAIN_ENTRY_SPEC);
|
|
486
|
-
if (appEntry && Array.isArray(appEntry.deps)) {
|
|
487
|
-
const vueDep = appEntry.deps.find((d) => typeof d === 'string' && /\.vue$/i.test(d));
|
|
488
|
-
if (vueDep)
|
|
489
|
-
candidate = vueDep;
|
|
490
|
-
}
|
|
491
|
-
if (!candidate) {
|
|
492
|
-
for (const id of graph.keys()) {
|
|
493
|
-
if (/\.vue$/i.test(id)) {
|
|
494
|
-
candidate = id;
|
|
495
|
-
break;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
// Fallback: SFC registry (same as rescue mount above)
|
|
500
|
-
if (!candidate && sfcArtifactMap.size > 0) {
|
|
501
|
-
for (const id of sfcArtifactMap.keys()) {
|
|
502
|
-
if (/\.vue$/i.test(id)) {
|
|
503
|
-
candidate = id;
|
|
504
|
-
if (VERBOSE)
|
|
505
|
-
console.log('[hmr][init] initial mount candidate from SFC registry:', id);
|
|
506
|
-
break;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
case 'typescript': {
|
|
513
|
-
// For TS flavor, do not perform client-driven initial mount; rely on Application.run.
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
447
|
+
if (TARGET_FLAVOR === 'typescript') {
|
|
448
|
+
// For TS flavor, do not perform client-driven initial mount; rely on Application.run.
|
|
449
|
+
return;
|
|
516
450
|
}
|
|
451
|
+
const candidate = CLIENT_STRATEGY?.selectMountCandidate?.({ graph, appMainEntrySpec: APP_MAIN_ENTRY_SPEC }) ?? null;
|
|
517
452
|
if (candidate) {
|
|
518
453
|
// Mark initial-mount in progress (both module-local and global) BEFORE scheduling async work
|
|
519
454
|
initialMounting = true;
|
|
@@ -558,21 +493,19 @@ function applyFullGraph(payload) {
|
|
|
558
493
|
}
|
|
559
494
|
catch { }
|
|
560
495
|
let comp = null;
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
}
|
|
575
|
-
break;
|
|
496
|
+
if (TARGET_FLAVOR === 'typescript') {
|
|
497
|
+
try {
|
|
498
|
+
const url = await requestModuleFromServer(candidate);
|
|
499
|
+
const mod = await import(/* @vite-ignore */ url);
|
|
500
|
+
comp = mod && (mod.default || mod);
|
|
501
|
+
}
|
|
502
|
+
catch (e) {
|
|
503
|
+
if (VERBOSE)
|
|
504
|
+
console.warn('[hmr][init] TS initial mount failed to import', candidate, e);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
else if (CLIENT_STRATEGY?.loadComponentForMount) {
|
|
508
|
+
comp = await CLIENT_STRATEGY.loadComponentForMount(candidate, 'initial_mount');
|
|
576
509
|
}
|
|
577
510
|
if (comp) {
|
|
578
511
|
const ok = await performResetRoot(comp);
|
|
@@ -633,11 +566,7 @@ function applyDelta(payload) {
|
|
|
633
566
|
setGraphVersion(payload.newVersion);
|
|
634
567
|
}
|
|
635
568
|
const changed = payload.changed || [];
|
|
636
|
-
|
|
637
|
-
case 'vue':
|
|
638
|
-
recordVuePayloadChanges(changed, getGraphVersion());
|
|
639
|
-
break;
|
|
640
|
-
}
|
|
569
|
+
CLIENT_STRATEGY?.recordPayloadChanges?.(changed, getGraphVersion());
|
|
641
570
|
(payload.changed || []).forEach((m) => {
|
|
642
571
|
if (!m || !m.id)
|
|
643
572
|
return;
|
|
@@ -723,11 +652,7 @@ function applyDelta(payload) {
|
|
|
723
652
|
// Deterministic navigation using the current Vue app instance rather than vendor-held rootApp
|
|
724
653
|
function __nsNavigateUsingApp(comp, opts = {}) {
|
|
725
654
|
const g = globalThis;
|
|
726
|
-
|
|
727
|
-
case 'vue':
|
|
728
|
-
ensureVueGlobals();
|
|
729
|
-
break;
|
|
730
|
-
}
|
|
655
|
+
CLIENT_STRATEGY?.beforeNavigateBuild?.();
|
|
731
656
|
const AppFactory = g.createApp;
|
|
732
657
|
const RootCtor = g.NSVRoot;
|
|
733
658
|
if (typeof AppFactory !== 'function' || typeof RootCtor !== 'function') {
|
|
@@ -757,11 +682,7 @@ function __nsNavigateUsingApp(comp, opts = {}) {
|
|
|
757
682
|
// at the destination as `[Vue warn]: Missing required prop` and any
|
|
758
683
|
// required-prop component would render with `undefined` bindings.
|
|
759
684
|
const app = AppFactory(normalizeComponent(comp, comp && (comp.__name || comp.name)), opts && opts.props);
|
|
760
|
-
|
|
761
|
-
case 'vue':
|
|
762
|
-
ensurePiniaOnApp(app);
|
|
763
|
-
break;
|
|
764
|
-
}
|
|
685
|
+
CLIENT_STRATEGY?.onNavAppCreated?.(app);
|
|
765
686
|
try {
|
|
766
687
|
const registry = g.__nsVendorRegistry;
|
|
767
688
|
const req = registry?.get ? g.__nsVendorRequire || g.__nsRequire || g.require : g.__nsRequire || g.require;
|
|
@@ -945,25 +866,7 @@ async function processQueue() {
|
|
|
945
866
|
// After evaluating the batch, perform flavor-specific UI refresh.
|
|
946
867
|
switch (TARGET_FLAVOR) {
|
|
947
868
|
case 'vue':
|
|
948
|
-
|
|
949
|
-
// (which drives its own overlay completion through
|
|
950
|
-
// `driveVueSfcUpdateOverlay`); nothing else to do
|
|
951
|
-
// for the view-tree refresh here.
|
|
952
|
-
//
|
|
953
|
-
// However, when a non-SFC file (e.g. a `.ts`
|
|
954
|
-
// utility module imported by an SFC) is the only
|
|
955
|
-
// changed entry, no `ns:vue-sfc-registry-update`
|
|
956
|
-
// will follow — and without an explicit 'complete'
|
|
957
|
-
// the overlay would stick on "Preparing update
|
|
958
|
-
// (5%)". Drive the closing frame here so the
|
|
959
|
-
// auto-hide timer can dismiss the toast in the
|
|
960
|
-
// pure-TS-change case. The detail surfaces the
|
|
961
|
-
// changed count so a user can correlate the
|
|
962
|
-
// overlay with the server-side `[hmr-ws][update]`
|
|
963
|
-
// log.
|
|
964
|
-
setUpdateOverlayStage('complete', {
|
|
965
|
-
detail: drained.length === 1 ? `Updated ${drained[0]} in ${Math.max(0, Date.now() - tQueueStart)}ms` : `Updated ${drained.length} modules in ${Math.max(0, Date.now() - tQueueStart)}ms`,
|
|
966
|
-
});
|
|
869
|
+
await CLIENT_STRATEGY?.refreshAfterBatch?.(drained, { setUpdateOverlayStage, startedAt: tQueueStart });
|
|
967
870
|
break;
|
|
968
871
|
case 'solid': {
|
|
969
872
|
// Boundaries discovered in this HMR cycle (tsx files reachable
|
|
@@ -1593,6 +1496,11 @@ async function handleHmrMessage(ev) {
|
|
|
1593
1496
|
setHmrPendingOverlay(msg.path);
|
|
1594
1497
|
return;
|
|
1595
1498
|
}
|
|
1499
|
+
// The per-flavor client strategy is loaded by a dynamic import(); make
|
|
1500
|
+
// sure it has resolved (and `install()` has run) before any handler that
|
|
1501
|
+
// delegates through it. After the first message this is an already-settled
|
|
1502
|
+
// promise (microtask only); for Solid/TypeScript it is `Promise.resolve()`.
|
|
1503
|
+
await CLIENT_STRATEGY_READY;
|
|
1596
1504
|
if (msg.type === 'ns:hmr-full-graph') {
|
|
1597
1505
|
// Bump a monotonic nonce so HTTP ESM imports can always be cache-busted per update.
|
|
1598
1506
|
try {
|
|
@@ -1844,7 +1752,7 @@ async function handleHmrMessage(ev) {
|
|
|
1844
1752
|
if (msg.type === 'ns:angular-update' && typeof msg.version === 'number') {
|
|
1845
1753
|
setGraphVersion(Number(msg.version || getGraphVersion() || 0));
|
|
1846
1754
|
}
|
|
1847
|
-
if (await
|
|
1755
|
+
if (CLIENT_STRATEGY?.handleHotUpdateMessage && (await CLIENT_STRATEGY.handleHotUpdateMessage(msg, { getCore, verbose: VERBOSE, performResetRoot, getOverlay: getHmrOverlayApi }))) {
|
|
1848
1756
|
return;
|
|
1849
1757
|
}
|
|
1850
1758
|
}
|
|
@@ -1908,28 +1816,17 @@ async function handleHmrMessage(ev) {
|
|
|
1908
1816
|
}
|
|
1909
1817
|
}
|
|
1910
1818
|
if (msg.type === 'ns:vue-sfc-registry') {
|
|
1911
|
-
|
|
1819
|
+
CLIENT_STRATEGY?.handleSfcRegistry?.(msg);
|
|
1912
1820
|
return;
|
|
1913
1821
|
}
|
|
1914
1822
|
if (msg.type === 'ns:vue-sfc-registry-update') {
|
|
1915
1823
|
if (typeof msg.version === 'number')
|
|
1916
1824
|
setGraphVersion(msg.version);
|
|
1917
|
-
// `ns:hmr-pending` already set the overlay to 'received' (5%).
|
|
1918
|
-
//
|
|
1919
|
-
//
|
|
1920
|
-
//
|
|
1921
|
-
|
|
1922
|
-
// and CSS drives inline above. `driveVueSfcUpdateOverlay` is a
|
|
1923
|
-
// thin orchestrator that walks 'evicting' → 'reimporting' →
|
|
1924
|
-
// 'rebooting' → 'complete' around the load + reset steps and
|
|
1925
|
-
// always lands on 'complete' (or a failure detail) so the
|
|
1926
|
-
// auto-hide timer can dismiss the toast.
|
|
1927
|
-
const sfcFilePath = typeof msg.path === 'string' ? msg.path : undefined;
|
|
1928
|
-
await driveVueSfcUpdateOverlay({
|
|
1929
|
-
filePath: sfcFilePath,
|
|
1930
|
-
loadComponent: () => handleVueSfcRegistryUpdate(msg, getGraphVersion()),
|
|
1931
|
-
applyComponent: (component) => performResetRoot(component),
|
|
1932
|
-
}, { getOverlay: getHmrOverlayApi });
|
|
1825
|
+
// `ns:hmr-pending` already set the overlay to 'received' (5%). The Vue
|
|
1826
|
+
// strategy walks 'evicting' → 'reimporting' → 'rebooting' → 'complete'
|
|
1827
|
+
// around the SFC load + reset so the toast always lands on 'complete'
|
|
1828
|
+
// (or a failure detail) and the auto-hide timer can dismiss it.
|
|
1829
|
+
await CLIENT_STRATEGY?.handleSfcRegistryUpdate?.(msg, getGraphVersion(), { getCore, verbose: VERBOSE, performResetRoot, getOverlay: getHmrOverlayApi });
|
|
1933
1830
|
return;
|
|
1934
1831
|
}
|
|
1935
1832
|
}
|
|
@@ -1949,7 +1846,7 @@ function normalizeComponent(input, nameHint) {
|
|
|
1949
1846
|
}
|
|
1950
1847
|
// If provided a render function, wrap with defineComponent
|
|
1951
1848
|
if (typeof input === 'function') {
|
|
1952
|
-
|
|
1849
|
+
CLIENT_STRATEGY?.beforeNavigateBuild?.();
|
|
1953
1850
|
const comp = globalThis.defineComponent
|
|
1954
1851
|
? globalThis.defineComponent({
|
|
1955
1852
|
name: nameHint || input.name || 'AnonymousSFC',
|
|
@@ -1960,7 +1857,7 @@ function normalizeComponent(input, nameHint) {
|
|
|
1960
1857
|
}
|
|
1961
1858
|
// If object has a render function property
|
|
1962
1859
|
if (input?.render && typeof input.render === 'function') {
|
|
1963
|
-
|
|
1860
|
+
CLIENT_STRATEGY?.beforeNavigateBuild?.();
|
|
1964
1861
|
const comp = globalThis.defineComponent
|
|
1965
1862
|
? globalThis.defineComponent({
|
|
1966
1863
|
name: nameHint || input.name || 'AnonymousSFC',
|
|
@@ -2018,35 +1915,32 @@ async function performResetRoot(newComponent) {
|
|
|
2018
1915
|
if (cachedRoot)
|
|
2019
1916
|
return cachedRoot;
|
|
2020
1917
|
try {
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
root = newComponent();
|
|
2031
|
-
}
|
|
2032
|
-
else {
|
|
2033
|
-
root = newComponent;
|
|
2034
|
-
}
|
|
1918
|
+
if (CLIENT_STRATEGY?.createRoot) {
|
|
1919
|
+
cachedRoot = CLIENT_STRATEGY.createRoot(newComponent, state);
|
|
1920
|
+
}
|
|
1921
|
+
else if (TARGET_FLAVOR === 'typescript') {
|
|
1922
|
+
// For TS flavor, treat the component as a factory or direct NS view.
|
|
1923
|
+
let root = null;
|
|
1924
|
+
try {
|
|
1925
|
+
if (typeof newComponent === 'function') {
|
|
1926
|
+
root = newComponent();
|
|
2035
1927
|
}
|
|
2036
|
-
|
|
2037
|
-
|
|
1928
|
+
else {
|
|
1929
|
+
root = newComponent;
|
|
2038
1930
|
}
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
1931
|
+
}
|
|
1932
|
+
catch (e) {
|
|
1933
|
+
console.warn('[hmr-client][ts] root factory invocation failed', e);
|
|
1934
|
+
}
|
|
1935
|
+
cachedRoot = root || {};
|
|
1936
|
+
// Heuristic: if the root "looks" like a Frame, prefer frame semantics
|
|
1937
|
+
try {
|
|
1938
|
+
const name = String(cachedRoot?.constructor?.name || '').replace(/^_+/, '');
|
|
1939
|
+
if (/^Frame(\$\d+)?$/.test(name)) {
|
|
1940
|
+
rootKind = 'frame';
|
|
2046
1941
|
}
|
|
2047
|
-
catch { }
|
|
2048
|
-
break;
|
|
2049
1942
|
}
|
|
1943
|
+
catch { }
|
|
2050
1944
|
}
|
|
2051
1945
|
return cachedRoot;
|
|
2052
1946
|
}
|
|
@@ -2197,7 +2091,7 @@ async function performResetRoot(newComponent) {
|
|
|
2197
2091
|
// page to the Frame — the screen keeps showing the previous render. resetRootView with a
|
|
2198
2092
|
// fresh Frame correctly reparents the Page and is the proven path that produces visible
|
|
2199
2093
|
// in-place updates for SFC HMR cycles. Non-Vue flavors keep the legacy navigate fast path.
|
|
2200
|
-
const allowNavigateFastPath =
|
|
2094
|
+
const allowNavigateFastPath = CLIENT_STRATEGY?.allowNavigateFastPath ?? true;
|
|
2201
2095
|
if (allowNavigateFastPath && !hadPlaceholder && !isFrameRoot && isAuthoritativeFrame && typeof existingAppFrame.navigate === 'function') {
|
|
2202
2096
|
try {
|
|
2203
2097
|
const navEntry = {
|
|
@@ -2361,12 +2255,9 @@ export function initHmrClient(opts) {
|
|
|
2361
2255
|
console.log('[hmr-client] deferring WebSocket connection until boot completes');
|
|
2362
2256
|
setTimeout(waitForBoot, 100);
|
|
2363
2257
|
}
|
|
2364
|
-
// Best-effort: install back wrapper even before first remount; original root may be captured later
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
ensureBackWrapperInstalled(performResetRoot, getCore);
|
|
2368
|
-
break;
|
|
2369
|
-
}
|
|
2258
|
+
// Best-effort: install back wrapper even before first remount; original root may be captured later.
|
|
2259
|
+
// Deferred until the dynamically-imported strategy resolves.
|
|
2260
|
+
void CLIENT_STRATEGY_READY.then(() => CLIENT_STRATEGY?.installBackWrapper?.(performResetRoot, getCore));
|
|
2370
2261
|
}
|
|
2371
2262
|
export default function startViteHMR(opts) {
|
|
2372
2263
|
if (VERBOSE)
|