UNPKG

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

Version:

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

997 lines (995 loc) 66.8 kB
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6'; import { Barrier } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async'; import { toErrorMessage } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errorMessage'; import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event'; import { MarkdownString } from '@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent'; import { Disposable, DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle'; import { Schemas } from '@codingame/monaco-vscode-api/vscode/vs/base/common/network'; import { mark } from '@codingame/monaco-vscode-api/vscode/vs/base/common/performance'; import { isCI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform'; import { isEqualOrParent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources'; import { StopWatch } from '@codingame/monaco-vscode-api/vscode/vs/base/common/stopwatch'; import { isDefined } from '@codingame/monaco-vscode-api/vscode/vs/base/common/types'; import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls'; import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service'; import { IDialogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/dialogs/common/dialogs.service'; import { InstallOperation } from '@codingame/monaco-vscode-api/vscode/vs/platform/extensionManagement/common/extensionManagement'; import { ImplicitActivationEvents } from '@codingame/monaco-vscode-api/vscode/vs/platform/extensionManagement/common/implicitActivationEvents'; import { ExtensionIdentifierMap, ExtensionIdentifier } from '@codingame/monaco-vscode-api/vscode/vs/platform/extensions/common/extensions'; import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service'; import { SyncDescriptor } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/descriptors'; import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation'; import { handleVetos } from '../../../../platform/lifecycle/common/lifecycle.js'; import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service'; import '@codingame/monaco-vscode-api/vscode/vs/platform/notification/common/notification'; import { INotificationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/notification/common/notification.service'; import { IProductService } from '@codingame/monaco-vscode-api/vscode/vs/platform/product/common/productService.service'; import { Registry } from '@codingame/monaco-vscode-api/vscode/vs/platform/registry/common/platform'; import { RemoteAuthorityResolverError, getRemoteAuthorityPrefix, RemoteAuthorityResolverErrorCode } from '@codingame/monaco-vscode-api/vscode/vs/platform/remote/common/remoteAuthorityResolver'; import { IRemoteAuthorityResolverService } from '@codingame/monaco-vscode-api/vscode/vs/platform/remote/common/remoteAuthorityResolver.service'; import { IRemoteExtensionsScannerService } from '@codingame/monaco-vscode-api/vscode/vs/platform/remote/common/remoteExtensionsScanner.service'; import { ITelemetryService } from '@codingame/monaco-vscode-api/vscode/vs/platform/telemetry/common/telemetry.service'; import { IWorkspaceContextService } from '@codingame/monaco-vscode-api/vscode/vs/platform/workspace/common/workspace.service'; import { IWorkbenchEnvironmentService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/environment/common/environmentService.service'; import { Extensions } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensionManagement/common/extensionFeatures'; import { IWorkbenchExtensionEnablementService, IWorkbenchExtensionManagementService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensionManagement/common/extensionManagement.service'; import { LockableExtensionDescriptionRegistry } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensionDescriptionRegistry'; import { parseExtensionDevOptions } from './extensionDevOptions.js'; import { ExtensionRunningPreference, ExtensionHostKind } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensionHostKind'; import { ExtensionHostManager } from './extensionHostManager.js'; import { IExtensionManifestPropertiesService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensionManifestPropertiesService.service'; import { RemoteRunningLocation, LocalProcessRunningLocation, LocalWebWorkerRunningLocation } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensionRunningLocation'; import { ExtensionRunningLocationTracker, filterExtensionIdentifiers } from './extensionRunningLocationTracker.js'; import { toExtensionDescription, ActivationKind, ExtensionHostStartup, ExtensionPointContribution, ActivationTimes, toExtension } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensions'; import { ExtensionsRegistry, ExtensionMessageCollector } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/extensionsRegistry'; import { LazyCreateExtensionHostManager } from './lazyCreateExtensionHostManager.js'; import { ResponsiveState } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/rpcProtocol'; import { checkGlobFileExists, checkActivateWorkspaceContainsExtension } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/extensions/common/workspaceContains'; import { WillShutdownJoinerOrder } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/lifecycle/common/lifecycle'; import { ILifecycleService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/lifecycle/common/lifecycle.service'; import { IRemoteAgentService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/remote/common/remoteAgentService.service'; import Severity from '@codingame/monaco-vscode-api/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( options, _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, leakWarningName: "ExtensionService._onDidChangeExtensions" }))); 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._pendingRemoteActivationEvents = ( new Set()); this._remoteCrashTracker = ( new ExtensionHostCrashTracker()); this._deltaExtensionsQueue = []; this._inHandleDeltaExtensions = false; this._extensionHostManagers = this._register(( new ExtensionHostCollection())); this._resolveAuthorityAttempt = 0; this._initializePromise = null; this._hasLocalProcess = options.hasLocalProcess; this._allowRemoteExtensionsInLocalWebWorker = options.allowRemoteExtensionsInLocalWebWorker; 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 = []; const toRemove = []; for (const { local, operation } of result) { if (local && local.isValid && operation !== InstallOperation.Migrate && this._safeInvokeIsEnabled(local)) { extensions.push(local); if (operation === InstallOperation.Update) { toRemove.push(local.identifier.id); } } } if (extensions.length) { if (isCI) { this._logService.info( `AbstractExtensionService.onDidInstallExtensions fired for ${( extensions.map(e => e.identifier.id)).join(", ")}` ); } this._handleDeltaExtensions(( new DeltaExtensionsQueueItem(extensions, toRemove))); } })); 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(async () => { try { await this._remoteAgentService.endConnection(); await this._doStopExtensionHosts(); this._remoteAgentService.getConnection()?.dispose(); } catch { this._logService.warn("Error while disconnecting remote agent"); } }, { id: "join.disconnectRemote", label: ( localize(16632, "Disconnect Remote Agent")), order: WillShutdownJoinerOrder.Last }); } else { event.join(this._doStopExtensionHosts(), { id: "join.stopExtensionHosts", label: ( localize(16633, "Stopping Extension Hosts")) }); } })); } _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.Error, message: ( localize( 16634, "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), false); 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 shouldActivateReason = null; let hasWorkspaceContains = false; const activationEvents = this._activationEventReader.readActivationEvents(extensionDescription); for (const activationEvent of activationEvents) { if (( this._allRequestedActivateEvents.has(activationEvent))) { shouldActivateReason = activationEvent; break; } if (activationEvent === "*") { shouldActivateReason = activationEvent; break; } if (/^workspaceContains/.test(activationEvent)) { hasWorkspaceContains = true; } if (activationEvent === "onStartupFinished") { shouldActivateReason = activationEvent; break; } } if (!shouldActivateReason && 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) { shouldActivateReason = result.activationEvent; } } if (shouldActivateReason) { await Promise.all(( this._extensionHostManagers.map( extHostManager => extHostManager.activate(extensionDescription.identifier, { startup: false, extensionId: extensionDescription.identifier, activationEvent: shouldActivateReason }) ))); } } _initializeIfNeeded() { if (!this._initializePromise) { this._initializePromise = this._initialize(); } return this._initializePromise; } async _initialize() { mark("code/willLoadExtensions"); this._startExtensionHostsIfNecessary(true, []); const lock = await this._registry.acquireLock("_initialize"); try { await this._resolveAndProcessExtensions(lock); this._startOnDemandExtensionHosts(); } finally { lock.dispose(); } this._releaseBarrier(); mark("code/didLoadExtensions"); this._activateDeferredRemoteEvents(); await this._handleExtensionTests(); } async _activateDeferredRemoteEvents() { if (this._pendingRemoteActivationEvents.size === 0) { return; } const remoteExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.Remote); if (remoteExtensionHosts.length === 0) { this._pendingRemoteActivationEvents.clear(); return; } await Promise.all(( remoteExtensionHosts.map(extHost => extHost.ready()))); for (const activationEvent of this._pendingRemoteActivationEvents) { const result = Promise.all(( remoteExtensionHosts.map( extHostManager => extHostManager.activateByEvent(activationEvent, ActivationKind.Normal) ))).then(() => {}); this._onWillActivateByEvent.fire({ event: activationEvent, activation: result, activationKind: ActivationKind.Normal }); } this._pendingRemoteActivationEvents.clear(); } async _resolveAndProcessExtensions(lock) { let resolverExtensions = []; let localExtensions = []; let remoteExtensions = []; for await (const extensions of this._resolveExtensions()) { if (extensions instanceof ResolverExtensions) { resolverExtensions = checkEnabledAndProposedAPI( this._logService, this._extensionEnablementService, this._extensionsProposedApi, extensions.extensions, false ); this._registry.deltaExtensions(lock, resolverExtensions, []); this._doHandleExtensionPoints(resolverExtensions, true); } if (extensions instanceof LocalExtensions) { localExtensions = checkEnabledAndProposedAPI( this._logService, this._extensionEnablementService, this._extensionsProposedApi, extensions.extensions, false ); } if (extensions instanceof RemoteExtensions) { remoteExtensions = checkEnabledAndProposedAPI( this._logService, this._extensionEnablementService, this._extensionsProposedApi, extensions.extensions, false ); } } this._runningLocations.initializeRunningLocation(localExtensions, remoteExtensions); this._startExtensionHostsIfNecessary(true, []); const remoteExtensionsThatNeedToRunLocally = (this._allowRemoteExtensionsInLocalWebWorker ? this._runningLocations.filterByExtensionHostKind(remoteExtensions, ExtensionHostKind.LocalWebWorker) : []); const localProcessExtensions = (this._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); let toAdd = allExtensions; if (resolverExtensions.length) { toAdd = allExtensions.filter(extension => !( resolverExtensions.some( e => ExtensionIdentifier.equals(e.identifier, extension.identifier) && ( e.extensionLocation.toString()) === ( extension.extensionLocation.toString()) ))); if (allExtensions.length < toAdd.length + resolverExtensions.length) { const toRemove = resolverExtensions.filter(registered => !( allExtensions.some( e => ExtensionIdentifier.equals(e.identifier, registered.identifier) && ( e.extensionLocation.toString()) === ( registered.extensionLocation.toString()) ))); if (toRemove.length) { this._registry.deltaExtensions(lock, [], ( toRemove.map(e => e.identifier))); this._doHandleExtensionPoints(toRemove, true); } } } const result = this._registry.deltaExtensions(lock, toAdd, []); if (result.removedDueToLooping.length > 0) { this._notificationService.notify({ severity: Severity.Error, message: ( localize( 16634, "The following extensions contain dependency loops and have been disabled: {0}", ( result.removedDueToLooping.map(e => `'${e.identifier.value}'`)).join(", ") )) }); } this._doHandleExtensionPoints(this._registry.getAllExtensionDescriptions(), false); } async _handleExtensionTests() { if (!this._environmentService.isExtensionDevelopment || !this._environmentService.extensionTestsLocationURI) { return; } const extensionHostManager = this.findTestExtensionHost(this._environmentService.extensionTestsLocationURI); if (!extensionHostManager) { const msg = ( localize( 16635, "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 )); } async stopExtensionHosts(reason, auto) { await this._initializeIfNeeded(); return this._doStopExtensionHostsWithVeto(reason, auto); } async _doStopExtensionHosts() { const previouslyActivatedExtensionIds = []; for (const extensionStatus of ( this._extensionStatus.values())) { if (extensionStatus.activationStarted) { previouslyActivatedExtensionIds.push(extensionStatus.id); } } await this._extensionHostManagers.stopAllInReverse(); for (const extensionStatus of ( this._extensionStatus.values())) { extensionStatus.clearRuntimeStatus(); } if (previouslyActivatedExtensionIds.length > 0) { this._onDidChangeExtensionsStatus.fire(previouslyActivatedExtensionIds); } } async _doStopExtensionHostsWithVeto(reason, auto = false) { if (auto && this._environmentService.isExtensionDevelopment) { return false; } const vetos = []; const vetoReasons = ( new Set()); this._onWillStop.fire({ reason, auto, 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(16636, "{0} (Error: {1})", reason, toErrorMessage(error)))); }); } } }); const veto = await handleVetos(vetos, error => this._logService.error(error)); if (!veto) { await 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(", ")})` ); const { confirmed } = await this._dialogService.confirm({ type: Severity.Warning, message: ( localize(16637, "Please confirm restart of extensions.")), detail: vetoReasonsArray.length === 1 ? vetoReasonsArray[0] : vetoReasonsArray.join("\n -"), primaryButton: ( localize(16638, "Restart Anyway")) }); if (confirmed) { return true; } } } 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.LazyAutoStart) { return this._instantiationService.createInstance( LazyCreateExtensionHostManager, extensionHost, initialActivationEvents, 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.stopOne(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(16639, "The remote extension host terminated unexpectedly. Restarting...")), { hideAfter: 5000 }); this._startExtensionHostsIfNecessary(false, Array.from(( this._allRequestedActivateEvents.keys()))); } else { this._notificationService.prompt(Severity.Error, ( localize( 16640, "Remote Extension host terminated unexpectedly 3 times within the last 5 minutes." )), [{ label: ( localize(16641, "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) { await 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()))); this._startOnDemandExtensionHosts(); const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess); await Promise.all(( localProcessExtensionHosts.map(extHost => extHost.ready()))); } finally { lock.dispose(); } } _startOnDemandExtensionHosts() { 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))); } } } 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) { void this._initializeIfNeeded(); return this._activateByEvent(activationEvent, activationKind); } return this._installedExtensionsReady.wait().then(() => this._activateByEvent(activationEvent, activationKind)); } } _activateByEvent(activationEvent, activationKind) { let managers; if (activationKind === ActivationKind.Immediate) { managers = this._extensionHostManagers.filter( extHostManager => extHostManager.kind === ExtensionHostKind.LocalProcess || extHostManager.kind === ExtensionHostKind.LocalWebWorker || extHostManager.isReady ); this._pendingRemoteActivationEvents.add(activationEvent); } else { managers = [...this._extensionHostManagers]; } const result = Promise.all(( managers.map( extHostManager => extHostManager.activateByEvent(activationEvent, activationKind) ))).then(() => {}); this._onWillActivateByEvent.fire({ event: activationEvent, activation: result, activationKind }); 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) { con