Send all extension descriptions to all extension hosts (#145307)

This commit is contained in:
Alex Dima 2022-04-20 15:06:31 +03:00
parent 02a92ee13f
commit a045f3f48a
No known key found for this signature in database
GPG key ID: 39563C1504FDD0C9
17 changed files with 311 additions and 132 deletions

View file

@ -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);

View file

@ -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>;

View file

@ -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) {

View file

@ -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) {

View file

@ -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');

View file

@ -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');

View file

@ -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),
};
}

View file

@ -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,

View file

@ -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 {

View file

@ -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);
}

View file

@ -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> {

View file

@ -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;

View file

@ -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>;

View file

@ -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;

View file

@ -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,

View file

@ -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 {

View file

@ -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,