mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-11 10:38:31 -05:00
Merge VS Code 1.23.1 (#1520)
This commit is contained in:
@@ -23,7 +23,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { generateRandomPipeName, Protocol } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import { createServer, Server, Socket } from 'net';
|
||||
import Event, { Emitter, debounceEvent, mapEvent, anyEvent, fromNodeEventEmitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter, debounceEvent, mapEvent, anyEvent, fromNodeEventEmitter } from 'vs/base/common/event';
|
||||
import { IInitData, IWorkspaceData, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
@@ -36,11 +36,10 @@ import { IRemoteConsoleLog, log, parse } from 'vs/base/node/console';
|
||||
import { getScopes } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
|
||||
|
||||
export class ExtensionHostProcessWorker {
|
||||
|
||||
private _onCrashed: Emitter<[number, string]> = new Emitter<[number, string]>();
|
||||
private readonly _onCrashed: Emitter<[number, string]> = new Emitter<[number, string]>();
|
||||
public readonly onCrashed: Event<[number, string]> = this._onCrashed.event;
|
||||
|
||||
private readonly _toDispose: IDisposable[];
|
||||
@@ -73,7 +72,6 @@ export class ExtensionHostProcessWorker {
|
||||
@IWorkspaceConfigurationService private readonly _configurationService: IWorkspaceConfigurationService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@ICrashReporterService private readonly _crashReporterService: ICrashReporterService,
|
||||
@IChoiceService private readonly _choiceService: IChoiceService,
|
||||
@ILogService private readonly _logService: ILogService
|
||||
) {
|
||||
// handle extension host lifecycle a bit special when we know we are developing an extension that runs inside
|
||||
@@ -143,7 +141,6 @@ export class ExtensionHostProcessWorker {
|
||||
AMD_ENTRYPOINT: 'vs/workbench/node/extensionHostProcess',
|
||||
PIPE_LOGGING: 'true',
|
||||
VERBOSE_LOGGING: true,
|
||||
VSCODE_WINDOW_ID: String(this._windowService.getCurrentWindowId()),
|
||||
VSCODE_IPC_HOOK_EXTHOST: pipeName,
|
||||
VSCODE_HANDLES_UNCAUGHT_ERRORS: true,
|
||||
VSCODE_LOG_STACK: !this._isExtensionDevTestFromCli && (this._isExtensionDevHost || !this._environmentService.isBuilt || product.quality !== 'stable' || this._environmentService.verbose)
|
||||
@@ -238,11 +235,12 @@ export class ExtensionHostProcessWorker {
|
||||
? nls.localize('extensionHostProcess.startupFailDebug', "Extension host did not start in 10 seconds, it might be stopped on the first line and needs a debugger to continue.")
|
||||
: nls.localize('extensionHostProcess.startupFail', "Extension host did not start in 10 seconds, that might be a problem.");
|
||||
|
||||
this._choiceService.choose(Severity.Warning, msg, [nls.localize('reloadWindow', "Reload Window")]).then(choice => {
|
||||
if (choice === 0) {
|
||||
this._windowService.reloadWindow();
|
||||
}
|
||||
});
|
||||
this._notificationService.prompt(Severity.Warning, msg,
|
||||
[{
|
||||
label: nls.localize('reloadWindow', "Reload Window"),
|
||||
run: () => this._windowService.reloadWindow()
|
||||
}]
|
||||
);
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
@@ -372,22 +370,17 @@ export class ExtensionHostProcessWorker {
|
||||
appRoot: this._environmentService.appRoot,
|
||||
appSettingsHome: this._environmentService.appSettingsHome,
|
||||
disableExtensions: this._environmentService.disableExtensions,
|
||||
userExtensionsHome: this._environmentService.extensionsPath,
|
||||
extensionDevelopmentPath: this._environmentService.extensionDevelopmentPath,
|
||||
extensionTestsPath: this._environmentService.extensionTestsPath,
|
||||
// globally disable proposed api when built and not insiders developing extensions
|
||||
enableProposedApiForAll: !this._environmentService.isBuilt || (!!this._environmentService.extensionDevelopmentPath && product.nameLong.indexOf('Insiders') >= 0),
|
||||
enableProposedApiFor: this._environmentService.args['enable-proposed-api'] || []
|
||||
extensionTestsPath: this._environmentService.extensionTestsPath
|
||||
},
|
||||
workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : <IWorkspaceData>this._contextService.getWorkspace(),
|
||||
extensions: extensionDescriptions,
|
||||
// Send configurations scopes only in development mode.
|
||||
configuration: !this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment ? { ...configurationData, configurationScopes: getScopes() } : configurationData,
|
||||
telemetryInfo,
|
||||
args: this._environmentService.args,
|
||||
execPath: this._environmentService.execPath,
|
||||
windowId: this._windowService.getCurrentWindowId(),
|
||||
logLevel: this._logService.getLevel()
|
||||
logLevel: this._logService.getLevel(),
|
||||
logsPath: this._environmentService.logsPath
|
||||
};
|
||||
return r;
|
||||
});
|
||||
|
||||
@@ -17,8 +17,8 @@ import * as platform from 'vs/base/common/platform';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
|
||||
import { IMessage, IExtensionDescription, IExtensionsStatus, IExtensionService, ExtensionPointContribution, ActivationTimes, ProfileSession } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { USER_MANIFEST_CACHE_FILE, BUILTIN_MANIFEST_CACHE_FILE, MANIFEST_CACHE_FOLDER } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionEnablementService, IExtensionIdentifier, EnablementState } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { areSameExtensions, BetterMergeId, BetterMergeDisabledNowKey } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IExtensionEnablementService, IExtensionIdentifier, EnablementState, IExtensionManagementService, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { areSameExtensions, BetterMergeId, BetterMergeDisabledNowKey, getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { ExtensionsRegistry, ExtensionPoint, IExtensionPointUser, ExtensionMessageCollector, IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { ExtensionScanner, ILog, ExtensionScannerInput, IExtensionResolver, IExtensionReference, Translations } from 'vs/workbench/services/extensions/node/extensionPoints';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier';
|
||||
@@ -35,13 +35,13 @@ import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { mark, time } from 'vs/base/common/performance';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler';
|
||||
import product from 'vs/platform/node/product';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IChoiceService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
|
||||
|
||||
let _SystemExtensionsRoot: string = null;
|
||||
function getSystemExtensionsRoot(): string {
|
||||
@@ -111,10 +111,160 @@ function messageWithSource2(source: string, message: string): string {
|
||||
const hasOwnProperty = Object.hasOwnProperty;
|
||||
const NO_OP_VOID_PROMISE = TPromise.wrap<void>(void 0);
|
||||
|
||||
export class ExtensionHostProcessManager extends Disposable {
|
||||
|
||||
public readonly onDidCrash: Event<[number, string]>;
|
||||
|
||||
/**
|
||||
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
|
||||
*/
|
||||
private readonly _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; };
|
||||
private readonly _extensionHostProcessActivationTimes: { [id: string]: ActivationTimes; };
|
||||
private readonly _extensionHostExtensionRuntimeErrors: { [id: string]: Error[]; };
|
||||
private _extensionHostProcessRPCProtocol: RPCProtocol;
|
||||
private readonly _extensionHostProcessCustomers: IDisposable[];
|
||||
private readonly _extensionHostProcessWorker: ExtensionHostProcessWorker;
|
||||
/**
|
||||
* winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object.
|
||||
*/
|
||||
private readonly _extensionHostProcessProxy: TPromise<{ value: ExtHostExtensionServiceShape; }>;
|
||||
|
||||
constructor(
|
||||
extensionHostProcessWorker: ExtensionHostProcessWorker,
|
||||
initialActivationEvents: string[],
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
|
||||
) {
|
||||
super();
|
||||
this._extensionHostProcessFinishedActivateEvents = Object.create(null);
|
||||
this._extensionHostProcessActivationTimes = Object.create(null);
|
||||
this._extensionHostExtensionRuntimeErrors = Object.create(null);
|
||||
this._extensionHostProcessRPCProtocol = null;
|
||||
this._extensionHostProcessCustomers = [];
|
||||
this._extensionHostProcessProxy = null;
|
||||
|
||||
this._extensionHostProcessWorker = extensionHostProcessWorker;
|
||||
this.onDidCrash = this._extensionHostProcessWorker.onCrashed;
|
||||
this._extensionHostProcessProxy = this._extensionHostProcessWorker.start().then(
|
||||
(protocol) => {
|
||||
return { value: this._createExtensionHostCustomers(protocol) };
|
||||
},
|
||||
(err) => {
|
||||
console.error('Error received from starting extension host');
|
||||
console.error(err);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
this._extensionHostProcessProxy.then(() => {
|
||||
initialActivationEvents.forEach((activationEvent) => this.activateByEvent(activationEvent));
|
||||
});
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this._extensionHostProcessWorker) {
|
||||
this._extensionHostProcessWorker.dispose();
|
||||
}
|
||||
if (this._extensionHostProcessRPCProtocol) {
|
||||
this._extensionHostProcessRPCProtocol.dispose();
|
||||
}
|
||||
for (let i = 0, len = this._extensionHostProcessCustomers.length; i < len; i++) {
|
||||
const customer = this._extensionHostProcessCustomers[i];
|
||||
try {
|
||||
customer.dispose();
|
||||
} catch (err) {
|
||||
errors.onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public getActivatedExtensionIds(): string[] {
|
||||
return Object.keys(this._extensionHostProcessActivationTimes);
|
||||
}
|
||||
|
||||
public getActivationTimes(): { [id: string]: ActivationTimes; } {
|
||||
return this._extensionHostProcessActivationTimes;
|
||||
}
|
||||
|
||||
public getRuntimeErrors(): { [id: string]: Error[]; } {
|
||||
return this._extensionHostExtensionRuntimeErrors;
|
||||
}
|
||||
|
||||
public canProfileExtensionHost(): boolean {
|
||||
return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort());
|
||||
}
|
||||
|
||||
private _createExtensionHostCustomers(protocol: IMessagePassingProtocol): ExtHostExtensionServiceShape {
|
||||
|
||||
if (logExtensionHostCommunication || this._environmentService.logExtensionHostCommunication) {
|
||||
protocol = asLoggingProtocol(protocol);
|
||||
}
|
||||
|
||||
this._extensionHostProcessRPCProtocol = new RPCProtocol(protocol);
|
||||
const extHostContext: IExtHostContext = this._extensionHostProcessRPCProtocol;
|
||||
|
||||
// Named customers
|
||||
const namedCustomers = ExtHostCustomersRegistry.getNamedCustomers();
|
||||
for (let i = 0, len = namedCustomers.length; i < len; i++) {
|
||||
const [id, ctor] = namedCustomers[i];
|
||||
const instance = this._instantiationService.createInstance(ctor, extHostContext);
|
||||
this._extensionHostProcessCustomers.push(instance);
|
||||
this._extensionHostProcessRPCProtocol.set(id, instance);
|
||||
}
|
||||
|
||||
// Customers
|
||||
const customers = ExtHostCustomersRegistry.getCustomers();
|
||||
for (let i = 0, len = customers.length; i < len; i++) {
|
||||
const ctor = customers[i];
|
||||
const instance = this._instantiationService.createInstance(ctor, extHostContext);
|
||||
this._extensionHostProcessCustomers.push(instance);
|
||||
}
|
||||
|
||||
// Check that no named customers are missing
|
||||
const expected: ProxyIdentifier<any>[] = Object.keys(MainContext).map((key) => MainContext[key]);
|
||||
this._extensionHostProcessRPCProtocol.assertRegistered(expected);
|
||||
|
||||
return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService);
|
||||
}
|
||||
|
||||
public activateByEvent(activationEvent: string): TPromise<void> {
|
||||
if (this._extensionHostProcessFinishedActivateEvents[activationEvent] || !this._extensionHostProcessProxy) {
|
||||
return NO_OP_VOID_PROMISE;
|
||||
}
|
||||
return this._extensionHostProcessProxy.then((proxy) => {
|
||||
return proxy.value.$activateByEvent(activationEvent);
|
||||
}).then(() => {
|
||||
this._extensionHostProcessFinishedActivateEvents[activationEvent] = true;
|
||||
});
|
||||
}
|
||||
|
||||
public startExtensionHostProfile(): TPromise<ProfileSession> {
|
||||
if (this._extensionHostProcessWorker) {
|
||||
let port = this._extensionHostProcessWorker.getInspectPort();
|
||||
if (port) {
|
||||
return this._instantiationService.createInstance(ExtensionHostProfiler, port).start();
|
||||
}
|
||||
}
|
||||
throw new Error('Extension host not running or no inspect port available');
|
||||
}
|
||||
|
||||
public onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void {
|
||||
this._extensionHostProcessActivationTimes[extensionId] = new ActivationTimes(startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent);
|
||||
}
|
||||
|
||||
public onExtensionRuntimeError(extensionId: string, err: Error): void {
|
||||
if (!this._extensionHostExtensionRuntimeErrors[extensionId]) {
|
||||
this._extensionHostExtensionRuntimeErrors[extensionId] = [];
|
||||
}
|
||||
this._extensionHostExtensionRuntimeErrors[extensionId].push(err);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtensionService extends Disposable implements IExtensionService {
|
||||
public _serviceBrand: any;
|
||||
|
||||
private _onDidRegisterExtensions: Emitter<void>;
|
||||
private readonly _onDidRegisterExtensions: Emitter<void>;
|
||||
|
||||
private _registry: ExtensionDescriptionRegistry;
|
||||
private readonly _installedExtensionsReady: Barrier;
|
||||
@@ -126,31 +276,18 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
public readonly onDidChangeExtensionsStatus: Event<string[]> = this._onDidChangeExtensionsStatus.event;
|
||||
|
||||
// --- Members used per extension host process
|
||||
|
||||
/**
|
||||
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
|
||||
*/
|
||||
private _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; };
|
||||
private _extensionHostProcessActivationTimes: { [id: string]: ActivationTimes; };
|
||||
private _extensionHostExtensionRuntimeErrors: { [id: string]: Error[]; };
|
||||
private _extensionHostProcessWorker: ExtensionHostProcessWorker;
|
||||
private _extensionHostProcessRPCProtocol: RPCProtocol;
|
||||
private _extensionHostProcessCustomers: IDisposable[];
|
||||
/**
|
||||
* winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object.
|
||||
*/
|
||||
private _extensionHostProcessProxy: TPromise<{ value: ExtHostExtensionServiceShape; }>;
|
||||
private _extensionHostProcessManager: ExtensionHostProcessManager;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@IChoiceService private readonly _choiceService: IChoiceService,
|
||||
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@IExtensionEnablementService private readonly _extensionEnablementService: IExtensionEnablementService,
|
||||
@IStorageService private readonly _storageService: IStorageService,
|
||||
@IWindowService private readonly _windowService: IWindowService,
|
||||
@ILifecycleService lifecycleService: ILifecycleService
|
||||
@ILifecycleService lifecycleService: ILifecycleService,
|
||||
@IExtensionManagementService private extensionManagementService: IExtensionManagementService
|
||||
) {
|
||||
super();
|
||||
this._registry = null;
|
||||
@@ -161,15 +298,12 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
|
||||
this._onDidRegisterExtensions = new Emitter<void>();
|
||||
|
||||
this._extensionHostProcessFinishedActivateEvents = Object.create(null);
|
||||
this._extensionHostProcessActivationTimes = Object.create(null);
|
||||
this._extensionHostExtensionRuntimeErrors = Object.create(null);
|
||||
this._extensionHostProcessWorker = null;
|
||||
this._extensionHostProcessRPCProtocol = null;
|
||||
this._extensionHostProcessCustomers = [];
|
||||
this._extensionHostProcessProxy = null;
|
||||
|
||||
this._extensionHostProcessManager = null;
|
||||
this.startDelayed(lifecycleService);
|
||||
|
||||
if (this._environmentService.disableExtensions) {
|
||||
this._notificationService.info(nls.localize('extensionsDisabled', "All extensions are disabled."));
|
||||
}
|
||||
}
|
||||
|
||||
private startDelayed(lifecycleService: ILifecycleService): void {
|
||||
@@ -223,51 +357,25 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
|
||||
private _stopExtensionHostProcess(): void {
|
||||
const previouslyActivatedExtensionIds = Object.keys(this._extensionHostProcessActivationTimes);
|
||||
let previouslyActivatedExtensionIds: string[] = [];
|
||||
|
||||
this._extensionHostProcessFinishedActivateEvents = Object.create(null);
|
||||
this._extensionHostProcessActivationTimes = Object.create(null);
|
||||
this._extensionHostExtensionRuntimeErrors = Object.create(null);
|
||||
if (this._extensionHostProcessWorker) {
|
||||
this._extensionHostProcessWorker.dispose();
|
||||
this._extensionHostProcessWorker = null;
|
||||
if (this._extensionHostProcessManager) {
|
||||
previouslyActivatedExtensionIds = this._extensionHostProcessManager.getActivatedExtensionIds();
|
||||
this._extensionHostProcessManager.dispose();
|
||||
this._extensionHostProcessManager = null;
|
||||
}
|
||||
if (this._extensionHostProcessRPCProtocol) {
|
||||
this._extensionHostProcessRPCProtocol.dispose();
|
||||
this._extensionHostProcessRPCProtocol = null;
|
||||
}
|
||||
for (let i = 0, len = this._extensionHostProcessCustomers.length; i < len; i++) {
|
||||
const customer = this._extensionHostProcessCustomers[i];
|
||||
try {
|
||||
customer.dispose();
|
||||
} catch (err) {
|
||||
errors.onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
this._extensionHostProcessCustomers = [];
|
||||
this._extensionHostProcessProxy = null;
|
||||
|
||||
this._onDidChangeExtensionsStatus.fire(previouslyActivatedExtensionIds);
|
||||
if (previouslyActivatedExtensionIds.length > 0) {
|
||||
this._onDidChangeExtensionsStatus.fire(previouslyActivatedExtensionIds);
|
||||
}
|
||||
}
|
||||
|
||||
private _startExtensionHostProcess(initialActivationEvents: string[]): void {
|
||||
this._stopExtensionHostProcess();
|
||||
|
||||
this._extensionHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, this);
|
||||
this._extensionHostProcessWorker.onCrashed(([code, signal]) => this._onExtensionHostCrashed(code, signal));
|
||||
this._extensionHostProcessProxy = this._extensionHostProcessWorker.start().then(
|
||||
(protocol) => {
|
||||
return { value: this._createExtensionHostCustomers(protocol) };
|
||||
},
|
||||
(err) => {
|
||||
console.error('Error received from starting extension host');
|
||||
console.error(err);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
this._extensionHostProcessProxy.then(() => {
|
||||
initialActivationEvents.forEach((activationEvent) => this.activateByEvent(activationEvent));
|
||||
});
|
||||
const extHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, this);
|
||||
this._extensionHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, extHostProcessWorker, initialActivationEvents);
|
||||
this._extensionHostProcessManager.onDidCrash(([code, signal]) => this._onExtensionHostCrashed(code, signal));
|
||||
}
|
||||
|
||||
private _onExtensionHostCrashed(code: number, signal: string): void {
|
||||
@@ -279,49 +387,16 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
message = nls.localize('extensionHostProcess.unresponsiveCrash', "Extension host terminated because it was not responsive.");
|
||||
}
|
||||
|
||||
this._choiceService.choose(Severity.Error, message, [nls.localize('devTools', "Developer Tools"), nls.localize('restart', "Restart Extension Host")]).then(choice => {
|
||||
switch (choice) {
|
||||
case 0 /* Open Dev Tools */:
|
||||
this._windowService.openDevTools();
|
||||
break;
|
||||
case 1 /* Restart Extension Host */:
|
||||
this._startExtensionHostProcess(Object.keys(this._allRequestedActivateEvents));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _createExtensionHostCustomers(protocol: IMessagePassingProtocol): ExtHostExtensionServiceShape {
|
||||
|
||||
if (logExtensionHostCommunication || this._environmentService.logExtensionHostCommunication) {
|
||||
protocol = asLoggingProtocol(protocol);
|
||||
}
|
||||
|
||||
this._extensionHostProcessRPCProtocol = new RPCProtocol(protocol);
|
||||
const extHostContext: IExtHostContext = this._extensionHostProcessRPCProtocol;
|
||||
|
||||
// Named customers
|
||||
const namedCustomers = ExtHostCustomersRegistry.getNamedCustomers();
|
||||
for (let i = 0, len = namedCustomers.length; i < len; i++) {
|
||||
const [id, ctor] = namedCustomers[i];
|
||||
const instance = this._instantiationService.createInstance(ctor, extHostContext);
|
||||
this._extensionHostProcessCustomers.push(instance);
|
||||
this._extensionHostProcessRPCProtocol.set(id, instance);
|
||||
}
|
||||
|
||||
// Customers
|
||||
const customers = ExtHostCustomersRegistry.getCustomers();
|
||||
for (let i = 0, len = customers.length; i < len; i++) {
|
||||
const ctor = customers[i];
|
||||
const instance = this._instantiationService.createInstance(ctor, extHostContext);
|
||||
this._extensionHostProcessCustomers.push(instance);
|
||||
}
|
||||
|
||||
// Check that no named customers are missing
|
||||
const expected: ProxyIdentifier<any>[] = Object.keys(MainContext).map((key) => MainContext[key]);
|
||||
this._extensionHostProcessRPCProtocol.assertRegistered(expected);
|
||||
|
||||
return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService);
|
||||
this._notificationService.prompt(Severity.Error, message,
|
||||
[{
|
||||
label: nls.localize('devTools', "Open Developer Tools"),
|
||||
run: () => this._windowService.openDevTools()
|
||||
},
|
||||
{
|
||||
label: nls.localize('restart', "Restart Extension Host"),
|
||||
run: () => this._startExtensionHostProcess(Object.keys(this._allRequestedActivateEvents))
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
// ---- begin IExtensionService
|
||||
@@ -349,15 +424,11 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
}
|
||||
|
||||
protected _activateByEvent(activationEvent: string): TPromise<void> {
|
||||
if (this._extensionHostProcessFinishedActivateEvents[activationEvent] || !this._extensionHostProcessProxy) {
|
||||
return NO_OP_VOID_PROMISE;
|
||||
private _activateByEvent(activationEvent: string): TPromise<void> {
|
||||
if (this._extensionHostProcessManager) {
|
||||
return this._extensionHostProcessManager.activateByEvent(activationEvent);
|
||||
}
|
||||
return this._extensionHostProcessProxy.then((proxy) => {
|
||||
return proxy.value.$activateByEvent(activationEvent);
|
||||
}).then(() => {
|
||||
this._extensionHostProcessFinishedActivateEvents[activationEvent] = true;
|
||||
});
|
||||
return NO_OP_VOID_PROMISE;
|
||||
}
|
||||
|
||||
public whenInstalledExtensionsRegistered(): TPromise<boolean> {
|
||||
@@ -388,6 +459,9 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
|
||||
public getExtensionsStatus(): { [id: string]: IExtensionsStatus; } {
|
||||
const activationTimes = this._extensionHostProcessManager ? this._extensionHostProcessManager.getActivationTimes() : {};
|
||||
const runtimeErrors = this._extensionHostProcessManager ? this._extensionHostProcessManager.getRuntimeErrors() : {};
|
||||
|
||||
let result: { [id: string]: IExtensionsStatus; } = Object.create(null);
|
||||
if (this._registry) {
|
||||
const extensions = this._registry.getAllExtensionDescriptions();
|
||||
@@ -396,8 +470,8 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
const id = extension.id;
|
||||
result[id] = {
|
||||
messages: this._extensionsMessages[id],
|
||||
activationTimes: this._extensionHostProcessActivationTimes[id],
|
||||
runtimeErrors: this._extensionHostExtensionRuntimeErrors[id],
|
||||
activationTimes: activationTimes[id],
|
||||
runtimeErrors: runtimeErrors[id],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -405,15 +479,15 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
|
||||
public canProfileExtensionHost(): boolean {
|
||||
return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort());
|
||||
if (this._extensionHostProcessManager) {
|
||||
return this._extensionHostProcessManager.canProfileExtensionHost();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public startExtensionHostProfile(): TPromise<ProfileSession> {
|
||||
if (this._extensionHostProcessWorker) {
|
||||
let port = this._extensionHostProcessWorker.getInspectPort();
|
||||
if (port) {
|
||||
return this._instantiationService.createInstance(ExtensionHostProfiler, port).start();
|
||||
}
|
||||
if (this._extensionHostProcessManager) {
|
||||
return this._extensionHostProcessManager.startExtensionHostProfile();
|
||||
}
|
||||
throw new Error('Extension host not running or no inspect port available');
|
||||
}
|
||||
@@ -424,7 +498,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
|
||||
private _scanAndHandleExtensions(): void {
|
||||
|
||||
this._getRuntimeExtension()
|
||||
this._getRuntimeExtensions()
|
||||
.then(runtimeExtensons => {
|
||||
this._registry = new ExtensionDescriptionRegistry(runtimeExtensons);
|
||||
|
||||
@@ -449,14 +523,13 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
});
|
||||
}
|
||||
|
||||
private _getRuntimeExtension(): TPromise<IExtensionDescription[]> {
|
||||
private _getRuntimeExtensions(): TPromise<IExtensionDescription[]> {
|
||||
const log = new Logger((severity, source, message) => {
|
||||
this._logOrShowMessage(severity, this._isDev ? messageWithSource2(source, message) : message);
|
||||
});
|
||||
|
||||
return ExtensionService._scanInstalledExtensions(this._windowService, this._choiceService, this._environmentService, log)
|
||||
return ExtensionService._scanInstalledExtensions(this._windowService, this._notificationService, this._environmentService, log)
|
||||
.then(({ system, user, development }) => {
|
||||
this._extensionEnablementService.migrateToIdentifiers(user); // TODO: @sandy Remove it after couple of milestones
|
||||
return this._extensionEnablementService.getDisabledExtensions()
|
||||
.then(disabledExtensions => {
|
||||
let result: { [extensionId: string]: IExtensionDescription; } = {};
|
||||
@@ -501,7 +574,11 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
});
|
||||
|
||||
if (extensionsToDisable.length) {
|
||||
return TPromise.join(extensionsToDisable.map(e => this._extensionEnablementService.setEnablement(e, EnablementState.Disabled)))
|
||||
return this.extensionManagementService.getInstalled(LocalExtensionType.User)
|
||||
.then(installed => {
|
||||
const toDisable = installed.filter(i => extensionsToDisable.some(e => areSameExtensions({ id: getGalleryExtensionIdFromLocal(i) }, e)));
|
||||
return TPromise.join(toDisable.map(e => this._extensionEnablementService.setEnablement(e, EnablementState.Disabled)));
|
||||
})
|
||||
.then(() => {
|
||||
this._storageService.store(BetterMergeDisabledNowKey, true);
|
||||
return runtimeExtensions;
|
||||
@@ -510,7 +587,36 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
return runtimeExtensions;
|
||||
}
|
||||
});
|
||||
});
|
||||
}).then(extensions => this._updateEnableProposedApi(extensions));
|
||||
}
|
||||
|
||||
private _updateEnableProposedApi(extensions: IExtensionDescription[]): IExtensionDescription[] {
|
||||
const enableProposedApiForAll = !this._environmentService.isBuilt || (!!this._environmentService.extensionDevelopmentPath && product.nameLong.indexOf('Insiders') >= 0);
|
||||
const enableProposedApiFor = this._environmentService.args['enable-proposed-api'] || [];
|
||||
for (const extension of extensions) {
|
||||
if (!isFalsyOrEmpty(product.extensionAllowedProposedApi)
|
||||
&& product.extensionAllowedProposedApi.indexOf(extension.id) >= 0
|
||||
) {
|
||||
// fast lane -> proposed api is available to all extensions
|
||||
// that are listed in product.json-files
|
||||
extension.enableProposedApi = true;
|
||||
|
||||
} else if (extension.enableProposedApi && !extension.isBuiltin) {
|
||||
if (
|
||||
!enableProposedApiForAll &&
|
||||
enableProposedApiFor.indexOf(extension.id) < 0
|
||||
) {
|
||||
extension.enableProposedApi = false;
|
||||
console.error(`Extension '${extension.id} cannot use PROPOSED API (must started out of dev or enabled via --enable-proposed-api)`);
|
||||
|
||||
} else {
|
||||
// proposed api is available when developing or when an extension was explicitly
|
||||
// spelled out via a command line argument
|
||||
console.warn(`Extension '${extension.id}' uses PROPOSED API which is subject to change and removal without notice.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
private _handleExtensionPointMessage(msg: IMessage) {
|
||||
@@ -531,7 +637,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
const { type, extensionId, extensionPointId, message } = msg;
|
||||
/* __GDPR__
|
||||
"extensionsMessage" : {
|
||||
"type" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"type" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
|
||||
"extensionId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"extensionPointId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"message": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
@@ -543,7 +649,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
}
|
||||
|
||||
private static async _validateExtensionsCache(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): TPromise<void> {
|
||||
private static async _validateExtensionsCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): TPromise<void> {
|
||||
const cacheFolder = path.join(environmentService.userDataPath, MANIFEST_CACHE_FOLDER);
|
||||
const cacheFile = path.join(cacheFolder, cacheKey);
|
||||
|
||||
@@ -568,11 +674,14 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
choiceService.choose(Severity.Error, nls.localize('extensionCache.invalid', "Extensions have been modified on disk. Please reload the window."), [nls.localize('reloadWindow', "Reload Window")]).then(choice => {
|
||||
if (choice === 0) {
|
||||
windowService.reloadWindow();
|
||||
}
|
||||
});
|
||||
notificationService.prompt(
|
||||
Severity.Error,
|
||||
nls.localize('extensionCache.invalid', "Extensions have been modified on disk. Please reload the window."),
|
||||
[{
|
||||
label: nls.localize('reloadWindow', "Reload Window"),
|
||||
run: () => windowService.reloadWindow()
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
private static async _readExtensionCache(environmentService: IEnvironmentService, cacheKey: string): TPromise<IExtensionCacheData> {
|
||||
@@ -606,7 +715,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
}
|
||||
|
||||
private static async _scanExtensionsWithCache(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): TPromise<IExtensionDescription[]> {
|
||||
private static async _scanExtensionsWithCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): TPromise<IExtensionDescription[]> {
|
||||
if (input.devMode) {
|
||||
// Do not cache when running out of sources...
|
||||
return ExtensionScanner.scanExtensions(input, log);
|
||||
@@ -624,7 +733,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
// Validate the cache asynchronously after 5s
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
await this._validateExtensionsCache(windowService, choiceService, environmentService, cacheKey, input);
|
||||
await this._validateExtensionsCache(windowService, notificationService, environmentService, cacheKey, input);
|
||||
} catch (err) {
|
||||
errors.onUnexpectedError(err);
|
||||
}
|
||||
@@ -646,7 +755,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static _scanInstalledExtensions(windowService: IWindowService, choiceService: IChoiceService, environmentService: IEnvironmentService, log: ILog): TPromise<{ system: IExtensionDescription[], user: IExtensionDescription[], development: IExtensionDescription[] }> {
|
||||
private static _scanInstalledExtensions(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, log: ILog): TPromise<{ system: IExtensionDescription[], user: IExtensionDescription[], development: IExtensionDescription[] }> {
|
||||
|
||||
const translationConfig: TPromise<Translations> = platform.translationsConfigFile
|
||||
? pfs.readFile(platform.translationsConfigFile, 'utf8').then((content) => {
|
||||
@@ -668,7 +777,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
|
||||
const builtinExtensions = this._scanExtensionsWithCache(
|
||||
windowService,
|
||||
choiceService,
|
||||
notificationService,
|
||||
environmentService,
|
||||
BUILTIN_MANIFEST_CACHE_FILE,
|
||||
new ExtensionScannerInput(version, commit, locale, devMode, getSystemExtensionsRoot(), true, translations),
|
||||
@@ -722,7 +831,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
? TPromise.as([])
|
||||
: this._scanExtensionsWithCache(
|
||||
windowService,
|
||||
choiceService,
|
||||
notificationService,
|
||||
environmentService,
|
||||
USER_MANIFEST_CACHE_FILE,
|
||||
new ExtensionScannerInput(version, commit, locale, devMode, environmentService.extensionsPath, false, translations),
|
||||
@@ -798,15 +907,12 @@ export class ExtensionService extends Disposable implements IExtensionService {
|
||||
}
|
||||
|
||||
public _onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void {
|
||||
this._extensionHostProcessActivationTimes[extensionId] = new ActivationTimes(startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent);
|
||||
this._extensionHostProcessManager.onExtensionActivated(extensionId, startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent);
|
||||
this._onDidChangeExtensionsStatus.fire([extensionId]);
|
||||
}
|
||||
|
||||
public _onExtensionRuntimeError(extensionId: string, err: Error): void {
|
||||
if (!this._extensionHostExtensionRuntimeErrors[extensionId]) {
|
||||
this._extensionHostExtensionRuntimeErrors[extensionId] = [];
|
||||
}
|
||||
this._extensionHostExtensionRuntimeErrors[extensionId].push(err);
|
||||
this._extensionHostProcessManager.onExtensionRuntimeError(extensionId, err);
|
||||
this._onDidChangeExtensionsStatus.fire([extensionId]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user