Vscode merge (#4582)

* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd

* fix issues with merges

* bump node version in azpipe

* replace license headers

* remove duplicate launch task

* fix build errors

* fix build errors

* fix tslint issues

* working through package and linux build issues

* more work

* wip

* fix packaged builds

* working through linux build errors

* wip

* wip

* wip

* fix mac and linux file limits

* iterate linux pipeline

* disable editor typing

* revert series to parallel

* remove optimize vscode from linux

* fix linting issues

* revert testing change

* add work round for new node

* readd packaging for extensions

* fix issue with angular not resolving decorator dependencies
This commit is contained in:
Anthony Dresser
2019-03-19 17:44:35 -07:00
committed by GitHub
parent 833d197412
commit 87765e8673
1879 changed files with 54505 additions and 38058 deletions

View File

@@ -6,7 +6,7 @@
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor } from 'electron';
import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform';
import { WindowsManager } from 'vs/code/electron-main/windows';
import { IWindowsService, OpenContext, ActiveWindowManager } from 'vs/platform/windows/common/windows';
import { IWindowsService, OpenContext, ActiveWindowManager, IURIToOpen } from 'vs/platform/windows/common/windows';
import { WindowsChannel } from 'vs/platform/windows/node/windowsIpc';
import { WindowsService } from 'vs/platform/windows/electron-main/windowsService';
import { ILifecycleService, LifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
@@ -16,7 +16,6 @@ import { UpdateChannel } from 'vs/platform/update/node/updateIpc';
import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc.electron-main';
import { Server, connect, Client } from 'vs/base/parts/ipc/node/ipc.net';
import { SharedProcess } from 'vs/code/electron-main/sharedProcess';
import { Mutex } from 'windows-mutex';
import { LaunchService, LaunchChannel, ILaunchService } from 'vs/platform/launch/electron-main/launchService';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@@ -33,14 +32,14 @@ import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { getDelayedChannel, StaticRouter } from 'vs/base/parts/ipc/node/ipc';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import product from 'vs/platform/product/node/product';
import pkg from 'vs/platform/product/node/package';
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { IHistoryMainService } from 'vs/platform/history/common/history';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { isUndefinedOrNull, withUndefinedAsNull } from 'vs/base/common/types';
import { KeyboardLayoutMonitor } from 'vs/code/electron-main/keyboard';
import { URI } from 'vs/base/common/uri';
import { WorkspacesChannel } from 'vs/platform/workspaces/node/workspacesIpc';
@@ -56,7 +55,7 @@ import { LogLevelSetterChannel } from 'vs/platform/log/node/logIpc';
import * as errors from 'vs/base/common/errors';
import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener';
import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver';
import { connectRemoteAgentManagement, RemoteAgentConnectionContext } from 'vs/platform/remote/node/remoteAgentConnection';
import { connectRemoteAgentManagement } from 'vs/platform/remote/node/remoteAgentConnection';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { MenubarService } from 'vs/platform/menubar/electron-main/menubarService';
import { MenubarChannel } from 'vs/platform/menubar/node/menubarIpc';
@@ -64,8 +63,8 @@ import { hasArgs } from 'vs/platform/environment/node/argv';
import { RunOnceScheduler } from 'vs/base/common/async';
import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu';
import { storeBackgroundColor } from 'vs/code/electron-main/theme';
import { nativeSep, join } from 'vs/base/common/paths';
import { homedir } from 'os';
import { join, sep } from 'vs/base/common/path';
import { localize } from 'vs/nls';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/platform/remote/node/remoteAgentFileSystemChannel';
@@ -73,13 +72,13 @@ import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityReso
import { SnapUpdateService } from 'vs/platform/update/electron-main/updateService.snap';
import { IStorageMainService, StorageMainService } from 'vs/platform/storage/node/storageMainService';
import { GlobalStorageDatabaseChannel } from 'vs/platform/storage/node/storageIpc';
import { generateUuid } from 'vs/base/common/uuid';
import { startsWith } from 'vs/base/common/strings';
import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
import { IBackupMainService } from 'vs/platform/backup/common/backup';
import { HistoryMainService } from 'vs/platform/history/electron-main/historyMainService';
import { URLService } from 'vs/platform/url/common/urlService';
import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
export class CodeApplication extends Disposable {
@@ -93,8 +92,8 @@ export class CodeApplication extends Disposable {
private sharedProcessClient: Promise<Client>;
constructor(
private mainIpcServer: Server,
private userEnv: IProcessEnvironment,
private readonly mainIpcServer: Server,
private readonly userEnv: IProcessEnvironment,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ILogService private readonly logService: ILogService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@@ -155,7 +154,7 @@ export class CodeApplication extends Disposable {
const srcUri = URI.parse(source).fsPath.toLowerCase();
const rootUri = URI.file(this.environmentService.appRoot).fsPath.toLowerCase();
return startsWith(srcUri, rootUri + nativeSep);
return startsWith(srcUri, rootUri + sep);
};
// Ensure defaults
@@ -188,14 +187,14 @@ export class CodeApplication extends Disposable {
});
});
let macOpenFileURIs: URI[] = [];
let macOpenFileURIs: IURIToOpen[] = [];
let runningTimeout: any = null;
app.on('open-file', (event: Event, path: string) => {
this.logService.trace('App#open-file: ', path);
event.preventDefault();
// Keep in array because more might come!
macOpenFileURIs.push(URI.file(path));
macOpenFileURIs.push({ uri: URI.file(path) });
// Clear previous handler if any
if (runningTimeout !== null) {
@@ -461,6 +460,7 @@ export class CodeApplication extends Disposable {
const appInstantiationService = this.instantiationService.createChild(services);
// Init services that require it
return appInstantiationService.invokeFunction(accessor => Promise.all([
this.initStorageService(accessor),
this.initBackupService(accessor)
@@ -473,35 +473,8 @@ export class CodeApplication extends Disposable {
// Ensure to close storage on shutdown
this.lifecycleService.onWillShutdown(e => e.join(storageMainService.close()));
// Initialize storage service
return storageMainService.initialize().then(undefined, error => {
errors.onUnexpectedError(error);
this.logService.error(error);
}).then(() => {
return Promise.resolve();
// Apply global telemetry values as part of the initialization
// These are global across all windows and thereby should be
// written from the main process once.
const telemetryInstanceId = 'telemetry.instanceId';
const instanceId = storageMainService.get(telemetryInstanceId, null);
if (instanceId === null) {
storageMainService.store(telemetryInstanceId, generateUuid());
}
const telemetryFirstSessionDate = 'telemetry.firstSessionDate';
const firstSessionDate = storageMainService.get(telemetryFirstSessionDate, null);
if (firstSessionDate === null) {
storageMainService.store(telemetryFirstSessionDate, new Date().toUTCString());
}
const telemetryCurrentSessionDate = 'telemetry.currentSessionDate';
const telemetryLastSessionDate = 'telemetry.lastSessionDate';
const lastSessionDate = storageMainService.get(telemetryCurrentSessionDate, null); // previous session date was the "current" one at that time
const currentSessionDate = new Date().toUTCString(); // current session date is "now"
storageMainService.store(telemetryLastSessionDate, lastSessionDate);
storageMainService.store(telemetryCurrentSessionDate, currentSessionDate);
});
}
private initBackupService(accessor: ServicesAccessor): Promise<void> {
@@ -545,7 +518,7 @@ export class CodeApplication extends Disposable {
this.electronIpcServer.registerChannel('url', urlChannel);
const storageMainService = accessor.get(IStorageMainService);
const storageChannel = this._register(new GlobalStorageDatabaseChannel(storageMainService as StorageMainService));
const storageChannel = this._register(new GlobalStorageDatabaseChannel(this.logService, storageMainService as StorageMainService));
this.electronIpcServer.registerChannel('storage', storageChannel);
// Log level management
@@ -584,13 +557,13 @@ export class CodeApplication extends Disposable {
});
}
// Register the multiple URL handker
// Register the multiple URL handler
urlService.registerHandler(multiplexURLHandler);
// Watch Electron URLs and forward them to the UrlService
const args = this.environmentService.args;
const urls = args['open-url'] ? args._urls : [];
const urlListener = new ElectronURLListener(urls, urlService, this.windowsMainService);
const urlListener = new ElectronURLListener(urls || [], urlService, this.windowsMainService);
this._register(urlListener);
this.windowsMainService.ready(this.userEnv);
@@ -607,7 +580,7 @@ export class CodeApplication extends Disposable {
}
if (macOpenFiles && macOpenFiles.length && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
return this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, urisToOpen: macOpenFiles.map(file => URI.file(file)), initialStartup: true }); // mac: open-file event received on startup
return this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, urisToOpen: macOpenFiles.map(file => ({ uri: URI.file(file) })), initialStartup: true }); // mac: open-file event received on startup
}
return this.windowsMainService.open({ context, cli: args, forceNewWindow: args['new-window'] || (!hasCliArgs && args['unity-launch']), diffMode: args.diff, initialStartup: true }); // default: read paths from cli
@@ -617,13 +590,12 @@ export class CodeApplication extends Disposable {
const windowsMainService = accessor.get(IWindowsMainService);
const historyMainService = accessor.get(IHistoryMainService);
let windowsMutex: Mutex | null = null;
if (isWindows) {
// Setup Windows mutex
try {
const Mutex = (require.__$__nodeRequire('windows-mutex') as any).Mutex;
windowsMutex = new Mutex(product.win32MutexName);
const windowsMutex = new Mutex(product.win32MutexName);
this._register(toDisposable(() => windowsMutex.release()));
} catch (e) {
if (!this.environmentService.isBuilt) {
@@ -677,17 +649,17 @@ export class CodeApplication extends Disposable {
const isBuilt = this.environmentService.isBuilt;
class ActiveConnection {
private _authority: string;
private _client: Promise<Client<RemoteAgentConnectionContext>>;
private _disposeRunner: RunOnceScheduler;
private readonly _authority: string;
private readonly _client: Promise<Client<RemoteAgentConnectionContext>>;
private readonly _disposeRunner: RunOnceScheduler;
constructor(authority: string, host: string, port: number) {
this._authority = authority;
this._client = connectRemoteAgentManagement(authority, host, port, `main`, isBuilt);
this._disposeRunner = new RunOnceScheduler(() => this._dispose(), 5000);
this._disposeRunner = new RunOnceScheduler(() => this.dispose(), 5000);
}
private _dispose(): void {
dispose(): void {
this._disposeRunner.dispose();
connectionPool.delete(this._authority);
this._client.then((connection) => {
@@ -695,7 +667,7 @@ export class CodeApplication extends Disposable {
});
}
public getClient(): Promise<Client<RemoteAgentConnectionContext>> {
getClient(): Promise<Client<RemoteAgentConnectionContext>> {
this._disposeRunner.schedule();
return this._client;
}
@@ -703,42 +675,49 @@ export class CodeApplication extends Disposable {
const resolvedAuthorities = new Map<string, ResolvedAuthority>();
ipc.on('vscode:remoteAuthorityResolved', (event: any, data: ResolvedAuthority) => {
this.logService.info('Received resolved authority', data.authority);
resolvedAuthorities.set(data.authority, data);
// Make sure to close and remove any existing connections
if (connectionPool.has(data.authority)) {
connectionPool.get(data.authority)!.dispose();
}
});
const resolveAuthority = (authority: string): ResolvedAuthority | null => {
this.logService.info('Resolving authority', authority);
if (authority.indexOf('+') >= 0) {
if (resolvedAuthorities.has(authority)) {
return resolvedAuthorities.get(authority);
return withUndefinedAsNull(resolvedAuthorities.get(authority));
}
this.logService.info('Didnot find resolved authority for', authority);
return null;
} else {
const [host, strPort] = authority.split(':');
const port = parseInt(strPort, 10);
return { authority, host, port, syncExtensions: false };
return { authority, host, port };
}
};
protocol.registerBufferProtocol(REMOTE_HOST_SCHEME, async (request, callback) => {
if (request.method !== 'GET') {
return callback(null);
return callback(undefined);
}
const uri = URI.parse(request.url);
let activeConnection: ActiveConnection = null;
let activeConnection: ActiveConnection | undefined;
if (connectionPool.has(uri.authority)) {
activeConnection = connectionPool.get(uri.authority);
} else {
let resolvedAuthority = resolveAuthority(uri.authority);
const resolvedAuthority = resolveAuthority(uri.authority);
if (!resolvedAuthority) {
callback(null);
callback(undefined);
return;
}
activeConnection = new ActiveConnection(uri.authority, resolvedAuthority.host, resolvedAuthority.port);
connectionPool.set(uri.authority, activeConnection);
}
try {
const rawClient = await activeConnection.getClient();
const rawClient = await activeConnection!.getClient();
if (connectionPool.has(uri.authority)) { // not disposed in the meantime
const channel = rawClient.getChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
@@ -746,11 +725,11 @@ export class CodeApplication extends Disposable {
const fileContents = await channel.call<Uint8Array>('readFile', [uri]);
callback(Buffer.from(fileContents));
} else {
callback(null);
callback(undefined);
}
} catch (err) {
errors.onUnexpectedError(err);
callback(null);
callback(undefined);
}
});
}

View File

@@ -6,10 +6,10 @@
import * as os from 'os';
import * as cp from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import * as path from 'vs/base/common/path';
import { localize } from 'vs/nls';
import product from 'vs/platform/node/product';
import product from 'vs/platform/product/node/product';
import { IRequestService } from 'vs/platform/request/node/request';
import { IRequestContext } from 'vs/base/node/request';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';

View File

@@ -7,15 +7,16 @@ import 'vs/code/code.main';
import { app, dialog } from 'electron';
import { assign } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import product from 'vs/platform/node/product';
import { parseMainProcessArgv } from 'vs/platform/environment/node/argvHelper';
import product from 'vs/platform/product/node/product';
import { parseMainProcessArgv, createWaitMarkerFile } from 'vs/platform/environment/node/argvHelper';
import { addArg } from 'vs/platform/environment/node/argv';
import { mkdirp } from 'vs/base/node/pfs';
import { validatePaths } from 'vs/code/node/paths';
import { LifecycleService, ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { LaunchChannelClient } from 'vs/platform/launch/electron-main/launchService';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/node/instantiationService';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ILogService, ConsoleLogMainService, MultiplexLogService, getLogLevel } from 'vs/platform/log/common/log';
@@ -36,7 +37,6 @@ import { IDiagnosticsService, DiagnosticsService } from 'vs/platform/diagnostics
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
import { uploadLogs } from 'vs/code/electron-main/logUploader';
import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { createWaitMarkerFile } from 'vs/code/node/wait';
class ExpectedError extends Error {
readonly isExpected = true;
@@ -114,7 +114,7 @@ function setupIPC(accessor: ServicesAccessor): Promise<Server> {
client => {
// Tests from CLI require to be the only instance currently
if (environmentService.extensionTestsPath && !environmentService.debugExtensionHost.break) {
if (environmentService.extensionTestsLocationURI && !environmentService.debugExtensionHost.break) {
const msg = 'Running extension tests from the command line is currently only supported if no other instance of Code is running.';
logService.error(msg);
client.dispose();
@@ -158,7 +158,7 @@ function setupIPC(accessor: ServicesAccessor): Promise<Server> {
logService.trace('Sending env to running instance...');
return allowSetForegroundWindow(service)
.then(() => service.start(environmentService.args, process.env))
.then(() => service.start(environmentService.args, process.env as platform.IProcessEnvironment))
.then(() => client.dispose())
.then(() => {
@@ -216,7 +216,7 @@ function handleStartupDataDirError(environmentService: IEnvironmentService, erro
if (error.code === 'EACCES' || error.code === 'EPERM') {
showStartupWarningDialog(
localize('startupDataDirError', "Unable to write program user data."),
localize('startupDataDirErrorDetail', "Please make sure the directory {0} is writeable.", environmentService.userDataPath)
localize('startupDataDirErrorDetail', "Please make sure the directories {0} and {1} are writeable.", environmentService.userDataPath, environmentService.extensionsPath)
);
}
}
@@ -316,14 +316,14 @@ function createServices(args: ParsedArgs, bufferLogService: BufferLogService): I
function initServices(environmentService: IEnvironmentService, stateService: StateService): Promise<any> {
// Ensure paths for environment service exist
const environmentServiceInitialization = Promise.all([
const environmentServiceInitialization = Promise.all<boolean | undefined>([
environmentService.extensionsPath,
environmentService.nodeCachedDataDir,
environmentService.logsPath,
environmentService.globalStorageHome,
environmentService.workspaceStorageHome,
environmentService.backupHome
].map(path => path && mkdirp(path)));
].map((path): undefined | Promise<boolean> => path ? mkdirp(path) : undefined));
// State service
const stateServiceInitialization = stateService.init();
@@ -359,7 +359,7 @@ function main(): void {
if (args.wait && !args.waitMarkerFilePath) {
createWaitMarkerFile(args.verbose).then(waitMarkerFilePath => {
if (waitMarkerFilePath) {
process.argv.push('--waitMarkerFilePath', waitMarkerFilePath);
addArg(process.argv, '--waitMarkerFilePath', waitMarkerFilePath);
args.waitMarkerFilePath = waitMarkerFilePath;
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import * as path from 'vs/base/common/path';
import * as objects from 'vs/base/common/objects';
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
@@ -13,7 +13,7 @@ import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/
import { ILogService } from 'vs/platform/log/common/log';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { parseArgs } from 'vs/platform/environment/node/argv';
import product from 'vs/platform/node/product';
import product from 'vs/platform/product/node/product';
import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, IRunActionInWindowRequest, getTitleBarStyle } from 'vs/platform/windows/common/windows';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
@@ -24,8 +24,8 @@ import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import * as perf from 'vs/base/common/performance';
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { getBackgroundColor } from 'vs/code/electron-main/theme';
import { IStorageMainService } from 'vs/platform/storage/node/storageMainService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { withNullAsUndefined } from 'vs/base/common/types';
export interface IWindowCreationOptions {
state: IWindowState;
@@ -70,14 +70,16 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private currentMenuBarVisibility: MenuBarVisibility;
private representedFilename: string;
private whenReadyCallbacks: { (window: ICodeWindow): void }[];
private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[];
private currentConfig: IWindowConfiguration;
private pendingLoadConfig: IWindowConfiguration;
private pendingLoadConfig?: IWindowConfiguration;
private marketplaceHeadersPromise: Promise<object>;
private touchBarGroups: Electron.TouchBarSegmentedControl[];
private readonly touchBarGroups: Electron.TouchBarSegmentedControl[];
private nodeless: boolean;
constructor(
config: IWindowCreationOptions,
@@ -87,7 +89,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
@IStateService private readonly stateService: IStateService,
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
@IBackupMainService private readonly backupMainService: IBackupMainService,
@IStorageMainService private readonly storageMainService: IStorageMainService
) {
super();
@@ -96,6 +97,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this._readyState = ReadyState.NONE;
this.whenReadyCallbacks = [];
this.nodeless = !!(environmentService.args.nodeless && !environmentService.isBuilt);
// create browser window
this.createBrowserWindow(config);
@@ -125,7 +128,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
height: this.windowState.height,
x: this.windowState.x,
y: this.windowState.y,
backgroundColor: getBackgroundColor(this.stateService),
backgroundColor: this.nodeless ? undefined : getBackgroundColor(this.stateService),
minWidth: CodeWindow.MIN_WIDTH,
minHeight: CodeWindow.MIN_HEIGHT,
show: !isFullscreenOrMaximized,
@@ -135,10 +138,14 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// want to enforce that Code stays in the foreground. This triggers a disable_hidden_
// flag that Electron provides via patch:
// https://github.com/electron/libchromiumcontent/blob/master/patches/common/chromium/disable_hidden.patch
'backgroundThrottling': false
backgroundThrottling: false
}
};
if (this.nodeless) {
options.webPreferences!.nodeIntegration = false; // simulate Electron 5 behaviour
}
if (isLinux) {
options.icon = path.join(this.environmentService.appRoot, 'resources/linux/code.png'); // Windows and Mac are better off using the embedded icon(s)
}
@@ -193,6 +200,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
}
if (this.nodeless) {
this._win.webContents.toggleDevTools();
}
this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too
}
@@ -208,7 +219,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return !!this.config.extensionTestsPath;
}
get extensionDevelopmentPath(): string {
get extensionDevelopmentPath(): string | undefined {
return this.config.extensionDevelopmentPath;
}
@@ -256,19 +267,19 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return this._lastFocusTime;
}
get backupPath(): string {
get backupPath(): string | undefined {
return this.currentConfig ? this.currentConfig.backupPath : undefined;
}
get openedWorkspace(): IWorkspaceIdentifier {
get openedWorkspace(): IWorkspaceIdentifier | undefined {
return this.currentConfig ? this.currentConfig.workspace : undefined;
}
get openedFolderUri(): URI {
get openedFolderUri(): URI | undefined {
return this.currentConfig ? this.currentConfig.folderUri : undefined;
}
get remoteAuthority(): string {
get remoteAuthority(): string | undefined {
return this.currentConfig ? this.currentConfig.remoteAuthority : undefined;
}
@@ -305,7 +316,11 @@ export class CodeWindow extends Disposable implements ICodeWindow {
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details: any, cb: any) => {
this.marketplaceHeadersPromise.then(headers => {
cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) });
const requestHeaders = objects.assign(details.requestHeaders, headers);
if (!this.configurationService.getValue('extensions.disableExperimentalAzureSearch')) {
requestHeaders['Cookie'] = `${requestHeaders['Cookie'] ? requestHeaders['Cookie'] + ';' : ''}EnableExternalSearchForVSCode=true`;
}
cb({ cancel: false, requestHeaders });
});
});
}
@@ -313,7 +328,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private registerListeners(): void {
// Prevent loading of svgs
this._win.webContents.session.webRequest.onBeforeRequest(null, (details, callback) => {
this._win.webContents.session.webRequest.onBeforeRequest(null!, (details, callback) => {
if (details.url.indexOf('.svg') > 0) {
const uri = URI.parse(details.url);
if (uri && !uri.scheme.match(/file/i) && (uri.path as any).endsWith('.svg')) {
@@ -324,7 +339,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return callback({});
});
this._win.webContents.session.webRequest.onHeadersReceived(null, (details: any, callback: any) => {
this._win.webContents.session.webRequest.onHeadersReceived(null!, (details: any, callback: any) => {
const contentType: string[] = (details.responseHeaders['content-type'] || details.responseHeaders['Content-Type']) as any;
if (contentType && Array.isArray(contentType) && contentType.some(x => x.toLowerCase().indexOf('image/svg') >= 0)) {
return callback({ cancel: true });
@@ -341,7 +356,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
if (this.pendingLoadConfig) {
this.currentConfig = this.pendingLoadConfig;
this.pendingLoadConfig = null;
this.pendingLoadConfig = undefined;
}
// To prevent flashing, we set the window visible after the page has finished to load but before Code is loaded
@@ -392,7 +407,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
// Window (Un)Maximize
this._win.on('maximize', e => {
this._win.on('maximize', (e: Event) => {
if (this.currentConfig) {
this.currentConfig.maximized = true;
}
@@ -400,7 +415,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
app.emit('browser-window-maximize', e, this._win);
});
this._win.on('unmaximize', e => {
this._win.on('unmaximize', (e: Event) => {
if (this.currentConfig) {
this.currentConfig.maximized = false;
}
@@ -522,7 +537,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Make window visible if it did not open in N seconds because this indicates an error
// Only do this when running out of sources and not when running tests
if (!this.environmentService.isBuilt && !this.environmentService.extensionTestsPath) {
if (!this.environmentService.isBuilt && !this.environmentService.extensionTestsLocationURI) {
this.showTimeoutHandle = setTimeout(() => {
if (this._win && !this._win.isVisible() && !this._win.isMinimized()) {
this._win.show();
@@ -548,8 +563,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// in extension development mode. These options are all development related.
if (this.isExtensionDevelopmentHost && cli) {
configuration.verbose = cli.verbose;
configuration.debugPluginHost = cli.debugPluginHost;
configuration.debugBrkPluginHost = cli.debugBrkPluginHost;
configuration['inspect-extensions'] = cli['inspect-extensions'];
configuration['inspect-brk-extensions'] = cli['inspect-brk-extensions'];
configuration.debugId = cli.debugId;
configuration['extensions-dir'] = cli['extensions-dir'];
}
@@ -593,7 +608,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
windowConfiguration.perfEntries = perf.exportEntries();
// Parts splash
windowConfiguration.partsSplashData = this.storageMainService.get('parts-splash-data', undefined);
windowConfiguration.partsSplashPath = path.join(this.environmentService.userDataPath, 'rapid_render.json');
// Config (combination of process.argv and window configuration)
const environment = parseArgs(process.argv);
@@ -623,6 +638,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
private doGetUrl(config: object): string {
if (this.nodeless) {
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.nodeless.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
}
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
}
@@ -688,7 +707,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private restoreWindowState(state?: IWindowState): IWindowState {
if (state) {
try {
state = this.validateWindowState(state);
state = withNullAsUndefined(this.validateWindowState(state));
} catch (err) {
this.logService.warn(`Unexpected error validating window state: ${err}\n${err.stack}`); // somehow display API can be picky about the state to validate
}
@@ -706,7 +725,11 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return null;
}
if ([state.x, state.y, state.width, state.height].some(n => typeof n !== 'number')) {
if (typeof state.x !== 'number'
|| typeof state.y !== 'number'
|| typeof state.width !== 'number'
|| typeof state.height !== 'number'
) {
return null;
}
@@ -1045,6 +1068,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
clearTimeout(this.showTimeoutHandle);
}
this._win = null; // Important to dereference the window object to allow for GC
this._win = null!; // Important to dereference the window object to allow for GC
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI, UriComponents } from 'vs/base/common/uri';
import { IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows';
import { IWindowState, IWindowsState } from 'vs/code/electron-main/windows';
export type WindowsStateStorageData = object;
interface ISerializedWindowsState {
lastActiveWindow?: ISerializedWindowState;
lastPluginDevelopmentHostWindow?: ISerializedWindowState;
openedWindows: ISerializedWindowState[];
}
interface ISerializedWindowState {
workspaceIdentifier?: { id: string; configURIPath: string };
folder?: string;
backupPath?: string;
remoteAuthority?: string;
uiState: IWindowUIState;
// deprecated
folderUri?: UriComponents;
folderPath?: string;
workspace?: { id: string; configPath: string };
}
export function restoreWindowsState(data: WindowsStateStorageData | undefined): IWindowsState {
const result: IWindowsState = { openedWindows: [] };
const windowsState = data as ISerializedWindowsState || { openedWindows: [] };
if (windowsState.lastActiveWindow) {
result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow);
}
if (windowsState.lastPluginDevelopmentHostWindow) {
result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow);
}
if (Array.isArray(windowsState.openedWindows)) {
result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState));
}
return result;
}
function restoreWindowState(windowState: ISerializedWindowState): IWindowState {
const result: IWindowState = { uiState: windowState.uiState };
if (windowState.backupPath) {
result.backupPath = windowState.backupPath;
}
if (windowState.remoteAuthority) {
result.remoteAuthority = windowState.remoteAuthority;
}
if (windowState.folder) {
result.folderUri = URI.parse(windowState.folder);
} else if (windowState.folderUri) {
result.folderUri = URI.revive(windowState.folderUri);
} else if (windowState.folderPath) {
result.folderUri = URI.file(windowState.folderPath);
}
if (windowState.workspaceIdentifier) {
result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) };
} else if (windowState.workspace) {
result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) };
}
return result;
}
export function getWindowsStateStoreData(windowsState: IWindowsState): WindowsStateStorageData {
return {
lastActiveWindow: windowsState.lastActiveWindow && serializeWindowState(windowsState.lastActiveWindow),
lastPluginDevelopmentHostWindow: windowsState.lastPluginDevelopmentHostWindow && serializeWindowState(windowsState.lastPluginDevelopmentHostWindow),
openedWindows: windowsState.openedWindows.map(ws => serializeWindowState(ws))
};
}
function serializeWindowState(windowState: IWindowState): ISerializedWindowState {
return {
workspaceIdentifier: windowState.workspace && { id: windowState.workspace.id, configURIPath: windowState.workspace.configPath.toString() },
folder: windowState.folderUri && windowState.folderUri.toString(),
backupPath: windowState.backupPath,
remoteAuthority: windowState.remoteAuthority,
uiState: windowState.uiState
};
}