From 3e7fed03dc37734636bc673356f1c079d6154420 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 20 Apr 2022 17:00:44 +0300 Subject: [PATCH] Update the extension path tree after `$deltaExtensions` --- .../api/common/extHostExtensionService.ts | 91 +++++++++++-------- .../api/common/extHostRequireInterceptor.ts | 11 +-- 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 312ef8d884a..f67924248f5 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -106,7 +106,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme private readonly _secretState: ExtHostSecretState; private readonly _storagePath: IExtensionStoragePaths; private readonly _activator: ExtensionsActivator; - private _extensionPathIndex: Promise> | null; + private _extensionPathIndex: Promise | null; private readonly _resolvers: { [authorityPrefix: string]: vscode.RemoteAuthorityResolver }; @@ -330,9 +330,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } // create trie to enable fast 'filename -> extension id' look up - public async getExtensionPathIndex(): Promise> { + public async getExtensionPathIndex(): Promise { if (!this._extensionPathIndex) { - this._extensionPathIndex = this._createExtensionPathIndex(this._myRegistry.getAllExtensionDescriptions()); + this._extensionPathIndex = this._createExtensionPathIndex(this._myRegistry.getAllExtensionDescriptions()).then((searchTree) => { + return new ExtensionPaths(searchTree); + }); } return this._extensionPathIndex; } @@ -712,6 +714,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme } private _startExtensionHost(): Promise { + + console.log(`$startExtensionHost CALLED!`); + console.log(`myExtensions: ${this._myRegistry.getAllExtensionDescriptions().length} extensions`); + console.log(`allExtensions: ${this._globalRegistry.getAllExtensionDescriptions().length} extensions`); + if (this._started) { throw new Error(`Extension host is already started!`); } @@ -835,18 +842,28 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme return result; } - public $startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise { - extensionsDelta.toAdd.forEach((extension) => (extension).extensionLocation = URI.revive(extension.extensionLocation)); - this._globalRegistry.deltaExtensions(extensionsDelta.toAdd, extensionsDelta.toRemove); + private static _applyExtensionsDelta(oldGlobalRegistry: ExtensionDescriptionRegistry, oldMyRegistry: ExtensionDescriptionRegistry, extensionsDelta: IExtensionDescriptionDelta) { + const globalRegistry = new ExtensionDescriptionRegistry(oldGlobalRegistry.getAllExtensionDescriptions()); + globalRegistry.deltaExtensions(extensionsDelta.toAdd, extensionsDelta.toRemove); - const myExtensions = extensionIdentifiersArrayToSet(this._myRegistry.getAllExtensionDescriptions().map(extension => extension.identifier)); + const myExtensionsSet = extensionIdentifiersArrayToSet(oldMyRegistry.getAllExtensionDescriptions().map(extension => extension.identifier)); for (const extensionId of extensionsDelta.myToRemove) { - myExtensions.delete(ExtensionIdentifier.toKey(extensionId)); + myExtensionsSet.delete(ExtensionIdentifier.toKey(extensionId)); } for (const extensionId of extensionsDelta.myToAdd) { - myExtensions.add(ExtensionIdentifier.toKey(extensionId)); + myExtensionsSet.add(ExtensionIdentifier.toKey(extensionId)); } - this._myRegistry.set(filterExtensions(this._globalRegistry, myExtensions)); + const myExtensions = filterExtensions(globalRegistry, myExtensionsSet); + + return { globalRegistry, myExtensions }; + } + + public $startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise { + extensionsDelta.toAdd.forEach((extension) => (extension).extensionLocation = URI.revive(extension.extensionLocation)); + + const { globalRegistry, myExtensions } = AbstractExtHostExtensionService._applyExtensionsDelta(this._globalRegistry, this._myRegistry, extensionsDelta); + this._globalRegistry.set(globalRegistry.getAllExtensionDescriptions()); + this._myRegistry.set(myExtensions); return this._startExtensionHost(); } @@ -875,32 +892,13 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme public async $deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise { extensionsDelta.toAdd.forEach((extension) => (extension).extensionLocation = URI.revive(extension.extensionLocation)); - this._globalRegistry.deltaExtensions(extensionsDelta.toAdd, extensionsDelta.toRemove); - - const myExtensions = extensionIdentifiersArrayToSet(this._myRegistry.getAllExtensionDescriptions().map(extension => extension.identifier)); - for (const extensionId of extensionsDelta.myToRemove) { - myExtensions.delete(ExtensionIdentifier.toKey(extensionId)); - } - for (const extensionId of extensionsDelta.myToAdd) { - myExtensions.add(ExtensionIdentifier.toKey(extensionId)); - } - this._myRegistry.set(filterExtensions(this._globalRegistry, myExtensions)); - - console.log(`TODO: update the extension path trie!`); - - // const trie = await this.getExtensionPathIndex(); - - // await Promise.all(toRemove.map(async (extensionId) => { - // const extensionDescription = this._myRegistry.getExtensionDescription(extensionId); - // if (extensionDescription) { - // trie.delete(await this._realPathExtensionUri(extensionDescription.extensionLocation)); - // } - // })); - - // await Promise.all(toAdd.map(async (extensionDescription) => { - // const realpathUri = await this._realPathExtensionUri(extensionDescription.extensionLocation); - // trie.set(realpathUri, extensionDescription); - // })); + // First build up and update the trie and only afterwards apply the delta + const { globalRegistry, myExtensions } = AbstractExtHostExtensionService._applyExtensionsDelta(this._globalRegistry, this._myRegistry, extensionsDelta); + const newSearchTree = await this._createExtensionPathIndex(myExtensions); + const extensionsPaths = await this.getExtensionPathIndex(); + extensionsPaths.setSearchTree(newSearchTree); + this._globalRegistry.set(globalRegistry.getAllExtensionDescriptions()); + this._myRegistry.set(myExtensions); return Promise.resolve(undefined); } @@ -972,7 +970,7 @@ export interface IExtHostExtensionService extends AbstractExtHostExtensionServic activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise; getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI | null | undefined; getExtensionRegistry(): Promise; - getExtensionPathIndex(): Promise>; + getExtensionPathIndex(): Promise; registerRemoteAuthorityResolver(authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver): vscode.Disposable; onDidChangeRemoteConnectionData: Event; @@ -1031,3 +1029,22 @@ function getRemoteAuthorityPrefix(remoteAuthority: string): string { } return remoteAuthority.substring(0, plusIndex); } + +export class ExtensionPaths { + + constructor( + private _searchTree: TernarySearchTree + ) { } + + setSearchTree(searchTree: TernarySearchTree): void { + this._searchTree = searchTree; + } + + findSubstr(key: URI): IExtensionDescription | undefined { + return this._searchTree.findSubstr(key); + } + + forEach(callback: (value: IExtensionDescription, index: URI) => any): void { + return this._searchTree.forEach(callback); + } +} diff --git a/src/vs/workbench/api/common/extHostRequireInterceptor.ts b/src/vs/workbench/api/common/extHostRequireInterceptor.ts index 9ce9a8f402f..459f32df428 100644 --- a/src/vs/workbench/api/common/extHostRequireInterceptor.ts +++ b/src/vs/workbench/api/common/extHostRequireInterceptor.ts @@ -4,19 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import * as performance from 'vs/base/common/performance'; -import { TernarySearchTree } from 'vs/base/common/map'; import { URI } from 'vs/base/common/uri'; import { MainThreadTelemetryShape, MainContext } from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostConfigProvider, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration'; import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; import * as vscode from 'vscode'; -import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IExtensionApiFactory } from 'vs/workbench/api/common/extHost.api.impl'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; +import { ExtensionPaths, IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; import { platform } from 'vs/base/common/process'; import { ILogService } from 'vs/platform/log/common/log'; import { escapeRegExpCharacters } from 'vs/base/common/strings'; @@ -156,7 +155,7 @@ class VSCodeNodeModuleFactory implements INodeModuleFactory { constructor( private readonly _apiFactory: IExtensionApiFactory, - private readonly _extensionPaths: TernarySearchTree, + private readonly _extensionPaths: ExtensionPaths, private readonly _extensionRegistry: ExtensionDescriptionRegistry, private readonly _configProvider: ExtHostConfigProvider, private readonly _logService: ILogService, @@ -208,7 +207,7 @@ class KeytarNodeModuleFactory implements INodeModuleFactory { private _impl: IKeytarModule; constructor( - private readonly _extensionPaths: TernarySearchTree, + private readonly _extensionPaths: ExtensionPaths, @IExtHostRpcService rpcService: IExtHostRpcService, @IExtHostInitDataService initData: IExtHostInitDataService, @@ -303,7 +302,7 @@ class OpenNodeModuleFactory implements INodeModuleFactory { private _mainThreadTelemetry: MainThreadTelemetryShape; constructor( - private readonly _extensionPaths: TernarySearchTree, + private readonly _extensionPaths: ExtensionPaths, private readonly _appUriScheme: string, @IExtHostRpcService rpcService: IExtHostRpcService, ) {