diff --git a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts index 09118ecfa68bd858884a0946953dbfcbc243e6e7..d0ab516ec4715ce1056877b98c89502b65dbb46e 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDecorations.ts @@ -7,21 +7,69 @@ import URI, { UriComponents } from 'vs/base/common/uri'; import { Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { ExtHostContext, MainContext, IExtHostContext, MainThreadDecorationsShape, ExtHostDecorationsShape } from '../node/extHost.protocol'; +import { ExtHostContext, MainContext, IExtHostContext, MainThreadDecorationsShape, ExtHostDecorationsShape, DecorationData, DecorationRequest } from '../node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { IDecorationsService, IDecorationData } from 'vs/workbench/services/decorations/browser/decorations'; +class DecorationRequestsQueue { + + private _idPool = 0; + private _requests: DecorationRequest[] = []; + private _resolver: { [id: number]: Function } = Object.create(null); + + private _timer: number; + + constructor( + private _proxy: ExtHostDecorationsShape + ) { + // + } + + enqueue(handle: number, uri: URI): Thenable { + return new Promise((resolve, reject) => { + const id = ++this._idPool; + this._requests.push({ id, handle, uri }); + this._resolver[id] = resolve; + this._processQueue(); + }); + } + + private _processQueue(): void { + if (typeof this._timer === 'number') { + // already queued + return; + } + this._timer = setTimeout(() => { + // make request + const requests = this._requests; + const resolver = this._resolver; + this._proxy.$provideDecorations(requests).then(data => { + for (const id in resolver) { + resolver[id](data[id]); + } + }); + + // reset + this._requests = []; + this._resolver = []; + this._timer = void 0; + }, 0); + } +} + @extHostNamedCustomer(MainContext.MainThreadDecorations) export class MainThreadDecorations implements MainThreadDecorationsShape { private readonly _provider = new Map, IDisposable]>(); private readonly _proxy: ExtHostDecorationsShape; + private readonly _requestQueue: DecorationRequestsQueue; constructor( context: IExtHostContext, @IDecorationsService private readonly _decorationsService: IDecorationsService ) { this._proxy = context.getProxy(ExtHostContext.ExtHostDecorations); + this._requestQueue = new DecorationRequestsQueue(this._proxy); } dispose() { @@ -30,12 +78,12 @@ export class MainThreadDecorations implements MainThreadDecorationsShape { } $registerDecorationProvider(handle: number, label: string): void { - let emitter = new Emitter(); - let registration = this._decorationsService.registerDecorationsProvider({ + const emitter = new Emitter(); + const registration = this._decorationsService.registerDecorationsProvider({ label, onDidChange: emitter.event, provideDecorations: (uri) => { - return this._proxy.$provideDecorations(handle, uri).then(data => { + return this._requestQueue.enqueue(handle, uri).then(data => { if (!data) { return undefined; } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 07acb77672f12a408bd49df341fd5a2640f21013..d4ed202afab02057b1e62f995c79c7b5999ed481 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -719,10 +719,17 @@ export interface ExtHostDebugServiceShape { } +export interface DecorationRequest { + readonly id: number; + readonly handle: number; + readonly uri: UriComponents; +} + export type DecorationData = [number, boolean, string, string, ThemeColor, string]; +export type DecorationReply = { [id: number]: DecorationData }; export interface ExtHostDecorationsShape { - $provideDecorations(handle: number, uri: UriComponents): TPromise; + $provideDecorations(requests: DecorationRequest[]): TPromise; } export interface ExtHostWindowShape { diff --git a/src/vs/workbench/api/node/extHostDecorations.ts b/src/vs/workbench/api/node/extHostDecorations.ts index cdbfc5e482c17f3294bfaf96dcf120ca880f6e32..89987b137bbea50e99aaa85b51ce4f1e9f64989b 100644 --- a/src/vs/workbench/api/node/extHostDecorations.ts +++ b/src/vs/workbench/api/node/extHostDecorations.ts @@ -5,8 +5,8 @@ 'use strict'; import * as vscode from 'vscode'; -import URI, { UriComponents } from 'vs/base/common/uri'; -import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData } from 'vs/workbench/api/node/extHost.protocol'; +import URI from 'vs/base/common/uri'; +import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData, DecorationRequest, DecorationReply } from 'vs/workbench/api/node/extHost.protocol'; import { TPromise } from 'vs/base/common/winjs.base'; import { Disposable } from 'vs/workbench/api/node/extHostTypes'; import { asWinJsPromise } from 'vs/base/common/async'; @@ -38,10 +38,19 @@ export class ExtHostDecorations implements ExtHostDecorationsShape { }); } - $provideDecorations(handle: number, data: UriComponents): TPromise { - const provider = this._provider.get(handle); - return asWinJsPromise(token => provider.provideDecoration(URI.revive(data), token)).then(data => { - return data && [data.priority, data.bubble, data.title, data.abbreviation, data.color, data.source]; + $provideDecorations(requests: DecorationRequest[]): TPromise { + const result: DecorationReply = Object.create(null); + return TPromise.join(requests.map(request => { + const { handle, uri, id } = request; + const provider = this._provider.get(handle); + return asWinJsPromise(token => provider.provideDecoration(URI.revive(uri), token)).then(data => { + result[id] = data && [data.priority, data.bubble, data.title, data.abbreviation, data.color, data.source]; + }, err => { + console.error(err); + }); + + })).then(() => { + return result; }); } }