diff --git a/src/vs/workbench/api/browser/mainThreadTask.ts b/src/vs/workbench/api/browser/mainThreadTask.ts index 75144c79406..8b37ab49c14 100644 --- a/src/vs/workbench/api/browser/mainThreadTask.ts +++ b/src/vs/workbench/api/browser/mainThreadTask.ts @@ -510,41 +510,41 @@ export class MainThreadTask implements MainThreadTaskShape { }); } - public $executeTask(value: TaskHandleDTO | TaskDTO): Promise { - return new Promise((resolve, reject) => { - if (TaskHandleDTO.is(value)) { - const workspaceFolder = typeof value.workspaceFolder === 'string' ? value.workspaceFolder : this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder)); - if (workspaceFolder) { - this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task | undefined) => { - if (!task) { - reject(new Error('Task not found')); - } else { - const result: TaskExecutionDTO = { - id: value.id, - task: TaskDTO.from(task) - }; - resolve(result); - this._taskService.run(task).then(undefined, reason => { - // eat the error, it has already been surfaced to the user and we don't care about it here - }); - } - }, (_error) => { - reject(new Error('Task not found')); - }); - } else { - reject(new Error('No workspace folder')); + public async $getTaskExecution(value: TaskHandleDTO | TaskDTO): Promise { + if (TaskHandleDTO.is(value)) { + const workspaceFolder = typeof value.workspaceFolder === 'string' ? value.workspaceFolder : this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder)); + if (workspaceFolder) { + const task = await this._taskService.getTask(workspaceFolder, value.id, true); + if (task) { + return { + id: task._id, + task: TaskDTO.from(task) + }; } + throw new Error('Task not found'); } else { - const task = TaskDTO.to(value, this._workspaceContextServer, true)!; - const result: TaskExecutionDTO = { - id: task._id, - task: TaskDTO.from(task) - }; - resolve(result); - this._taskService.run(task).then(undefined, reason => { - // eat the error, it has already been surfaced to the user and we don't care about it here - }); + throw new Error('No workspace folder'); } + } else { + const task = TaskDTO.to(value, this._workspaceContextServer, true)!; + return { + id: task._id, + task: TaskDTO.from(task) + }; + } + } + + public $executeTask(value: TaskDTO): Promise { + return new Promise((resolve, reject) => { + const task = TaskDTO.to(value, this._workspaceContextServer, true)!; + this._taskService.run(task).then(undefined, reason => { + // eat the error, it has already been surfaced to the user and we don't care about it here + }); + const result: TaskExecutionDTO = { + id: task._id, + task: TaskDTO.from(task) + }; + resolve(result); }); } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 6936e77dd34..f35f7b80b9d 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -774,7 +774,8 @@ export interface MainThreadTaskShape extends IDisposable { $registerTaskProvider(handle: number, type: string): Promise; $unregisterTaskProvider(handle: number): Promise; $fetchTasks(filter?: tasks.TaskFilterDTO): Promise; - $executeTask(task: tasks.TaskHandleDTO | tasks.TaskDTO): Promise; + $getTaskExecution(value: tasks.TaskHandleDTO | tasks.TaskDTO): Promise; + $executeTask(task: tasks.TaskDTO): Promise; $terminateTask(id: string): Promise; $registerTaskSystem(scheme: string, info: tasks.TaskSystemInfoDTO): void; $customExecutionComplete(id: string, result?: number): Promise; diff --git a/src/vs/workbench/api/common/extHostTask.ts b/src/vs/workbench/api/common/extHostTask.ts index 271ee362aaf..fd67691d82b 100644 --- a/src/vs/workbench/api/common/extHostTask.ts +++ b/src/vs/workbench/api/common/extHostTask.ts @@ -718,7 +718,9 @@ export class WorkerExtHostTask extends ExtHostTaskBase { throw new Error('Not implemented'); } - return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task)); + // Always get the task execution first to prevent timing issues when retrieving it later + const execution = await this.getTaskExecution(await this._proxy.$getTaskExecution(dto), task); + return this._proxy.$executeTask(dto).then(() => execution); } protected provideTasksInternal(validTypes: { [key: string]: boolean; }, taskIdPromises: Promise[], handler: HandlerData, value: vscode.Task[] | null | undefined): { tasks: tasks.TaskDTO[], extension: IExtensionDescription } { diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 5ec632cc283..8f21cd8c316 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -53,7 +53,13 @@ export class ExtHostTask extends ExtHostTaskBase { const tTask = (task as types.Task); // We have a preserved ID. So the task didn't change. if (tTask._id !== undefined) { - return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, task)); + // Always get the task execution first to prevent timing issues when retrieving it later + const executionDTO = await this._proxy.$getTaskExecution(TaskHandleDTO.from(tTask)); + if (executionDTO.task === undefined) { + throw new Error('Task from execution DTO is undefined'); + } + const execution = await this.getTaskExecution(executionDTO, task); + return this._proxy.$executeTask(executionDTO.task).then(() => execution); } else { const dto = TaskDTO.from(task, extension); if (dto === undefined) { @@ -66,8 +72,9 @@ export class ExtHostTask extends ExtHostTaskBase { if (CustomExecutionDTO.is(dto.execution)) { await this.addCustomExecution(dto, task, false); } - - return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task)); + // Always get the task execution first to prevent timing issues when retrieving it later + const execution = await this.getTaskExecution(await this._proxy.$getTaskExecution(dto), task); + return this._proxy.$executeTask(dto).then(() => execution); } }