From 0abd8212779cb9189fd041408ab96ffd810e281e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 13 Dec 2017 15:36:47 +0100 Subject: [PATCH] Further simplifications (#36972) --- .../api/electron-browser/extHostCustomers.ts | 2 +- src/vs/workbench/api/node/extHost.api.impl.ts | 2 +- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/node/extensionHostMain.ts | 14 +-- .../electron-browser/extensionService.ts | 24 ++--- .../node/proxyIdentifier.ts} | 0 .../services/extensions/node/rpcProtocol.ts | 69 ++++++++++++--- .../thread/node/abstractThreadService.ts | 87 ------------------- .../electron-browser/api/testThreadService.ts | 2 +- 9 files changed, 78 insertions(+), 124 deletions(-) rename src/vs/workbench/services/{thread/common/threadService.ts => extensions/node/proxyIdentifier.ts} (100%) delete mode 100644 src/vs/workbench/services/thread/node/abstractThreadService.ts diff --git a/src/vs/workbench/api/electron-browser/extHostCustomers.ts b/src/vs/workbench/api/electron-browser/extHostCustomers.ts index b3a700850d4..6ce6d843443 100644 --- a/src/vs/workbench/api/electron-browser/extHostCustomers.ts +++ b/src/vs/workbench/api/electron-browser/extHostCustomers.ts @@ -6,7 +6,7 @@ 'use strict'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService'; +import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol'; diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 79c6f5ec341..559d47a2a69 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -49,7 +49,7 @@ import * as paths from 'vs/base/common/paths'; import { MainContext, ExtHostContext, IInitData, IExtHostContext } from './extHost.protocol'; import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration'; import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions'; -import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService'; +import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs'; import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem'; import { FileChangeType, FileType } from 'vs/platform/files/common/files'; diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 23373988b5e..435f8c7011b 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -8,7 +8,7 @@ import { createMainContextProxyIdentifier as createMainId, createExtHostContextProxyIdentifier as createExtId, ProxyIdentifier -} from 'vs/workbench/services/thread/common/threadService'; +} from 'vs/workbench/services/extensions/node/proxyIdentifier'; import * as vscode from 'vscode'; diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index 3545161a485..9466bd04ec4 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -25,7 +25,7 @@ import { createLogService } from 'vs/platform/log/node/spdlogService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; -import { AbstractThreadService } from 'vs/workbench/services/thread/node/abstractThreadService'; +import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; // const nativeExit = process.exit.bind(process); function patchProcess(allowExit: boolean) { @@ -88,8 +88,8 @@ export class ExtensionHostMain { patchProcess(allowExit); // services - const threadService = new AbstractThreadService(protocol, false); - const extHostWorkspace = new ExtHostWorkspace(threadService, initData.workspace); + const rpcProtocol = new RPCProtocol(protocol); + const extHostWorkspace = new ExtHostWorkspace(rpcProtocol, initData.workspace); const environmentService = new EnvironmentService(initData.args, initData.execPath); this._logService = createLogService(`exthost${initData.windowId}`, environmentService); this.disposables.push(this._logService); @@ -97,8 +97,8 @@ export class ExtensionHostMain { this._logService.info('extension host started'); this._logService.trace('initData', initData); - this._extHostConfiguration = new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration); - this._extensionService = new ExtHostExtensionService(initData, threadService, extHostWorkspace, this._extHostConfiguration, this._logService); + this._extHostConfiguration = new ExtHostConfiguration(rpcProtocol.get(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration); + this._extensionService = new ExtHostExtensionService(initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._logService); // error forwarding and stack trace scanning const extensionErrors = new WeakMap(); @@ -119,8 +119,8 @@ export class ExtensionHostMain { return `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`; }; }); - const mainThreadExtensions = threadService.get(MainContext.MainThreadExtensionService); - const mainThreadErrors = threadService.get(MainContext.MainThreadErrors); + const mainThreadExtensions = rpcProtocol.get(MainContext.MainThreadExtensionService); + const mainThreadErrors = rpcProtocol.get(MainContext.MainThreadErrors); errors.setUnexpectedErrorHandler(err => { const data = errors.transformErrorForSerialization(err); const extension = extensionErrors.get(err); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index df2ae6c820d..11d5067a946 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -21,7 +21,7 @@ import { areSameExtensions, BetterMergeId, BetterMergeDisabledNowKey } from 'vs/ import { ExtensionsRegistry, ExtensionPoint, IExtensionPointUser, ExtensionMessageCollector, IExtensionPoint } from 'vs/platform/extensions/common/extensionsRegistry'; import { ExtensionScanner, ILog, ExtensionScannerInput } from 'vs/workbench/services/extensions/electron-browser/extensionPoints'; import { IMessageService, CloseAction } from 'vs/platform/message/common/message'; -import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService'; +import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { ExtHostContext, ExtHostExtensionServiceShape, IExtHostContext, MainContext } from 'vs/workbench/api/node/extHost.protocol'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -41,7 +41,7 @@ import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; import product from 'vs/platform/node/product'; import * as strings from 'vs/base/common/strings'; -import { AbstractThreadService } from 'vs/workbench/services/thread/node/abstractThreadService'; +import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; const SystemExtensionsRoot = path.normalize(path.join(URI.parse(require.toUrl('')).fsPath, '..', 'extensions')); @@ -85,7 +85,7 @@ export class ExtensionService extends Disposable implements IExtensionService { private _extensionHostProcessActivationTimes: { [id: string]: ActivationTimes; }; private _extensionHostExtensionRuntimeErrors: { [id: string]: Error[]; }; private _extensionHostProcessWorker: ExtensionHostProcessWorker; - private _extensionHostProcessThreadService: AbstractThreadService; + private _extensionHostProcessRPCProtocol: RPCProtocol; private _extensionHostProcessCustomers: IDisposable[]; /** * winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object. @@ -115,7 +115,7 @@ export class ExtensionService extends Disposable implements IExtensionService { this._extensionHostProcessActivationTimes = Object.create(null); this._extensionHostExtensionRuntimeErrors = Object.create(null); this._extensionHostProcessWorker = null; - this._extensionHostProcessThreadService = null; + this._extensionHostProcessRPCProtocol = null; this._extensionHostProcessCustomers = []; this._extensionHostProcessProxy = null; @@ -167,9 +167,9 @@ export class ExtensionService extends Disposable implements IExtensionService { this._extensionHostProcessWorker.dispose(); this._extensionHostProcessWorker = null; } - if (this._extensionHostProcessThreadService) { - this._extensionHostProcessThreadService.dispose(); - this._extensionHostProcessThreadService = null; + if (this._extensionHostProcessRPCProtocol) { + this._extensionHostProcessRPCProtocol.dispose(); + this._extensionHostProcessRPCProtocol = null; } for (let i = 0, len = this._extensionHostProcessCustomers.length; i < len; i++) { const customer = this._extensionHostProcessCustomers[i]; @@ -238,8 +238,8 @@ export class ExtensionService extends Disposable implements IExtensionService { protocol = asLoggingProtocol(protocol); } - this._extensionHostProcessThreadService = new AbstractThreadService(protocol, true); - const extHostContext: IExtHostContext = this._extensionHostProcessThreadService; + this._extensionHostProcessRPCProtocol = new RPCProtocol(protocol); + const extHostContext: IExtHostContext = this._extensionHostProcessRPCProtocol; // Named customers const namedCustomers = ExtHostCustomersRegistry.getNamedCustomers(); @@ -247,7 +247,7 @@ export class ExtensionService extends Disposable implements IExtensionService { const [id, ctor] = namedCustomers[i]; const instance = this._instantiationService.createInstance(ctor, extHostContext); this._extensionHostProcessCustomers.push(instance); - this._extensionHostProcessThreadService.set(id, instance); + this._extensionHostProcessRPCProtocol.set(id, instance); } // Customers @@ -260,9 +260,9 @@ export class ExtensionService extends Disposable implements IExtensionService { // Check that no named customers are missing const expected: ProxyIdentifier[] = Object.keys(MainContext).map((key) => MainContext[key]); - this._extensionHostProcessThreadService.assertRegistered(expected); + this._extensionHostProcessRPCProtocol.assertRegistered(expected); - return this._extensionHostProcessThreadService.get(ExtHostContext.ExtHostExtensionService); + return this._extensionHostProcessRPCProtocol.get(ExtHostContext.ExtHostExtensionService); } // ---- begin IExtensionService diff --git a/src/vs/workbench/services/thread/common/threadService.ts b/src/vs/workbench/services/extensions/node/proxyIdentifier.ts similarity index 100% rename from src/vs/workbench/services/thread/common/threadService.ts rename to src/vs/workbench/services/extensions/node/proxyIdentifier.ts diff --git a/src/vs/workbench/services/extensions/node/rpcProtocol.ts b/src/vs/workbench/services/extensions/node/rpcProtocol.ts index ea7e8f93f46..a0fce5f91f4 100644 --- a/src/vs/workbench/services/extensions/node/rpcProtocol.ts +++ b/src/vs/workbench/services/extensions/node/rpcProtocol.ts @@ -9,15 +9,16 @@ import * as marshalling from 'vs/base/common/marshalling'; import * as errors from 'vs/base/common/errors'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { LazyPromise } from 'vs/workbench/services/extensions/node/lazyPromise'; +import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; +import { CharCode } from 'vs/base/common/charCode'; -export interface IDispatcher { - invoke(proxyId: string, methodName: string, args: any[]): any; -} +declare var Proxy: any; // TODO@TypeScript export class RPCProtocol { private _isDisposed: boolean; - private _bigHandler: IDispatcher; + private readonly _locals: { [id: string]: any; }; + private readonly _proxies: { [id: string]: any; }; private _lastMessageId: number; private readonly _invokedHandlers: { [req: string]: TPromise; }; private readonly _pendingRPCReplies: { [msgId: string]: LazyPromise; }; @@ -25,7 +26,8 @@ export class RPCProtocol { constructor(protocol: IMessagePassingProtocol) { this._isDisposed = false; - this._bigHandler = null; + this._locals = Object.create(null); + this._proxies = Object.create(null); this._lastMessageId = 0; this._invokedHandlers = Object.create(null); this._pendingRPCReplies = {}; @@ -42,6 +44,41 @@ export class RPCProtocol { }); } + public get(identifier: ProxyIdentifier): T { + if (!this._proxies[identifier.id]) { + this._proxies[identifier.id] = this._createProxy(identifier.id); + } + return this._proxies[identifier.id]; + } + + private _createProxy(proxyId: string): T { + let handler = { + get: (target, name: string) => { + if (!target[name] && name.charCodeAt(0) === CharCode.DollarSign) { + target[name] = (...myArgs: any[]) => { + return this.fancyRemoteCall(proxyId, name, myArgs); + }; + } + return target[name]; + } + }; + return new Proxy(Object.create(null), handler); + } + + public set(identifier: ProxyIdentifier, value: R): R { + this._locals[identifier.id] = value; + return value; + } + + public assertRegistered(identifiers: ProxyIdentifier[]): void { + for (let i = 0, len = identifiers.length; i < len; i++) { + const identifier = identifiers[i]; + if (!this._locals[identifier.id]) { + throw new Error(`Missing actor ${identifier.id} (isMain: ${identifier.isMain})`); + } + } + } + private _receiveOneMessage(rawmsg: string): void { if (this._isDisposed) { return; @@ -72,10 +109,6 @@ export class RPCProtocol { } private _receiveRequest(msg: RequestMessage | FancyRequestMessage): void { - if (!this._bigHandler) { - throw new Error('got message before big handler attached!'); - } - const callId = msg.id; const proxyId = msg.proxyId; const isFancy = (msg.type === MessageType.FancyRequest); // a fancy request gets a fancy reply @@ -135,12 +168,24 @@ export class RPCProtocol { private _invokeHandler(proxyId: string, methodName: string, args: any[]): TPromise { try { - return TPromise.as(this._bigHandler.invoke(proxyId, methodName, args)); + return TPromise.as(this._doInvokeHandler(proxyId, methodName, args)); } catch (err) { return TPromise.wrapError(err); } } + private _doInvokeHandler(proxyId: string, methodName: string, args: any[]): any { + if (!this._locals[proxyId]) { + throw new Error('Unknown actor ' + proxyId); + } + let actor = this._locals[proxyId]; + let method = actor[methodName]; + if (typeof method !== 'function') { + throw new Error('Unknown method ' + methodName + ' on actor ' + proxyId); + } + return method.apply(actor, args); + } + public remoteCall(proxyId: string, methodName: string, args: any[]): TPromise { return this._remoteCall(proxyId, methodName, args, false); } @@ -169,10 +214,6 @@ export class RPCProtocol { return result; } - - public setDispatcher(handler: IDispatcher): void { - this._bigHandler = handler; - } } /** diff --git a/src/vs/workbench/services/thread/node/abstractThreadService.ts b/src/vs/workbench/services/thread/node/abstractThreadService.ts deleted file mode 100644 index 0d707330439..00000000000 --- a/src/vs/workbench/services/thread/node/abstractThreadService.ts +++ /dev/null @@ -1,87 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { TPromise } from 'vs/base/common/winjs.base'; -import { IDispatcher, RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; -import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService'; -import { CharCode } from 'vs/base/common/charCode'; -import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; - -declare var Proxy: any; // TODO@TypeScript - -export class AbstractThreadService implements IDispatcher { - - private readonly _rpcProtocol: RPCProtocol; - private readonly _isMain: boolean; - protected readonly _locals: { [id: string]: any; }; - private readonly _proxies: { [id: string]: any; } = Object.create(null); - - constructor(protocol: IMessagePassingProtocol, isMain: boolean) { - this._rpcProtocol = new RPCProtocol(protocol); - this._isMain = isMain; - this._locals = Object.create(null); - this._proxies = Object.create(null); - this._rpcProtocol.setDispatcher(this); - } - - public dispose(): void { - this._rpcProtocol.dispose(); - } - - public invoke(proxyId: string, methodName: string, args: any[]): any { - if (!this._locals[proxyId]) { - throw new Error('Unknown actor ' + proxyId); - } - let actor = this._locals[proxyId]; - let method = actor[methodName]; - if (typeof method !== 'function') { - throw new Error('Unknown method ' + methodName + ' on actor ' + proxyId); - } - return method.apply(actor, args); - } - - get(identifier: ProxyIdentifier): T { - if (!this._proxies[identifier.id]) { - this._proxies[identifier.id] = this._createProxy(identifier.id); - } - return this._proxies[identifier.id]; - } - - private _createProxy(proxyId: string): T { - let handler = { - get: (target, name: string) => { - if (!target[name] && name.charCodeAt(0) === CharCode.DollarSign) { - target[name] = (...myArgs: any[]) => { - return this._callOnRemote(proxyId, name, myArgs); - }; - } - return target[name]; - } - }; - return new Proxy(Object.create(null), handler); - } - - set(identifier: ProxyIdentifier, value: R): R { - if (identifier.isMain !== this._isMain) { - throw new Error('Mismatch in object registration!'); - } - this._locals[identifier.id] = value; - return value; - } - - assertRegistered(identifiers: ProxyIdentifier[]): void { - for (let i = 0, len = identifiers.length; i < len; i++) { - const identifier = identifiers[i]; - if (!this._locals[identifier.id]) { - throw new Error(`Missing actor ${identifier.id} (isMain: ${identifier.isMain})`); - } - } - } - - private _callOnRemote(proxyId: string, methodName: string, args: any[]): TPromise { - return this._rpcProtocol.fancyRemoteCall(proxyId, methodName, args); - } -} diff --git a/src/vs/workbench/test/electron-browser/api/testThreadService.ts b/src/vs/workbench/test/electron-browser/api/testThreadService.ts index 75543d40523..c22dfd95099 100644 --- a/src/vs/workbench/test/electron-browser/api/testThreadService.ts +++ b/src/vs/workbench/test/electron-browser/api/testThreadService.ts @@ -6,7 +6,7 @@ 'use strict'; import { TPromise } from 'vs/base/common/winjs.base'; -import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService'; +import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; export function OneGetThreadService(thing: any) { return { -- GitLab