Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions lib/common/mobile/windows/windows-application-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { IBuildData } from "../../../definitions/build";
export const WINDOWS_INSPECTOR_MARKER = "ns-inspector";
export const WINDOWS_DEBUGBREAK_MARKER = "ns-debugbreak";
export const WINDOWS_DEBUGGER_STARTED_MARKER = "ns-debugger-started";
// Written by a running debug host that watches for WINDOWS_LIVESYNC_MARKER.
export const WINDOWS_LIVESYNC_READY_MARKER = "ns-livesync-ready";
export const WINDOWS_LIVESYNC_MARKER = "ns-livesync";

export class WindowsApplicationManager extends ApplicationManagerBase {
private _runningPid: number | null = null;
Expand Down Expand Up @@ -373,6 +376,28 @@ export class WindowsApplicationManager extends ApplicationManagerBase {
return this._localStatePath(pfn, fileName);
}

/**
* Asks the running app to apply the files just synced into bin\app: the debug host watches
* LocalState for the marker and calls global.__onLiveSync(), which runs webpack's hot update.
* Returns false when the app's host does not watch for it (EXE targets, older runtimes).
*/
public async signalLiveSync(appId: string): Promise<boolean> {
const pfn = await this._resolvePackageFamilyName(appId);
const readyPath = this._localStatePath(pfn, WINDOWS_LIVESYNC_READY_MARKER);
const markerPath = this._localStatePath(pfn, WINDOWS_LIVESYNC_MARKER);
if (!readyPath || !markerPath || !fs.existsSync(readyPath)) {
return false;
}
try {
// New content on every sync, so a marker the host has not consumed yet still changes.
fs.writeFileSync(markerPath, String(Date.now()), "utf8");
return true;
} catch (e) {
this.$logger.trace(`[Windows] Could not write ${WINDOWS_LIVESYNC_MARKER} marker: ${e}`);
return false;
}
}

private _localStatePath(pfn: string, fileName: string): string | null {
const localAppData = process.env.LOCALAPPDATA;
if (!localAppData) return null;
Expand Down
33 changes: 24 additions & 9 deletions lib/services/livesync/windows-device-livesync-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { spawnSync } from "child_process";
import { DeviceLiveSyncServiceBase } from "./device-livesync-service-base";
import { IPlatformsDataService } from "../../definitions/platform";
import { IProjectData } from "../../definitions/project";
import { WindowsApplicationManager } from "../../common/mobile/windows/windows-application-manager";

export class WindowsDeviceLiveSyncService
extends DeviceLiveSyncServiceBase
Expand Down Expand Up @@ -40,22 +41,36 @@ export class WindowsDeviceLiveSyncService
_projectData: IProjectData,
liveSyncInfo: ILiveSyncResultInfo,
): Promise<boolean> {
return !liveSyncInfo.useHotModuleReload || !!liveSyncInfo.waitForDebugger;
// A full sync (also the CLI's recovery after a failed hot update) needs a fresh start.
return (
!liveSyncInfo.useHotModuleReload ||
!!liveSyncInfo.isFullSync ||
!!liveSyncInfo.waitForDebugger
);
}

public async tryRefreshApplication(
projectData: IProjectData,
liveSyncInfo: ILiveSyncResultInfo,
): Promise<boolean> {
// Vite HMR: a running app pulls every change from the dev server over its WebSocket
// (HTTP ES modules), so a synced file never needs a restart. But an app that isn't
// running yet (first sync after install) must still be launched. Webpack HMR isn't
// implemented for Windows: signal a restart.
// An app that isn't running yet (first sync after install) must still be launched.
if (
!liveSyncInfo.useHotModuleReload ||
!this.isAppRunning(projectData.projectName)
) {
return false;
}
// Vite HMR: the app pulls every change from the dev server over its WebSocket
// (HTTP ES modules), so a synced file never needs a restart.
if (projectData.bundler === "vite") {
return true;
}
// Webpack HMR: the hot-update files are already in bin\app; tell the app to apply them.
const appId =
projectData.projectIdentifiers?.["windows"] ?? projectData.projectId;
return (
projectData.bundler === "vite" &&
!!liveSyncInfo.useHotModuleReload &&
this.isAppRunning(projectData.projectName)
);
this.device.applicationManager as WindowsApplicationManager
).signalLiveSync(appId);
}

private isAppRunning(processName: string): boolean {
Expand Down
Loading