Skip to content

Commit

Permalink
RPC Protocol ClientProxyHandler Init Events #13172
Browse files Browse the repository at this point in the history
* add other dependencies
* make sure to not start initialization multiple times
  • Loading branch information
jfaltermeier committed Dec 18, 2023
1 parent 14e6270 commit 5d35e32
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 28 deletions.
9 changes: 7 additions & 2 deletions packages/plugin-ext/src/common/proxy-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface InvocationHandlerOptions extends RpcHandlerOptions {
export class ClientProxyHandler<T extends object> implements ProxyHandler<T> {
private rpcDeferred: Deferred<RpcProtocol> = new Deferred();
private isRpcInitialized = false;
private isInitializing = false;

readonly id: string;
private readonly channelProvider: () => Promise<Channel>;
Expand All @@ -50,12 +51,14 @@ export class ClientProxyHandler<T extends object> implements ProxyHandler<T> {
}

initializeRpc(): void {
if (!this.isRpcInitialized) {
if (!this.isRpcInitialized && !this.isInitializing) {
this.isInitializing = true;
const clientOptions: RpcProtocolOptions = { encoder: this.encoder, decoder: this.decoder, mode: 'clientOnly' };
this.channelProvider().then(channel => {
const rpc = new RpcProtocol(channel, undefined, clientOptions);
this.rpcDeferred.resolve(rpc);
this.isRpcInitialized = true;
this.isInitializing = false;
if (this.onInitialize) {
this.onInitialize();
}
Expand All @@ -64,7 +67,9 @@ export class ClientProxyHandler<T extends object> implements ProxyHandler<T> {
}

get(target: any, name: string, receiver: any): any {
this.initializeRpc();
if (!this.isRpcInitialized) {
this.initializeRpc();
}

if (target[name] || name.charCodeAt(0) !== 36 /* CharCode.DollarSign */) {
return target[name];
Expand Down
4 changes: 1 addition & 3 deletions packages/plugin-ext/src/common/rpc-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ export class RPCProtocolImpl implements RPCProtocol {
private readonly multiplexer: ChannelMultiplexer;
private readonly encoder = new MsgPackMessageEncoder();
private readonly decoder = new MsgPackMessageDecoder();
private readonly onInitializeEmitter: Emitter<string> = new Emitter();

private readonly toDispose = new DisposableCollection(
Disposable.create(() => { /* mark as no disposed */ })
Expand All @@ -96,7 +95,6 @@ export class RPCProtocolImpl implements RPCProtocol {
this.toDispose.push(Disposable.create(() => this.proxies.clear()));
this.toDispose.push(Disposable.create(() => this.handler.clear()));
this.toDispose.push(Disposable.create(() => this.remoteDependencies.clear()));
this.toDispose.push(this.onInitializeEmitter);
}

dispose(): void {
Expand Down Expand Up @@ -176,7 +174,7 @@ export class RPCProtocolImpl implements RPCProtocol {
return instance;
}

initialize<T>(proxyId: ProxyIdentifier<T>): void {
protected initialize<T>(proxyId: ProxyIdentifier<T>): void {
/* make sure proxy exists */
this.getProxy(proxyId);
/* init */
Expand Down
12 changes: 7 additions & 5 deletions packages/plugin-ext/src/hosted/browser/worker/worker-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import 'reflect-metadata';
import { BasicChannel } from '@theia/core/lib/common/message-rpc/channel';
import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from '@theia/core/lib/common/message-rpc/uint8-array-message-buffer';
import * as theia from '@theia/plugin';
import { emptyPlugin, MAIN_RPC_CONTEXT, Plugin, TerminalServiceExt } from '../../../common/plugin-api-rpc';
import { emptyPlugin, MAIN_RPC_CONTEXT, Plugin, TerminalServiceExt, PLUGIN_RPC_CONTEXT } from '../../../common/plugin-api-rpc';
import { ExtPluginApi } from '../../../common/plugin-ext-api-contribution';
import { getPluginId, PluginMetadata } from '../../../common/plugin-protocol';
import { RPCProtocolImpl } from '../../../common/rpc-protocol';
Expand Down Expand Up @@ -208,12 +208,14 @@ const handler = {
};
ctx['theia'] = new Proxy(Object.create(null), handler);

rpc.set(MAIN_RPC_CONTEXT.HOSTED_PLUGIN_MANAGER_EXT, pluginManager);
rpc.set(MAIN_RPC_CONTEXT.HOSTED_PLUGIN_MANAGER_EXT, pluginManager,
new Set([PLUGIN_RPC_CONTEXT.PREFERENCE_REGISTRY_MAIN, PLUGIN_RPC_CONTEXT.MESSAGE_REGISTRY_MAIN, PLUGIN_RPC_CONTEXT.NOTIFICATION_MAIN, PLUGIN_RPC_CONTEXT.STORAGE_MAIN,
PLUGIN_RPC_CONTEXT.WEBVIEWS_MAIN]));
rpc.set(MAIN_RPC_CONTEXT.EDITORS_AND_DOCUMENTS_EXT, editorsAndDocuments);
rpc.set(MAIN_RPC_CONTEXT.WORKSPACE_EXT, workspaceExt);
rpc.set(MAIN_RPC_CONTEXT.PREFERENCE_REGISTRY_EXT, preferenceRegistryExt);
rpc.set(MAIN_RPC_CONTEXT.WORKSPACE_EXT, workspaceExt, new Set([PLUGIN_RPC_CONTEXT.WORKSPACE_MAIN, PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN, PLUGIN_RPC_CONTEXT.TEXT_EDITORS_MAIN]));
rpc.set(MAIN_RPC_CONTEXT.PREFERENCE_REGISTRY_EXT, preferenceRegistryExt, new Set([PLUGIN_RPC_CONTEXT.PREFERENCE_REGISTRY_MAIN, PLUGIN_RPC_CONTEXT.WORKSPACE_MAIN]));
rpc.set(MAIN_RPC_CONTEXT.STORAGE_EXT, storageProxy);
rpc.set(MAIN_RPC_CONTEXT.WEBVIEWS_EXT, webviewExt);
rpc.set(MAIN_RPC_CONTEXT.WEBVIEWS_EXT, webviewExt, new Set([PLUGIN_RPC_CONTEXT.WEBVIEWS_MAIN, PLUGIN_RPC_CONTEXT.WORKSPACE_MAIN]));

function isElectron(): boolean {
if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {
Expand Down
13 changes: 7 additions & 6 deletions packages/plugin-ext/src/main/browser/main-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,14 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_EDITORS_MAIN, notebookEditorsMain);
const notebookDocumentsMain = new NotebookDocumentsMainImpl(rpc, container);
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN, notebookDocumentsMain);
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_AND_EDITORS_MAIN, new NotebooksAndEditorsMain(rpc, container, notebookDocumentsMain, notebookEditorsMain));
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_AND_EDITORS_MAIN, new NotebooksAndEditorsMain(rpc, container, notebookDocumentsMain, notebookEditorsMain),
new Set([MAIN_RPC_CONTEXT.NOTEBOOKS_EXT, MAIN_RPC_CONTEXT.NOTEBOOK_EDITORS_EXT, MAIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_EXT]));
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_KERNELS_MAIN, new NotebookKernelsMainImpl(rpc, container));

const bulkEditService = container.get(MonacoBulkEditService);
const monacoEditorService = container.get(MonacoEditorService);
const editorsMain = new TextEditorsMainImpl(editorsAndDocuments, documentsMain, rpc, bulkEditService, monacoEditorService);
rpc.set(PLUGIN_RPC_CONTEXT.TEXT_EDITORS_MAIN, editorsMain);
rpc.set(PLUGIN_RPC_CONTEXT.TEXT_EDITORS_MAIN, editorsMain, new Set([MAIN_RPC_CONTEXT.TEXT_EDITORS_EXT, MAIN_RPC_CONTEXT.DOCUMENTS_EXT]));

// start listening only after all clients are subscribed to events
editorsAndDocuments.listen();
Expand All @@ -132,7 +133,7 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
rpc.set(PLUGIN_RPC_CONTEXT.NOTIFICATION_MAIN, notificationMain);

const testingMain = new TestingMainImpl(rpc, container, commandRegistryMain);
rpc.set(PLUGIN_RPC_CONTEXT.TESTING_MAIN, testingMain);
rpc.set(PLUGIN_RPC_CONTEXT.TESTING_MAIN, testingMain, new Set([MAIN_RPC_CONTEXT.TESTING_EXT, MAIN_RPC_CONTEXT.COMMAND_REGISTRY_EXT]));

const terminalMain = new TerminalServiceMainImpl(rpc, container);
rpc.set(PLUGIN_RPC_CONTEXT.TERMINAL_MAIN, terminalMain);
Expand All @@ -152,10 +153,10 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
rpc.set(PLUGIN_RPC_CONTEXT.WEBVIEWS_MAIN, webviewsMain);

const customEditorsMain = new CustomEditorsMainImpl(rpc, container, webviewsMain);
rpc.set(PLUGIN_RPC_CONTEXT.CUSTOM_EDITORS_MAIN, customEditorsMain);
rpc.set(PLUGIN_RPC_CONTEXT.CUSTOM_EDITORS_MAIN, customEditorsMain, new Set([MAIN_RPC_CONTEXT.CUSTOM_EDITORS_EXT, MAIN_RPC_CONTEXT.WEBVIEWS_EXT]));

const webviewViewsMain = new WebviewViewsMainImpl(rpc, container, webviewsMain);
rpc.set(PLUGIN_RPC_CONTEXT.WEBVIEW_VIEWS_MAIN, webviewViewsMain);
rpc.set(PLUGIN_RPC_CONTEXT.WEBVIEW_VIEWS_MAIN, webviewViewsMain, new Set([MAIN_RPC_CONTEXT.WEBVIEW_VIEWS_EXT, MAIN_RPC_CONTEXT.WEBVIEWS_EXT]));

const storageMain = new StorageMainImpl(container);
rpc.set(PLUGIN_RPC_CONTEXT.STORAGE_MAIN, storageMain);
Expand All @@ -167,7 +168,7 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
rpc.set(PLUGIN_RPC_CONTEXT.TASKS_MAIN, tasksMain);

const debugMain = new DebugMainImpl(rpc, connectionMain, container);
rpc.set(PLUGIN_RPC_CONTEXT.DEBUG_MAIN, debugMain);
rpc.set(PLUGIN_RPC_CONTEXT.DEBUG_MAIN, debugMain, new Set([MAIN_RPC_CONTEXT.DEBUG_EXT, MAIN_RPC_CONTEXT.CONNECTION_EXT]));

const fs = new FileSystemMainImpl(rpc, container);
const fsEventService = new MainFileSystemEventService(rpc, container);
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/plugin/node/debug/debug.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('Debug API', () => {
},
dispose(): void {
// Nothing
},
}
};

const debug = new DebugExtImpl(mockRPCProtocol);
Expand Down
34 changes: 23 additions & 11 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,31 +272,43 @@ export function createAPIFactory(
const notificationExt = rpc.set(MAIN_RPC_CONTEXT.NOTIFICATION_EXT, new NotificationExtImpl(rpc));
const editors = rpc.set(MAIN_RPC_CONTEXT.TEXT_EDITORS_EXT, new TextEditorsExtImpl(rpc, editorsAndDocumentsExt));
const documents = rpc.set(MAIN_RPC_CONTEXT.DOCUMENTS_EXT, new DocumentsExtImpl(rpc, editorsAndDocumentsExt));
const notebooksExt = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOKS_EXT, new NotebooksExtImpl(rpc, commandRegistry, editorsAndDocumentsExt, documents));
const notebooksExt = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOKS_EXT, new NotebooksExtImpl(rpc, commandRegistry, editorsAndDocumentsExt, documents),
new Set([PLUGIN_RPC_CONTEXT.NOTEBOOKS_MAIN, PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN, PLUGIN_RPC_CONTEXT.NOTEBOOK_EDITORS_MAIN,
PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN, PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN]));
const notebookEditors = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOK_EDITORS_EXT, new NotebookEditorsExtImpl(notebooksExt));
const notebookRenderers = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOK_RENDERERS_EXT, new NotebookRenderersExtImpl(rpc, notebooksExt));
const notebookKernels = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOK_KERNELS_EXT, new NotebookKernelsExtImpl(rpc, notebooksExt, commandRegistry));
const notebookRenderers = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOK_RENDERERS_EXT, new NotebookRenderersExtImpl(rpc, notebooksExt),
new Set([PLUGIN_RPC_CONTEXT.NOTEBOOK_RENDERERS_MAIN, PLUGIN_RPC_CONTEXT.NOTEBOOKS_MAIN, PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN,
PLUGIN_RPC_CONTEXT.NOTEBOOK_EDITORS_MAIN]));
const notebookKernels = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOK_KERNELS_EXT, new NotebookKernelsExtImpl(rpc, notebooksExt, commandRegistry),
new Set([PLUGIN_RPC_CONTEXT.NOTEBOOK_KERNELS_MAIN, PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN, PLUGIN_RPC_CONTEXT.NOTEBOOKS_MAIN, PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN,
PLUGIN_RPC_CONTEXT.NOTEBOOK_EDITORS_MAIN]));
const notebookDocuments = rpc.set(MAIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_EXT, new NotebookDocumentsExtImpl(notebooksExt));
const statusBarMessageRegistryExt = new StatusBarMessageRegistryExt(rpc);
const terminalExt = rpc.set(MAIN_RPC_CONTEXT.TERMINAL_EXT, new TerminalServiceExtImpl(rpc));
const outputChannelRegistryExt = rpc.set(MAIN_RPC_CONTEXT.OUTPUT_CHANNEL_REGISTRY_EXT, new OutputChannelRegistryExtImpl(rpc));
const treeViewsExt = rpc.set(MAIN_RPC_CONTEXT.TREE_VIEWS_EXT, new TreeViewsExtImpl(rpc, commandRegistry));
const tasksExt = rpc.set(MAIN_RPC_CONTEXT.TASKS_EXT, new TasksExtImpl(rpc, terminalExt));
const treeViewsExt = rpc.set(MAIN_RPC_CONTEXT.TREE_VIEWS_EXT, new TreeViewsExtImpl(rpc, commandRegistry),
new Set([PLUGIN_RPC_CONTEXT.TREE_VIEWS_MAIN, PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN]));
const tasksExt = rpc.set(MAIN_RPC_CONTEXT.TASKS_EXT, new TasksExtImpl(rpc, terminalExt), new Set([PLUGIN_RPC_CONTEXT.TASKS_MAIN, PLUGIN_RPC_CONTEXT.TERMINAL_MAIN]));
const connectionExt = rpc.set(MAIN_RPC_CONTEXT.CONNECTION_EXT, new ConnectionImpl(rpc.getProxy(PLUGIN_RPC_CONTEXT.CONNECTION_MAIN)));
const fileSystemExt = rpc.set(MAIN_RPC_CONTEXT.FILE_SYSTEM_EXT, new FileSystemExtImpl(rpc));
const languagesExt = rpc.set(MAIN_RPC_CONTEXT.LANGUAGES_EXT, new LanguagesExtImpl(rpc, documents, commandRegistry, fileSystemExt));
const languagesExt = rpc.set(MAIN_RPC_CONTEXT.LANGUAGES_EXT, new LanguagesExtImpl(rpc, documents, commandRegistry, fileSystemExt),
new Set([PLUGIN_RPC_CONTEXT.LANGUAGES_MAIN, PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN, PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN, PLUGIN_RPC_CONTEXT.FILE_SYSTEM_MAIN]));
const extHostFileSystemEvent = rpc.set(MAIN_RPC_CONTEXT.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpc, editorsAndDocumentsExt));
const scmExt = rpc.set(MAIN_RPC_CONTEXT.SCM_EXT, new ScmExtImpl(rpc, commandRegistry));
const scmExt = rpc.set(MAIN_RPC_CONTEXT.SCM_EXT, new ScmExtImpl(rpc, commandRegistry), new Set([PLUGIN_RPC_CONTEXT.SCM_MAIN, PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN]));
const decorationsExt = rpc.set(MAIN_RPC_CONTEXT.DECORATIONS_EXT, new DecorationsExtImpl(rpc));
const labelServiceExt = rpc.set(MAIN_RPC_CONTEXT.LABEL_SERVICE_EXT, new LabelServiceExtImpl(rpc));
const timelineExt = rpc.set(MAIN_RPC_CONTEXT.TIMELINE_EXT, new TimelineExtImpl(rpc, commandRegistry));
const timelineExt = rpc.set(MAIN_RPC_CONTEXT.TIMELINE_EXT, new TimelineExtImpl(rpc, commandRegistry),
new Set([PLUGIN_RPC_CONTEXT.TIMELINE_MAIN, PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN]));
const themingExt = rpc.set(MAIN_RPC_CONTEXT.THEMING_EXT, new ThemingExtImpl(rpc));
const commentsExt = rpc.set(MAIN_RPC_CONTEXT.COMMENTS_EXT, new CommentsExtImpl(rpc, commandRegistry, documents));
const commentsExt = rpc.set(MAIN_RPC_CONTEXT.COMMENTS_EXT, new CommentsExtImpl(rpc, commandRegistry, documents),
new Set([PLUGIN_RPC_CONTEXT.COMMENTS_MAIN, PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN, PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN]));
const tabsExt = rpc.set(MAIN_RPC_CONTEXT.TABS_EXT, new TabsExtImpl(rpc));
const customEditorExt = rpc.set(MAIN_RPC_CONTEXT.CUSTOM_EDITORS_EXT, new CustomEditorsExtImpl(rpc, documents, webviewExt, workspaceExt));
const customEditorExt = rpc.set(MAIN_RPC_CONTEXT.CUSTOM_EDITORS_EXT, new CustomEditorsExtImpl(rpc, documents, webviewExt, workspaceExt),
new Set([PLUGIN_RPC_CONTEXT.CUSTOM_EDITORS_MAIN, PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN]));
const webviewViewsExt = rpc.set(MAIN_RPC_CONTEXT.WEBVIEW_VIEWS_EXT, new WebviewViewsExtImpl(rpc, webviewExt));
const telemetryExt = rpc.set(MAIN_RPC_CONTEXT.TELEMETRY_EXT, new TelemetryExtImpl());
const testingExt = rpc.set(MAIN_RPC_CONTEXT.TESTING_EXT, new TestingExtImpl(rpc, commandRegistry));
const testingExt = rpc.set(MAIN_RPC_CONTEXT.TESTING_EXT, new TestingExtImpl(rpc, commandRegistry),
new Set([PLUGIN_RPC_CONTEXT.TESTING_MAIN, PLUGIN_RPC_CONTEXT.COMMAND_REGISTRY_MAIN]));
rpc.set(MAIN_RPC_CONTEXT.DEBUG_EXT, debugExt);

return function (plugin: InternalPlugin): typeof theia {
Expand Down

0 comments on commit 5d35e32

Please sign in to comment.