Skip to content

Commit e3bacd5

Browse files
author
Dimitar Tachev
authored
Merge pull request #4917 from NativeScript/tachev/fix-fast-livesync
fix: avoid getting crashed LiveSync when the fast sync fails
2 parents 5ebd184 + 196cd3c commit e3bacd5

File tree

4 files changed

+51
-19
lines changed

4 files changed

+51
-19
lines changed

lib/commands/test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
abstract class TestCommandBase {
22
public allowedParameters: ICommandParameter[] = [];
3+
public dashedOptions = {
4+
hmr: { type: OptionType.Boolean, default: false, hasSensitiveValue: false },
5+
};
6+
37
protected abstract platform: string;
48
protected abstract $projectData: IProjectData;
59
protected abstract $testExecutionService: ITestExecutionService;
@@ -50,6 +54,13 @@ abstract class TestCommandBase {
5054

5155
async canExecute(args: string[]): Promise<boolean | ICanExecuteCommandOutput> {
5256
if (!this.$options.force) {
57+
if (this.$options.hmr) {
58+
// With HMR we are not restarting after LiveSync which is causing a 30 seconds app start on Android
59+
// because the Runtime does not watch for the `/data/local/tmp<appId>-livesync-in-progress` file deletion.
60+
// The App is closing itself after each test execution and the bug will be reproducible on each LiveSync.
61+
this.$errors.fail("The `--hmr` option is not supported for this command.");
62+
}
63+
5364
await this.$migrateController.validate({ projectDir: this.$projectData.projectDir, platforms: [this.platform] });
5465
}
5566

lib/controllers/run-controller.ts

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { HmrConstants, DeviceDiscoveryEventNames } from "../common/constants";
22
import { PREPARE_READY_EVENT_NAME, TrackActionNames, DEBUGGER_DETACHED_EVENT_NAME, RunOnDeviceEvents, USER_INTERACTION_NEEDED_EVENT_NAME } from "../constants";
33
import { cache, performanceLog } from "../common/decorators";
44
import { EventEmitter } from "events";
5+
import * as util from "util";
56

67
export class RunController extends EventEmitter implements IRunController {
78
private prepareReadyEventHandler: any = null;
@@ -270,7 +271,7 @@ export class RunController extends EventEmitter implements IRunController {
270271
}
271272

272273
private async syncInitialDataOnDevices(projectData: IProjectData, liveSyncInfo: ILiveSyncInfo, deviceDescriptors: ILiveSyncDeviceDescriptor[]): Promise<void> {
273-
const rebuiltInformation: IDictionary<{ packageFilePath: string, platform: string, isEmulator: boolean }> = { };
274+
const rebuiltInformation: IDictionary<{ packageFilePath: string, platform: string, isEmulator: boolean }> = {};
274275

275276
const deviceAction = async (device: Mobile.IDevice) => {
276277
const deviceDescriptor = _.find(deviceDescriptors, dd => dd.identifier === device.deviceInfo.identifier);
@@ -333,15 +334,16 @@ export class RunController extends EventEmitter implements IRunController {
333334
error: err,
334335
});
335336

336-
await this.stop({ projectDir: projectData.projectDir, deviceIdentifiers: [device.deviceInfo.identifier], stopOptions: { shouldAwaitAllActions: false }});
337+
await this.stop({ projectDir: projectData.projectDir, deviceIdentifiers: [device.deviceInfo.identifier], stopOptions: { shouldAwaitAllActions: false } });
337338
}
338339
};
339340

340341
await this.addActionToChain(projectData.projectDir, () => this.$devicesService.execute(deviceAction, (device: Mobile.IDevice) => _.some(deviceDescriptors, deviceDescriptor => deviceDescriptor.identifier === device.deviceInfo.identifier)));
341342
}
342343

343344
private async syncChangedDataOnDevices(data: IFilesChangeEventData, projectData: IProjectData, liveSyncInfo: ILiveSyncInfo): Promise<void> {
344-
const rebuiltInformation: IDictionary<{ packageFilePath: string, platform: string, isEmulator: boolean }> = { };
345+
const successfullySyncedMessageFormat = `Successfully synced application %s on device %s.`;
346+
const rebuiltInformation: IDictionary<{ packageFilePath: string, platform: string, isEmulator: boolean }> = {};
345347

346348
const deviceAction = async (device: Mobile.IDevice) => {
347349
const deviceDescriptors = this.$liveSyncProcessDataService.getDeviceDescriptors(projectData.projectDir);
@@ -380,28 +382,47 @@ export class RunController extends EventEmitter implements IRunController {
380382
await this.$deviceInstallAppService.installOnDevice(device, deviceDescriptor.buildData, rebuiltInformation[platformData.platformNameLowerCase].packageFilePath);
381383
await platformLiveSyncService.syncAfterInstall(device, watchInfo);
382384
await this.refreshApplication(projectData, { deviceAppData, modifiedFilesData: [], isFullSync: false, useHotModuleReload: liveSyncInfo.useHotModuleReload }, data, deviceDescriptor);
385+
this.$logger.info(util.format(successfullySyncedMessageFormat, deviceAppData.appIdentifier, device.deviceInfo.identifier));
383386
} else {
384387
const isInHMRMode = liveSyncInfo.useHotModuleReload && data.hmrData && data.hmrData.hash;
385388
if (isInHMRMode) {
386389
this.$hmrStatusService.watchHmrStatus(device.deviceInfo.identifier, data.hmrData.hash);
387390
}
388391

389-
let liveSyncResultInfo = await platformLiveSyncService.liveSyncWatchAction(device, watchInfo);
390-
await this.refreshApplication(projectData, liveSyncResultInfo, data, deviceDescriptor);
391-
392-
if (!liveSyncResultInfo.didRecover && isInHMRMode) {
393-
const status = await this.$hmrStatusService.getHmrStatus(device.deviceInfo.identifier, data.hmrData.hash);
394-
if (status === HmrConstants.HMR_ERROR_STATUS) {
395-
watchInfo.filesToSync = data.hmrData.fallbackFiles;
396-
liveSyncResultInfo = await platformLiveSyncService.liveSyncWatchAction(device, watchInfo);
397-
// We want to force a restart of the application.
398-
liveSyncResultInfo.isFullSync = true;
399-
await this.refreshApplication(projectData, liveSyncResultInfo, data, deviceDescriptor);
392+
const watchAction = async (): Promise<void> => {
393+
let liveSyncResultInfo = await platformLiveSyncService.liveSyncWatchAction(device, watchInfo);
394+
await this.refreshApplication(projectData, liveSyncResultInfo, data, deviceDescriptor);
395+
396+
if (!liveSyncResultInfo.didRecover && isInHMRMode) {
397+
const status = await this.$hmrStatusService.getHmrStatus(device.deviceInfo.identifier, data.hmrData.hash);
398+
if (status === HmrConstants.HMR_ERROR_STATUS) {
399+
watchInfo.filesToSync = data.hmrData.fallbackFiles;
400+
liveSyncResultInfo = await platformLiveSyncService.liveSyncWatchAction(device, watchInfo);
401+
// We want to force a restart of the application.
402+
liveSyncResultInfo.isFullSync = true;
403+
await this.refreshApplication(projectData, liveSyncResultInfo, data, deviceDescriptor);
404+
}
405+
}
406+
407+
this.$logger.info(util.format(successfullySyncedMessageFormat, deviceAppData.appIdentifier, device.deviceInfo.identifier));
408+
};
409+
410+
if (liveSyncInfo.useHotModuleReload) {
411+
try {
412+
this.$logger.trace("Try executing watch action without any preparation of files.");
413+
await watchAction();
414+
this.$logger.trace("Successfully executed watch action without any preparation of files.");
415+
return;
416+
} catch (err) {
417+
this.$logger.trace(`Error while trying to execute fast sync. Now we'll check the state of the app and we'll try to resurrect from the error. The error is: ${err}`);
400418
}
401419
}
420+
421+
await this.$deviceInstallAppService.installOnDeviceIfNeeded(device, deviceDescriptor.buildData);
422+
watchInfo.connectTimeout = null;
423+
await watchAction();
402424
}
403425

404-
this.$logger.info(`Successfully synced application ${deviceAppData.appIdentifier} on device ${device.deviceInfo.identifier}.`);
405426
} catch (err) {
406427
this.$logger.warn(`Unable to apply changes for device: ${device.deviceInfo.identifier}. Error is: ${err && err.message}.`);
407428

npm-shrinkwrap.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "nativescript",
33
"preferGlobal": true,
4-
"version": "6.0.2",
4+
"version": "6.0.3",
55
"author": "Telerik <[email protected]>",
66
"description": "Command-line interface for building NativeScript projects",
77
"bin": {
@@ -139,4 +139,4 @@
139139
"engines": {
140140
"node": ">=10.0.0 <13.0.0"
141141
}
142-
}
142+
}

0 commit comments

Comments
 (0)