From 1d7279888fe2aa06a97dd3b5457a579487e31952 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 22 Sep 2016 16:29:46 +0200 Subject: [PATCH 1/6] save participants do not run on shutdown --- src/vs/platform/lifecycle/common/lifecycle.ts | 7 +++++++ src/vs/test/utils/servicesTestUtils.ts | 2 ++ .../parts/files/common/editors/textFileEditorModel.ts | 6 +++++- .../lifecycle/electron-browser/lifecycleService.ts | 10 ++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/lifecycle/common/lifecycle.ts b/src/vs/platform/lifecycle/common/lifecycle.ts index 881196ef1fe..675d8da166f 100644 --- a/src/vs/platform/lifecycle/common/lifecycle.ts +++ b/src/vs/platform/lifecycle/common/lifecycle.ts @@ -32,6 +32,12 @@ export interface ILifecycleService { _serviceBrand: any; + /** + * A flag indicating if the application is in the process of shutting down. This will be true + * before the onWillShutdown event is fired and false if the shutdown is being vetoed. + */ + willShutdown: boolean; + /** * Fired before shutdown happens. Allows listeners to veto against the * shutdown. @@ -47,6 +53,7 @@ export interface ILifecycleService { export const NullLifecycleService: ILifecycleService = { _serviceBrand: null, + willShutdown: false, onWillShutdown: () => ({ dispose() { } }), onShutdown: () => ({ dispose() { } }) }; diff --git a/src/vs/test/utils/servicesTestUtils.ts b/src/vs/test/utils/servicesTestUtils.ts index d0317c15d80..9c4b88924c8 100644 --- a/src/vs/test/utils/servicesTestUtils.ts +++ b/src/vs/test/utils/servicesTestUtils.ts @@ -607,6 +607,8 @@ export class TestLifecycleService implements ILifecycleService { public _serviceBrand: any; + public willShutdown: boolean; + private _onWillShutdown = new Emitter(); private _onShutdown = new Emitter(); diff --git a/src/vs/workbench/parts/files/common/editors/textFileEditorModel.ts b/src/vs/workbench/parts/files/common/editors/textFileEditorModel.ts index 9291a1d4a15..0643c2e34e4 100644 --- a/src/vs/workbench/parts/files/common/editors/textFileEditorModel.ts +++ b/src/vs/workbench/parts/files/common/editors/textFileEditorModel.ts @@ -17,6 +17,7 @@ import diagnostics = require('vs/base/common/diagnostics'); import types = require('vs/base/common/types'); import {IModelContentChangedEvent} from 'vs/editor/common/editorCommon'; import {IMode} from 'vs/editor/common/modes'; +import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle'; import {ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveErrorHandler, ISaveParticipant, StateChange} from 'vs/workbench/parts/files/common/files'; import {EncodingMode, EditorModel} from 'vs/workbench/common/editor'; import {BaseTextEditorModel} from 'vs/workbench/common/editor/textEditorModel'; @@ -64,6 +65,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil @IModeService modeService: IModeService, @IModelService modelService: IModelService, @IFileService private fileService: IFileService, + @ILifecycleService private lifecycleService: ILifecycleService, @IInstantiationService private instantiationService: IInstantiationService, @ITelemetryService private telemetryService: ITelemetryService, @ITextFileService private textFileService: ITextFileService @@ -441,9 +443,11 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil // A save participant can still change the model now and since we are so close to saving // we do not want to trigger another auto save or similar, so we block this // In addition we update our version right after in case it changed because of a model change + // We DO NOT run any save participant if we are in the shutdown phase and files are being + // saved as a result of that. let saveParticipantPromise = TPromise.as(versionId); - if (TextFileEditorModel.saveParticipant) { + if (TextFileEditorModel.saveParticipant && !this.lifecycleService.willShutdown) { saveParticipantPromise = TPromise.as(undefined).then(() => { this.blockModelContentChange = true; return TextFileEditorModel.saveParticipant.participate(this, { isAutoSaved }); diff --git a/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts b/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts index 68ff9196890..f9902a3bf76 100644 --- a/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts +++ b/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts @@ -20,6 +20,8 @@ export class LifecycleService implements ILifecycleService { private _onWillShutdown = new Emitter(); private _onShutdown = new Emitter(); + private _willShutdown: boolean; + constructor( @IMessageService private messageService: IMessageService, @IWindowService private windowService: IWindowService @@ -27,6 +29,10 @@ export class LifecycleService implements ILifecycleService { this.registerListeners(); } + public get willShutdown(): boolean { + return this._willShutdown; + } + public get onWillShutdown(): Event { return this._onWillShutdown.event; } @@ -40,8 +46,12 @@ export class LifecycleService implements ILifecycleService { // Main side indicates that window is about to unload, check for vetos ipc.on('vscode:beforeUnload', (event, reply: { okChannel: string, cancelChannel: string }) => { + this._willShutdown = true; + + // trigger onWillShutdown events and veto collecting this.onBeforeUnload().done(veto => { if (veto) { + this._willShutdown = false; // reset this flag since the shutdown has been vetoed! ipc.send(reply.cancelChannel, windowId); } else { this._onShutdown.fire(); From bd818acc3702554493c73531d8b90d51e46b2021 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 22 Sep 2016 16:30:34 +0200 Subject: [PATCH 2/6] use final v1.13.0 of debug protocol --- npm-shrinkwrap.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1af9577f15e..fcd3bc3628b 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -405,9 +405,9 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" }, "vscode-debugprotocol": { - "version": "1.13.0-pre.3", + "version": "1.13.0", "from": "vscode-debugprotocol@1.13.0", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.13.0-pre.3.tgz" + "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.13.0.tgz" }, "vscode-textmate": { "version": "2.2.0", diff --git a/package.json b/package.json index b8b972fa967..66f528533a2 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "pty.js": "https://github.com/Tyriar/pty.js/tarball/fffbf86eb9e8051b5b2be4ba9c7b07faa018ce8d", "fast-plist": "0.1.1", "semver": "4.3.6", - "vscode-debugprotocol": "1.13.0-pre.3", + "vscode-debugprotocol": "1.13.0", "vscode-textmate": "2.2.0", "winreg": "1.2.0", "xterm": "git+https://github.com/Tyriar/xterm.js.git#vscode-release/1.6", From 4e09528ffc0de17e183f16510438a999c142b53c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 22 Sep 2016 16:31:47 +0200 Subject: [PATCH 3/6] fix bad npe --- .../workbench/browser/parts/editor/sideBySideEditorControl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/sideBySideEditorControl.ts b/src/vs/workbench/browser/parts/editor/sideBySideEditorControl.ts index 0ff5dea8bf8..dab8c813905 100644 --- a/src/vs/workbench/browser/parts/editor/sideBySideEditorControl.ts +++ b/src/vs/workbench/browser/parts/editor/sideBySideEditorControl.ts @@ -992,7 +992,7 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti function createOverlay(target: HTMLElement): void { if (!overlay) { - const {showTabs} = this.getConfig(); + const {showTabs} = $this.getConfig(); const containers = $this.visibleEditors.filter(e => !!e).map(e => e.getContainer()); containers.forEach((container, index) => { if (container && DOM.isAncestor(target, container.getHTMLElement())) { From 94862958cb31b300702fe415049e05ed85a2ec7c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 22 Sep 2016 17:25:41 +0200 Subject: [PATCH 4/6] localize extension metadata with default english --- .../common/extensionNls.ts | 33 +++++++++++++++++++ .../node/extensionManagementService.ts | 32 ++++++++++++++---- 2 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 src/vs/platform/extensionManagement/common/extensionNls.ts diff --git a/src/vs/platform/extensionManagement/common/extensionNls.ts b/src/vs/platform/extensionManagement/common/extensionNls.ts new file mode 100644 index 00000000000..53ed6658d5a --- /dev/null +++ b/src/vs/platform/extensionManagement/common/extensionNls.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { cloneAndChange } from 'vs/base/common/objects'; +import { IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement'; + +const nlsRegex = /^%([\w\d.]+)%$/i; + +export interface ITranslations { + [key: string]: string; +} + +export function localizeManifest(manifest: IExtensionManifest, translations: ITranslations): IExtensionManifest { + const patcher = value => { + if (typeof value !== 'string') { + return; + } + + const match = nlsRegex.exec(value); + + if (!match) { + return; + } + + return translations[match[1]] || value; + }; + + return cloneAndChange(manifest, patcher); +} diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 687802b7cb4..3e117459f63 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -17,6 +17,7 @@ import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IExtensionIdentity, IExtensionManifest, IGalleryMetadata, InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { localizeManifest } from '../common/extensionNls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { Limiter } from 'vs/base/common/async'; import Event, { Emitter } from 'vs/base/common/event'; @@ -61,6 +62,23 @@ function validate(zipPath: string, extension?: IExtensionIdentity, version?: str }); } +function readManifest(extensionPath: string): TPromise<{ manifest: IExtensionManifest; metadata: IGalleryMetadata; }> { + const promises = [ + pfs.readFile(path.join(extensionPath, 'package.json'), 'utf8') + .then(raw => parseManifest(raw)), + pfs.readFile(path.join(extensionPath, 'package.nls.json'), 'utf8') + .then(null, err => err.code !== 'ENOENT' ? TPromise.wrapError(err) : '{}') + .then(raw => JSON.parse(raw)) + ]; + + return TPromise.join(promises).then(([{ manifest, metadata }, translations]) => { + return { + manifest: localizeManifest(manifest, translations), + metadata + }; + }); +} + function getExtensionId(extension: IExtensionIdentity, version: string): string { return `${ extension.publisher }.${ extension.name }-${ version }`; } @@ -145,11 +163,9 @@ export class ExtensionManagementService implements IExtensionManagementService { private installExtension(zipPath: string, id: string, metadata: IGalleryMetadata = null): TPromise { const extensionPath = path.join(this.extensionsPath, id); - const manifestPath = path.join(extensionPath, 'package.json'); return extract(zipPath, extensionPath, { sourcePath: 'extension', overwrite: true }) - .then(() => pfs.readFile(manifestPath, 'utf8')) - .then(raw => parseManifest(raw)) + .then(() => readManifest(extensionPath)) .then(({ manifest }) => { return pfs.readdir(extensionPath).then(children => { const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0]; @@ -159,9 +175,12 @@ export class ExtensionManagementService implements IExtensionManagementService { const type = LocalExtensionType.User; const local: ILocalExtension = { type, id, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl }; - const rawManifest = assign(manifest, { __metadata: metadata }); + const manifestPath = path.join(extensionPath, 'package.json'); - return pfs.writeFile(manifestPath, JSON.stringify(rawManifest, null, '\t')) + return pfs.readFile(manifestPath, 'utf8') + .then(raw => parseManifest(raw)) + .then(({ manifest }) => assign(manifest, { __metadata: metadata })) + .then(manifest => pfs.writeFile(manifestPath, JSON.stringify(manifest, null, '\t'))) .then(() => local); }); }); @@ -230,8 +249,7 @@ export class ExtensionManagementService implements IExtensionManagementService { const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0]; const changelogUrl = changelog ? URI.file(path.join(extensionPath, changelog)).toString() : null; - return pfs.readFile(path.join(extensionPath, 'package.json'), 'utf8') - .then(raw => parseManifest(raw)) + return readManifest(extensionPath) .then(({ manifest, metadata }) => ({ type, id, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl })); }).then(null, () => null); From cb19176a04fd4bc5bda861cb20387ca7b7406a34 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 22 Sep 2016 17:55:50 +0200 Subject: [PATCH 5/6] add watch dog, bubble errors a little, #239 --- .../node/extHostDocumentSaveParticipant.ts | 72 +++++++++++-------- .../extHostDocumentSaveParticipant.test.ts | 51 +++++++++++++ 2 files changed, 92 insertions(+), 31 deletions(-) diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index e8a551d103a..1d18c8709d9 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -7,7 +7,7 @@ import Event from 'vs/base/common/event'; import CallbackList from 'vs/base/common/callbackList'; import URI from 'vs/base/common/uri'; -import {sequence} from 'vs/base/common/async'; +import {sequence, always} from 'vs/base/common/async'; import {illegalState} from 'vs/base/common/errors'; import {TPromise} from 'vs/base/common/winjs.base'; import {MainThreadWorkspaceShape, ExtHostDocumentSaveParticipantShape} from 'vs/workbench/api/node/extHost.protocol'; @@ -21,12 +21,14 @@ export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipa private _documents: ExtHostDocuments; private _workspace: MainThreadWorkspaceShape; + private _listenerTimeout: number; private _callbacks = new CallbackList(); - constructor(documents: ExtHostDocuments, workspace: MainThreadWorkspaceShape) { + constructor(documents: ExtHostDocuments, workspace: MainThreadWorkspaceShape, listenerTimeout: number = 1000) { super(); this._documents = documents; this._workspace = workspace; + this._listenerTimeout = listenerTimeout; } dispose(): void { @@ -61,7 +63,7 @@ export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipa const {version} = document; - const event = Object.freeze( { + const event = Object.freeze({ document, waitUntil(p: Thenable) { if (Object.isFrozen(promises)) { @@ -74,41 +76,49 @@ export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipa try { // fire event listener.apply(thisArg, [event]); - } finally { - // freeze promises after event call - Object.freeze(promises); + } catch (err) { + return TPromise.as(new Error(err)); + } - return TPromise.join(promises).then(values => { + // freeze promises after event call + Object.freeze(promises); - const edits: IResourceEdit[] = []; - for (const value of values) { - if (Array.isArray(value) && ( value).every(e => e instanceof TextEdit)) { - for (const {newText, range} of value) { - edits.push({ - resource: document.uri, - range: fromRange(range), - newText - }); - } + return new TPromise((resolve, reject) => { + // join on all listener promises, reject after timeout + const handle = setTimeout(() => reject(new Error('timeout')), this._listenerTimeout); + return always(TPromise.join(promises), () => clearTimeout(handle)).then(resolve, reject); + + }).then(values => { + + const edits: IResourceEdit[] = []; + for (const value of values) { + if (Array.isArray(value) && (value).every(e => e instanceof TextEdit)) { + for (const {newText, range} of value) { + edits.push({ + resource: document.uri, + range: fromRange(range), + newText + }); } } + } - // apply edits iff any and iff document - // didn't change somehow in the meantime - if (edits.length === 0) { - return; - } + // apply edits iff any and iff document + // didn't change somehow in the meantime + if (edits.length === 0) { + return; + } - if (version === document.version) { - return this._workspace.$applyWorkspaceEdit(edits); - } + if (version === document.version) { + return this._workspace.$applyWorkspaceEdit(edits); + } - // TODO@joh bubble this to listener? - return new Error('ignoring change because of concurrent edits'); + // TODO@joh bubble this to listener? + return new Error('ignoring change because of concurrent edits'); - }, err => { - // ignore error - }); - } + }, err => { + // soft ignore, turning into result + return err; + }); } } \ No newline at end of file diff --git a/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts index 2ed91e8f17a..58bc8c2756d 100644 --- a/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts @@ -81,6 +81,41 @@ suite('ExtHostDocumentSaveParticipant', () => { }); }); + test('event delivery, bad listener', () => { + const participant = new ExtHostDocumentSaveParticipant(documents, workspace); + + let sub = participant.onWillSaveTextDocumentEvent(function (e) { + throw new Error('💀'); + }); + + return participant.$participateInSave(resource).then(values => { + sub.dispose(); + + const [first] = values; + assert.ok(first instanceof Error); + assert.ok((first).message); + }); + }); + + test('event delivery, bad listener doesn\'t prevent more events', () => { + const participant = new ExtHostDocumentSaveParticipant(documents, workspace); + + let sub1 = participant.onWillSaveTextDocumentEvent(function (e) { + throw new Error('💀'); + }); + let event: vscode.TextDocumentWillSaveEvent; + let sub2 = participant.onWillSaveTextDocumentEvent(function (e) { + event = e; + }); + + return participant.$participateInSave(resource).then(() => { + sub1.dispose(); + sub2.dispose(); + + assert.ok(event); + }); + }); + test('event delivery, in subscriber order', () => { const participant = new ExtHostDocumentSaveParticipant(documents, workspace); @@ -138,6 +173,22 @@ suite('ExtHostDocumentSaveParticipant', () => { }); }); + test('event delivery, waitUntil will timeout', () => { + const participant = new ExtHostDocumentSaveParticipant(documents, workspace, 5); + + let sub = participant.onWillSaveTextDocumentEvent(function (event) { + event.waitUntil(TPromise.timeout(15)); + }); + + return participant.$participateInSave(resource).then(values => { + sub.dispose(); + + const [first] = values; + assert.ok(first instanceof Error); + assert.ok((first).message); + }); + }); + test('event delivery, waitUntil failure handling', () => { const participant = new ExtHostDocumentSaveParticipant(documents, workspace); From 7baf009e27c8a0ce11f4a33c75150becbbac5be1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 22 Sep 2016 11:02:55 +0200 Subject: [PATCH 6/6] WindowEventChannel: Create it before registerting channel - Initial window events are bufferred --- src/vs/base/parts/ipc/node/ipc.net.ts | 3 +++ src/vs/code/common/windows.ts | 2 +- src/vs/code/common/windowsIpc.ts | 8 ++++---- src/vs/code/electron-main/main.ts | 5 +++-- src/vs/code/node/sharedProcessMain.ts | 4 +--- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts index d1573af1828..694963fdb8f 100644 --- a/src/vs/base/parts/ipc/node/ipc.net.ts +++ b/src/vs/base/parts/ipc/node/ipc.net.ts @@ -114,6 +114,9 @@ class RoutingChannelClient implements IRoutingChannelClient, IDisposable { getChannel(channelName: string, router: IClientRouter): T { const call = (command: string, arg: any) => { const id = router.routeCall(command, arg); + if (!id) { + return TPromise.wrapError('Client id should be provided'); + } return this.getClient(id).then(client => client.getChannel(channelName).call(command, arg)); }; return { call } as T; diff --git a/src/vs/code/common/windows.ts b/src/vs/code/common/windows.ts index 28df548ebcc..7e268b1945c 100644 --- a/src/vs/code/common/windows.ts +++ b/src/vs/code/common/windows.ts @@ -30,7 +30,7 @@ export class ActiveWindowManager implements IDisposable { this._activeWindowId = windowId; } - public get activeWindowId(): string { + public get activeClientId(): string { return `window:${ this._activeWindowId }`; } diff --git a/src/vs/code/common/windowsIpc.ts b/src/vs/code/common/windowsIpc.ts index feec4bbd2be..4af2306e0c2 100644 --- a/src/vs/code/common/windowsIpc.ts +++ b/src/vs/code/common/windowsIpc.ts @@ -7,16 +7,16 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc'; -import { IWindowEventService } from './windows'; +import { IWindowEventService } from 'vs/code/common/windows'; import Event, { buffer } from 'vs/base/common/event'; -export interface IWindowsChannel extends IChannel { +export interface IWindowEventChannel extends IChannel { call(command: 'event:onNewWindowOpen'): TPromise; call(command: 'event:onWindowFocus'): TPromise; call(command: string, arg: any): any; } -export class WindowsChannel implements IWindowsChannel { +export class WindowEventChannel implements IWindowEventChannel { onNewWindowOpen: Event; onWindowFocus: Event; @@ -41,7 +41,7 @@ export class WindowEventChannelClient implements IWindowEventService { _serviceBrand: any; - constructor(private channel: IWindowsChannel) { } + constructor(private channel: IWindowEventChannel) { } private _onNewWindowOpen: Event = eventFromCall(this.channel, 'event:onNewWindowOpen'); get onNewWindowOpen(): Event { diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index c9a317dd98e..7315a2005c4 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -15,7 +15,7 @@ import { mkdirp } from 'vs/base/node/pfs'; import { IProcessEnvironment, IEnvService, EnvService } from 'vs/code/electron-main/env'; import { IWindowsService, WindowsManager, WindowEventService } from 'vs/code/electron-main/windows'; import { IWindowEventService } from 'vs/code/common/windows'; -import { WindowsChannel } from 'vs/code/common/windowsIpc'; +import { WindowEventChannel } from 'vs/code/common/windowsIpc'; import { ILifecycleService, LifecycleService } from 'vs/code/electron-main/lifecycle'; import { VSCodeMenu } from 'vs/code/electron-main/menus'; import { IUpdateService, UpdateManager } from 'vs/code/electron-main/update-manager'; @@ -74,6 +74,7 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: IProce const lifecycleService = accessor.get(ILifecycleService); const updateService = accessor.get(IUpdateService); const configurationService = accessor.get(IConfigurationService) as ConfigurationService; + const windowEventChannel = new WindowEventChannel(windowEventService); // We handle uncaught exceptions here to prevent electron from opening a dialog to the user process.on('uncaughtException', (err: any) => { @@ -136,7 +137,7 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: IProce sharedProcessDisposable = disposable; const sharedProcessConnect = connect(environmentService.sharedIPCHandle, 'main'); sharedProcessConnect.done(client => { - client.registerChannel('windowEvent', new WindowsChannel(windowEventService)); + client.registerChannel('windowEvent', windowEventChannel); }); }); diff --git a/src/vs/code/node/sharedProcessMain.ts b/src/vs/code/node/sharedProcessMain.ts index a3ceb02679e..6e873db4c39 100644 --- a/src/vs/code/node/sharedProcessMain.ts +++ b/src/vs/code/node/sharedProcessMain.ts @@ -75,9 +75,7 @@ function main(server: Server, initData: ISharedProcessInitData): void { const activeWindowManager = new ActiveWindowManager(windowEventService); services.set(IChoiceService, new ChoiceChannelClient(server.getChannel('choice', { - routeCall: (command: any, arg: any) => { - return activeWindowManager.activeWindowId; - } + routeCall: () => activeWindowManager.activeClientId }))); const instantiationService = new InstantiationService(services);