UNPKG

@codingame/monaco-vscode-extensions-service-override

Version:

VSCode public API plugged on the monaco editor - extensions service-override

942 lines (941 loc) 59 kB
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