diff --git a/lib/controllers/prepare-controller.ts b/lib/controllers/prepare-controller.ts index 8361c686c0..9d6a85195d 100644 --- a/lib/controllers/prepare-controller.ts +++ b/lib/controllers/prepare-controller.ts @@ -14,6 +14,7 @@ export class PrepareController extends EventEmitter { private watchersData: IDictionary> = {}; private isInitialPrepareReady = false; private persistedData: IFilesChangeEventData[] = []; + private webpackCompilerHandler: any = null; constructor( private $platformController: IPlatformController, @@ -46,7 +47,8 @@ export class PrepareController extends EventEmitter { } if (this.watchersData && this.watchersData[projectDir] && this.watchersData[projectDir][platformLowerCase] && this.watchersData[projectDir][platformLowerCase].hasWebpackCompilerProcess) { - await this.$webpackCompilerService.stopWebpackCompiler(platform); + await this.$webpackCompilerService.stopWebpackCompiler(platformLowerCase); + this.$webpackCompilerService.removeListener(WEBPACK_COMPILATION_COMPLETE, this.webpackCompilerHandler); this.watchersData[projectDir][platformLowerCase].hasWebpackCompilerProcess = false; } } @@ -110,11 +112,14 @@ export class PrepareController extends EventEmitter { private async startJSWatcherWithPrepare(platformData: IPlatformData, projectData: IProjectData, prepareData: IPrepareData): Promise { if (!this.watchersData[projectData.projectDir][platformData.platformNameLowerCase].hasWebpackCompilerProcess) { - this.$webpackCompilerService.on(WEBPACK_COMPILATION_COMPLETE, data => { + const handler = (data: any) => { if (data.platform.toLowerCase() === platformData.platformNameLowerCase) { this.emitPrepareEvent({ ...data, hasNativeChanges: false }); } - }); + }; + + this.webpackCompilerHandler = handler.bind(this); + this.$webpackCompilerService.on(WEBPACK_COMPILATION_COMPLETE, this.webpackCompilerHandler); this.watchersData[projectData.projectDir][platformData.platformNameLowerCase].hasWebpackCompilerProcess = true; await this.$webpackCompilerService.compileWithWatch(platformData, projectData, prepareData); diff --git a/lib/controllers/preview-app-controller.ts b/lib/controllers/preview-app-controller.ts index 9634718d99..b53ca164e3 100644 --- a/lib/controllers/preview-app-controller.ts +++ b/lib/controllers/preview-app-controller.ts @@ -15,6 +15,7 @@ export class PreviewAppController extends EventEmitter implements IPreviewAppCon constructor( private $analyticsService: IAnalyticsService, + private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, private $errors: IErrors, private $hmrStatusService: IHmrStatusService, private $logger: ILogger, @@ -39,11 +40,15 @@ export class PreviewAppController extends EventEmitter implements IPreviewAppCon return result; } - public async stopPreview(): Promise { + public async stopPreview(data: IProjectDir): Promise { this.$previewSdkService.stop(); this.$previewDevicesService.updateConnectedDevices([]); + + await this.$prepareController.stopWatchers(data.projectDir, this.$devicePlatformsConstants.Android); + await this.$prepareController.stopWatchers(data.projectDir, this.$devicePlatformsConstants.iOS); + if (this.prepareReadyEventHandler) { - this.removeListener(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); + this.$prepareController.removeListener(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); this.prepareReadyEventHandler = null; } } @@ -83,10 +88,12 @@ export class PreviewAppController extends EventEmitter implements IPreviewAppCon await this.$previewAppPluginsService.comparePluginsOnDevice(data, device); if (!this.prepareReadyEventHandler) { - this.prepareReadyEventHandler = async (currentPrepareData: IFilesChangeEventData) => { + const handler = async (currentPrepareData: IFilesChangeEventData) => { await this.handlePrepareReadyEvent(data, currentPrepareData); }; - this.$prepareController.on(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler.bind(this)); + + this.prepareReadyEventHandler = handler.bind(this); + this.$prepareController.on(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); } data.env = data.env || {}; diff --git a/lib/controllers/run-controller.ts b/lib/controllers/run-controller.ts index e4a0c637d2..d6cc35912e 100644 --- a/lib/controllers/run-controller.ts +++ b/lib/controllers/run-controller.ts @@ -51,7 +51,7 @@ export class RunController extends EventEmitter implements IRunController { } if (!this.prepareReadyEventHandler) { - this.prepareReadyEventHandler = async (data: IFilesChangeEventData) => { + const handler = async (data: IFilesChangeEventData) => { if (data.hasNativeChanges) { const platformData = this.$platformsDataService.getPlatformData(data.platform, projectData); const prepareData = this.$prepareDataService.getPrepareData(liveSyncInfo.projectDir, data.platform, { ...liveSyncInfo, watch: !liveSyncInfo.skipWatcher }); @@ -63,7 +63,9 @@ export class RunController extends EventEmitter implements IRunController { await this.syncChangedDataOnDevices(data, projectData, liveSyncInfo); } }; - this.$prepareController.on(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler.bind(this)); + + this.prepareReadyEventHandler = handler.bind(this); + this.$prepareController.on(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); } await this.syncInitialDataOnDevices(projectData, liveSyncInfo, deviceDescriptorsForInitialSync); @@ -113,7 +115,7 @@ export class RunController extends EventEmitter implements IRunController { liveSyncProcessInfo.deviceDescriptors = []; if (this.prepareReadyEventHandler) { - this.removeListener(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); + this.$prepareController.removeListener(PREPARE_READY_EVENT_NAME, this.prepareReadyEventHandler); this.prepareReadyEventHandler = null; } @@ -377,7 +379,7 @@ export class RunController extends EventEmitter implements IRunController { await this.$deviceInstallAppService.installOnDevice(device, deviceDescriptor.buildData, rebuiltInformation[platformData.platformNameLowerCase].packageFilePath); await platformLiveSyncService.syncAfterInstall(device, watchInfo); - await platformLiveSyncService.restartApplication(projectData, { deviceAppData, modifiedFilesData: [], isFullSync: false, useHotModuleReload: liveSyncInfo.useHotModuleReload }); + await this.refreshApplication(projectData, { deviceAppData, modifiedFilesData: [], isFullSync: false, useHotModuleReload: liveSyncInfo.useHotModuleReload }, data, deviceDescriptor); } else { const isInHMRMode = liveSyncInfo.useHotModuleReload && data.hmrData && data.hmrData.hash; if (isInHMRMode) { diff --git a/lib/definitions/preview-app-livesync.d.ts b/lib/definitions/preview-app-livesync.d.ts index 414b4cffe7..6c8f125aed 100644 --- a/lib/definitions/preview-app-livesync.d.ts +++ b/lib/definitions/preview-app-livesync.d.ts @@ -77,6 +77,6 @@ declare global { interface IPreviewAppController { startPreview(data: IPreviewAppLiveSyncData): Promise; - stopPreview(): Promise; + stopPreview(data: IProjectDir): Promise; } } \ No newline at end of file diff --git a/lib/services/webpack/webpack-compiler-service.ts b/lib/services/webpack/webpack-compiler-service.ts index e0af115380..6a6fbcb94a 100644 --- a/lib/services/webpack/webpack-compiler-service.ts +++ b/lib/services/webpack/webpack-compiler-service.ts @@ -72,6 +72,7 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp childProcess.on("error", (err) => { this.$logger.trace(`Unable to start webpack process in watch mode. Error is: ${err}`); + delete this.webpackProcesses[platformData.platformNameLowerCase]; reject(err); }); @@ -82,6 +83,7 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp this.$logger.trace(`Webpack process exited with code ${exitCode} when we expected it to be long living with watch.`); const error = new Error(`Executing webpack failed with exit code ${exitCode}.`); error.code = exitCode; + delete this.webpackProcesses[platformData.platformNameLowerCase]; reject(error); }); }); @@ -97,12 +99,14 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp const childProcess = await this.startWebpackProcess(platformData, projectData, prepareData); childProcess.on("error", (err) => { this.$logger.trace(`Unable to start webpack process in non-watch mode. Error is: ${err}`); + delete this.webpackProcesses[platformData.platformNameLowerCase]; reject(err); }); childProcess.on("close", async (arg: any) => { await this.$cleanupService.removeKillProcess(childProcess.pid.toString()); + delete this.webpackProcesses[platformData.platformNameLowerCase]; const exitCode = typeof arg === "number" ? arg : arg && arg.code; if (exitCode === 0) { resolve(); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index fa4d54cd5c..2aeebbccc8 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "nativescript", - "version": "6.0.1", + "version": "6.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 63c06551b4..468664b837 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nativescript", "preferGlobal": true, - "version": "6.0.1", + "version": "6.0.2", "author": "Telerik ", "description": "Command-line interface for building NativeScript projects", "bin": { diff --git a/test/controllers/run-controller.ts b/test/controllers/run-controller.ts index e33fbc4688..6b0c200278 100644 --- a/test/controllers/run-controller.ts +++ b/test/controllers/run-controller.ts @@ -96,7 +96,8 @@ function createTestInjector() { prepareData = currentPrepareData; return { platform: prepareData.platform, hasNativeChanges: false }; }, - on: () => ({}) + on: () => ({}), + removeListener: (): void => undefined }); injector.register("prepareNativePlatformService", {}); injector.register("projectChangesService", {});