mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
Send all extension descriptions to all extension hosts (#145307)
This commit is contained in:
parent
02a92ee13f
commit
a045f3f48a
|
@ -26,6 +26,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
|||
import { IRemoteConnectionData } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { FileAccess } from 'vs/base/common/network';
|
||||
import { IExtensionDescriptionDelta } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadExtensionService)
|
||||
export class MainThreadExtensionService implements MainThreadExtensionServiceShape {
|
||||
|
@ -204,8 +205,8 @@ class ExtensionHostProxy implements IExtensionHostProxy {
|
|||
const uriComponents = await this._actual.$getCanonicalURI(remoteAuthority, uri);
|
||||
return (uriComponents ? URI.revive(uriComponents) : uriComponents);
|
||||
}
|
||||
startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
return this._actual.$startExtensionHost(enabledExtensionIds);
|
||||
startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
|
||||
return this._actual.$startExtensionHost(extensionsDelta);
|
||||
}
|
||||
extensionTestsExecute(): Promise<number> {
|
||||
return this._actual.$extensionTestsExecute();
|
||||
|
@ -225,8 +226,8 @@ class ExtensionHostProxy implements IExtensionHostProxy {
|
|||
updateRemoteConnectionData(connectionData: IRemoteConnectionData): Promise<void> {
|
||||
return this._actual.$updateRemoteConnectionData(connectionData);
|
||||
}
|
||||
deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
|
||||
return this._actual.$deltaExtensions(toAdd, toRemove);
|
||||
deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
|
||||
return this._actual.$deltaExtensions(extensionsDelta);
|
||||
}
|
||||
test_latency(n: number): Promise<number> {
|
||||
return this._actual.$test_latency(n);
|
||||
|
|
|
@ -62,7 +62,7 @@ import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescrip
|
|||
import { TypeHierarchyItem } from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
|
||||
import { AuthenticationProviderInformation, AuthenticationSession, AuthenticationSessionsChangeEvent } from 'vs/workbench/services/authentication/common/authentication';
|
||||
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { IStaticWorkspaceData } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { IExtensionDescriptionDelta, IStaticWorkspaceData } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { IResolveAuthorityResult } from 'vs/workbench/services/extensions/common/extensionHostProxy';
|
||||
import { ActivationKind, ExtensionActivationReason, MissingExtensionDependency } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { createProxyIdentifier, Dto, IRPCProtocol, SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
|
@ -1434,7 +1434,7 @@ export interface ExtHostExtensionServiceShape {
|
|||
* Returns `null` if no resolver for `remoteAuthority` is found.
|
||||
*/
|
||||
$getCanonicalURI(remoteAuthority: string, uri: UriComponents): Promise<UriComponents | null>;
|
||||
$startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
|
||||
$startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise<void>;
|
||||
$extensionTestsExecute(): Promise<number>;
|
||||
$extensionTestsExit(code: number): Promise<void>;
|
||||
$activateByEvent(activationEvent: string, activationKind: ActivationKind): Promise<void>;
|
||||
|
@ -1442,7 +1442,7 @@ export interface ExtHostExtensionServiceShape {
|
|||
$setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
|
||||
$updateRemoteConnectionData(connectionData: IRemoteConnectionData): Promise<void>;
|
||||
|
||||
$deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void>;
|
||||
$deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void>;
|
||||
|
||||
$test_latency(n: number): Promise<number>;
|
||||
$test_up(b: VSBuffer): Promise<number>;
|
||||
|
|
|
@ -13,12 +13,12 @@ import { TernarySearchTree } from 'vs/base/common/map';
|
|||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostExtensionServiceShape, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IExtensionHostInitData } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { IExtensionDescriptionDelta, IExtensionHostInitData } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ActivatedExtension, EmptyExtension, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ExtHostStorage, IExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { MissingExtensionDependency, ActivationKind, checkProposedApiEnabled, isProposedApiEnabled, ExtensionActivationReason } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { MissingExtensionDependency, ActivationKind, checkProposedApiEnabled, isProposedApiEnabled, ExtensionActivationReason, extensionIdentifiersArrayToSet } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import type * as vscode from 'vscode';
|
||||
|
@ -100,7 +100,8 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
private readonly _readyToRunExtensions: Barrier;
|
||||
private readonly _eagerExtensionsActivated: Barrier;
|
||||
|
||||
protected readonly _registry: ExtensionDescriptionRegistry;
|
||||
protected readonly _myRegistry: ExtensionDescriptionRegistry;
|
||||
protected readonly _globalRegistry: ExtensionDescriptionRegistry;
|
||||
private readonly _storage: ExtHostStorage;
|
||||
private readonly _secretState: ExtHostSecretState;
|
||||
private readonly _storagePath: IExtensionStoragePaths;
|
||||
|
@ -144,7 +145,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
this._readyToStartExtensionHost = new Barrier();
|
||||
this._readyToRunExtensions = new Barrier();
|
||||
this._eagerExtensionsActivated = new Barrier();
|
||||
this._registry = new ExtensionDescriptionRegistry(this._initData.extensions);
|
||||
this._globalRegistry = new ExtensionDescriptionRegistry(this._initData.allExtensions);
|
||||
const myExtensionsSet = extensionIdentifiersArrayToSet(this._initData.myExtensions);
|
||||
this._myRegistry = new ExtensionDescriptionRegistry(
|
||||
filterExtensions(this._globalRegistry, myExtensionsSet)
|
||||
);
|
||||
this._storage = new ExtHostStorage(this._extHostContext);
|
||||
this._secretState = new ExtHostSecretState(this._extHostContext);
|
||||
this._storagePath = storagePath;
|
||||
|
@ -154,24 +159,33 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
[IExtHostSecretState, this._secretState]
|
||||
));
|
||||
|
||||
const hostExtensions = new Set<string>();
|
||||
this._initData.hostExtensions.forEach((extensionId) => hostExtensions.add(ExtensionIdentifier.toKey(extensionId)));
|
||||
let resolvedExtensions: ExtensionIdentifier[] = [];
|
||||
let hostExtensions: ExtensionIdentifier[] = [];
|
||||
if (this._initData.remote.isRemote) {
|
||||
resolvedExtensions = this._initData.allExtensions.filter(extension => !extension.main && !extension.browser).map(extension => extension.identifier);
|
||||
hostExtensions = (
|
||||
this._initData.allExtensions
|
||||
.filter(extension => !myExtensionsSet.has(ExtensionIdentifier.toKey(extension.identifier.value)))
|
||||
.filter(extension => (extension.main || extension.browser) && extension.api === 'none').map(extension => extension.identifier)
|
||||
);
|
||||
}
|
||||
const hostExtensionsSet = extensionIdentifiersArrayToSet(hostExtensions);
|
||||
|
||||
this._activator = this._register(new ExtensionsActivator(
|
||||
this._registry,
|
||||
this._initData.resolvedExtensions,
|
||||
this._initData.hostExtensions,
|
||||
this._myRegistry,
|
||||
resolvedExtensions,
|
||||
hostExtensions,
|
||||
{
|
||||
onExtensionActivationError: (extensionId: ExtensionIdentifier, error: Error, missingExtensionDependency: MissingExtensionDependency | null): void => {
|
||||
this._mainThreadExtensionsProxy.$onExtensionActivationError(extensionId, errors.transformErrorForSerialization(error), missingExtensionDependency);
|
||||
},
|
||||
|
||||
actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension> => {
|
||||
if (hostExtensions.has(ExtensionIdentifier.toKey(extensionId))) {
|
||||
if (hostExtensionsSet.has(ExtensionIdentifier.toKey(extensionId))) {
|
||||
await this._mainThreadExtensionsProxy.$activateExtension(extensionId, reason);
|
||||
return new HostExtension();
|
||||
}
|
||||
const extensionDescription = this._registry.getExtensionDescription(extensionId)!;
|
||||
const extensionDescription = this._myRegistry.getExtensionDescription(extensionId)!;
|
||||
return this._activateExtension(extensionDescription, reason);
|
||||
}
|
||||
},
|
||||
|
@ -210,7 +224,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
|
||||
let allPromises: Promise<void>[] = [];
|
||||
try {
|
||||
const allExtensions = this._registry.getAllExtensionDescriptions();
|
||||
const allExtensions = this._myRegistry.getAllExtensionDescriptions();
|
||||
const allExtensionsIds = allExtensions.map(ext => ext.identifier);
|
||||
const activatedExtensions = allExtensionsIds.filter(id => this.isActivated(id));
|
||||
|
||||
|
@ -293,7 +307,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
}
|
||||
|
||||
public getExtensionRegistry(): Promise<ExtensionDescriptionRegistry> {
|
||||
return this._readyToRunExtensions.wait().then(_ => this._registry);
|
||||
return this._readyToRunExtensions.wait().then(_ => this._myRegistry);
|
||||
}
|
||||
|
||||
public getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI | null | undefined {
|
||||
|
@ -326,7 +340,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
return extUriBiasedIgnorePathCase.ignorePathCasing(key);
|
||||
});
|
||||
// const tst = TernarySearchTree.forUris<IExtensionDescription>(key => true);
|
||||
for (const ext of this._registry.getAllExtensionDescriptions()) {
|
||||
for (const ext of this._myRegistry.getAllExtensionDescriptions()) {
|
||||
if (this._getEntryPoint(ext)) {
|
||||
const uri = await this._realPathExtensionUri(ext.extensionLocation);
|
||||
tst.set(uri, ext);
|
||||
|
@ -572,7 +586,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
// startup is considered finished
|
||||
this._mainThreadExtensionsProxy.$setPerformanceMarks(performance.getMarks());
|
||||
|
||||
for (const desc of this._registry.getAllExtensionDescriptions()) {
|
||||
for (const desc of this._myRegistry.getAllExtensionDescriptions()) {
|
||||
if (desc.activationEvents) {
|
||||
for (const activationEvent of desc.activationEvents) {
|
||||
if (activationEvent === 'onStartupFinished') {
|
||||
|
@ -607,7 +621,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
}
|
||||
|
||||
return Promise.all(
|
||||
this._registry.getAllExtensionDescriptions().map((desc) => {
|
||||
this._myRegistry.getAllExtensionDescriptions().map((desc) => {
|
||||
return this._handleWorkspaceContainsEagerExtension(folders, desc);
|
||||
})
|
||||
).then(() => { });
|
||||
|
@ -816,8 +830,19 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
return result;
|
||||
}
|
||||
|
||||
public $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
this._registry.keepOnly(enabledExtensionIds);
|
||||
public $startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
|
||||
extensionsDelta.toAdd.forEach((extension) => (<any>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));
|
||||
|
||||
return this._startExtensionHost();
|
||||
}
|
||||
|
||||
|
@ -834,7 +859,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
|
||||
public async $activate(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean> {
|
||||
await this._readyToRunExtensions.wait();
|
||||
if (!this._registry.getExtensionDescription(extensionId)) {
|
||||
if (!this._myRegistry.getExtensionDescription(extensionId)) {
|
||||
// unknown extension => ignore
|
||||
return false;
|
||||
}
|
||||
|
@ -842,24 +867,36 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
return true;
|
||||
}
|
||||
|
||||
public async $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
|
||||
toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
|
||||
public async $deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
|
||||
extensionsDelta.toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
|
||||
|
||||
const trie = await this.getExtensionPathIndex();
|
||||
this._globalRegistry.deltaExtensions(extensionsDelta.toAdd, extensionsDelta.toRemove);
|
||||
|
||||
await Promise.all(toRemove.map(async (extensionId) => {
|
||||
const extensionDescription = this._registry.getExtensionDescription(extensionId);
|
||||
if (extensionDescription) {
|
||||
trie.delete(await this._realPathExtensionUri(extensionDescription.extensionLocation));
|
||||
}
|
||||
}));
|
||||
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));
|
||||
|
||||
await Promise.all(toAdd.map(async (extensionDescription) => {
|
||||
const realpathUri = await this._realPathExtensionUri(extensionDescription.extensionLocation);
|
||||
trie.set(realpathUri, extensionDescription);
|
||||
}));
|
||||
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);
|
||||
// }));
|
||||
|
||||
this._registry.deltaExtensions(toAdd, toRemove);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
|
@ -976,6 +1013,12 @@ export class Extension<T extends object | null | undefined> implements vscode.Ex
|
|||
}
|
||||
}
|
||||
|
||||
function filterExtensions(globalRegistry: ExtensionDescriptionRegistry, desiredExtensions: Set<string>): IExtensionDescription[] {
|
||||
return globalRegistry.getAllExtensionDescriptions().filter(
|
||||
extension => desiredExtensions.has(ExtensionIdentifier.toKey(extension.identifier))
|
||||
);
|
||||
}
|
||||
|
||||
function getRemoteAuthorityPrefix(remoteAuthority: string): string {
|
||||
const plusIndex = remoteAuthority.indexOf('+');
|
||||
if (plusIndex === -1) {
|
||||
|
|
|
@ -120,7 +120,7 @@ export class ExtensionHostMain {
|
|||
}
|
||||
|
||||
private static _transform(initData: IExtensionHostInitData, rpcProtocol: RPCProtocol): IExtensionHostInitData {
|
||||
initData.extensions.forEach((ext) => (<any>ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation)));
|
||||
initData.allExtensions.forEach((ext) => (<any>ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation)));
|
||||
initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot));
|
||||
const extDevLocs = initData.environment.extensionDevelopmentLocationURI;
|
||||
if (extDevLocs) {
|
||||
|
|
|
@ -72,7 +72,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
|||
}
|
||||
|
||||
// Module loading tricks
|
||||
const interceptor = this._instaService.createInstance(NodeModuleRequireInterceptor, extensionApiFactory, this._registry);
|
||||
const interceptor = this._instaService.createInstance(NodeModuleRequireInterceptor, extensionApiFactory, this._myRegistry);
|
||||
await interceptor.install();
|
||||
performance.mark('code/extHost/didInitAPI');
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
|||
|
||||
// initialize API and register actors
|
||||
const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors);
|
||||
this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, this._registry);
|
||||
this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, this._myRegistry);
|
||||
await this._fakeModules.install();
|
||||
performance.mark('code/extHost/didInitAPI');
|
||||
|
||||
|
|
|
@ -112,8 +112,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||
const allExtensions = await this.getExtensions();
|
||||
const localWebWorkerExtensions = this._filterByRunningLocation(allExtensions, desiredRunningLocation);
|
||||
return {
|
||||
autoStart: true,
|
||||
extensions: localWebWorkerExtensions
|
||||
allExtensions: allExtensions,
|
||||
myExtensions: localWebWorkerExtensions.map(extension => extension.identifier)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -232,8 +232,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||
extensionHostLogsPath: remoteEnv.extensionHostLogsPath,
|
||||
globalStorageHome: remoteEnv.globalStorageHome,
|
||||
workspaceStorageHome: remoteEnv.workspaceStorageHome,
|
||||
extensions: remoteExtensions,
|
||||
allExtensions: this._registry.getAllExtensionDescriptions()
|
||||
allExtensions: this._registry.getAllExtensionDescriptions(),
|
||||
myExtensions: remoteExtensions.map(extension => extension.identifier),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtensionHost, ExtensionHostLogFileName, LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionHost, ExtensionHostLogFileName, LocalWebWorkerRunningLocation, ExtensionHostExtensions } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
|
@ -30,11 +30,10 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
|||
import { FileAccess } from 'vs/base/common/network';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { parentOriginHash } from 'vs/workbench/browser/webview';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
|
||||
export interface IWebWorkerExtensionHostInitData {
|
||||
readonly autoStart: boolean;
|
||||
readonly extensions: IExtensionDescription[];
|
||||
readonly allExtensions: IExtensionDescription[];
|
||||
readonly myExtensions: ExtensionIdentifier[];
|
||||
}
|
||||
|
||||
export interface IWebWorkerExtensionHostDataProvider {
|
||||
|
@ -45,7 +44,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
|||
|
||||
public readonly remoteAuthority = null;
|
||||
public readonly lazyStart: boolean;
|
||||
public readonly extensions = new ExtensionDescriptionRegistry([]);
|
||||
public readonly extensions = new ExtensionHostExtensions();
|
||||
|
||||
private readonly _onDidExit = this._register(new Emitter<[number, string | null]>());
|
||||
public readonly onExit: Event<[number, string | null]> = this._onDidExit.event;
|
||||
|
@ -267,7 +266,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
|||
private async _createExtHostInitData(): Promise<IExtensionHostInitData> {
|
||||
const [telemetryInfo, initData] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._initDataProvider.getInitData()]);
|
||||
const workspace = this._contextService.getWorkspace();
|
||||
this.extensions.deltaExtensions(initData.extensions, []);
|
||||
const deltaExtensions = this.extensions.set(initData.allExtensions, initData.myExtensions);
|
||||
return {
|
||||
commit: this._productService.commit,
|
||||
version: this._productService.version,
|
||||
|
@ -289,14 +288,13 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
|||
name: this._labelService.getWorkspaceLabel(workspace),
|
||||
transient: workspace.transient
|
||||
},
|
||||
resolvedExtensions: [],
|
||||
hostExtensions: [],
|
||||
extensions: this.extensions.getAllExtensionDescriptions(),
|
||||
allExtensions: deltaExtensions.toAdd,
|
||||
myExtensions: deltaExtensions.myToAdd,
|
||||
telemetryInfo,
|
||||
logLevel: this._logService.getLevel(),
|
||||
logsLocation: this._extensionHostLogsLocation,
|
||||
logFile: this._extensionHostLogFile,
|
||||
autoStart: initData.autoStart,
|
||||
autoStart: true,
|
||||
remote: {
|
||||
authority: this._environmentService.remoteAuthority,
|
||||
connectionData: null,
|
||||
|
|
|
@ -628,12 +628,10 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
|
|||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
private async _updateExtensionsOnExtHost(extensionHostManager: IExtensionHostManager, _toAdd: IExtensionDescription[], _toRemove: ExtensionIdentifier[], removedRunningLocation: Map<string, ExtensionRunningLocation | null>): Promise<void> {
|
||||
const toAdd = filterByExtensionHostManager(_toAdd, this._runningLocation, extensionHostManager);
|
||||
const toRemove = _filterByExtensionHostManager(_toRemove, extId => extId, removedRunningLocation, extensionHostManager);
|
||||
if (toRemove.length > 0 || toAdd.length > 0) {
|
||||
await extensionHostManager.deltaExtensions(toAdd, toRemove);
|
||||
}
|
||||
private async _updateExtensionsOnExtHost(extensionHostManager: IExtensionHostManager, toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[], removedRunningLocation: Map<string, ExtensionRunningLocation | null>): Promise<void> {
|
||||
const myToAdd = filterByExtensionHostManager(toAdd, this._runningLocation, extensionHostManager);
|
||||
const myToRemove = _filterByExtensionHostManager(toRemove, extId => extId, removedRunningLocation, extensionHostManager);
|
||||
await extensionHostManager.deltaExtensions({ toRemove, toAdd, myToRemove, myToAdd: myToAdd.map(extension => extension.identifier) });
|
||||
}
|
||||
|
||||
public canAddExtension(extension: IExtensionDescription): boolean {
|
||||
|
|
|
@ -61,10 +61,8 @@ export class ExtensionDescriptionRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
public keepOnly(extensionIds: ExtensionIdentifier[]): void {
|
||||
const toKeep = new Set<string>();
|
||||
extensionIds.forEach(extensionId => toKeep.add(ExtensionIdentifier.toKey(extensionId)));
|
||||
this._extensionDescriptions = this._extensionDescriptions.filter(extension => toKeep.has(ExtensionIdentifier.toKey(extension.identifier)));
|
||||
public set(extensionDescriptions: IExtensionDescription[]) {
|
||||
this._extensionDescriptions = extensionDescriptions;
|
||||
this._initialize();
|
||||
this._onDidChange.fire(undefined);
|
||||
}
|
||||
|
|
|
@ -19,13 +19,14 @@ import { registerAction2, Action2 } from 'vs/platform/actions/common/actions';
|
|||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IExtensionHost, ExtensionHostKind, ActivationKind, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService, ExtensionRunningLocation } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionHost, ExtensionHostKind, ActivationKind, extensionHostKindToString, ExtensionActivationReason, IInternalExtensionService, ExtensionRunningLocation, ExtensionHostExtensions } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { Barrier, timeout } from 'vs/base/common/async';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IExtensionHostProxy, IResolveAuthorityResult } from 'vs/workbench/services/extensions/common/extensionHostProxy';
|
||||
import { IExtensionDescriptionDelta } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
|
||||
// Enable to see detailed message communication between window and extension host
|
||||
const LOG_EXTENSION_HOST_COMMUNICATION = false;
|
||||
|
@ -39,7 +40,7 @@ export interface IExtensionHostManager {
|
|||
dispose(): void;
|
||||
ready(): Promise<void>;
|
||||
representsRunningLocation(runningLocation: ExtensionRunningLocation): boolean;
|
||||
deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void>;
|
||||
deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void>;
|
||||
containsExtension(extensionId: ExtensionIdentifier): boolean;
|
||||
activate(extension: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean>;
|
||||
activateByEvent(activationEvent: string, activationKind: ActivationKind): Promise<void>;
|
||||
|
@ -50,7 +51,7 @@ export interface IExtensionHostManager {
|
|||
* Returns `null` if no resolver for `remoteAuthority` is found.
|
||||
*/
|
||||
getCanonicalURI(remoteAuthority: string, uri: URI): Promise<URI | null>;
|
||||
start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
|
||||
start(allExtensions: IExtensionDescription[], myExtensions: ExtensionIdentifier[]): Promise<void>;
|
||||
extensionTestsExecute(): Promise<number>;
|
||||
extensionTestsSendExit(exitCode: number): Promise<void>;
|
||||
setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
|
||||
|
@ -398,13 +399,13 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager {
|
|||
return proxy.getCanonicalURI(remoteAuthority, uri);
|
||||
}
|
||||
|
||||
public async start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
public async start(allExtensions: IExtensionDescription[], myExtensions: ExtensionIdentifier[]): Promise<void> {
|
||||
const proxy = await this._proxy;
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
this._extensionHost.extensions.keepOnly(enabledExtensionIds);
|
||||
return proxy.startExtensionHost(enabledExtensionIds);
|
||||
const deltaExtensions = this._extensionHost.extensions.set(allExtensions, myExtensions);
|
||||
return proxy.startExtensionHost(deltaExtensions);
|
||||
}
|
||||
|
||||
public async extensionTestsExecute(): Promise<number> {
|
||||
|
@ -433,13 +434,13 @@ class ExtensionHostManager extends Disposable implements IExtensionHostManager {
|
|||
return this._extensionHost.runningLocation.equals(runningLocation);
|
||||
}
|
||||
|
||||
public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
|
||||
public async deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
|
||||
const proxy = await this._proxy;
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
this._extensionHost.extensions.deltaExtensions(toAdd, toRemove);
|
||||
return proxy.deltaExtensions(toAdd, toRemove);
|
||||
this._extensionHost.extensions.delta(extensionsDelta);
|
||||
return proxy.deltaExtensions(extensionsDelta);
|
||||
}
|
||||
|
||||
public containsExtension(extensionId: ExtensionIdentifier): boolean {
|
||||
|
@ -468,6 +469,7 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost
|
|||
private readonly _extensionHost: IExtensionHost;
|
||||
private _startCalled: Barrier;
|
||||
private _actual: ExtensionHostManager | null;
|
||||
private _lazyStartExtensions: ExtensionHostExtensions | null;
|
||||
|
||||
public get kind(): ExtensionHostKind {
|
||||
return this._extensionHost.runningLocation.kind;
|
||||
|
@ -485,6 +487,7 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost
|
|||
this.onDidExit = extensionHost.onExit;
|
||||
this._startCalled = new Barrier();
|
||||
this._actual = null;
|
||||
this._lazyStartExtensions = null;
|
||||
}
|
||||
|
||||
private _createActual(reason: string): ExtensionHostManager {
|
||||
|
@ -500,7 +503,7 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost
|
|||
return this._actual;
|
||||
}
|
||||
const actual = this._createActual(reason);
|
||||
await actual.start([]);
|
||||
await actual.start([], []);
|
||||
return actual;
|
||||
}
|
||||
|
||||
|
@ -513,13 +516,17 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost
|
|||
public representsRunningLocation(runningLocation: ExtensionRunningLocation): boolean {
|
||||
return this._extensionHost.runningLocation.equals(runningLocation);
|
||||
}
|
||||
public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
|
||||
public async deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
|
||||
await this._startCalled.wait();
|
||||
const extensionHostAlreadyStarted = Boolean(this._actual);
|
||||
const shouldStartExtensionHost = (toAdd.length > 0);
|
||||
if (extensionHostAlreadyStarted || shouldStartExtensionHost) {
|
||||
const actual = await this._getOrCreateActualAndStart(`contains ${toAdd.length} new extension(s) (installed or enabled): ${toAdd.map(ext => ext.identifier.value)}`);
|
||||
return actual.deltaExtensions(toAdd, toRemove);
|
||||
if (this._actual) {
|
||||
return this._actual.deltaExtensions(extensionsDelta);
|
||||
}
|
||||
this._lazyStartExtensions!.delta(extensionsDelta);
|
||||
if (extensionsDelta.myToAdd.length > 0) {
|
||||
const actual = this._createActual(`contains ${extensionsDelta.myToAdd.length} new extension(s) (installed or enabled): ${extensionsDelta.myToAdd.map(extId => extId.value)}`);
|
||||
const { toAdd, myToAdd } = this._lazyStartExtensions!.toDelta();
|
||||
actual.start(toAdd, myToAdd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
public containsExtension(extensionId: ExtensionIdentifier): boolean {
|
||||
|
@ -582,15 +589,17 @@ class LazyStartExtensionHostManager extends Disposable implements IExtensionHost
|
|||
}
|
||||
throw new Error(`Cannot resolve canonical URI`);
|
||||
}
|
||||
public async start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
if (enabledExtensionIds.length > 0) {
|
||||
public async start(allExtensions: IExtensionDescription[], myExtensions: ExtensionIdentifier[]): Promise<void> {
|
||||
if (myExtensions.length > 0) {
|
||||
// there are actual extensions, so let's launch the extension host
|
||||
const actual = this._createActual(`contains ${enabledExtensionIds.length} extension(s): ${enabledExtensionIds.map(extId => extId.value)}.`);
|
||||
const result = actual.start(enabledExtensionIds);
|
||||
const actual = this._createActual(`contains ${myExtensions.length} extension(s): ${myExtensions.map(extId => extId.value)}.`);
|
||||
const result = actual.start(allExtensions, myExtensions);
|
||||
this._startCalled.open();
|
||||
return result;
|
||||
}
|
||||
// there are no actual extensions
|
||||
// there are no actual extensions running, store extensions in `this._lazyStartExtensions`
|
||||
this._lazyStartExtensions = new ExtensionHostExtensions();
|
||||
this._lazyStartExtensions.set(allExtensions, myExtensions);
|
||||
this._startCalled.open();
|
||||
}
|
||||
public async extensionTestsExecute(): Promise<number> {
|
||||
|
|
|
@ -10,15 +10,21 @@ import { LogLevel } from 'vs/platform/log/common/log';
|
|||
import { IRemoteConnectionData } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
export interface IExtensionDescriptionDelta {
|
||||
readonly toRemove: ExtensionIdentifier[];
|
||||
readonly toAdd: IExtensionDescription[];
|
||||
readonly myToRemove: ExtensionIdentifier[];
|
||||
readonly myToAdd: ExtensionIdentifier[];
|
||||
}
|
||||
|
||||
export interface IExtensionHostInitData {
|
||||
version: string;
|
||||
commit?: string;
|
||||
parentPid: number;
|
||||
environment: IEnvironment;
|
||||
workspace?: IStaticWorkspaceData | null;
|
||||
resolvedExtensions: ExtensionIdentifier[];
|
||||
hostExtensions: ExtensionIdentifier[];
|
||||
extensions: IExtensionDescription[];
|
||||
allExtensions: IExtensionDescription[];
|
||||
myExtensions: ExtensionIdentifier[];
|
||||
telemetryInfo: ITelemetryInfo;
|
||||
logLevel: LogLevel;
|
||||
logsLocation: URI;
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IRemoteConnectionData, RemoteAuthorityResolverErrorCode, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { IExtensionDescriptionDelta } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { ActivationKind, ExtensionActivationReason } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
export interface IResolveAuthorityErrorResult {
|
||||
|
@ -31,14 +32,14 @@ export interface IExtensionHostProxy {
|
|||
* Returns `null` if no resolver for `remoteAuthority` is found.
|
||||
*/
|
||||
getCanonicalURI(remoteAuthority: string, uri: URI): Promise<URI | null>;
|
||||
startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
|
||||
startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise<void>;
|
||||
extensionTestsExecute(): Promise<number>;
|
||||
extensionTestsExit(code: number): Promise<void>;
|
||||
activateByEvent(activationEvent: string, activationKind: ActivationKind): Promise<void>;
|
||||
activate(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean>;
|
||||
setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
|
||||
updateRemoteConnectionData(connectionData: IRemoteConnectionData): Promise<void>;
|
||||
deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void>;
|
||||
deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void>;
|
||||
test_latency(n: number): Promise<number>;
|
||||
test_up(b: VSBuffer): Promise<number>;
|
||||
test_down(size: number): Promise<VSBuffer>;
|
||||
|
|
|
@ -13,7 +13,7 @@ import { getExtensionId, getGalleryExtensionId } from 'vs/platform/extensionMana
|
|||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { ApiProposalName } from 'vs/workbench/services/extensions/common/extensionsApiProposals';
|
||||
import { IV8Profile } from 'vs/platform/profiling/common/profiling';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import { IExtensionDescriptionDelta } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
|
||||
export const nullExtensionDescription = Object.freeze<IExtensionDescription>({
|
||||
identifier: new ExtensionIdentifier('nullExtensionDescription'),
|
||||
|
@ -150,10 +150,11 @@ export interface IExtensionHost {
|
|||
readonly remoteAuthority: string | null;
|
||||
readonly lazyStart: boolean;
|
||||
/**
|
||||
* A collection of extensions that will execute or are executing on this extension host.
|
||||
* A collection of extensions which includes information about which
|
||||
* extension will execute or is executing on this extension host.
|
||||
* **NOTE**: this will reflect extensions correctly only after `start()` resolves.
|
||||
*/
|
||||
readonly extensions: ExtensionDescriptionRegistry;
|
||||
readonly extensions: ExtensionHostExtensions;
|
||||
readonly onExit: Event<[number, string | null]>;
|
||||
|
||||
start(): Promise<IMessagePassingProtocol> | null;
|
||||
|
@ -162,6 +163,142 @@ export interface IExtensionHost {
|
|||
dispose(): void;
|
||||
}
|
||||
|
||||
export class ExtensionHostExtensions {
|
||||
|
||||
private _allExtensions: IExtensionDescription[];
|
||||
private _myExtensions: ExtensionIdentifier[];
|
||||
|
||||
constructor() {
|
||||
this._allExtensions = [];
|
||||
this._myExtensions = [];
|
||||
}
|
||||
|
||||
public toDelta(): IExtensionDescriptionDelta {
|
||||
return {
|
||||
toRemove: [],
|
||||
toAdd: this._allExtensions,
|
||||
myToRemove: [],
|
||||
myToAdd: this._myExtensions
|
||||
};
|
||||
}
|
||||
|
||||
public set(allExtensions: IExtensionDescription[], myExtensions: ExtensionIdentifier[]): IExtensionDescriptionDelta {
|
||||
const toRemove: ExtensionIdentifier[] = [];
|
||||
const toAdd: IExtensionDescription[] = [];
|
||||
const myToRemove: ExtensionIdentifier[] = [];
|
||||
const myToAdd: ExtensionIdentifier[] = [];
|
||||
|
||||
const oldExtensionsMap = extensionDescriptionArrayToMap(this._allExtensions);
|
||||
const newExtensionsMap = extensionDescriptionArrayToMap(allExtensions);
|
||||
const extensionsAreTheSame = (a: IExtensionDescription, b: IExtensionDescription) => {
|
||||
return (
|
||||
(a.extensionLocation.toString() === b.extensionLocation.toString())
|
||||
|| (a.isBuiltin === b.isBuiltin)
|
||||
|| (a.isUserBuiltin === b.isUserBuiltin)
|
||||
|| (a.isUnderDevelopment === b.isUnderDevelopment)
|
||||
);
|
||||
};
|
||||
|
||||
for (const oldExtension of this._allExtensions) {
|
||||
const newExtension = newExtensionsMap.get(ExtensionIdentifier.toKey(oldExtension.identifier));
|
||||
if (!newExtension) {
|
||||
toRemove.push(oldExtension.identifier);
|
||||
oldExtensionsMap.delete(ExtensionIdentifier.toKey(oldExtension.identifier));
|
||||
continue;
|
||||
}
|
||||
if (!extensionsAreTheSame(oldExtension, newExtension)) {
|
||||
// The new extension is different than the old one
|
||||
// (e.g. maybe it executes in a different location)
|
||||
toRemove.push(oldExtension.identifier);
|
||||
oldExtensionsMap.delete(ExtensionIdentifier.toKey(oldExtension.identifier));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (const newExtension of allExtensions) {
|
||||
const oldExtension = oldExtensionsMap.get(ExtensionIdentifier.toKey(newExtension.identifier));
|
||||
if (!oldExtension) {
|
||||
toAdd.push(newExtension);
|
||||
continue;
|
||||
}
|
||||
if (!extensionsAreTheSame(oldExtension, newExtension)) {
|
||||
// The new extension is different than the old one
|
||||
// (e.g. maybe it executes in a different location)
|
||||
toRemove.push(oldExtension.identifier);
|
||||
oldExtensionsMap.delete(ExtensionIdentifier.toKey(oldExtension.identifier));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const myOldExtensionsSet = extensionIdentifiersArrayToSet(this._myExtensions);
|
||||
const myNewExtensionsSet = extensionIdentifiersArrayToSet(myExtensions);
|
||||
for (const oldExtensionId of this._myExtensions) {
|
||||
if (!myNewExtensionsSet.has(ExtensionIdentifier.toKey(oldExtensionId))) {
|
||||
myToRemove.push(oldExtensionId);
|
||||
}
|
||||
}
|
||||
for (const newExtensionId of myExtensions) {
|
||||
if (!myOldExtensionsSet.has(ExtensionIdentifier.toKey(newExtensionId))) {
|
||||
myToAdd.push(newExtensionId);
|
||||
}
|
||||
}
|
||||
|
||||
const delta = { toRemove, toAdd, myToRemove, myToAdd };
|
||||
this.delta(delta);
|
||||
return delta;
|
||||
}
|
||||
|
||||
public delta(extensionsDelta: IExtensionDescriptionDelta): void {
|
||||
const { toRemove, toAdd, myToRemove, myToAdd } = extensionsDelta;
|
||||
// First handle removals
|
||||
const toRemoveSet = extensionIdentifiersArrayToSet(toRemove);
|
||||
const myToRemoveSet = extensionIdentifiersArrayToSet(myToRemove);
|
||||
for (let i = 0; i < this._allExtensions.length; i++) {
|
||||
if (toRemoveSet.has(ExtensionIdentifier.toKey(this._allExtensions[i].identifier))) {
|
||||
this._allExtensions.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < this._myExtensions.length; i++) {
|
||||
if (myToRemoveSet.has(ExtensionIdentifier.toKey(this._myExtensions[i]))) {
|
||||
this._myExtensions.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
// Then handle additions
|
||||
for (const extension of toAdd) {
|
||||
this._allExtensions.push(extension);
|
||||
}
|
||||
for (const extensionId of myToAdd) {
|
||||
this._myExtensions.push(extensionId);
|
||||
}
|
||||
}
|
||||
|
||||
public containsExtension(extensionId: ExtensionIdentifier): boolean {
|
||||
for (const myExtensionId of this._myExtensions) {
|
||||
if (ExtensionIdentifier.equals(myExtensionId, extensionId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function extensionIdentifiersArrayToSet(extensionIds: ExtensionIdentifier[]): Set<string> {
|
||||
const result = new Set<string>();
|
||||
for (const extensionId of extensionIds) {
|
||||
result.add(ExtensionIdentifier.toKey(extensionId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function extensionDescriptionArrayToMap(extensions: IExtensionDescription[]): Map<string, IExtensionDescription> {
|
||||
const result = new Map<string, IExtensionDescription>();
|
||||
for (const extension of extensions) {
|
||||
result.set(ExtensionIdentifier.toKey(extension.identifier), extension);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||
if (!extension.enabledApiProposals) {
|
||||
return false;
|
||||
|
|
|
@ -25,10 +25,9 @@ import { ISignService } from 'vs/platform/sign/common/sign';
|
|||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions';
|
||||
import { createMessageOfType, isMessageOfType, MessageType, IExtensionHostInitData, UIKind } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { ExtensionHostLogFileName, IExtensionHost, RemoteRunningLocation } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionHostExtensions, ExtensionHostLogFileName, IExtensionHost, RemoteRunningLocation } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { Extensions, IOutputChannelRegistry } from 'vs/workbench/services/output/common/output';
|
||||
|
||||
|
@ -39,8 +38,8 @@ export interface IRemoteExtensionHostInitData {
|
|||
readonly extensionHostLogsPath: URI;
|
||||
readonly globalStorageHome: URI;
|
||||
readonly workspaceStorageHome: URI;
|
||||
readonly extensions: IExtensionDescription[];
|
||||
readonly allExtensions: IExtensionDescription[];
|
||||
readonly myExtensions: ExtensionIdentifier[];
|
||||
}
|
||||
|
||||
export interface IRemoteExtensionHostDataProvider {
|
||||
|
@ -52,7 +51,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
|||
|
||||
public readonly remoteAuthority: string;
|
||||
public readonly lazyStart = false;
|
||||
public readonly extensions = new ExtensionDescriptionRegistry([]);
|
||||
public readonly extensions = new ExtensionHostExtensions();
|
||||
|
||||
private _onExit: Emitter<[number, string | null]> = this._register(new Emitter<[number, string | null]>());
|
||||
public readonly onExit: Event<[number, string | null]> = this._onExit.event;
|
||||
|
@ -213,19 +212,8 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
|||
|
||||
private async _createExtHostInitData(isExtensionDevelopmentDebug: boolean): Promise<IExtensionHostInitData> {
|
||||
const [telemetryInfo, remoteInitData] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._initDataProvider.getInitData()]);
|
||||
|
||||
// Collect all identifiers for extension ids which can be considered "resolved"
|
||||
const remoteExtensions = new Set<string>();
|
||||
remoteInitData.extensions.forEach((extension) => remoteExtensions.add(ExtensionIdentifier.toKey(extension.identifier.value)));
|
||||
|
||||
const resolvedExtensions = remoteInitData.allExtensions.filter(extension => !extension.main && !extension.browser).map(extension => extension.identifier);
|
||||
const hostExtensions = (
|
||||
remoteInitData.allExtensions
|
||||
.filter(extension => !remoteExtensions.has(ExtensionIdentifier.toKey(extension.identifier.value)))
|
||||
.filter(extension => (extension.main || extension.browser) && extension.api === 'none').map(extension => extension.identifier)
|
||||
);
|
||||
const workspace = this._contextService.getWorkspace();
|
||||
this.extensions.deltaExtensions(remoteInitData.extensions, []);
|
||||
const deltaExtensions = this.extensions.set(remoteInitData.allExtensions, remoteInitData.myExtensions);
|
||||
return {
|
||||
commit: this._productService.commit,
|
||||
version: this._productService.version,
|
||||
|
@ -253,9 +241,8 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
|||
authority: this._initDataProvider.remoteAuthority,
|
||||
connectionData: remoteInitData.connectionData
|
||||
},
|
||||
resolvedExtensions: resolvedExtensions,
|
||||
hostExtensions: hostExtensions,
|
||||
extensions: this.extensions.getAllExtensionDescriptions(),
|
||||
allExtensions: deltaExtensions.toAdd,
|
||||
myExtensions: deltaExtensions.myToAdd,
|
||||
telemetryInfo,
|
||||
logLevel: this._logService.getLevel(),
|
||||
logsLocation: remoteInitData.extensionHostLogsPath,
|
||||
|
|
|
@ -162,18 +162,20 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||
// Here we load even extensions that would be disabled by workspace trust
|
||||
const localExtensions = this._checkEnabledAndProposedAPI(await this._scanAllLocalExtensions(), /* ignore workspace trust */true);
|
||||
const runningLocation = this._determineRunningLocation(localExtensions);
|
||||
const localProcessExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredRunningLocation);
|
||||
const myExtensions = filterByRunningLocation(localExtensions, runningLocation, desiredRunningLocation);
|
||||
return {
|
||||
autoStart: false,
|
||||
extensions: localProcessExtensions
|
||||
allExtensions: localExtensions,
|
||||
myExtensions: myExtensions.map(extension => extension.identifier)
|
||||
};
|
||||
} else {
|
||||
// restart case
|
||||
const allExtensions = await this.getExtensions();
|
||||
const localProcessExtensions = this._filterByRunningLocation(allExtensions, desiredRunningLocation);
|
||||
const myExtensions = this._filterByRunningLocation(allExtensions, desiredRunningLocation);
|
||||
return {
|
||||
autoStart: true,
|
||||
extensions: localProcessExtensions
|
||||
allExtensions: allExtensions,
|
||||
myExtensions: myExtensions.map(extension => extension.identifier)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -561,8 +563,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||
extensionHostLogsPath: remoteEnv.extensionHostLogsPath,
|
||||
globalStorageHome: remoteEnv.globalStorageHome,
|
||||
workspaceStorageHome: remoteEnv.workspaceStorageHome,
|
||||
extensions: remoteExtensions,
|
||||
allExtensions: this._registry.getAllExtensionDescriptions(),
|
||||
myExtensions: remoteExtensions.map(extension => extension.identifier),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -583,7 +585,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
|||
|
||||
private _startExtensionHost(extensionHostManager: IExtensionHostManager, _extensions: IExtensionDescription[]): void {
|
||||
const extensions = this._filterByExtensionHostManager(_extensions, extensionHostManager);
|
||||
extensionHostManager.start(extensions.map(extension => extension.identifier));
|
||||
extensionHostManager.start(this._registry.getAllExtensionDescriptions(), extensions.map(extension => extension.identifier));
|
||||
}
|
||||
|
||||
public _onExtensionHostExit(code: number): void {
|
||||
|
|
|
@ -29,11 +29,11 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
|||
import { isUntitledWorkspace, IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { MessageType, createMessageOfType, isMessageOfType, IExtensionHostInitData, UIKind } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { parseExtensionDevOptions } from '../common/extensionDevOptions';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
|
||||
import { IExtensionHost, ExtensionHostLogFileName, LocalProcessRunningLocation } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionHost, ExtensionHostLogFileName, LocalProcessRunningLocation, ExtensionHostExtensions } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
|
@ -43,12 +43,12 @@ import { IExtensionHostProcessOptions, IExtensionHostStarter } from 'vs/platform
|
|||
import { SerializedError } from 'vs/base/common/errors';
|
||||
import { removeDangerousEnvVariables } from 'vs/base/common/processes';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import { process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
|
||||
export interface ILocalProcessExtensionHostInitData {
|
||||
readonly autoStart: boolean;
|
||||
readonly extensions: IExtensionDescription[];
|
||||
readonly allExtensions: IExtensionDescription[];
|
||||
readonly myExtensions: ExtensionIdentifier[];
|
||||
}
|
||||
|
||||
export interface ILocalProcessExtensionHostDataProvider {
|
||||
|
@ -108,7 +108,7 @@ export class LocalProcessExtensionHost implements IExtensionHost {
|
|||
|
||||
public readonly remoteAuthority = null;
|
||||
public readonly lazyStart = false;
|
||||
public readonly extensions = new ExtensionDescriptionRegistry([]);
|
||||
public readonly extensions = new ExtensionHostExtensions();
|
||||
|
||||
private readonly _onExit: Emitter<[number, string]> = new Emitter<[number, string]>();
|
||||
public readonly onExit: Event<[number, string]> = this._onExit.event;
|
||||
|
@ -498,7 +498,7 @@ export class LocalProcessExtensionHost implements IExtensionHost {
|
|||
private async _createExtHostInitData(): Promise<IExtensionHostInitData> {
|
||||
const [telemetryInfo, initData] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._initDataProvider.getInitData()]);
|
||||
const workspace = this._contextService.getWorkspace();
|
||||
this.extensions.deltaExtensions(initData.extensions, []);
|
||||
const deltaExtensions = this.extensions.set(initData.allExtensions, initData.myExtensions);
|
||||
return {
|
||||
commit: this._productService.commit,
|
||||
version: this._productService.version,
|
||||
|
@ -527,9 +527,8 @@ export class LocalProcessExtensionHost implements IExtensionHost {
|
|||
connectionData: null,
|
||||
isRemote: false
|
||||
},
|
||||
resolvedExtensions: [],
|
||||
hostExtensions: [],
|
||||
extensions: this.extensions.getAllExtensionDescriptions(),
|
||||
allExtensions: deltaExtensions.toAdd,
|
||||
myExtensions: deltaExtensions.myToAdd,
|
||||
telemetryInfo,
|
||||
logLevel: this._logService.getLevel(),
|
||||
logsLocation: this._environmentService.extHostLogsPath,
|
||||
|
|
Loading…
Reference in a new issue