From 755c02a3abe5dddbb76e785a8c05230457899b8b Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Tue, 6 Nov 2018 12:51:24 +0100 Subject: [PATCH] Fixes #62655: mainThreadTask should use unique keys for task provider registration --- .../api/electron-browser/mainThreadTask.ts | 28 ++++++++++--------- .../parts/tasks/common/taskService.ts | 4 +-- .../electron-browser/task.contribution.ts | 18 ++++++++---- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadTask.ts b/src/vs/workbench/api/electron-browser/mainThreadTask.ts index 545e9f7d2a6..8d827f0bacb 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTask.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTask.ts @@ -11,6 +11,7 @@ import * as Objects from 'vs/base/common/objects'; import * as Types from 'vs/base/common/types'; import * as Platform from 'vs/base/common/platform'; import { IStringDictionary } from 'vs/base/common/collections'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -19,9 +20,11 @@ import { PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource, TaskSourceKind, ExtensionTaskSource, RevealKind, PanelKind } from 'vs/workbench/parts/tasks/common/tasks'; -import { TaskDefinition } from 'vs/workbench/parts/tasks/node/tasks'; -import { ITaskService, TaskFilter } from 'vs/workbench/parts/tasks/common/taskService'; +import { ResolveSet, ResolvedVariables } from 'vs/workbench/parts/tasks/common/taskSystem'; +import { ITaskService, TaskFilter, ITaskProvider } from 'vs/workbench/parts/tasks/common/taskService'; + +import { TaskDefinition } from 'vs/workbench/parts/tasks/node/tasks'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/node/extHost.protocol'; @@ -29,7 +32,6 @@ import { TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO, ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO } from 'vs/workbench/api/shared/tasks'; -import { ResolveSet, ResolvedVariables } from 'vs/workbench/parts/tasks/common/taskSystem'; namespace TaskExecutionDTO { export function from(value: TaskExecution): TaskExecutionDTO { @@ -362,7 +364,7 @@ export class MainThreadTask implements MainThreadTaskShape { private _extHostContext: IExtHostContext; private _proxy: ExtHostTaskShape; - private _activeHandles: { [handle: number]: boolean; }; + private _providers: Map; constructor( extHostContext: IExtHostContext, @@ -370,7 +372,7 @@ export class MainThreadTask implements MainThreadTaskShape { @IWorkspaceContextService private readonly _workspaceContextServer: IWorkspaceContextService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTask); - this._activeHandles = Object.create(null); + this._providers = new Map(); this._taskService.onDidStateChange((event: TaskEvent) => { let task = event.__task; if (event.kind === TaskEventKind.Start) { @@ -386,14 +388,14 @@ export class MainThreadTask implements MainThreadTaskShape { } public dispose(): void { - Object.keys(this._activeHandles).forEach((handle) => { - this._taskService.unregisterTaskProvider(parseInt(handle, 10)); + this._providers.forEach((value) => { + value.disposable.dispose(); }); - this._activeHandles = Object.create(null); + this._providers.clear(); } public $registerTaskProvider(handle: number): Thenable { - this._taskService.registerTaskProvider(handle, { + let provider: ITaskProvider = { provideTasks: (validTypes: IStringDictionary) => { return Promise.resolve(this._proxy.$provideTasks(handle, validTypes)).then((value) => { let tasks: Task[] = []; @@ -417,14 +419,14 @@ export class MainThreadTask implements MainThreadTaskShape { return value; }); } - }); - this._activeHandles[handle] = true; + }; + let disposable = this._taskService.registerTaskProvider(provider); + this._providers.set(handle, { disposable, provider }); return Promise.resolve(undefined); } public $unregisterTaskProvider(handle: number): Thenable { - this._taskService.unregisterTaskProvider(handle); - delete this._activeHandles[handle]; + this._providers.delete(handle); return Promise.resolve(undefined); } diff --git a/src/vs/workbench/parts/tasks/common/taskService.ts b/src/vs/workbench/parts/tasks/common/taskService.ts index 316d7878209..6eed335a670 100644 --- a/src/vs/workbench/parts/tasks/common/taskService.ts +++ b/src/vs/workbench/parts/tasks/common/taskService.ts @@ -8,6 +8,7 @@ import { Action } from 'vs/base/common/actions'; import { Event } from 'vs/base/common/event'; import { LinkedMap } from 'vs/base/common/map'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { Task, ContributedTask, CustomTask, TaskSet, TaskSorter, TaskEvent, TaskIdentifier } from 'vs/workbench/parts/tasks/common/tasks'; @@ -66,8 +67,7 @@ export interface ITaskService { customize(task: ContributedTask | CustomTask, properties?: {}, openConfig?: boolean): TPromise; openConfig(task: CustomTask): TPromise; - registerTaskProvider(handle: number, taskProvider: ITaskProvider): void; - unregisterTaskProvider(handle: number): boolean; + registerTaskProvider(taskProvider: ITaskProvider): IDisposable; registerTaskSystem(scheme: string, taskSystemInfo: TaskSystemInfo): void; } diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index f7be344a054..947b379a079 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -444,6 +444,8 @@ class TaskService extends Disposable implements ITaskService { public static OutputChannelId: string = 'tasks'; public static OutputChannelLabel: string = nls.localize('tasks', "Tasks"); + private static nextHandle: number = 0; + private _configHasErrors: boolean; private _schemaVersion: JsonSchemaVersion; private _executionEngine: ExecutionEngine; @@ -675,15 +677,19 @@ class TaskService extends Disposable implements ITaskService { } } - public registerTaskProvider(handle: number, provider: ITaskProvider): void { + public registerTaskProvider(provider: ITaskProvider): IDisposable { if (!provider) { - return; + return { + dispose: () => { } + }; } + let handle = TaskService.nextHandle++; this._providers.set(handle, provider); - } - - public unregisterTaskProvider(handle: number): boolean { - return this._providers.delete(handle); + return { + dispose: () => { + this._providers.delete(handle); + } + }; } public registerTaskSystem(key: string, info: TaskSystemInfo): void {