diff --git a/lib/services/ios-debug-service.ts b/lib/services/ios-debug-service.ts index a7adaf468e..08bed47627 100644 --- a/lib/services/ios-debug-service.ts +++ b/lib/services/ios-debug-service.ts @@ -160,7 +160,7 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS private async deviceDebugBrk(debugData: IDebugData, debugOptions: IDebugOptions): Promise { await this.$devicesService.initialize({ platform: this.platform, deviceId: debugData.deviceIdentifier }); - const action = async (device: iOSDevice.IOSDevice) => { + const action = async (device: iOSDevice.IOSDevice): Promise => { if (device.isEmulator) { return await this.emulatorDebugBrk(debugData, debugOptions); } @@ -170,14 +170,13 @@ export class IOSDebugService extends DebugServiceBase implements IPlatformDebugS emulator: debugOptions.emulator, justlaunch: debugOptions.justlaunch }; - // we intentionally do not wait on this here, because if we did, we'd miss the AppLaunching notification - const startApplicationAction = this.$platformService.startApplication(this.platform, runOptions, debugData.applicationIdentifier); - const result = await this.debugBrkCore(device, debugData, debugOptions); + const promisesResults = await Promise.all([ + this.$platformService.startApplication(this.platform, runOptions, debugData.applicationIdentifier), + this.debugBrkCore(device, debugData, debugOptions) + ]); - await startApplicationAction; - - return result; + return _.last(promisesResults); }; const deviceActionResult = await this.$devicesService.execute(action, this.getCanExecuteAction(debugData.deviceIdentifier)); diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 941f396f07..8a91a15b84 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -4,7 +4,9 @@ import { EOL } from "os"; import { EventEmitter } from "events"; import { hook } from "../../common/helpers"; import { APP_FOLDER_NAME, PACKAGE_JSON_FILE_NAME, LiveSyncTrackActionNames, USER_INTERACTION_NEEDED_EVENT_NAME, DEBUGGER_ATTACHED_EVENT_NAME, DEBUGGER_DETACHED_EVENT_NAME, TrackActionNames } from "../../constants"; -import { FileExtensions, DeviceTypes } from "../../common/constants"; +import { FileExtensions, DeviceTypes, DeviceDiscoveryEventNames } from "../../common/constants"; +import { cache } from "../../common/decorators"; + const deviceDescriptorPrimaryKey = "identifier"; const LiveSyncEvents = { @@ -473,6 +475,8 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi // Execute the action only on the deviceDescriptors passed to initialSync. // In case where we add deviceDescriptors to already running application, we've already executed initialSync for them. await this.addActionToChain(projectData.projectDir, () => this.$devicesService.execute(deviceAction, (device: Mobile.IDevice) => _.some(deviceDescriptors, deviceDescriptor => deviceDescriptor.identifier === device.deviceInfo.identifier))); + + this.attachDeviceLostHandler(); } private getDefaultLatestAppPackageInstalledSettings(): ILatestAppPackageInstalledSettings { @@ -632,13 +636,24 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi this.stopLiveSync(projectDir); }); }); - - this.$devicesService.on("deviceLost", async (device: Mobile.IDevice) => { - await this.stopLiveSync(projectData.projectDir, [device.deviceInfo.identifier]); - }); } } + @cache() + private attachDeviceLostHandler(): void { + this.$devicesService.on(DeviceDiscoveryEventNames.DEVICE_LOST, async (device: Mobile.IDevice) => { + this.$logger.trace(`Received ${DeviceDiscoveryEventNames.DEVICE_LOST} event in LiveSync service for ${device.deviceInfo.identifier}. Will stop LiveSync operation for this device.`); + + for (const projectDir in this.liveSyncProcessesInfo) { + try { + await this.stopLiveSync(projectDir, [device.deviceInfo.identifier]); + } catch (err) { + this.$logger.warn(`Unable to stop LiveSync operation for ${device.deviceInfo.identifier}.`, err); + } + } + }); + } + private async addActionToChain(projectDir: string, action: () => Promise): Promise { const liveSyncInfo = this.liveSyncProcessesInfo[projectDir]; if (liveSyncInfo) { diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index 268c2c2095..22895ae564 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -587,6 +587,11 @@ export class PlatformService extends EventEmitter implements IPlatformService { await this.trackActionForPlatform({ action: constants.TrackActionNames.Deploy, platform: device.deviceInfo.platform, isForDevice: !device.isEmulator, deviceOsVersion: device.deviceInfo.version }); }; + if (deployOptions.device) { + const device = await this.$devicesService.getDevice(deployOptions.device); + deployOptions.device = device.deviceInfo.identifier; + } + await this.$devicesService.execute(action, this.getCanExecuteAction(platform, deployOptions)); } @@ -599,6 +604,12 @@ export class PlatformService extends EventEmitter implements IPlatformService { }; await this.$devicesService.initialize({ platform: platform, deviceId: runOptions.device }); + + if (runOptions.device) { + const device = await this.$devicesService.getDevice(runOptions.device); + runOptions.device = device.deviceInfo.identifier; + } + await this.$devicesService.execute(action, this.getCanExecuteAction(platform, runOptions)); } @@ -715,10 +726,7 @@ export class PlatformService extends EventEmitter implements IPlatformService { private getCanExecuteAction(platform: string, options: IDeviceEmulator): any { const canExecute = (currentDevice: Mobile.IDevice): boolean => { if (options.device && currentDevice && currentDevice.deviceInfo) { - const device = this.$devicesService.getDeviceByDeviceOption(); - if (device && device.deviceInfo) { - return currentDevice.deviceInfo.identifier === device.deviceInfo.identifier; - } + return currentDevice.deviceInfo.identifier === options.device; } if (this.$mobileHelper.isiOSPlatform(platform) && this.$hostInfo.isDarwin) { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 86732bf537..ac17b802aa 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -83,7 +83,7 @@ "@types/universal-analytics": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/universal-analytics/-/universal-analytics-0.4.1.tgz", - "integrity": "sha512-AZSPpDUEZ4mAgO9geHc62dp/xCLmBJ1yIpbgTq5W/cWcVQsxmU/FyKwYKHXk2hnT9TAmYVFFdAijMrCdYjuHsA==", + "integrity": "sha1-7mESGwqJiwvqXuskcgCJjg+o8Jw=", "dev": true }, "abbrev": { @@ -2945,9 +2945,9 @@ } }, "ios-sim-portable": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/ios-sim-portable/-/ios-sim-portable-3.1.1.tgz", - "integrity": "sha1-AmL3x3N6ZnfyAI48rem2KMEIN6c=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/ios-sim-portable/-/ios-sim-portable-3.1.2.tgz", + "integrity": "sha1-Fq6f+F2gUE0K+4gyj73sCQafFG0=", "requires": { "bplist-parser": "https://github.com/telerik/node-bplist-parser/tarball/master", "colors": "0.6.2", @@ -5186,7 +5186,7 @@ "universal-analytics": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.15.tgz", - "integrity": "sha512-9Dt6WBWsHsmv74G+N/rmEgi6KFZxVvQXkVhr0disegeUryybQAUQwMD1l5EtqaOu+hSOGbhL/hPPQYisZIqPRw==", + "integrity": "sha1-SrxhsVn/52W+FE4Ht7c54O57iKs=", "requires": { "async": "1.2.1", "request": "2.81.0", diff --git a/package.json b/package.json index ec9320ba40..9de808b468 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "inquirer": "0.9.0", "ios-device-lib": "0.4.9", "ios-mobileprovision-finder": "1.0.10", - "ios-sim-portable": "3.1.1", + "ios-sim-portable": "3.1.2", "lockfile": "1.0.3", "lodash": "4.13.1", "log4js": "1.0.1",