Merge from vscode 817eb6b0c720a4ecbc13c020afbbebfed667aa09 (#7356)

This commit is contained in:
Anthony Dresser
2019-09-24 21:36:17 -07:00
committed by GitHub
parent a29ae4d3b9
commit 6a6048d40f
541 changed files with 7045 additions and 7287 deletions

View File

@@ -16,7 +16,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IURLHandler, IURLService } from 'vs/platform/url/common/url';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@@ -65,7 +65,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
@INotificationService private readonly notificationService: INotificationService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
@IWindowService private readonly windowService: IWindowService,
@IHostService private readonly hostService: IHostService,
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
@IStorageService private readonly storageService: IStorageService,
@IConfigurationService private readonly configurationService: IConfigurationService
@@ -277,7 +277,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
private async reloadAndHandle(url: URI): Promise<void> {
this.storageService.store(URL_TO_HANDLE, JSON.stringify(url.toJSON()), StorageScope.WORKSPACE);
await this.windowService.reloadWindow();
await this.hostService.reload();
}
// forget about all uris buffered more than 5 minutes ago

View File

@@ -24,6 +24,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
import { IFileService } from 'vs/platform/files/common/files';
import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions';
import { IProductService } from 'vs/platform/product/common/productService';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
const hasOwnProperty = Object.hasOwnProperty;
const NO_OP_VOID_PROMISE = Promise.resolve<void>(undefined);
@@ -290,17 +291,21 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
}
protected _isEnabled(extension: IExtensionDescription): boolean {
return !this._isDisabled(extension);
}
protected _isDisabled(extension: IExtensionDescription): boolean {
if (this._isExtensionUnderDevelopment(extension)) {
// Never disable extensions under development
return true;
return false;
}
if (ExtensionIdentifier.equals(extension.identifier, BetterMergeId)) {
// Check if this is the better merge extension which was migrated to a built-in extension
return false;
return true;
}
return this._extensionEnablementService.isEnabled(toExtension(extension));
return !this._extensionEnablementService.isEnabled(toExtension(extension));
}
protected _doHandleExtensionPoints(affectedExtensions: IExtensionDescription[]): void {
@@ -406,9 +411,9 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
}
}
public async _activateById(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void> {
public async _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
const results = await Promise.all(
this._extensionHostProcessManagers.map(manager => manager.activate(extensionId, activationEvent))
this._extensionHostProcessManagers.map(manager => manager.activate(extensionId, reason))
);
const activated = results.some(e => e);
if (!activated) {
@@ -420,8 +425,8 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
this._extensionHostActiveExtensions.set(ExtensionIdentifier.toKey(extensionId), extensionId);
}
public _onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void {
this._extensionHostProcessActivationTimes.set(ExtensionIdentifier.toKey(extensionId), new ActivationTimes(startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent));
public _onDidActivateExtension(extensionId: ExtensionIdentifier, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationReason: ExtensionActivationReason): void {
this._extensionHostProcessActivationTimes.set(ExtensionIdentifier.toKey(extensionId), new ActivationTimes(codeLoadingTime, activateCallTime, activateResolvedTime, activationReason));
this._onDidChangeExtensionsStatus.fire([extensionId]);
}

View File

@@ -26,6 +26,7 @@ import { IUntitledResourceInput } from 'vs/workbench/common/editor';
import { StopWatch } from 'vs/base/common/stopwatch';
import { VSBuffer } from 'vs/base/common/buffer';
import { IExtensionHostStarter } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
// Enable to see detailed message communication between window and extension host
const LOG_EXTENSION_HOST_COMMUNICATION = false;
@@ -215,12 +216,12 @@ export class ExtensionHostProcessManager extends Disposable {
return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService);
}
public async activate(extension: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
public async activate(extension: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean> {
const proxy = await this._getExtensionHostProcessProxy();
if (!proxy) {
return false;
}
return proxy.$activate(extension, activationEvent);
return proxy.$activate(extension, reason);
}
public activateByEvent(activationEvent: string): Promise<void> {

View File

@@ -15,6 +15,10 @@ export interface IExtHostSocketMessage {
skipWebSocketFrames: boolean;
}
export interface IExtHostReduceGraceTimeMessage {
type: 'VSCODE_EXTHOST_IPC_REDUCE_GRACE_TIME';
}
export const enum MessageType {
Initialized,
Ready,
@@ -44,4 +48,4 @@ export function isMessageOfType(message: VSBuffer, type: MessageType): boolean {
case 3: return type === MessageType.Terminate;
default: return false;
}
}
}

View File

@@ -11,6 +11,7 @@ import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensi
import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
export const nullExtensionDescription = Object.freeze(<IExtensionDescription>{
identifier: new ExtensionIdentifier('nullExtensionDescription'),
@@ -99,11 +100,10 @@ export type ProfileSegmentId = string | 'idle' | 'program' | 'gc' | 'self';
export class ActivationTimes {
constructor(
public readonly startup: boolean,
public readonly codeLoadingTime: number,
public readonly activateCallTime: number,
public readonly activateResolvedTime: number,
public readonly activationEvent: string
public readonly activationReason: ExtensionActivationReason
) {
}
}
@@ -226,9 +226,9 @@ export interface IExtensionService {
setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
_logOrShowMessage(severity: Severity, msg: string): void;
_activateById(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void>;
_activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void>;
_onWillActivateExtension(extensionId: ExtensionIdentifier): void;
_onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void;
_onDidActivateExtension(extensionId: ExtensionIdentifier, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationReason: ExtensionActivationReason): void;
_onExtensionRuntimeError(extensionId: ExtensionIdentifier, err: Error): void;
_onExtensionHostExit(code: number): void;
}
@@ -276,9 +276,9 @@ export class NullExtensionService implements IExtensionService {
canAddExtension(): boolean { return false; }
canRemoveExtension(): boolean { return false; }
_logOrShowMessage(_severity: Severity, _msg: string): void { }
_activateById(_extensionId: ExtensionIdentifier, _activationEvent: string): Promise<void> { return Promise.resolve(); }
_activateById(_extensionId: ExtensionIdentifier, _reason: ExtensionActivationReason): Promise<void> { return Promise.resolve(); }
_onWillActivateExtension(_extensionId: ExtensionIdentifier): void { }
_onDidActivateExtension(_extensionId: ExtensionIdentifier, _startup: boolean, _codeLoadingTime: number, _activateCallTime: number, _activateResolvedTime: number, _activationEvent: string): void { }
_onDidActivateExtension(_extensionId: ExtensionIdentifier, _codeLoadingTime: number, _activateCallTime: number, _activateResolvedTime: number, _activationReason: ExtensionActivationReason): void { }
_onExtensionRuntimeError(_extensionId: ExtensionIdentifier, _err: Error): void { }
_onExtensionHostExit(code: number): void { }
}

View File

@@ -19,7 +19,7 @@ import { IExtensionEnablementService } from 'vs/workbench/services/extensionMana
import { BUILTIN_MANIFEST_CACHE_FILE, MANIFEST_CACHE_FOLDER, USER_MANIFEST_CACHE_FILE, ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import product from 'vs/platform/product/common/product';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { ExtensionScanner, ExtensionScannerInput, IExtensionReference, IExtensionResolver, IRelaxedExtensionDescription } from 'vs/workbench/services/extensions/node/extensionPoints';
import { Translations, ILog } from 'vs/workbench/services/extensions/common/extensionPoints';
@@ -55,7 +55,7 @@ export class CachedExtensionScanner {
@INotificationService private readonly _notificationService: INotificationService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@IExtensionEnablementService private readonly _extensionEnablementService: IExtensionEnablementService,
@IWindowService private readonly _windowService: IWindowService,
@IHostService private readonly _hostService: IHostService,
) {
this.scannedExtensions = new Promise<IExtensionDescription[]>((resolve, reject) => {
this._scannedExtensionsResolve = resolve;
@@ -78,7 +78,7 @@ export class CachedExtensionScanner {
public async startScanningExtensions(log: ILog): Promise<void> {
try {
const translations = await this.translationConfig;
const { system, user, development } = await CachedExtensionScanner._scanInstalledExtensions(this._windowService, this._notificationService, this._environmentService, this._extensionEnablementService, log, translations);
const { system, user, development } = await CachedExtensionScanner._scanInstalledExtensions(this._hostService, this._notificationService, this._environmentService, this._extensionEnablementService, log, translations);
let result = new Map<string, IExtensionDescription>();
system.forEach((systemExtension) => {
@@ -111,7 +111,7 @@ export class CachedExtensionScanner {
}
}
private static async _validateExtensionsCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): Promise<void> {
private static async _validateExtensionsCache(hostService: IHostService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput): Promise<void> {
const cacheFolder = path.join(environmentService.userDataPath, MANIFEST_CACHE_FOLDER);
const cacheFile = path.join(cacheFolder, cacheKey);
@@ -141,7 +141,7 @@ export class CachedExtensionScanner {
nls.localize('extensionCache.invalid', "Extensions have been modified on disk. Please reload the window."),
[{
label: nls.localize('reloadWindow', "Reload Window"),
run: () => windowService.reloadWindow()
run: () => hostService.reload()
}]
);
}
@@ -177,7 +177,7 @@ export class CachedExtensionScanner {
}
}
private static async _scanExtensionsWithCache(windowService: IWindowService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): Promise<IExtensionDescription[]> {
private static async _scanExtensionsWithCache(hostService: IHostService, notificationService: INotificationService, environmentService: IEnvironmentService, cacheKey: string, input: ExtensionScannerInput, log: ILog): Promise<IExtensionDescription[]> {
if (input.devMode) {
// Do not cache when running out of sources...
return ExtensionScanner.scanExtensions(input, log);
@@ -195,7 +195,7 @@ export class CachedExtensionScanner {
// Validate the cache asynchronously after 5s
setTimeout(async () => {
try {
await this._validateExtensionsCache(windowService, notificationService, environmentService, cacheKey, input);
await this._validateExtensionsCache(hostService, notificationService, environmentService, cacheKey, input);
} catch (err) {
errors.onUnexpectedError(err);
}
@@ -234,7 +234,7 @@ export class CachedExtensionScanner {
}
private static _scanInstalledExtensions(
windowService: IWindowService,
hostService: IHostService,
notificationService: INotificationService,
environmentService: IEnvironmentService,
extensionEnablementService: IExtensionEnablementService,
@@ -248,7 +248,7 @@ export class CachedExtensionScanner {
const locale = platform.language;
const builtinExtensions = this._scanExtensionsWithCache(
windowService,
hostService,
notificationService,
environmentService,
BUILTIN_MANIFEST_CACHE_FILE,
@@ -282,7 +282,7 @@ export class CachedExtensionScanner {
extensionEnablementService.allUserExtensionsDisabled || !environmentService.extensionsPath
? Promise.resolve([])
: this._scanExtensionsWithCache(
windowService,
hostService,
notificationService,
environmentService,
USER_MANIFEST_CACHE_FILE,

View File

@@ -27,7 +27,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import product from 'vs/platform/product/common/product';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IInitData, UIKind } from 'vs/workbench/api/common/extHost.protocol';
import { MessageType, createMessageOfType, isMessageOfType } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
@@ -38,6 +38,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
import { IExtensionHostStarter } from 'vs/workbench/services/extensions/common/extensions';
import { isEqualOrParent } from 'vs/base/common/resources';
import { IHostService } from 'vs/workbench/services/host/browser/host';
export class ExtensionHostProcessWorker implements IExtensionHostStarter {
@@ -68,13 +69,14 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
private readonly _extensionHostLogsLocation: URI,
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService,
@INotificationService private readonly _notificationService: INotificationService,
@IWindowService private readonly _windowService: IWindowService,
@IElectronService private readonly _electronService: IElectronService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@ILogService private readonly _logService: ILogService,
@ILabelService private readonly _labelService: ILabelService,
@IExtensionHostDebugService private readonly _extensionHostDebugService: IExtensionHostDebugService
@IExtensionHostDebugService private readonly _extensionHostDebugService: IExtensionHostDebugService,
@IHostService private readonly _hostService: IHostService
) {
const devOpts = parseExtensionDevOptions(this._environmentService);
this._isExtensionDevHost = devOpts.isExtensionDevHost;
@@ -96,12 +98,12 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
this._toDispose.add(this._lifecycleService.onShutdown(reason => this.terminate()));
this._toDispose.add(this._extensionHostDebugService.onClose(event => {
if (this._isExtensionDevHost && this._environmentService.debugExtensionHost.debugId === event.sessionId) {
this._windowService.closeWindow();
this._electronService.closeWindow();
}
}));
this._toDispose.add(this._extensionHostDebugService.onReload(event => {
if (this._isExtensionDevHost && this._environmentService.debugExtensionHost.debugId === event.sessionId) {
this._windowService.reloadWindow();
this._hostService.reload();
}
}));
@@ -234,7 +236,7 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
this._notificationService.prompt(Severity.Warning, msg,
[{
label: nls.localize('reloadWindow', "Reload Window"),
run: () => this._windowService.reloadWindow()
run: () => this._hostService.reload()
}],
{ sticky: true }
);

View File

@@ -19,13 +19,14 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { IInitDataProvider, RemoteExtensionHostClient } from 'vs/workbench/services/extensions/common/remoteExtensionHostClient';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IRemoteAuthorityResolverService, RemoteAuthorityResolverError, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { isUIExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
import { isUIExtension as isUIExtensionFunc } from 'vs/workbench/services/extensions/common/extensionsUtil';
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IExtensionService, toExtension } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionHostProcessManager } from 'vs/workbench/services/extensions/common/extensionHostProcessManager';
import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
@@ -36,6 +37,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
import { Logger } from 'vs/workbench/services/extensions/common/extensionPoints';
import { flatten } from 'vs/base/common/arrays';
import { IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
import { IElectronService } from 'vs/platform/electron/node/electron';
class DeltaExtensionsQueueItem {
constructor(
@@ -67,6 +69,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@IWindowService protected readonly _windowService: IWindowService,
@IStaticExtensionsService private readonly _staticExtensions: IStaticExtensionsService,
@IElectronService private readonly _electronService: IElectronService,
@IHostService private readonly _hostService: IHostService
) {
super(
instantiationService,
@@ -82,7 +86,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
this._notificationService.prompt(Severity.Info, nls.localize('extensionsDisabled', "All installed extensions are temporarily disabled. Reload the window to return to the previous state."), [{
label: nls.localize('Reload', "Reload"),
run: () => {
this._windowService.reloadWindow();
this._hostService.reload();
}
}]);
}
@@ -326,7 +330,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
if (shouldActivate) {
await Promise.all(
this._extensionHostProcessManagers.map(extHostManager => extHostManager.activate(extensionDescription.identifier, shouldActivateReason!))
this._extensionHostProcessManagers.map(extHostManager => extHostManager.activate(extensionDescription.identifier, { startup: false, extensionId: extensionDescription.identifier, activationEvent: shouldActivateReason! }))
).then(() => { });
}
}
@@ -384,8 +388,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
label: nls.localize('relaunch', "Relaunch VS Code"),
run: () => {
this._instantiationService.invokeFunction((accessor) => {
const windowsService = accessor.get(IWindowsService);
windowsService.relaunch({});
const hostService = accessor.get(IHostService);
hostService.restart();
});
}
}]
@@ -396,7 +400,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
this._notificationService.prompt(Severity.Error, nls.localize('extensionService.crash', "Extension host terminated unexpectedly."),
[{
label: nls.localize('devTools', "Open Developer Tools"),
run: () => this._windowService.openDevTools()
run: () => this._electronService.openDevTools()
},
{
label: nls.localize('restart', "Restart Extension Host"),
@@ -435,6 +439,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
}
protected async _scanAndHandleExtensions(): Promise<void> {
const isUIExtension = (extension: IExtensionDescription) => isUIExtensionFunc(extension, this._productService, this._configurationService);
this._extensionScanner.startScanningExtensions(this.createLogger());
const remoteAuthority = this._environmentService.configuration.remoteAuthority;
@@ -446,7 +452,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
this._checkEnableProposedApi(localExtensions);
// remove disabled extensions
localExtensions = localExtensions.filter(extension => this._isEnabled(extension));
localExtensions = remove(localExtensions, extension => this._isDisabled(extension));
if (remoteAuthority) {
let resolvedAuthority: ResolverResult;
@@ -502,18 +508,16 @@ export class ExtensionService extends AbstractExtensionService implements IExten
this._checkEnableProposedApi(remoteEnv.extensions);
// remove disabled extensions
remoteEnv.extensions = remoteEnv.extensions.filter(extension => this._isEnabled(extension));
// remove UI extensions from the remote extensions
remoteEnv.extensions = remoteEnv.extensions.filter(extension => !isUIExtension(extension, this._productService, this._configurationService));
remoteEnv.extensions = remove(remoteEnv.extensions, extension => this._isDisabled(extension));
// remove non-UI extensions from the local extensions
localExtensions = localExtensions.filter(extension => extension.isBuiltin || isUIExtension(extension, this._productService, this._configurationService));
localExtensions = remove(localExtensions, extension => !extension.isBuiltin && !isUIExtension(extension));
// in case of overlap, the remote wins
const isRemoteExtension = new Set<string>();
remoteEnv.extensions.forEach(extension => isRemoteExtension.add(ExtensionIdentifier.toKey(extension.identifier)));
localExtensions = localExtensions.filter(extension => !isRemoteExtension.has(ExtensionIdentifier.toKey(extension.identifier)));
// in case of UI extensions overlap, the local extension wins
remoteEnv.extensions = remove(remoteEnv.extensions, localExtensions.filter(extension => isUIExtension(extension)));
// in case of other extensions overlap, the remote extension wins
localExtensions = remove(localExtensions, remoteEnv.extensions);
// save for remote extension's init data
this._remoteExtensionsEnvironmentData.set(remoteAuthority, remoteEnv);
@@ -548,7 +552,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
public _onExtensionHostExit(code: number): void {
// Expected development extension termination: When the extension host goes down we also shutdown the window
if (!this._isExtensionDevTestFromCli) {
this._windowService.closeWindow();
this._electronService.closeWindow();
}
// When CLI testing make sure to exit with proper exit code
@@ -558,4 +562,23 @@ export class ExtensionService extends AbstractExtensionService implements IExten
}
}
function remove(arr: IExtensionDescription[], predicate: (item: IExtensionDescription) => boolean): IExtensionDescription[];
function remove(arr: IExtensionDescription[], toRemove: IExtensionDescription[]): IExtensionDescription[];
function remove(arr: IExtensionDescription[], arg2: ((item: IExtensionDescription) => boolean) | IExtensionDescription[]): IExtensionDescription[] {
if (typeof arg2 === 'function') {
return _removePredicate(arr, arg2);
}
return _removeSet(arr, arg2);
}
function _removePredicate(arr: IExtensionDescription[], predicate: (item: IExtensionDescription) => boolean): IExtensionDescription[] {
return arr.filter(extension => !predicate(extension));
}
function _removeSet(arr: IExtensionDescription[], toRemove: IExtensionDescription[]): IExtensionDescription[] {
const toRemoveSet = new Set<string>();
toRemove.forEach(extension => toRemoveSet.add(ExtensionIdentifier.toKey(extension.identifier)));
return arr.filter(extension => !toRemoveSet.has(ExtensionIdentifier.toKey(extension.identifier)));
}
registerSingleton(IExtensionService, ExtensionService);

View File

@@ -13,7 +13,7 @@ import { PersistentProtocol, ProtocolConstants, BufferedEmitter } from 'vs/base/
import { NodeSocket, WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
import product from 'vs/platform/product/common/product';
import { IInitData } from 'vs/workbench/api/common/extHost.protocol';
import { MessageType, createMessageOfType, isMessageOfType, IExtHostSocketMessage, IExtHostReadyMessage } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
import { MessageType, createMessageOfType, isMessageOfType, IExtHostSocketMessage, IExtHostReadyMessage, IExtHostReduceGraceTimeMessage } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
import { ExtensionHostMain, IExitFn } from 'vs/workbench/services/extensions/common/extensionHostMain';
import { VSBuffer } from 'vs/base/common/buffer';
import { IURITransformer, URITransformer, IRawURITransformer } from 'vs/base/common/uriIpc';
@@ -21,6 +21,7 @@ import { exists } from 'vs/base/node/pfs';
import { realpath } from 'vs/base/node/extpath';
import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
import 'vs/workbench/api/node/extHost.services';
import { RunOnceScheduler } from 'vs/base/common/async';
interface ParsedExtHostArgs {
uriTransformerPath?: string;
@@ -91,9 +92,12 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
reject(new Error('VSCODE_EXTHOST_IPC_SOCKET timeout'));
}, 60000);
let disconnectWaitTimer: NodeJS.Timeout | null = null;
const reconnectionGraceTime = ProtocolConstants.ReconnectionGraceTime;
const reconnectionShortGraceTime = ProtocolConstants.ReconnectionShortGraceTime;
const disconnectRunner1 = new RunOnceScheduler(() => onTerminate(), reconnectionGraceTime);
const disconnectRunner2 = new RunOnceScheduler(() => onTerminate(), reconnectionShortGraceTime);
process.on('message', (msg: IExtHostSocketMessage, handle: net.Socket) => {
process.on('message', (msg: IExtHostSocketMessage | IExtHostReduceGraceTimeMessage, handle: net.Socket) => {
if (msg && msg.type === 'VSCODE_EXTHOST_IPC_SOCKET') {
const initialDataChunk = VSBuffer.wrap(Buffer.from(msg.initialDataChunk, 'base64'));
let socket: NodeSocket | WebSocketNodeSocket;
@@ -104,10 +108,8 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
}
if (protocol) {
// reconnection case
if (disconnectWaitTimer) {
clearTimeout(disconnectWaitTimer);
disconnectWaitTimer = null;
}
disconnectRunner1.cancel();
disconnectRunner2.cancel();
protocol.beginAcceptReconnection(socket, initialDataChunk);
protocol.endAcceptReconnection();
} else {
@@ -116,21 +118,21 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
protocol.onClose(() => onTerminate());
resolve(protocol);
if (msg.skipWebSocketFrames) {
// Wait for rich client to reconnect
protocol.onSocketClose(() => {
// The socket has closed, let's give the renderer a certain amount of time to reconnect
disconnectWaitTimer = setTimeout(() => {
disconnectWaitTimer = null;
onTerminate();
}, ProtocolConstants.ReconnectionGraceTime);
});
} else {
// Do not wait for web companion to reconnect
protocol.onSocketClose(() => {
onTerminate();
});
}
// Wait for rich client to reconnect
protocol.onSocketClose(() => {
// The socket has closed, let's give the renderer a certain amount of time to reconnect
disconnectRunner1.schedule();
});
}
}
if (msg && msg.type === 'VSCODE_EXTHOST_IPC_REDUCE_GRACE_TIME') {
if (disconnectRunner2.isScheduled()) {
// we are disconnected and already running the short reconnection timer
return;
}
if (disconnectRunner1.isScheduled()) {
// we are disconnected and running the long reconnection timer
disconnectRunner2.schedule();
}
}
});