@codingame/monaco-vscode-extensions-service-override
Version:
VSCode public API plugged on the monaco editor - extensions service-override
942 lines (941 loc) • 59 kB
JavaScript
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js';
import { Barrier } from 'vscode/vscode/vs/base/common/async';
import { toErrorMessage } from 'vscode/vscode/vs/base/common/errorMessage';
import { Emitter } from 'vscode/vscode/vs/base/common/event';
import { MarkdownString } from 'vscode/vscode/vs/base/common/htmlContent';
import { Disposable, DisposableStore } from 'vscode/vscode/vs/base/common/lifecycle';
import { Schemas } from 'vscode/vscode/vs/base/common/network';
import { mark } from 'vscode/vscode/vs/base/common/performance';
import { isCI } from 'vscode/vscode/vs/base/common/platform';
import { isEqualOrParent } from 'vscode/vscode/vs/base/common/resources';
import { StopWatch } from 'vscode/vscode/vs/base/common/stopwatch';
import { isDefined } from 'vscode/vscode/vs/base/common/types';
import { localize } from 'vscode/vscode/vs/nls';
import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
import { IDialogService } from 'vscode/vscode/vs/platform/dialogs/common/dialogs.service';
import { InstallOperation } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagement';
import { ImplicitActivationEvents } from 'vscode/vscode/vs/platform/extensionManagement/common/implicitActivationEvents';
import { ExtensionIdentifierMap, ExtensionIdentifier } from 'vscode/vscode/vs/platform/extensions/common/extensions';
import { IFileService } from 'vscode/vscode/vs/platform/files/common/files.service';
import { SyncDescriptor } from 'vscode/vscode/vs/platform/instantiation/common/descriptors';
import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
import { handleVetos } from '../../../../platform/lifecycle/common/lifecycle.js';
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service';
import 'vscode/vscode/vs/platform/notification/common/notification';
import { INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification.service';
import { IProductService } from 'vscode/vscode/vs/platform/product/common/productService.service';
import { Registry } from 'vscode/vscode/vs/platform/registry/common/platform';
import { RemoteAuthorityResolverError, getRemoteAuthorityPrefix, RemoteAuthorityResolverErrorCode } from 'vscode/vscode/vs/platform/remote/common/remoteAuthorityResolver';
import { IRemoteAuthorityResolverService } from 'vscode/vscode/vs/platform/remote/common/remoteAuthorityResolver.service';
import { IRemoteExtensionsScannerService } from 'vscode/vscode/vs/platform/remote/common/remoteExtensionsScanner.service';
import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry.service';
import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace.service';
import { IWorkbenchEnvironmentService } from 'vscode/vscode/vs/workbench/services/environment/common/environmentService.service';
import { Extensions } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionFeatures';
import { IWorkbenchExtensionEnablementService, IWorkbenchExtensionManagementService } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionManagement.service';
import { LockableExtensionDescriptionRegistry } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import { parseExtensionDevOptions } from './extensionDevOptions.js';
import { ExtensionRunningPreference, ExtensionHostKind } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionHostKind';
import { ExtensionHostManager } from './extensionHostManager.js';
import { IExtensionManifestPropertiesService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionManifestPropertiesService.service';
import { RemoteRunningLocation, LocalProcessRunningLocation, LocalWebWorkerRunningLocation } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionRunningLocation';
import { ExtensionRunningLocationTracker, filterExtensionIdentifiers } from './extensionRunningLocationTracker.js';
import { toExtensionDescription, ExtensionHostStartup, ActivationKind, ExtensionPointContribution, ActivationTimes, toExtension } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions';
import { ExtensionsRegistry, ExtensionMessageCollector } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionsRegistry';
import { LazyCreateExtensionHostManager } from './lazyCreateExtensionHostManager.js';
import { ResponsiveState } from 'vscode/vscode/vs/workbench/services/extensions/common/rpcProtocol';
import { checkGlobFileExists, checkActivateWorkspaceContainsExtension } from 'vscode/vscode/vs/workbench/services/extensions/common/workspaceContains';
import { WillShutdownJoinerOrder } from 'vscode/vscode/vs/workbench/services/lifecycle/common/lifecycle';
import { ILifecycleService } from 'vscode/vscode/vs/workbench/services/lifecycle/common/lifecycle.service';
import { IRemoteAgentService } from 'vscode/vscode/vs/workbench/services/remote/common/remoteAgentService.service';
import Severity$1 from 'vscode/vscode/vs/base/common/severity';
var AbstractExtensionService_1;
const hasOwnProperty = Object.hasOwnProperty;
const NO_OP_VOID_PROMISE = Promise.resolve(undefined);
let AbstractExtensionService = AbstractExtensionService_1 = class AbstractExtensionService extends Disposable {
constructor(_extensionsProposedApi, _extensionHostFactory, _extensionHostKindPicker, _instantiationService, _notificationService, _environmentService, _telemetryService, _extensionEnablementService, _fileService, _productService, _extensionManagementService, _contextService, _configurationService, _extensionManifestPropertiesService, _logService, _remoteAgentService, _remoteExtensionsScannerService, _lifecycleService, _remoteAuthorityResolverService, _dialogService) {
super();
this._extensionsProposedApi = _extensionsProposedApi;
this._extensionHostFactory = _extensionHostFactory;
this._extensionHostKindPicker = _extensionHostKindPicker;
this._instantiationService = _instantiationService;
this._notificationService = _notificationService;
this._environmentService = _environmentService;
this._telemetryService = _telemetryService;
this._extensionEnablementService = _extensionEnablementService;
this._fileService = _fileService;
this._productService = _productService;
this._extensionManagementService = _extensionManagementService;
this._contextService = _contextService;
this._configurationService = _configurationService;
this._extensionManifestPropertiesService = _extensionManifestPropertiesService;
this._logService = _logService;
this._remoteAgentService = _remoteAgentService;
this._remoteExtensionsScannerService = _remoteExtensionsScannerService;
this._lifecycleService = _lifecycleService;
this._remoteAuthorityResolverService = _remoteAuthorityResolverService;
this._dialogService = _dialogService;
this._onDidRegisterExtensions = this._register(( (new Emitter())));
this.onDidRegisterExtensions = this._onDidRegisterExtensions.event;
this._onDidChangeExtensionsStatus = this._register(( (new Emitter())));
this.onDidChangeExtensionsStatus = this._onDidChangeExtensionsStatus.event;
this._onDidChangeExtensions = this._register(( (new Emitter({ leakWarningThreshold: 400 }))));
this.onDidChangeExtensions = this._onDidChangeExtensions.event;
this._onWillActivateByEvent = this._register(( (new Emitter())));
this.onWillActivateByEvent = this._onWillActivateByEvent.event;
this._onDidChangeResponsiveChange = this._register(( (new Emitter())));
this.onDidChangeResponsiveChange = this._onDidChangeResponsiveChange.event;
this._onWillStop = this._register(( (new Emitter())));
this.onWillStop = this._onWillStop.event;
this._activationEventReader = ( (new ImplicitActivationAwareReader()));
this._registry = ( (new LockableExtensionDescriptionRegistry(this._activationEventReader)));
this._installedExtensionsReady = ( (new Barrier()));
this._extensionStatus = ( (new ExtensionIdentifierMap()));
this._allRequestedActivateEvents = ( (new Set()));
this._remoteCrashTracker = ( (new ExtensionHostCrashTracker()));
this._deltaExtensionsQueue = [];
this._inHandleDeltaExtensions = false;
this._extensionHostManagers = this._register(( (new ExtensionHostCollection())));
this._resolveAuthorityAttempt = 0;
this._register(this._fileService.onWillActivateFileSystemProvider(e => {
if (e.scheme !== Schemas.vscodeRemote) {
e.join(this.activateByEvent(`onFileSystem:${e.scheme}`));
}
}));
this._runningLocations = ( (new ExtensionRunningLocationTracker(
this._registry,
this._extensionHostKindPicker,
this._environmentService,
this._configurationService,
this._logService,
this._extensionManifestPropertiesService
)));
this._register(this._extensionEnablementService.onEnablementChanged((extensions) => {
const toAdd = [];
const toRemove = [];
for (const extension of extensions) {
if (this._safeInvokeIsEnabled(extension)) {
toAdd.push(extension);
}
else {
toRemove.push(extension);
}
}
if (isCI) {
this._logService.info(`AbstractExtensionService.onEnablementChanged fired for ${( (extensions.map(e => e.identifier.id))).join(', ')}`);
}
this._handleDeltaExtensions(( (new DeltaExtensionsQueueItem(toAdd, toRemove))));
}));
this._register(this._extensionManagementService.onDidChangeProfile(({ added, removed }) => {
if (added.length || removed.length) {
if (isCI) {
this._logService.info(`AbstractExtensionService.onDidChangeProfile fired`);
}
this._handleDeltaExtensions(( (new DeltaExtensionsQueueItem(added, removed))));
}
}));
this._register(this._extensionManagementService.onDidEnableExtensions(extensions => {
if (extensions.length) {
if (isCI) {
this._logService.info(`AbstractExtensionService.onDidEnableExtensions fired`);
}
this._handleDeltaExtensions(( (new DeltaExtensionsQueueItem(extensions, []))));
}
}));
this._register(this._extensionManagementService.onDidInstallExtensions((result) => {
const extensions = [];
for (const { local, operation } of result) {
if (local && local.isValid && operation !== InstallOperation.Migrate && this._safeInvokeIsEnabled(local)) {
extensions.push(local);
}
}
if (extensions.length) {
if (isCI) {
this._logService.info(`AbstractExtensionService.onDidInstallExtensions fired for ${( (extensions.map(e => e.identifier.id))).join(', ')}`);
}
this._handleDeltaExtensions(( (new DeltaExtensionsQueueItem(extensions, []))));
}
}));
this._register(this._extensionManagementService.onDidUninstallExtension((event) => {
if (!event.error) {
if (isCI) {
this._logService.info(`AbstractExtensionService.onDidUninstallExtension fired for ${event.identifier.id}`);
}
this._handleDeltaExtensions(( (new DeltaExtensionsQueueItem([], [event.identifier.id]))));
}
}));
this._register(this._lifecycleService.onWillShutdown(event => {
if (this._remoteAgentService.getConnection()) {
event.join(() => this._remoteAgentService.endConnection(), {
id: 'join.disconnectRemote',
label: ( localize(1126, "Disconnect Remote Agent")),
order: WillShutdownJoinerOrder.Last
});
}
}));
this._register(this._lifecycleService.onDidShutdown(() => {
const connection = this._remoteAgentService.getConnection();
connection?.dispose();
this._doStopExtensionHosts();
}));
}
_getExtensionHostManagers(kind) {
return this._extensionHostManagers.getByKind(kind);
}
async _handleDeltaExtensions(item) {
this._deltaExtensionsQueue.push(item);
if (this._inHandleDeltaExtensions) {
return;
}
let lock = null;
try {
this._inHandleDeltaExtensions = true;
await this._installedExtensionsReady.wait();
lock = await this._registry.acquireLock('handleDeltaExtensions');
while (this._deltaExtensionsQueue.length > 0) {
const item = this._deltaExtensionsQueue.shift();
await this._deltaExtensions(lock, item.toAdd, item.toRemove);
}
}
finally {
this._inHandleDeltaExtensions = false;
lock?.dispose();
}
}
async _deltaExtensions(lock, _toAdd, _toRemove) {
if (isCI) {
this._logService.info(`AbstractExtensionService._deltaExtensions: toAdd: [${( (_toAdd.map(e => e.identifier.id))).join(',')}] toRemove: [${( (_toRemove.map(e => typeof e === 'string' ? e : e.identifier.id))).join(',')}]`);
}
let toRemove = [];
for (let i = 0, len = _toRemove.length; i < len; i++) {
const extensionOrId = _toRemove[i];
const extensionId = (typeof extensionOrId === 'string' ? extensionOrId : extensionOrId.identifier.id);
const extension = (typeof extensionOrId === 'string' ? null : extensionOrId);
const extensionDescription = this._registry.getExtensionDescription(extensionId);
if (!extensionDescription) {
continue;
}
if (extension && extensionDescription.extensionLocation.scheme !== extension.location.scheme) {
continue;
}
if (!this.canRemoveExtension(extensionDescription)) {
continue;
}
toRemove.push(extensionDescription);
}
const toAdd = [];
for (let i = 0, len = _toAdd.length; i < len; i++) {
const extension = _toAdd[i];
const extensionDescription = toExtensionDescription(extension, false);
if (!extensionDescription) {
continue;
}
if (!this._canAddExtension(extensionDescription, toRemove)) {
continue;
}
toAdd.push(extensionDescription);
}
if (toAdd.length === 0 && toRemove.length === 0) {
return;
}
const result = this._registry.deltaExtensions(lock, toAdd, ( (toRemove.map(e => e.identifier))));
this._onDidChangeExtensions.fire({ added: toAdd, removed: toRemove });
toRemove = toRemove.concat(result.removedDueToLooping);
if (result.removedDueToLooping.length > 0) {
this._notificationService.notify({
severity: Severity$1.Error,
message: ( localize(
1127,
"The following extensions contain dependency loops and have been disabled: {0}",
( (result.removedDueToLooping.map(e => `'${e.identifier.value}'`))).join(', ')
))
});
}
this._extensionsProposedApi.updateEnabledApiProposals(toAdd);
this._doHandleExtensionPoints([].concat(toAdd).concat(toRemove));
await this._updateExtensionsOnExtHosts(result.versionId, toAdd, ( (toRemove.map(e => e.identifier))));
for (let i = 0; i < toAdd.length; i++) {
this._activateAddedExtensionIfNeeded(toAdd[i]);
}
}
async _updateExtensionsOnExtHosts(versionId, toAdd, toRemove) {
const removedRunningLocation = this._runningLocations.deltaExtensions(toAdd, toRemove);
const promises = ( (this._extensionHostManagers.map(
extHostManager => this._updateExtensionsOnExtHost(extHostManager, versionId, toAdd, toRemove, removedRunningLocation)
)));
await Promise.all(promises);
}
async _updateExtensionsOnExtHost(extensionHostManager, versionId, toAdd, toRemove, removedRunningLocation) {
const myToAdd = this._runningLocations.filterByExtensionHostManager(toAdd, extensionHostManager);
const myToRemove = filterExtensionIdentifiers(toRemove, removedRunningLocation, extRunningLocation => extensionHostManager.representsRunningLocation(extRunningLocation));
const addActivationEvents = ImplicitActivationEvents.createActivationEventsMap(toAdd);
if (isCI) {
const printExtIds = (extensions) => ( (extensions.map(e => e.identifier.value))).join(',');
const printIds = (extensions) => ( (extensions.map(e => e.value))).join(',');
this._logService.info(`AbstractExtensionService: Calling deltaExtensions: toRemove: [${printIds(toRemove)}], toAdd: [${printExtIds(toAdd)}], myToRemove: [${printIds(myToRemove)}], myToAdd: [${printExtIds(myToAdd)}],`);
}
await extensionHostManager.deltaExtensions({ versionId, toRemove, toAdd, addActivationEvents, myToRemove, myToAdd: ( (myToAdd.map(extension => extension.identifier))) });
}
canAddExtension(extension) {
return this._canAddExtension(extension, []);
}
_canAddExtension(extension, extensionsBeingRemoved) {
const existing = this._registry.getExtensionDescriptionByIdOrUUID(extension.identifier, extension.id);
if (existing) {
const isBeingRemoved = ( (extensionsBeingRemoved.some(
(extensionDescription) => ExtensionIdentifier.equals(extension.identifier, extensionDescription.identifier)
)));
if (!isBeingRemoved) {
return false;
}
}
const extensionKinds = this._runningLocations.readExtensionKinds(extension);
const isRemote = extension.extensionLocation.scheme === Schemas.vscodeRemote;
const extensionHostKind = this._extensionHostKindPicker.pickExtensionHostKind(extension.identifier, extensionKinds, !isRemote, isRemote, ExtensionRunningPreference.None);
if (extensionHostKind === null) {
return false;
}
return true;
}
canRemoveExtension(extension) {
const extensionDescription = this._registry.getExtensionDescription(extension.identifier);
if (!extensionDescription) {
return false;
}
if (this._extensionStatus.get(extensionDescription.identifier)?.activationStarted) {
return false;
}
return true;
}
async _activateAddedExtensionIfNeeded(extensionDescription) {
let shouldActivate = false;
let shouldActivateReason = null;
let hasWorkspaceContains = false;
const activationEvents = this._activationEventReader.readActivationEvents(extensionDescription);
for (const activationEvent of activationEvents) {
if (( (this._allRequestedActivateEvents.has(activationEvent)))) {
shouldActivate = true;
shouldActivateReason = activationEvent;
break;
}
if (activationEvent === '*') {
shouldActivate = true;
shouldActivateReason = activationEvent;
break;
}
if (/^workspaceContains/.test(activationEvent)) {
hasWorkspaceContains = true;
}
if (activationEvent === 'onStartupFinished') {
shouldActivate = true;
shouldActivateReason = activationEvent;
break;
}
}
if (shouldActivate) {
await Promise.all(( (this._extensionHostManagers.map(
extHostManager => extHostManager.activate(extensionDescription.identifier, { startup: false, extensionId: extensionDescription.identifier, activationEvent: shouldActivateReason })
)))).then(() => { });
}
else if (hasWorkspaceContains) {
const workspace = await this._contextService.getCompleteWorkspace();
const forceUsingSearch = !!this._environmentService.remoteAuthority;
const host = {
logService: this._logService,
folders: ( (workspace.folders.map(folder => folder.uri))),
forceUsingSearch: forceUsingSearch,
exists: (uri) => this._fileService.exists(uri),
checkExists: (folders, includes, token) => this._instantiationService.invokeFunction((accessor) => checkGlobFileExists(accessor, folders, includes, token))
};
const result = await checkActivateWorkspaceContainsExtension(host, extensionDescription);
if (!result) {
return;
}
await Promise.all(( (this._extensionHostManagers.map(
extHostManager => extHostManager.activate(extensionDescription.identifier, { startup: false, extensionId: extensionDescription.identifier, activationEvent: result.activationEvent })
)))).then(() => { });
}
}
async _initialize() {
mark('code/willLoadExtensions');
this._startExtensionHostsIfNecessary(true, []);
const lock = await this._registry.acquireLock('_initialize');
try {
const resolvedExtensions = await this._resolveExtensions();
this._processExtensions(lock, resolvedExtensions);
const snapshot = this._registry.getSnapshot();
for (const extHostManager of this._extensionHostManagers) {
if (extHostManager.startup !== ExtensionHostStartup.EagerAutoStart) {
const extensions = this._runningLocations.filterByExtensionHostManager(snapshot.extensions, extHostManager);
extHostManager.start(snapshot.versionId, snapshot.extensions, ( (extensions.map(extension => extension.identifier))));
}
}
}
finally {
lock.dispose();
}
this._releaseBarrier();
mark('code/didLoadExtensions');
await this._handleExtensionTests();
}
_processExtensions(lock, resolvedExtensions) {
const { allowRemoteExtensionsInLocalWebWorker, hasLocalProcess } = resolvedExtensions;
const localExtensions = checkEnabledAndProposedAPI(this._logService, this._extensionEnablementService, this._extensionsProposedApi, resolvedExtensions.local, false);
let remoteExtensions = checkEnabledAndProposedAPI(this._logService, this._extensionEnablementService, this._extensionsProposedApi, resolvedExtensions.remote, false);
this._runningLocations.initializeRunningLocation(localExtensions, remoteExtensions);
this._startExtensionHostsIfNecessary(true, []);
const remoteExtensionsThatNeedToRunLocally = (allowRemoteExtensionsInLocalWebWorker ? this._runningLocations.filterByExtensionHostKind(remoteExtensions, ExtensionHostKind.LocalWebWorker) : []);
const localProcessExtensions = (hasLocalProcess ? this._runningLocations.filterByExtensionHostKind(localExtensions, ExtensionHostKind.LocalProcess) : []);
const localWebWorkerExtensions = this._runningLocations.filterByExtensionHostKind(localExtensions, ExtensionHostKind.LocalWebWorker);
remoteExtensions = this._runningLocations.filterByExtensionHostKind(remoteExtensions, ExtensionHostKind.Remote);
for (const ext of remoteExtensionsThatNeedToRunLocally) {
if (!includes(localWebWorkerExtensions, ext.identifier)) {
localWebWorkerExtensions.push(ext);
}
}
const allExtensions = remoteExtensions.concat(localProcessExtensions).concat(localWebWorkerExtensions);
const result = this._registry.deltaExtensions(lock, allExtensions, []);
if (result.removedDueToLooping.length > 0) {
this._notificationService.notify({
severity: Severity$1.Error,
message: ( localize(
1127,
"The following extensions contain dependency loops and have been disabled: {0}",
( (result.removedDueToLooping.map(e => `'${e.identifier.value}'`))).join(', ')
))
});
}
this._doHandleExtensionPoints(this._registry.getAllExtensionDescriptions());
}
async _handleExtensionTests() {
if (!this._environmentService.isExtensionDevelopment || !this._environmentService.extensionTestsLocationURI) {
return;
}
const extensionHostManager = this.findTestExtensionHost(this._environmentService.extensionTestsLocationURI);
if (!extensionHostManager) {
const msg = ( localize(
1128,
"No extension host found that can launch the test runner at {0}.",
(this._environmentService.extensionTestsLocationURI.toString())
));
console.error(msg);
this._notificationService.error(msg);
return;
}
let exitCode;
try {
exitCode = await extensionHostManager.extensionTestsExecute();
if (isCI) {
this._logService.info(`Extension host test runner exit code: ${exitCode}`);
}
}
catch (err) {
if (isCI) {
this._logService.error(`Extension host test runner error`, err);
}
console.error(err);
exitCode = 1 ;
}
this._onExtensionHostExit(exitCode);
}
findTestExtensionHost(testLocation) {
let runningLocation = null;
for (const extension of this._registry.getAllExtensionDescriptions()) {
if (isEqualOrParent(testLocation, extension.extensionLocation)) {
runningLocation = this._runningLocations.getRunningLocation(extension.identifier);
break;
}
}
if (runningLocation === null) {
if (testLocation.scheme === Schemas.vscodeRemote) {
runningLocation = ( (new RemoteRunningLocation()));
}
else {
runningLocation = ( (new LocalProcessRunningLocation(0)));
}
}
if (runningLocation !== null) {
return this._extensionHostManagers.getByRunningLocation(runningLocation);
}
return null;
}
_releaseBarrier() {
this._installedExtensionsReady.open();
this._onDidRegisterExtensions.fire(undefined);
this._onDidChangeExtensionsStatus.fire(( (this._registry.getAllExtensionDescriptions().map(e => e.identifier))));
}
async _resolveAuthorityInitial(remoteAuthority) {
const MAX_ATTEMPTS = 5;
for (let attempt = 1;; attempt++) {
try {
return this._resolveAuthorityWithLogging(remoteAuthority);
}
catch (err) {
if (RemoteAuthorityResolverError.isNoResolverFound(err)) {
throw err;
}
if (RemoteAuthorityResolverError.isNotAvailable(err)) {
throw err;
}
if (attempt >= MAX_ATTEMPTS) {
throw err;
}
}
}
}
async _resolveAuthorityAgain() {
const remoteAuthority = this._environmentService.remoteAuthority;
if (!remoteAuthority) {
return;
}
this._remoteAuthorityResolverService._clearResolvedAuthority(remoteAuthority);
try {
const result = await this._resolveAuthorityWithLogging(remoteAuthority);
this._remoteAuthorityResolverService._setResolvedAuthority(result.authority, result.options);
}
catch (err) {
this._remoteAuthorityResolverService._setResolvedAuthorityError(remoteAuthority, err);
}
}
async _resolveAuthorityWithLogging(remoteAuthority) {
const authorityPrefix = getRemoteAuthorityPrefix(remoteAuthority);
const sw = StopWatch.create(false);
this._logService.info(`Invoking resolveAuthority(${authorityPrefix})...`);
try {
mark(`code/willResolveAuthority/${authorityPrefix}`);
const result = await this._resolveAuthority(remoteAuthority);
mark(`code/didResolveAuthorityOK/${authorityPrefix}`);
this._logService.info(`resolveAuthority(${authorityPrefix}) returned '${result.authority.connectTo}' after ${sw.elapsed()} ms`);
return result;
}
catch (err) {
mark(`code/didResolveAuthorityError/${authorityPrefix}`);
this._logService.error(`resolveAuthority(${authorityPrefix}) returned an error after ${sw.elapsed()} ms`, err);
throw err;
}
}
async _resolveAuthorityOnExtensionHosts(kind, remoteAuthority) {
const extensionHosts = this._getExtensionHostManagers(kind);
if (extensionHosts.length === 0) {
throw ( (new Error(`Cannot resolve authority`)));
}
this._resolveAuthorityAttempt++;
const results = await Promise.all(( (extensionHosts.map(
extHost => extHost.resolveAuthority(remoteAuthority, this._resolveAuthorityAttempt)
))));
let bestErrorResult = null;
for (const result of results) {
if (result.type === 'ok') {
return result.value;
}
if (!bestErrorResult) {
bestErrorResult = result;
continue;
}
const bestErrorIsUnknown = (bestErrorResult.error.code === RemoteAuthorityResolverErrorCode.Unknown);
const errorIsUnknown = (result.error.code === RemoteAuthorityResolverErrorCode.Unknown);
if (bestErrorIsUnknown && !errorIsUnknown) {
bestErrorResult = result;
}
}
throw ( (new RemoteAuthorityResolverError(
bestErrorResult.error.message,
bestErrorResult.error.code,
bestErrorResult.error.detail
)));
}
stopExtensionHosts(reason, auto) {
return this._doStopExtensionHostsWithVeto(reason, auto);
}
_doStopExtensionHosts() {
const previouslyActivatedExtensionIds = [];
for (const extensionStatus of ( (this._extensionStatus.values()))) {
if (extensionStatus.activationStarted) {
previouslyActivatedExtensionIds.push(extensionStatus.id);
}
}
this._extensionHostManagers.disposeAllInReverse();
for (const extensionStatus of ( (this._extensionStatus.values()))) {
extensionStatus.clearRuntimeStatus();
}
if (previouslyActivatedExtensionIds.length > 0) {
this._onDidChangeExtensionsStatus.fire(previouslyActivatedExtensionIds);
}
}
async _doStopExtensionHostsWithVeto(reason, auto) {
const vetos = [];
const vetoReasons = ( (new Set()));
this._onWillStop.fire({
reason,
veto(value, reason) {
vetos.push(value);
if (typeof value === 'boolean') {
if (value === true) {
vetoReasons.add(reason);
}
}
else {
value.then(value => {
if (value) {
vetoReasons.add(reason);
}
}).catch(error => {
vetoReasons.add(( localize(1129, "{0} (Error: {1})", reason, toErrorMessage(error))));
});
}
}
});
const veto = await handleVetos(vetos, error => this._logService.error(error));
if (!veto) {
this._doStopExtensionHosts();
}
else {
if (!auto) {
const vetoReasonsArray = Array.from(vetoReasons);
this._logService.warn(`Extension host was not stopped because of veto (stop reason: ${reason}, veto reason: ${vetoReasonsArray.join(', ')})`);
await this._dialogService.warn(( localize(1130, "The following operation was blocked: {0}", reason)), vetoReasonsArray.length === 1 ?
( localize(1131, "The reason for blocking the operation: {0}", vetoReasonsArray[0])) :
( localize(
1132,
"The reasons for blocking the operation:\n- {0}",
vetoReasonsArray.join('\n -')
)));
}
}
return !veto;
}
_startExtensionHostsIfNecessary(isInitialStart, initialActivationEvents) {
const locations = [];
for (let affinity = 0; affinity <= this._runningLocations.maxLocalProcessAffinity; affinity++) {
locations.push(( (new LocalProcessRunningLocation(affinity))));
}
for (let affinity = 0; affinity <= this._runningLocations.maxLocalWebWorkerAffinity; affinity++) {
locations.push(( (new LocalWebWorkerRunningLocation(affinity))));
}
locations.push(( (new RemoteRunningLocation())));
for (const location of locations) {
if (this._extensionHostManagers.getByRunningLocation(location)) {
continue;
}
const res = this._createExtensionHostManager(location, isInitialStart, initialActivationEvents);
if (res) {
const [extHostManager, disposableStore] = res;
this._extensionHostManagers.add(extHostManager, disposableStore);
}
}
}
_createExtensionHostManager(runningLocation, isInitialStart, initialActivationEvents) {
const extensionHost = this._extensionHostFactory.createExtensionHost(this._runningLocations, runningLocation, isInitialStart);
if (!extensionHost) {
return null;
}
const processManager = this._doCreateExtensionHostManager(extensionHost, initialActivationEvents);
const disposableStore = ( (new DisposableStore()));
disposableStore.add(processManager.onDidExit(([code, signal]) => this._onExtensionHostCrashOrExit(processManager, code, signal)));
disposableStore.add(processManager.onDidChangeResponsiveState((responsiveState) => {
this._logService.info(`Extension host (${processManager.friendyName}) is ${responsiveState === ResponsiveState.Responsive ? 'responsive' : 'unresponsive'}.`);
this._onDidChangeResponsiveChange.fire({
extensionHostKind: processManager.kind,
isResponsive: responsiveState === ResponsiveState.Responsive,
getInspectListener: (tryEnableInspector) => {
return processManager.getInspectPort(tryEnableInspector);
}
});
}));
return [processManager, disposableStore];
}
_doCreateExtensionHostManager(extensionHost, initialActivationEvents) {
const internalExtensionService = this._acquireInternalAPI(extensionHost);
if (extensionHost.startup === ExtensionHostStartup.Lazy && initialActivationEvents.length === 0) {
return this._instantiationService.createInstance(LazyCreateExtensionHostManager, extensionHost, internalExtensionService);
}
return this._instantiationService.createInstance(ExtensionHostManager, extensionHost, initialActivationEvents, internalExtensionService);
}
_onExtensionHostCrashOrExit(extensionHost, code, signal) {
const isExtensionDevHost = parseExtensionDevOptions(this._environmentService).isExtensionDevHost;
if (!isExtensionDevHost) {
this._onExtensionHostCrashed(extensionHost, code, signal);
return;
}
this._onExtensionHostExit(code);
}
_onExtensionHostCrashed(extensionHost, code, signal) {
console.error(`Extension host (${extensionHost.friendyName}) terminated unexpectedly. Code: ${code}, Signal: ${signal}`);
if (extensionHost.kind === ExtensionHostKind.LocalProcess) {
this._doStopExtensionHosts();
}
else if (extensionHost.kind === ExtensionHostKind.Remote) {
if (signal) {
this._onRemoteExtensionHostCrashed(extensionHost, signal);
}
this._extensionHostManagers.disposeOne(extensionHost);
}
}
_getExtensionHostExitInfoWithTimeout(reconnectionToken) {
return (
(new Promise((resolve, reject) => {
const timeoutHandle = setTimeout(() => {
reject(( (new Error('getExtensionHostExitInfo timed out'))));
}, 2000);
this._remoteAgentService.getExtensionHostExitInfo(reconnectionToken).then((r) => {
clearTimeout(timeoutHandle);
resolve(r);
}, reject);
}))
);
}
async _onRemoteExtensionHostCrashed(extensionHost, reconnectionToken) {
try {
const info = await this._getExtensionHostExitInfoWithTimeout(reconnectionToken);
if (info) {
this._logService.error(`Extension host (${extensionHost.friendyName}) terminated unexpectedly with code ${info.code}.`);
}
this._logExtensionHostCrash(extensionHost);
this._remoteCrashTracker.registerCrash();
if (this._remoteCrashTracker.shouldAutomaticallyRestart()) {
this._logService.info(`Automatically restarting the remote extension host.`);
this._notificationService.status(( localize(1133, "The remote extension host terminated unexpectedly. Restarting...")), { hideAfter: 5000 });
this._startExtensionHostsIfNecessary(false, Array.from(( (this._allRequestedActivateEvents.keys()))));
}
else {
this._notificationService.prompt(Severity$1.Error, ( localize(
1134,
"Remote Extension host terminated unexpectedly 3 times within the last 5 minutes."
)), [{
label: ( localize(1135, "Restart Remote Extension Host")),
run: () => {
this._startExtensionHostsIfNecessary(false, Array.from(( (this._allRequestedActivateEvents.keys()))));
}
}]);
}
}
catch (err) {
}
}
_logExtensionHostCrash(extensionHost) {
const activatedExtensions = [];
for (const extensionStatus of ( (this._extensionStatus.values()))) {
if (extensionStatus.activationStarted && extensionHost.containsExtension(extensionStatus.id)) {
activatedExtensions.push(extensionStatus.id);
}
}
if (activatedExtensions.length > 0) {
this._logService.error(`Extension host (${extensionHost.friendyName}) terminated unexpectedly. The following extensions were running: ${( (activatedExtensions.map(id => id.value))).join(', ')}`);
}
else {
this._logService.error(`Extension host (${extensionHost.friendyName}) terminated unexpectedly. No extensions were activated.`);
}
}
async startExtensionHosts(updates) {
this._doStopExtensionHosts();
if (updates) {
await this._handleDeltaExtensions(( (new DeltaExtensionsQueueItem(updates.toAdd, updates.toRemove))));
}
const lock = await this._registry.acquireLock('startExtensionHosts');
try {
this._startExtensionHostsIfNecessary(false, Array.from(( (this._allRequestedActivateEvents.keys()))));
const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess);
await Promise.all(( (localProcessExtensionHosts.map(extHost => extHost.ready()))));
}
finally {
lock.dispose();
}
}
activateByEvent(activationEvent, activationKind = ActivationKind.Normal) {
if (this._installedExtensionsReady.isOpen()) {
this._allRequestedActivateEvents.add(activationEvent);
if (!this._registry.containsActivationEvent(activationEvent)) {
return NO_OP_VOID_PROMISE;
}
return this._activateByEvent(activationEvent, activationKind);
}
else {
this._allRequestedActivateEvents.add(activationEvent);
if (activationKind === ActivationKind.Immediate) {
return this._activateByEvent(activationEvent, activationKind);
}
return this._installedExtensionsReady.wait().then(() => this._activateByEvent(activationEvent, activationKind));
}
}
_activateByEvent(activationEvent, activationKind) {
const result = Promise.all(( (this._extensionHostManagers.map(
extHostManager => extHostManager.activateByEvent(activationEvent, activationKind)
)))).then(() => { });
this._onWillActivateByEvent.fire({
event: activationEvent,
activation: result
});
return result;
}
activateById(extensionId, reason) {
return this._activateById(extensionId, reason);
}
activationEventIsDone(activationEvent) {
if (!this._installedExtensionsReady.isOpen()) {
return false;
}
if (!this._registry.containsActivationEvent(activationEvent)) {
return true;
}
return this._extensionHostManagers.every(manager => manager.activationEventIsDone(activationEvent));
}
whenInstalledExtensionsRegistered() {
return this._installedExtensionsReady.wait();
}
get extensions() {
return this._registry.getAllExtensionDescriptions();
}
_getExtensionRegistrySnapshotWhenReady() {
return this._installedExtensionsReady.wait().then(() => this._registry.getSnapshot());
}
getExtension(id) {
return this._installedExtensionsReady.wait().then(() => {
return this._registry.getExtensionDescription(id);
});
}
readExtensionPointContributions(extPoint) {
return this._installedExtensionsReady.wait().then(() => {
const availableExtensions = this._registry.getAllExtensionDescriptions();
const result = [];
for (const desc of availableExtensions) {
if (desc.contributes && hasOwnProperty.call(desc.contributes, extPoint.name)) {
result.push(( (new ExtensionPointContribution(desc, desc.contributes[extPoint.name]))));
}
}
return result;
});
}
getExtensionsStatus() {
const result = Object.create(null);
if (this._registry) {
const extensions = this._registry.getAllExtensionDescriptions();
for (const extension of extensions) {
const extensionStatus = this._extensionStatus.get(extension.identifier);
result[extension.identifier.value] = {
id: extension.identifier,
messages: extensionStatus?.messages ?? [],
activationStarted: extensionStatus?.activationStarted ?? false,
activationTimes: extensionStatus?.activationTimes ?? undefined,
runtimeErrors: extensionStatus?.runtimeErrors ?? [],
runningLocation: this._runningLocations.getRunningLocation(extension.identifier),
};
}
}
return result;
}
async getInspectPorts(extensionHostKind, tryEnableInspector) {
const result = await Promise.all(( (this._getExtensionHostManagers(extensionHostKind).map(extHost => extHost.getInspectPort(tryEnableInspector)))));
return result.filter(isDefined);
}
async setRemoteEnvironment(env) {
await ( (this._extensionHostManagers
.map(manager => manager.setRemoteEnvironment(env))));
}
_safeInvokeIsEnabled(extension) {
try {
return this._extensionEnablementService.isEnabled(extension);
}
catch (err) {
return false;
}
}
_doHandleExtensionPoints(affectedExtensions) {
const affectedExtensionPoints = Object.create(null);
for (const extensionDescription of affectedExtensions) {
if (extensionDescription.contributes) {
for (const extPointName in extensionDescription.contributes) {
if (hasOwnProperty.call(extensionDescription.contributes, extPointName)) {
affectedExtensionPoints[extPointName] = true;
}
}
}
}
const messageHandler = (msg) => this._handleExtensionPointMessage(msg);
const availableExtensions = this._registry.getAllExtensionDescriptions();
const extensionPoints = ExtensionsRegistry.getExtensionPoints();
mark('code/willHandleExtensionPoints');
for (const extensionPoint of extensionPoints) {
if (affectedExtensionPoints[extensionPoint.name]) {
mark(`code/willHandleExtensionPoint/${extensionPoint.name}`);
AbstractExtensionService_1._handleExtensionPoint(extensionPoint, availableExtensions, messageHandler);
mark(`code/didHandleExtensionPoint/${extensionPoint.name}`);
}
}
mark('code/didHandleExtensionPoints');
}
_getOrCreateExtensionStatus(extensionId) {
if (!( (this._extensionStatus.has(extensionId)))) {
this._extensionStatus.set(extensionId, ( (new ExtensionStatus(extensionId))));
}
return this._extensionStatus.get(extensionId);
}
_handleExtensionPointMessage(msg) {
const extensionStatus = this._getOrCreateExtensionStatus(msg.extensionId);
extensionStatus.addMessage(msg);
const extension = this._registry.getExtensionDescription(msg.extensionId);
const strMsg = `[${msg.extensionId.value}]: ${msg.message}`;
if (msg.type === Severity$1.Error) {
if (extension && extension.isUnderDevelopment) {
this._notificationService.notify({ severity: Severity$1.Error, message: strMsg });
}
this._logService.error(strMsg);
}
else if (msg.type === Severity$1.Warning) {
if (extension && extension.isUnderDevelopment) {
this._notificationService.notify({ severity: Severity$1.Warning, message: strMsg });
}
this._logService.warn(strMsg);
}
else {
this._logService.info(strMsg);
}
if (msg.extensionId && this._environmentService.isBuilt && !this._environmentService.isExtensionDevelopment) {
const { type, extensionId, extensionPointId, message } = msg;
this._telemetryService.publicLog2('extensionsMessage', {
type, extensionId: extensionId.value, extensionPointId, message
});
}
}
static _handleExtensionPoint(extensionPoint, availableExtensions, messageHandler) {
const users = [];
for (const desc of availableExtensions) {
if (desc.contributes && hasOwnProperty.call(desc.contributes, extensionPoint.name)) {
users.push({
description: desc,
value: desc.contributes[extensionPoint.name],
collector: ( (new ExtensionMessageCollector(messageHandler, desc, extensionPoint.name)))
});
}
}
extensionPoint.acceptUsers(users);
}
_acquireInternalAPI(extensionHost) {
return {
_activateById: (extensionId, reason) => {
return this._activateById(extensionId, reason);
},
_onWillActivateExtension: (extensionId) => {
return this._onWillActivateExtension(extensionId, extensionHost.runningLocation);
},
_onDidActivateExtension: (extensionId, codeLoadingTime, activateCallTime, activateResolvedTime, activationReason) => {
return this._onDidActivateExtension(extensionId, codeLoadingTime, activateCallTime, activateResolvedTime, activationReason);
},
_onDidActivateExtensionError: (extensionId, error) => {
return this._onDidActivateExtensionError(extensionId, error);
},
_onExtensionRuntimeError: (extensionId, err) => {
return this._onExtensionRuntimeError(extensionId, err);
}
};
}
async _activateById(extensionId, reason) {
const results = await Promise.all(( (this._extensionHostManagers.map(manager => manager.activate(extensionId, reason)))));
const activated = ( (results.some(e => e)));
if (!activated) {
throw ( (new Error(`Unknown extension ${extensionId.value}`)));
}
}
_onWillActivateExtension(extensionId, runningLocation) {
this._runningLocations.set(extensionId, runningLocation);
const extensionStatus = this._getOrCreateExtensionStatus(extensionId);
extensionStatus.onWillActiv