Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap api objects returned to clients in a proxy #14213

Merged
merged 3 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions packages/plugin-ext/src/plugin/file-system-ext-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ import { State, StateMachine, LinkComputer, Edge } from '../common/link-computer
import { commonPrefixLength } from '@theia/core/lib/common/strings';
import { CharCode } from '@theia/core/lib/common/char-code';
import { BinaryBuffer } from '@theia/core/lib/common/buffer';
import { Emitter } from '@theia/core/shared/vscode-languageserver-protocol';
import { MarkdownString } from '../common/plugin-api-rpc-model';
import { Emitter } from '@theia/core/lib/common';
import { createAPIObject } from './plugin-context';

type IDisposable = vscode.Disposable;

Expand Down Expand Up @@ -137,8 +138,11 @@ export class FsLinkProvider {
}

class ConsumerFileSystem implements vscode.FileSystem {
apiObject: vscode.FileSystem;

constructor(private _proxy: FileSystemMain, private _capabilities: Map<string, number>) { }
constructor(private _proxy: FileSystemMain, private _capabilities: Map<string, number>) {
this.apiObject = createAPIObject(this);
}

stat(uri: vscode.Uri): Promise<vscode.FileStat> {
return this._proxy.$stat(uri).catch(ConsumerFileSystem._handleError);
Expand Down Expand Up @@ -210,7 +214,7 @@ export class FileSystemExtImpl implements FileSystemExt {

private _handlePool: number = 0;

readonly fileSystem: vscode.FileSystem;
readonly fileSystem: ConsumerFileSystem;

constructor(rpc: RPCProtocol) {
this._proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.FILE_SYSTEM_MAIN);
Expand Down
48 changes: 34 additions & 14 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,21 @@ import { NotebookEditorsExtImpl } from './notebook/notebook-editors';
import { TestingExtImpl } from './tests';
import { UriExtImpl } from './uri-ext';

export function createAPIObject<T extends Object>(rawObject: T): T {
return new Proxy({}, {
get(target, p, receiver) {
const isOwnProperty = !!Object.getOwnPropertyDescriptor(rawObject, p);
const val = Reflect.get(rawObject, p);
if (!isOwnProperty && typeof val === 'function') {
// bind functions that are inherited from the prototype to the object itself.
// This should handle the case of events.
return val.bind(rawObject);
}
return val;
},
}) as T;
msujew marked this conversation as resolved.
Show resolved Hide resolved
}

export function createAPIFactory(
rpc: RPCProtocol,
pluginManager: PluginManager,
Expand Down Expand Up @@ -492,7 +507,8 @@ export function createAPIFactory(
return quickOpenExt.showQuickPick(plugin, items, options, token);
},
createQuickPick<T extends theia.QuickPickItem>(): theia.QuickPick<T> {
return quickOpenExt.createQuickPick(plugin);

return createAPIObject(quickOpenExt.createQuickPick(plugin));
},
showWorkspaceFolderPick(options?: theia.WorkspaceFolderPickOptions): PromiseLike<theia.WorkspaceFolder | undefined> {
return workspaceExt.pickWorkspaceFolder(options);
Expand Down Expand Up @@ -531,9 +547,12 @@ export function createAPIFactory(
priority = priorityOrAlignment;
}

// TODO: here
return statusBarMessageRegistryExt.createStatusBarItem(alignment, priority, id);
},
createOutputChannel(name: string, options?: { log: true }): any {

// TODO: here
return !options
? outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin))
: outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin), options);
Expand All @@ -542,7 +561,7 @@ export function createAPIFactory(
title: string,
showOptions: theia.ViewColumn | theia.WebviewPanelShowOptions,
options: theia.WebviewPanelOptions & theia.WebviewOptions = {}): theia.WebviewPanel {
return webviewExt.createWebview(viewType, title, showOptions, options, plugin);
return createAPIObject(webviewExt.createWebview(viewType, title, showOptions, options, plugin));
},
registerWebviewPanelSerializer(viewType: string, serializer: theia.WebviewPanelSerializer): theia.Disposable {
return webviewExt.registerWebviewPanelSerializer(viewType, serializer, plugin);
Expand Down Expand Up @@ -570,19 +589,19 @@ export function createAPIFactory(
createTerminal(nameOrOptions: theia.TerminalOptions | theia.ExtensionTerminalOptions | theia.ExtensionTerminalOptions | (string | undefined),
shellPath?: string,
shellArgs?: string[] | string): theia.Terminal {
return terminalExt.createTerminal(plugin, nameOrOptions, shellPath, shellArgs);
return createAPIObject(terminalExt.createTerminal(plugin, nameOrOptions, shellPath, shellArgs));
},
onDidChangeTerminalState,
onDidCloseTerminal,
onDidOpenTerminal,
createTextEditorDecorationType(options: theia.DecorationRenderOptions): theia.TextEditorDecorationType {
return editors.createTextEditorDecorationType(options);
return createAPIObject(editors.createTextEditorDecorationType(options));
},
registerTreeDataProvider<T>(viewId: string, treeDataProvider: theia.TreeDataProvider<T>): Disposable {
return treeViewsExt.registerTreeDataProvider(plugin, viewId, treeDataProvider);
},
createTreeView<T>(viewId: string, options: theia.TreeViewOptions<T>): theia.TreeView<T> {
return treeViewsExt.createTreeView(plugin, viewId, options);
return createAPIObject(treeViewsExt.createTreeView(plugin, viewId, options));
},
withScmProgress<R>(task: (progress: theia.Progress<number>) => Thenable<R>) {
const options: ProgressOptions = { location: ProgressLocation.SourceControl };
Expand All @@ -601,7 +620,7 @@ export function createAPIFactory(
return uriExt.registerUriHandler(handler, pluginToPluginInfo(plugin));
},
createInputBox(): theia.InputBox {
return quickOpenExt.createInputBox(plugin);
return createAPIObject(quickOpenExt.createInputBox(plugin));
},
registerTerminalLinkProvider(provider: theia.TerminalLinkProvider): theia.Disposable {
return terminalExt.registerTerminalLinkProvider(provider);
Expand Down Expand Up @@ -649,7 +668,7 @@ export function createAPIFactory(
const workspace: typeof theia.workspace = {

get fs(): theia.FileSystem {
return fileSystemExt.fileSystem;
return fileSystemExt.fileSystem.apiObject;
},

get rootPath(): string | undefined {
Expand Down Expand Up @@ -752,7 +771,7 @@ export function createAPIFactory(
return notebooksExt.getNotebookDocument(uri).apiNotebook;
},
createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): theia.FileSystemWatcher =>
extHostFileSystemEvent.createFileSystemWatcher(fromGlobPattern(pattern), ignoreCreate, ignoreChange, ignoreDelete),
createAPIObject(extHostFileSystemEvent.createFileSystemWatcher(fromGlobPattern(pattern), ignoreCreate, ignoreChange, ignoreDelete)),
findFiles(include: theia.GlobPattern, exclude?: theia.GlobPattern | null, maxResults?: number, token?: CancellationToken): PromiseLike<URI[]> {
return workspaceExt.findFiles(include, exclude, maxResults, token);
},
Expand Down Expand Up @@ -845,7 +864,7 @@ export function createAPIFactory(
return telemetryExt.onDidChangeTelemetryEnabled;
},
createTelemetryLogger(sender: theia.TelemetrySender, options?: theia.TelemetryLoggerOptions): theia.TelemetryLogger {
return telemetryExt.createTelemetryLogger(sender, options);
return createAPIObject(telemetryExt.createTelemetryLogger(sender, options));
},
get remoteName(): string | undefined { return envExt.remoteName; },
get machineId(): string { return envExt.machineId; },
Expand Down Expand Up @@ -920,7 +939,7 @@ export function createAPIFactory(
return <any>languagesExt.getDiagnostics(resource);
},
createDiagnosticCollection(name?: string): theia.DiagnosticCollection {
return languagesExt.createDiagnosticCollection(name);
return createAPIObject(languagesExt.createDiagnosticCollection(name));
},
setLanguageConfiguration(language: string, configuration: theia.LanguageConfiguration): theia.Disposable {
return languagesExt.setLanguageConfiguration(language, configuration);
Expand Down Expand Up @@ -1057,7 +1076,7 @@ export function createAPIFactory(

const tests: typeof theia.tests = {
createTestController(id, label: string) {
return testingExt.createTestController(id, label);
return createAPIObject(testingExt.createTestController(id, label));
}
};
/* End of Tests API */
Expand Down Expand Up @@ -1169,6 +1188,7 @@ export function createAPIFactory(
},

get taskExecutions(): ReadonlyArray<theia.TaskExecution> {
// TODO: here
return tasksExt.taskExecutions;
},
onDidStartTask(listener, thisArg?, disposables?) {
Expand All @@ -1189,19 +1209,19 @@ export function createAPIFactory(
get inputBox(): theia.SourceControlInputBox {
const inputBox = scmExt.getLastInputBox(plugin);
if (inputBox) {
return inputBox;
return inputBox.apiObject;
} else {
throw new Error('Input box not found!');
}
},
createSourceControl(id: string, label: string, rootUri?: URI): theia.SourceControl {
return scmExt.createSourceControl(plugin, id, label, rootUri);
return createAPIObject(scmExt.createSourceControl(plugin, id, label, rootUri));
}
};

const comments: typeof theia.comments = {
createCommentController(id: string, label: string): theia.CommentController {
return commentsExt.createCommentController(plugin, id, label);
return createAPIObject(commentsExt.createCommentController(plugin, id, label));
}
};

Expand Down
9 changes: 5 additions & 4 deletions packages/plugin-ext/src/plugin/scm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { URI, ThemeIcon } from './types-impl';
import { ScmCommandArg } from '../common/plugin-api-rpc';
import { sep } from '@theia/core/lib/common/paths';
import { PluginIconPath } from './plugin-icon-path';
import { createAPIObject } from './plugin-context';
type ProviderHandle = number;
type GroupHandle = number;
type ResourceStateHandle = number;
Expand Down Expand Up @@ -290,6 +291,7 @@ interface ValidateInput {
export class ScmInputBoxImpl implements theia.SourceControlInputBox {

private _value: string = '';
apiObject: theia.SourceControlInputBox;

get value(): string {
return this._value;
Expand Down Expand Up @@ -354,7 +356,7 @@ export class ScmInputBoxImpl implements theia.SourceControlInputBox {
}

constructor(private plugin: Plugin, private proxy: ScmMain, private sourceControlHandle: number) {
// noop
this.apiObject = createAPIObject(this);
}

onInputBoxValueChange(value: string): void {
Expand Down Expand Up @@ -543,8 +545,7 @@ class SourceControlImpl implements theia.SourceControl {
return this._rootUri;
}

private _inputBox: ScmInputBoxImpl;
get inputBox(): ScmInputBoxImpl { return this._inputBox; }
readonly inputBox: ScmInputBoxImpl;

private _count: number | undefined = undefined;

Expand Down Expand Up @@ -642,7 +643,7 @@ class SourceControlImpl implements theia.SourceControl {
private _label: string,
private _rootUri?: theia.Uri
) {
this._inputBox = new ScmInputBoxImpl(plugin, this.proxy, this.handle);
this.inputBox = new ScmInputBoxImpl(plugin, this.proxy, this.handle);
this.proxy.$registerSourceControl(this.handle, _id, _label, _rootUri);
}

Expand Down
Loading