Merge from vscode a348d103d1256a06a2c9b3f9b406298a9fef6898 (#15681)

* Merge from vscode a348d103d1256a06a2c9b3f9b406298a9fef6898

* Fixes and cleanup

* Distro

* Fix hygiene yarn

* delete no yarn lock changes file

* Fix hygiene

* Fix layer check

* Fix CI

* Skip lib checks

* Remove tests deleted in vs code

* Fix tests

* Distro

* Fix tests and add removed extension point

* Skip failing notebook tests for now

* Disable broken tests and cleanup build folder

* Update yarn.lock and fix smoke tests

* Bump sqlite

* fix contributed actions and file spacing

* Fix user data path

* Update yarn.locks

Co-authored-by: ADS Merger <karlb@microsoft.com>
This commit is contained in:
Charles Gagnon
2021-06-17 08:17:11 -07:00
committed by GitHub
parent fdcb97c7f7
commit 3cb2f552a6
2582 changed files with 124827 additions and 87099 deletions

View File

@@ -4,6 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import { statSync } from 'fs';
import { release, hostname } from 'os';
import product from 'vs/platform/product/common/product';
import { mark, getMarks } from 'vs/base/common/performance';
import { basename, normalize, join, posix } from 'vs/base/common/path';
import { localize } from 'vs/nls';
import { coalesce, distinct, firstOrDefault } from 'vs/base/common/arrays';
@@ -12,15 +15,15 @@ import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup';
import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { IStateService } from 'vs/platform/state/node/state';
import { CodeWindow } from 'vs/code/electron-main/window';
import { BrowserWindow, MessageBoxOptions, WebContents } from 'electron';
import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { CodeWindow } from 'vs/platform/windows/electron-main/window';
import { app, BrowserWindow, MessageBoxOptions, nativeTheme, WebContents } from 'electron';
import { ILifecycleMainService, UnloadReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration, INativeOpenFileRequest } from 'vs/platform/windows/common/windows';
import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder';
import { Emitter } from 'vs/base/common/event';
import product from 'vs/platform/product/common/product';
import { Event, Emitter } from 'vs/base/common/event';
import { IProductService } from 'vs/platform/product/common/productService';
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows';
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
@@ -33,14 +36,16 @@ import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
import { IWindowState, WindowsStateHandler } from 'vs/platform/windows/electron-main/windowsStateHandler';
import { getSingleFolderWorkspaceIdentifier, getWorkspaceIdentifier, IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
import { once } from 'vs/base/common/functional';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService';
import { withNullAsUndefined } from 'vs/base/common/types';
import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types';
import { isWindowsDriveLetter, toSlashes, parseLineAndColumnAware, sanitizeFilePath } from 'vs/base/common/extpath';
import { CharCode } from 'vs/base/common/charCode';
import { getPathLabel } from 'vs/base/common/labels';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IFileService } from 'vs/platform/files/common/files';
import { cwd } from 'vs/base/common/process';
import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol';
//#region Helper Interfaces
@@ -68,6 +73,10 @@ interface IOpenBrowserWindowOptions {
interface IPathResolveOptions {
readonly ignoreFileNotFound?: boolean;
readonly gotoLineMode?: boolean;
readonly forceOpenWorkspaceAsFile?: boolean;
/**
* The remoteAuthority to use if the URL to open is neither file nor vscode-remote
*/
readonly remoteAuthority?: string;
}
@@ -118,17 +127,17 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private static readonly WINDOWS: ICodeWindow[] = [];
private readonly _onWindowOpened = this._register(new Emitter<ICodeWindow>());
readonly onWindowOpened = this._onWindowOpened.event;
private readonly _onDidOpenWindow = this._register(new Emitter<ICodeWindow>());
readonly onDidOpenWindow = this._onDidOpenWindow.event;
private readonly _onWindowReady = this._register(new Emitter<ICodeWindow>());
readonly onWindowReady = this._onWindowReady.event;
private readonly _onDidSignalReadyWindow = this._register(new Emitter<ICodeWindow>());
readonly onDidSignalReadyWindow = this._onDidSignalReadyWindow.event;
private readonly _onWindowDestroyed = this._register(new Emitter<ICodeWindow>());
readonly onWindowDestroyed = this._onWindowDestroyed.event;
private readonly _onDidDestroyWindow = this._register(new Emitter<ICodeWindow>());
readonly onDidDestroyWindow = this._onDidDestroyWindow.event;
private readonly _onWindowsCountChanged = this._register(new Emitter<IWindowsCountChangedEvent>());
readonly onWindowsCountChanged = this._onWindowsCountChanged.event;
private readonly _onDidChangeWindowsCount = this._register(new Emitter<IWindowsCountChangedEvent>());
readonly onDidChangeWindowsCount = this._onDidChangeWindowsCount.event;
private readonly windowsStateHandler = this._register(new WindowsStateHandler(this, this.stateService, this.lifecycleMainService, this.logService, this.configurationService));
@@ -137,7 +146,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private readonly initialUserEnv: IProcessEnvironment,
@ILogService private readonly logService: ILogService,
@IStateService private readonly stateService: IStateService,
@IEnvironmentMainService private readonly environmentService: IEnvironmentMainService,
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IBackupMainService private readonly backupMainService: IBackupMainService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@@ -145,31 +154,49 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
@IWorkspacesManagementMainService private readonly workspacesManagementMainService: IWorkspacesManagementMainService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@IFileService private readonly fileService: IFileService
@IFileService private readonly fileService: IFileService,
@IProductService private readonly productService: IProductService,
@IProtocolMainService private readonly protocolMainService: IProtocolMainService
) {
super();
this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
this.registerListeners();
}
private registerListeners(): void {
// Signal a window is ready after having entered a workspace
this._register(this.workspacesManagementMainService.onWorkspaceEntered(event => this._onWindowReady.fire(event.window)));
this._register(this.workspacesManagementMainService.onDidEnterWorkspace(event => this._onDidSignalReadyWindow.fire(event.window)));
// Update valid roots in protocol service for extension dev windows
this._register(this.onDidSignalReadyWindow(window => {
if (window.config?.extensionDevelopmentPath || window.config?.extensionTestsPath) {
const disposables = new DisposableStore();
disposables.add(Event.any(window.onDidClose, window.onDidDestroy)(() => disposables.dispose()));
// Allow access to extension development path
if (window.config.extensionDevelopmentPath) {
for (const extensionDevelopmentPath of window.config.extensionDevelopmentPath) {
disposables.add(this.protocolMainService.addValidFileRoot(URI.file(extensionDevelopmentPath)));
}
}
// Allow access to extension tests path
if (window.config.extensionTestsPath) {
disposables.add(this.protocolMainService.addValidFileRoot(URI.file(window.config.extensionTestsPath)));
}
}
}));
}
openEmptyWindow(openConfig: IOpenEmptyConfiguration, options?: IOpenEmptyWindowOptions): ICodeWindow[] {
let cli = this.environmentService.args;
const remote = options?.remoteAuthority;
if (cli && (cli.remote !== remote)) {
cli = { ...cli, remote };
}
let cli = this.environmentMainService.args;
const remoteAuthority = options?.remoteAuthority || undefined;
const forceEmpty = true;
const forceReuseWindow = options?.forceReuseWindow;
const forceNewWindow = !forceReuseWindow;
return this.open({ ...openConfig, cli, forceEmpty, forceNewWindow, forceReuseWindow });
return this.open({ ...openConfig, cli, forceEmpty, forceNewWindow, forceReuseWindow, remoteAuthority });
}
open(openConfig: IOpenConfiguration): ICodeWindow[] {
@@ -298,11 +325,11 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
const recents: IRecent[] = [];
for (const pathToOpen of pathsToOpen) {
if (isWorkspacePathToOpen(pathToOpen)) {
recents.push({ label: pathToOpen.label, workspace: pathToOpen.workspace });
recents.push({ label: pathToOpen.label, workspace: pathToOpen.workspace, remoteAuthority: pathToOpen.remoteAuthority });
} else if (isSingleFolderWorkspacePathToOpen(pathToOpen)) {
recents.push({ label: pathToOpen.label, folderUri: pathToOpen.workspace.uri });
recents.push({ label: pathToOpen.label, folderUri: pathToOpen.workspace.uri, remoteAuthority: pathToOpen.remoteAuthority });
} else if (pathToOpen.fileUri) {
recents.push({ label: pathToOpen.label, fileUri: pathToOpen.fileUri });
recents.push({ label: pathToOpen.label, fileUri: pathToOpen.fileUri, remoteAuthority: pathToOpen.remoteAuthority });
}
}
@@ -314,7 +341,15 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
// process can continue. We do this by deleting the waitMarkerFilePath.
const waitMarkerFileURI = openConfig.waitMarkerFileURI;
if (openConfig.context === OpenContext.CLI && waitMarkerFileURI && usedWindows.length === 1 && usedWindows[0]) {
usedWindows[0].whenClosedOrLoaded.then(() => this.fileService.del(waitMarkerFileURI), () => undefined);
(async () => {
await usedWindows[0].whenClosedOrLoaded;
try {
await this.fileService.del(waitMarkerFileURI);
} catch (error) {
// ignore - could have been deleted from the window already
}
})();
}
return usedWindows;
@@ -507,7 +542,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
emptyToOpen++;
}
const remoteAuthority = filesToOpen ? filesToOpen.remoteAuthority : (openConfig.cli && openConfig.cli.remote || undefined);
const remoteAuthority = filesToOpen ? filesToOpen.remoteAuthority : openConfig.remoteAuthority;
for (let i = 0; i < emptyToOpen; i++) {
addUsedWindow(this.doOpenEmpty(openConfig, openFolderInNewWindow, remoteAuthority, filesToOpen), !!filesToOpen);
@@ -650,7 +685,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private doExtractPathsFromAPI(openConfig: IOpenConfiguration): IPathToOpen[] {
const pathsToOpen: IPathToOpen[] = [];
const pathResolveOptions: IPathResolveOptions = { gotoLineMode: openConfig.gotoLineMode };
const pathResolveOptions: IPathResolveOptions = { gotoLineMode: openConfig.gotoLineMode, remoteAuthority: openConfig.remoteAuthority };
for (const pathToOpen of coalesce(openConfig.urisToOpen || [])) {
const path = this.resolveOpenable(pathToOpen, pathResolveOptions);
@@ -665,12 +700,12 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
const uri = this.resourceFromOpenable(pathToOpen);
const options: MessageBoxOptions = {
title: product.nameLong,
title: this.productService.nameLong,
type: 'info',
buttons: [localize('ok', "OK")],
message: uri.scheme === Schemas.file ? localize('pathNotExistTitle', "Path does not exist") : localize('uriInvalidTitle', "URI can not be opened"),
detail: uri.scheme === Schemas.file ?
localize('pathNotExistDetail', "The path '{0}' does not seem to exist anymore on disk.", getPathLabel(uri.fsPath, this.environmentService)) :
localize('pathNotExistDetail', "The path '{0}' does not seem to exist anymore on disk.", getPathLabel(uri.fsPath, this.environmentMainService)) :
localize('uriInvalidDetail', "The URI '{0}' is not valid and can not be opened.", uri.toString()),
noLink: true
};
@@ -684,7 +719,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private doExtractPathsFromCLI(cli: NativeParsedArgs): IPath[] {
const pathsToOpen: IPathToOpen[] = [];
const pathResolveOptions: IPathResolveOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto, remoteAuthority: cli.remote || undefined };
const pathResolveOptions: IPathResolveOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto, remoteAuthority: cli.remote || undefined, forceOpenWorkspaceAsFile: false };
// folder uris
const folderUris = cli['folder-uri'];
@@ -717,12 +752,11 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
// folder or file paths
const cliPaths = cli._;
for (const cliPath of cliPaths) {
const path = this.doResolveFileOpenable(cliPath, pathResolveOptions);
const path = pathResolveOptions.remoteAuthority ? this.doResolvePathRemote(cliPath, pathResolveOptions) : this.doResolveFilePath(cliPath, pathResolveOptions);
if (path) {
pathsToOpen.push(path);
}
}
return pathsToOpen;
}
@@ -819,7 +853,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
// handle file:// openables with some extra validation
let uri = this.resourceFromOpenable(openable);
if (uri.scheme === Schemas.file) {
return this.doResolveFileOpenable(openable, options);
if (isFileToOpen(openable)) {
options = { ...options, forceOpenWorkspaceAsFile: true };
}
return this.doResolveFilePath(uri.fsPath, options);
}
// handle non file:// openables
@@ -829,8 +866,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private doResolveRemoteOpenable(openable: IWindowOpenable, options: IPathResolveOptions): IPathToOpen | undefined {
let uri = this.resourceFromOpenable(openable);
// open remote if either specified in the cli or if it's a remotehost URI
const remoteAuthority = options.remoteAuthority || getRemoteAuthority(uri);
// use remote authority from vscode
const remoteAuthority = getRemoteAuthority(uri) || options.remoteAuthority;
// normalize URI
uri = removeTrailingPathSeparator(normalizePath(uri));
@@ -867,88 +904,25 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return openable.fileUri;
}
private doResolveFileOpenable(path: string, options: IPathResolveOptions): IPathToOpen | undefined;
private doResolveFileOpenable(openable: IWindowOpenable, options: IPathResolveOptions): IPathToOpen | undefined;
private doResolveFileOpenable(pathOrOpenable: string | IWindowOpenable, options: IPathResolveOptions): IPathToOpen | undefined {
let path: string;
let forceOpenWorkspaceAsFile = false;
if (typeof pathOrOpenable === 'string') {
path = pathOrOpenable;
} else {
path = this.resourceFromOpenable(pathOrOpenable).fsPath;
forceOpenWorkspaceAsFile = isFileToOpen(pathOrOpenable);
}
private doResolveFilePath(path: string, options: IPathResolveOptions): IPathToOpen | undefined {
// Extract line/col information from path
let lineNumber: number | undefined;
let columnNumber: number | undefined;
if (options.gotoLineMode) {
const parsedPath = parseLineAndColumnAware(path);
lineNumber = parsedPath.line;
columnNumber = parsedPath.column;
path = parsedPath.path;
({ path, line: lineNumber, column: columnNumber } = parseLineAndColumnAware(path));
}
// With remote: resolve path as remote URI
const remoteAuthority = options.remoteAuthority;
if (remoteAuthority) {
return this.doResolvePathRemote(path, remoteAuthority, forceOpenWorkspaceAsFile);
}
// Without remote: resolve path as local URI
return this.doResolvePathLocal(path, options, lineNumber, columnNumber, forceOpenWorkspaceAsFile);
}
private doResolvePathRemote(path: string, remoteAuthority: string, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
const first = path.charCodeAt(0);
// make absolute
if (first !== CharCode.Slash) {
if (isWindowsDriveLetter(first) && path.charCodeAt(path.charCodeAt(1)) === CharCode.Colon) {
path = toSlashes(path);
}
path = `/${path}`;
}
const uri = URI.from({ scheme: Schemas.vscodeRemote, authority: remoteAuthority, path: path });
// guess the file type:
// - if it ends with a slash it's a folder
// - if it has a file extension, it's a file or a workspace
// - by defaults it's a folder
if (path.charCodeAt(path.length - 1) !== CharCode.Slash) {
// file name ends with .code-workspace
if (hasWorkspaceFileExtension(path)) {
if (forceOpenWorkspaceAsFile) {
return { fileUri: uri, remoteAuthority };
}
return { workspace: getWorkspaceIdentifier(uri), remoteAuthority };
}
// file name starts with a dot or has an file extension
else if (posix.basename(path).indexOf('.') !== -1) {
return { fileUri: uri, remoteAuthority };
}
}
return { workspace: getSingleFolderWorkspaceIdentifier(uri), remoteAuthority };
}
private doResolvePathLocal(path: string, options: IPathResolveOptions, lineNumber: number | undefined, columnNumber: number | undefined, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
// Ensure the path is normalized and absolute
path = sanitizeFilePath(normalize(path), process.env['VSCODE_CWD'] || process.cwd());
path = sanitizeFilePath(normalize(path), cwd());
try {
const pathStat = statSync(path);
if (pathStat.isFile()) {
// Workspace (unless disabled via flag)
if (!forceOpenWorkspaceAsFile) {
if (!options.forceOpenWorkspaceAsFile) {
const workspace = this.workspacesManagementMainService.resolveLocalWorkspaceSync(URI.file(path));
if (workspace) {
return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority: workspace.remoteAuthority, exists: true };
@@ -972,7 +946,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
this.workspacesHistoryMainService.removeRecentlyOpened([fileUri]);
// assume this is a file that does not yet exist
if (options?.ignoreFileNotFound) {
if (options.ignoreFileNotFound) {
return { fileUri, exists: false };
}
}
@@ -980,6 +954,52 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return undefined;
}
private doResolvePathRemote(path: string, options: IPathResolveOptions): IPathToOpen | undefined {
const first = path.charCodeAt(0);
const remoteAuthority = options.remoteAuthority;
// Extract line/col information from path
let lineNumber: number | undefined;
let columnNumber: number | undefined;
if (options.gotoLineMode) {
({ path, line: lineNumber, column: columnNumber } = parseLineAndColumnAware(path));
}
// make absolute
if (first !== CharCode.Slash) {
if (isWindowsDriveLetter(first) && path.charCodeAt(path.charCodeAt(1)) === CharCode.Colon) {
path = toSlashes(path);
}
path = `/${path}`;
}
const uri = URI.from({ scheme: Schemas.vscodeRemote, authority: remoteAuthority, path: path });
// guess the file type:
// - if it ends with a slash it's a folder
// - if in goto line mode or if it has a file extension, it's a file or a workspace
// - by defaults it's a folder
if (path.charCodeAt(path.length - 1) !== CharCode.Slash) {
// file name ends with .code-workspace
if (hasWorkspaceFileExtension(path)) {
if (options.forceOpenWorkspaceAsFile) {
return { fileUri: uri, lineNumber, columnNumber, remoteAuthority: options.remoteAuthority };
}
return { workspace: getWorkspaceIdentifier(uri), remoteAuthority };
}
// file name starts with a dot or has an file extension
else if (options.gotoLineMode || posix.basename(path).indexOf('.') !== -1) {
return { fileUri: uri, lineNumber, columnNumber, remoteAuthority };
}
}
return { workspace: getSingleFolderWorkspaceIdentifier(uri), remoteAuthority };
}
private shouldOpenNewWindow(openConfig: IOpenConfiguration): { openFolderInNewWindow: boolean; openFilesInNewWindow: boolean; } {
// let the user settings override how folders are open in a new window or same window unless we are forced
@@ -1060,17 +1080,18 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
}
}
let authority = '';
let remoteAuthority = openConfig.remoteAuthority;
for (const extensionDevelopmentPath of extensionDevelopmentPaths) {
if (extensionDevelopmentPath.match(/^[a-zA-Z][a-zA-Z0-9\+\-\.]+:/)) {
const url = URI.parse(extensionDevelopmentPath);
if (url.scheme === Schemas.vscodeRemote) {
if (authority) {
if (url.authority !== authority) {
const extensionDevelopmentPathRemoteAuthority = getRemoteAuthority(url);
if (extensionDevelopmentPathRemoteAuthority) {
if (remoteAuthority) {
if (extensionDevelopmentPathRemoteAuthority !== remoteAuthority) {
this.logService.error('more than one extension development path authority');
}
} else {
authority = url.authority;
remoteAuthority = extensionDevelopmentPathRemoteAuthority;
}
}
}
@@ -1086,7 +1107,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return false;
}
return uri.authority === authority;
return getRemoteAuthority(uri) === remoteAuthority;
});
folderUris = folderUris.filter(folderUriStr => {
@@ -1095,7 +1116,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return false;
}
return folderUri ? folderUri.authority === authority : false;
return folderUri ? getRemoteAuthority(folderUri) === remoteAuthority : false;
});
fileUris = fileUris.filter(fileUriStr => {
@@ -1104,18 +1125,14 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return false;
}
return fileUri ? fileUri.authority === authority : false;
return fileUri ? getRemoteAuthority(fileUri) === remoteAuthority : false;
});
openConfig.cli._ = cliArgs;
openConfig.cli['folder-uri'] = folderUris;
openConfig.cli['file-uri'] = fileUris;
// if there are no files or folders cli args left, use the "remote" cli argument
const noFilesOrFolders = !cliArgs.length && !folderUris.length && !fileUris.length;
if (noFilesOrFolders && authority) {
openConfig.cli.remote = authority;
}
// Open it
const openArgs: IOpenConfiguration = {
@@ -1125,40 +1142,68 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
forceEmpty: noFilesOrFolders,
userEnv: openConfig.userEnv,
noRecentEntry: true,
waitMarkerFileURI: openConfig.waitMarkerFileURI
waitMarkerFileURI: openConfig.waitMarkerFileURI,
remoteAuthority
};
return this.open(openArgs);
}
private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow {
const windowConfig = this.configurationService.getValue<IWindowSettings | undefined>('window');
// Build `INativeWindowConfiguration` from config and options
const configuration = { ...options.cli } as INativeWindowConfiguration;
configuration.appRoot = this.environmentService.appRoot;
configuration.machineId = this.machineId;
configuration.nodeCachedDataDir = this.environmentService.nodeCachedDataDir;
configuration.mainPid = process.pid;
configuration.execPath = process.execPath;
configuration.userEnv = { ...this.initialUserEnv, ...options.userEnv };
configuration.isInitialStartup = options.initialStartup;
configuration.workspace = options.workspace;
configuration.remoteAuthority = options.remoteAuthority;
// Build up the window configuration from provided options, config and environment
const configuration: INativeWindowConfiguration = {
const filesToOpen = options.filesToOpen;
if (filesToOpen) {
configuration.filesToOpenOrCreate = filesToOpen.filesToOpenOrCreate;
configuration.filesToDiff = filesToOpen.filesToDiff;
configuration.filesToWait = filesToOpen.filesToWait;
}
// Inherit CLI arguments from environment and/or
// the specific properties from this launch if provided
...this.environmentMainService.args,
...options.cli,
// if we know the backup folder upfront (for empty windows to restore), we can set it
// directly here which helps for restoring UI state associated with that window.
// For all other cases we first call into registerEmptyWindowBackupSync() to set it before
// loading the window.
if (options.emptyWindowBackupInfo) {
configuration.backupPath = join(this.environmentService.backupHome, options.emptyWindowBackupInfo.backupFolder);
}
machineId: this.machineId,
windowId: -1, // Will be filled in by the window once loaded later
mainPid: process.pid,
appRoot: this.environmentMainService.appRoot,
execPath: process.execPath,
nodeCachedDataDir: this.environmentMainService.nodeCachedDataDir,
partsSplashPath: join(this.environmentMainService.userDataPath, 'rapid_render.json'),
// If we know the backup folder upfront (for empty windows to restore), we can set it
// directly here which helps for restoring UI state associated with that window.
// For all other cases we first call into registerEmptyWindowBackupSync() to set it before
// loading the window.
backupPath: options.emptyWindowBackupInfo ? join(this.environmentMainService.backupHome, options.emptyWindowBackupInfo.backupFolder) : undefined,
homeDir: this.environmentMainService.userHome.fsPath,
tmpDir: this.environmentMainService.tmpDir.fsPath,
userDataDir: this.environmentMainService.userDataPath,
remoteAuthority: options.remoteAuthority,
workspace: options.workspace,
userEnv: { ...this.initialUserEnv, ...options.userEnv },
filesToOpenOrCreate: options.filesToOpen?.filesToOpenOrCreate,
filesToDiff: options.filesToOpen?.filesToDiff,
filesToWait: options.filesToOpen?.filesToWait,
logLevel: this.logService.getLevel(),
logsPath: this.environmentMainService.logsPath,
product,
isInitialStartup: options.initialStartup,
perfMarks: getMarks(),
os: { release: release(), hostname: hostname() },
zoomLevel: typeof windowConfig?.zoomLevel === 'number' ? windowConfig.zoomLevel : undefined,
autoDetectHighContrast: windowConfig?.autoDetectHighContrast ?? true,
accessibilitySupport: app.accessibilitySupportEnabled,
colorScheme: {
dark: nativeTheme.shouldUseDarkColors,
highContrast: nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors
}
};
let window: ICodeWindow | undefined;
if (!options.forceNewWindow && !options.forceNewTabbedWindow) {
@@ -1173,11 +1218,13 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
const state = this.windowsStateHandler.getNewWindowState(configuration);
// Create the window
const createdWindow = window = this.instantiationService.createInstance(CodeWindow, {
mark('code/willCreateCodeWindow');
const createdWindow = window = this.instantiationService.createInstance(<any>CodeWindow, { // {{SQL CARBON EDIT}} Fix weird compile error...
state,
extensionDevelopmentPath: configuration.extensionDevelopmentPath,
isExtensionTestHost: !!configuration.extensionTestsPath
});
mark('code/didCreateCodeWindow');
// Add as window tab if configured (macOS only)
if (options.forceNewTabbedWindow) {
@@ -1191,20 +1238,22 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
WindowsMainService.WINDOWS.push(createdWindow);
// Indicate new window via event
this._onWindowOpened.fire(createdWindow);
this._onDidOpenWindow.fire(createdWindow);
// Indicate number change via event
this._onWindowsCountChanged.fire({ oldCount: this.getWindowCount() - 1, newCount: this.getWindowCount() });
this._onDidChangeWindowsCount.fire({ oldCount: this.getWindowCount() - 1, newCount: this.getWindowCount() });
// Window Events
once(createdWindow.onReady)(() => this._onWindowReady.fire(createdWindow));
once(createdWindow.onClose)(() => this.onWindowClosed(createdWindow));
once(createdWindow.onDestroy)(() => this._onWindowDestroyed.fire(createdWindow));
createdWindow.win.webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own
createdWindow.win.webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(createdWindow));
once(createdWindow.onDidSignalReady)(() => this._onDidSignalReadyWindow.fire(createdWindow));
once(createdWindow.onDidClose)(() => this.onWindowClosed(createdWindow));
once(createdWindow.onDidDestroy)(() => this._onDidDestroyWindow.fire(createdWindow));
const webContents = assertIsDefined(createdWindow.win?.webContents);
webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own
webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(createdWindow));
// Lifecycle
(this.lifecycleMainService as LifecycleMainService).registerWindow(createdWindow);
this.lifecycleMainService.registerWindow(createdWindow);
}
// Existing window
@@ -1223,6 +1272,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
}
}
// Update window identifier and session now
// that we have the window object in hand.
configuration.windowId = window.id;
// If the window was already loaded, make sure to unload it
// first and only load the new configuration if that was
// not vetoed
@@ -1264,7 +1317,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
WindowsMainService.WINDOWS.splice(index, 1);
// Emit
this._onWindowsCountChanged.fire({ oldCount: this.getWindowCount() + 1, newCount: this.getWindowCount() });
this._onDidChangeWindowsCount.fire({ oldCount: this.getWindowCount() + 1, newCount: this.getWindowCount() });
}
getFocusedWindow(): ICodeWindow | undefined {