Merge from vscode e3c4990c67c40213af168300d1cfeb71d680f877 (#16569)

This commit is contained in:
Cory Rivera
2021-08-25 16:28:29 -07:00
committed by GitHub
parent ab1112bfb3
commit cb7b7da0a4
1752 changed files with 59525 additions and 33878 deletions

View File

@@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { basename, dirname, join } from 'vs/base/common/path';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable } from 'vs/base/common/lifecycle';
import { Promises } from 'vs/base/node/pfs';
import { IProductService } from 'vs/platform/product/common/productService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
export class CodeCacheCleaner extends Disposable {
private readonly _DataMaxAge = this.productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week (insiders)
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months (stable)
constructor(
currentCodeCachePath: string | undefined,
@IProductService private readonly productService: IProductService,
@ILogService private readonly logService: ILogService
) {
super();
// Cached data is stored as user data and we run a cleanup task everytime
// the editor starts. The strategy is to delete all files that are older than
// 3 months (1 week respectively)
if (currentCodeCachePath) {
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpCodeCaches(currentCodeCachePath);
}, 30 * 1000 /* after 30s */));
scheduler.schedule();
}
}
private async cleanUpCodeCaches(currentCodeCachePath: string): Promise<void> {
this.logService.info('[code cache cleanup]: Starting to clean up old code cache folders.');
try {
const now = Date.now();
// The folder which contains folders of cached data.
// Each of these folders is partioned per commit
const codeCacheRootPath = dirname(currentCodeCachePath);
const currentCodeCache = basename(currentCodeCachePath);
const codeCaches = await Promises.readdir(codeCacheRootPath);
await Promise.all(codeCaches.map(async codeCache => {
if (codeCache === currentCodeCache) {
return; // not the current cache folder
}
// Delete cache folder if old enough
const codeCacheEntryPath = join(codeCacheRootPath, codeCache);
const codeCacheEntryStat = await Promises.stat(codeCacheEntryPath);
if (codeCacheEntryStat.isDirectory() && (now - codeCacheEntryStat.mtime.getTime()) > this._DataMaxAge) {
this.logService.info(`[code cache cleanup]: Removing code cache folder ${codeCache}.`);
return Promises.rm(codeCacheEntryPath);
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View File

@@ -3,17 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
import * as path from 'vs/base/common/path';
import * as pfs from 'vs/base/node/pfs';
import { join } from 'vs/base/common/path';
import { Promises } from 'vs/base/node/pfs';
import { IStringDictionary } from 'vs/base/common/collections';
import { IProductService } from 'vs/platform/product/common/productService';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ILogService } from 'vs/platform/log/common/log';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { RunOnceScheduler } from 'vs/base/common/async';
interface ExtensionEntry {
interface IExtensionEntry {
version: string;
extensionIdentifier: {
id: string;
@@ -21,87 +21,88 @@ interface ExtensionEntry {
};
}
interface LanguagePackEntry {
interface ILanguagePackEntry {
hash: string;
extensions: ExtensionEntry[];
extensions: IExtensionEntry[];
}
interface LanguagePackFile {
[locale: string]: LanguagePackEntry;
interface ILanguagePackFile {
[locale: string]: ILanguagePackEntry;
}
export class LanguagePackCachedDataCleaner extends Disposable {
private readonly _DataMaxAge = this._productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
private readonly _DataMaxAge = this.productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week (insiders)
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months (stable)
constructor(
@INativeEnvironmentService private readonly _environmentService: INativeEnvironmentService,
@ILogService private readonly _logService: ILogService,
@IProductService private readonly _productService: IProductService
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@ILogService private readonly logService: ILogService,
@IProductService private readonly productService: IProductService
) {
super();
// We have no Language pack support for dev version (run from source)
// So only cleanup when we have a build version.
if (this._environmentService.isBuilt) {
this._manageCachedDataSoon();
if (this.environmentService.isBuilt) {
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpLanguagePackCache();
}, 40 * 1000 /* after 40s */));
scheduler.schedule();
}
}
private _manageCachedDataSoon(): void {
let handle: any = setTimeout(async () => {
handle = undefined;
this._logService.info('Starting to clean up unused language packs.');
try {
const installed: IStringDictionary<boolean> = Object.create(null);
const metaData: LanguagePackFile = JSON.parse(await fs.promises.readFile(path.join(this._environmentService.userDataPath, 'languagepacks.json'), 'utf8'));
for (let locale of Object.keys(metaData)) {
const entry = metaData[locale];
installed[`${entry.hash}.${locale}`] = true;
private async cleanUpLanguagePackCache(): Promise<void> {
this.logService.info('[language pack cache cleanup]: Starting to clean up unused language packs.');
try {
const installed: IStringDictionary<boolean> = Object.create(null);
const metaData: ILanguagePackFile = JSON.parse(await Promises.readFile(join(this.environmentService.userDataPath, 'languagepacks.json'), 'utf8'));
for (let locale of Object.keys(metaData)) {
const entry = metaData[locale];
installed[`${entry.hash}.${locale}`] = true;
}
// Cleanup entries for language packs that aren't installed anymore
const cacheDir = join(this.environmentService.userDataPath, 'clp');
const cacheDirExists = await Promises.exists(cacheDir);
if (!cacheDirExists) {
return;
}
const entries = await Promises.readdir(cacheDir);
for (const entry of entries) {
if (installed[entry]) {
this.logService.info(`[language pack cache cleanup]: Skipping folder ${entry}. Language pack still in use.`);
continue;
}
// Cleanup entries for language packs that aren't installed anymore
const cacheDir = path.join(this._environmentService.userDataPath, 'clp');
const exists = await pfs.exists(cacheDir);
if (!exists) {
return;
}
for (let entry of await pfs.readdir(cacheDir)) {
if (installed[entry]) {
this._logService.info(`Skipping directory ${entry}. Language pack still in use.`);
this.logService.info(`[language pack cache cleanup]: Removing unused language pack: ${entry}`);
await Promises.rm(join(cacheDir, entry));
}
const now = Date.now();
for (const packEntry of Object.keys(installed)) {
const folder = join(cacheDir, packEntry);
const entries = await Promises.readdir(folder);
for (const entry of entries) {
if (entry === 'tcf.json') {
continue;
}
this._logService.info('Removing unused language pack:', entry);
await pfs.rimraf(path.join(cacheDir, entry));
}
const now = Date.now();
for (let packEntry of Object.keys(installed)) {
const folder = path.join(cacheDir, packEntry);
for (let entry of await pfs.readdir(folder)) {
if (entry === 'tcf.json') {
continue;
}
const candidate = path.join(folder, entry);
const stat = await fs.promises.stat(candidate);
if (stat.isDirectory()) {
const diff = now - stat.mtime.getTime();
if (diff > this._DataMaxAge) {
this._logService.info('Removing language pack cache entry: ', path.join(packEntry, entry));
await pfs.rimraf(candidate);
}
}
const candidate = join(folder, entry);
const stat = await Promises.stat(candidate);
if (stat.isDirectory() && (now - stat.mtime.getTime()) > this._DataMaxAge) {
this.logService.info(`[language pack cache cleanup]: Removing language pack cache folder: ${join(packEntry, entry)}`);
await Promises.rm(candidate);
}
}
} catch (error) {
onUnexpectedError(error);
}
}, 40 * 1000);
this._register(toDisposable(() => {
if (handle !== undefined) {
clearTimeout(handle);
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View File

@@ -5,42 +5,46 @@
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { join, dirname, basename } from 'vs/base/common/path';
import { readdir, rimraf } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Promises } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
export class LogsDataCleaner extends Disposable {
constructor(
@IEnvironmentService private readonly environmentService: IEnvironmentService
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@ILogService private readonly logService: ILogService
) {
super();
this.cleanUpOldLogsSoon();
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpOldLogs();
}, 10 * 1000 /* after 10s */));
scheduler.schedule();
}
private cleanUpOldLogsSoon(): void {
let handle: NodeJS.Timeout | undefined = setTimeout(() => {
handle = undefined;
private async cleanUpOldLogs(): Promise<void> {
this.logService.info('[logs cleanup]: Starting to clean up old logs.');
try {
const currentLog = basename(this.environmentService.logsPath);
const logsRoot = dirname(this.environmentService.logsPath);
readdir(logsRoot).then(children => {
const allSessions = children.filter(name => /^\d{8}T\d{6}$/.test(name));
const oldSessions = allSessions.sort().filter((d, i) => d !== currentLog);
const toDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9));
const logFiles = await Promises.readdir(logsRoot);
return Promises.settled(toDelete.map(name => rimraf(join(logsRoot, name))));
}).then(null, onUnexpectedError);
}, 10 * 1000);
const allSessions = logFiles.filter(logFile => /^\d{8}T\d{6}$/.test(logFile));
const oldSessions = allSessions.sort().filter(session => session !== currentLog);
const sessionsToDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9));
this._register(toDisposable(() => {
if (handle) {
clearTimeout(handle);
handle = undefined;
if (sessionsToDelete.length > 0) {
this.logService.info(`[logs cleanup]: Removing log folders '${sessionsToDelete.join(', ')}'`);
await Promise.all(sessionsToDelete.map(sessionToDelete => Promises.rm(join(logsRoot, sessionToDelete))));
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View File

@@ -1,87 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { promises } from 'fs';
import { basename, dirname, join } from 'vs/base/common/path';
import { onUnexpectedError } from 'vs/base/common/errors';
import { toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { readdir, rimraf } from 'vs/base/node/pfs';
import { IProductService } from 'vs/platform/product/common/productService';
export class NodeCachedDataCleaner {
private readonly _DataMaxAge = this.productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
private readonly _disposables = new DisposableStore();
constructor(
private readonly nodeCachedDataDir: string | undefined,
@IProductService private readonly productService: IProductService
) {
this._manageCachedDataSoon();
}
dispose(): void {
this._disposables.dispose();
}
private _manageCachedDataSoon(): void {
// Cached data is stored as user data and we run a cleanup task everytime
// the editor starts. The strategy is to delete all files that are older than
// 3 months (1 week respectively)
if (!this.nodeCachedDataDir) {
return;
}
// The folder which contains folders of cached data. Each of these folder is per
// version
const nodeCachedDataRootDir = dirname(this.nodeCachedDataDir);
const nodeCachedDataCurrent = basename(this.nodeCachedDataDir);
let handle: NodeJS.Timeout | undefined = setTimeout(() => {
handle = undefined;
readdir(nodeCachedDataRootDir).then(entries => {
const now = Date.now();
const deletes: Promise<unknown>[] = [];
entries.forEach(entry => {
// name check
// * not the current cached data folder
if (entry !== nodeCachedDataCurrent) {
const path = join(nodeCachedDataRootDir, entry);
deletes.push(promises.stat(path).then(stats => {
// stat check
// * only directories
// * only when old enough
if (stats.isDirectory()) {
const diff = now - stats.mtime.getTime();
if (diff > this._DataMaxAge) {
return rimraf(path);
}
}
return undefined;
}));
}
});
return Promise.all(deletes);
}).then(undefined, onUnexpectedError);
}, 30 * 1000);
this._disposables.add(toDisposable(() => {
if (handle) {
clearTimeout(handle);
handle = undefined;
}
}));
}
}

View File

@@ -3,13 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { promises } from 'fs';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { join } from 'vs/base/common/path';
import { readdir, rimraf } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { IBackupWorkspacesFormat } from 'vs/platform/backup/node/backup';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
export class StorageDataCleaner extends Disposable {
@@ -18,52 +19,44 @@ export class StorageDataCleaner extends Disposable {
constructor(
private readonly backupWorkspacesPath: string,
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@ILogService private readonly logService: ILogService
) {
super();
this.cleanUpStorageSoon();
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpStorage();
}, 30 * 1000 /* after 30s */));
scheduler.schedule();
}
private cleanUpStorageSoon(): void {
let handle: NodeJS.Timeout | undefined = setTimeout(() => {
handle = undefined;
private async cleanUpStorage(): Promise<void> {
this.logService.info('[storage cleanup]: Starting to clean up storage folders.');
(async () => {
try {
// Leverage the backup workspace file to find out which empty workspace is currently in use to
// determine which empty workspace storage can safely be deleted
const contents = await promises.readFile(this.backupWorkspacesPath, 'utf8');
try {
const workspaces = JSON.parse(contents) as IBackupWorkspacesFormat;
const emptyWorkspaces = workspaces.emptyWorkspaceInfos.map(info => info.backupFolder);
// Leverage the backup workspace file to find out which empty workspace is currently in use to
// determine which empty workspace storage can safely be deleted
const contents = await Promises.readFile(this.backupWorkspacesPath, 'utf8');
// Read all workspace storage folders that exist
const storageFolders = await readdir(this.environmentService.workspaceStorageHome.fsPath);
const deletes: Promise<void>[] = [];
const workspaces = JSON.parse(contents) as IBackupWorkspacesFormat;
const emptyWorkspaces = workspaces.emptyWorkspaceInfos.map(emptyWorkspace => emptyWorkspace.backupFolder);
storageFolders.forEach(storageFolder => {
if (storageFolder.length === StorageDataCleaner.NON_EMPTY_WORKSPACE_ID_LENGTH) {
return;
}
if (emptyWorkspaces.indexOf(storageFolder) === -1) {
deletes.push(rimraf(join(this.environmentService.workspaceStorageHome.fsPath, storageFolder)));
}
});
await Promise.all(deletes);
} catch (error) {
onUnexpectedError(error);
// Read all workspace storage folders that exist
const storageFolders = await Promises.readdir(this.environmentService.workspaceStorageHome.fsPath);
await Promise.all(storageFolders.map(async storageFolder => {
if (storageFolder.length === StorageDataCleaner.NON_EMPTY_WORKSPACE_ID_LENGTH) {
return;
}
})();
}, 30 * 1000);
this._register(toDisposable(() => {
if (handle) {
clearTimeout(handle);
handle = undefined;
}
}));
if (emptyWorkspaces.indexOf(storageFolder) === -1) {
this.logService.info(`[storage cleanup]: Deleting storage folder ${storageFolder}.`);
await Promises.rm(join(this.environmentService.workspaceStorageHome.fsPath, storageFolder));
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View File

@@ -46,10 +46,7 @@
* forceEnableDeveloperKeybindings?: boolean,
* disallowReloadKeybinding?: boolean,
* removeDeveloperKeybindingsAfterLoad?: boolean
* },
* canModifyDOM?: (config: ISandboxConfiguration) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }
* }
* ) => Promise<unknown>
* }}

View File

@@ -36,7 +36,7 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza
import { combinedDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { DownloadService } from 'vs/platform/download/common/downloadService';
import { IDownloadService } from 'vs/platform/download/common/download';
import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner';
import { CodeCacheCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/codeCacheCleaner';
import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner';
import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner';
import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner';
@@ -77,7 +77,7 @@ import { LocalizationsUpdater } from 'vs/code/electron-browser/sharedProcess/con
import { DeprecatedExtensionsCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/deprecatedExtensionsCleaner';
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { TerminalIpcChannels } from 'vs/platform/terminal/common/terminal';
import { LocalReconnectConstants, TerminalIpcChannels } from 'vs/platform/terminal/common/terminal';
import { PtyHostService } from 'vs/platform/terminal/node/ptyHostService';
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncServiceIpc';
@@ -131,7 +131,7 @@ class SharedProcessMain extends Disposable {
// Instantiate Contributions
this._register(combinedDisposable(
instantiationService.createInstance(NodeCachedDataCleaner, this.configuration.nodeCachedDataDir),
instantiationService.createInstance(CodeCacheCleaner, this.configuration.codeCachePath),
instantiationService.createInstance(LanguagePackCachedDataCleaner),
instantiationService.createInstance(StorageDataCleaner, this.configuration.backupWorkspacesPath),
instantiationService.createInstance(LogsDataCleaner),
@@ -272,7 +272,19 @@ class SharedProcessMain extends Disposable {
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
// Terminal
services.set(ILocalPtyService, this._register(new PtyHostService(logService, telemetryService)));
services.set(
ILocalPtyService,
this._register(
new PtyHostService({
GraceTime: LocalReconnectConstants.GraceTime,
ShortGraceTime: LocalReconnectConstants.ShortGraceTime
},
configurationService,
logService,
telemetryService
)
)
);
return new InstantiationService(services);
}

View File

@@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview:; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https: ws:; font-src 'self' https: vscode-remote-resource:;">
<!-- <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types default TrustedFunctionWorkaround ExtensionScripts amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget domLineBreaksComputer editorViewLayer diffReview extensionHostWorker insane notebookOutputRenderer safeInnerHtml standaloneColorizer tokenizeToString webNestedWorkerExtensionHost webWorkerExtensionHost;"> {{SQL CARBON EDIT}} TODO @chgagnon Comment out until we can investigate a proper fix for ADS not starting up -->
<!-- <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types default TrustedFunctionWorkaround ExtensionScripts amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget editorGhostText domLineBreaksComputer editorViewLayer diffReview extensionHostWorker insane notebookRenderer safeInnerHtml standaloneColorizer tokenizeToString webNestedWorkerExtensionHost webWorkerExtensionHost;"> {{SQL CARBON EDIT}} TODO @chgagnon Comment out until we can investigate a proper fix for ADS not starting up -->
</head>
<body aria-label="">
</body>

View File

@@ -44,7 +44,7 @@
};
},
canModifyDOM: function (windowConfig) {
showPartsSplash(windowConfig);
showSplash(windowConfig);
},
beforeLoaderConfig: function (loaderConfig) {
loaderConfig.recordStats = true;
@@ -90,19 +90,20 @@
/**
* @typedef {import('../../../platform/windows/common/windows').INativeWindowConfiguration} INativeWindowConfiguration
* @typedef {import('../../../platform/environment/common/argv').NativeParsedArgs} NativeParsedArgs
*
* @returns {{
* load: (
* modules: string[],
* resultCallback: (result, configuration: INativeWindowConfiguration) => unknown,
* resultCallback: (result, configuration: INativeWindowConfiguration & NativeParsedArgs) => unknown,
* options?: {
* configureDeveloperSettings?: (config: INativeWindowConfiguration & object) => {
* configureDeveloperSettings?: (config: INativeWindowConfiguration & NativeParsedArgs) => {
* forceDisableShowDevtoolsOnError?: boolean,
* forceEnableDeveloperKeybindings?: boolean,
* disallowReloadKeybinding?: boolean,
* removeDeveloperKeybindingsAfterLoad?: boolean
* },
* canModifyDOM?: (config: INativeWindowConfiguration & object) => void,
* canModifyDOM?: (config: INativeWindowConfiguration & NativeParsedArgs) => void,
* beforeLoaderConfig?: (loaderConfig: object) => void,
* beforeRequire?: () => void
* }
@@ -115,28 +116,15 @@
}
/**
* @param {{
* partsSplashPath?: string,
* colorScheme: ('light' | 'dark' | 'hc'),
* autoDetectHighContrast?: boolean,
* extensionDevelopmentPath?: string[],
* workspace?: import('../../../platform/workspaces/common/workspaces').IWorkspaceIdentifier | import('../../../platform/workspaces/common/workspaces').ISingleFolderWorkspaceIdentifier
* }} configuration
* @param {INativeWindowConfiguration & NativeParsedArgs} configuration
*/
function showPartsSplash(configuration) {
function showSplash(configuration) {
performance.mark('code/willShowPartsSplash');
let data;
if (typeof configuration.partsSplashPath === 'string') {
try {
data = JSON.parse(require.__$__nodeRequire('fs').readFileSync(configuration.partsSplashPath, 'utf8'));
} catch (e) {
// ignore
}
}
let data = configuration.partsSplash;
// high contrast mode has been turned on from the outside, e.g. OS -> ignore stored colors and layouts
const isHighContrast = configuration.colorScheme === 'hc' /* ColorScheme.HIGH_CONTRAST */ && configuration.autoDetectHighContrast;
const isHighContrast = configuration.colorScheme.highContrast && configuration.autoDetectHighContrast;
if (data && isHighContrast && data.baseTheme !== 'hc-black') {
data = undefined;
}
@@ -161,16 +149,18 @@
shellBackground = '#1E1E1E';
shellForeground = '#CCCCCC';
}
const style = document.createElement('style');
style.className = 'initialShellColors';
document.head.appendChild(style);
style.textContent = `body { background-color: ${shellBackground}; color: ${shellForeground}; margin: 0; padding: 0; }`;
if (data && data.layoutInfo) {
// restore parts if possible (we might not always store layout info)
const { id, layoutInfo, colorInfo } = data;
// restore parts if possible (we might not always store layout info)
if (data?.layoutInfo) {
const { layoutInfo, colorInfo } = data;
const splash = document.createElement('div');
splash.id = id;
splash.id = 'monaco-parts-splash';
splash.className = baseTheme;
if (layoutInfo.windowBorder) {
@@ -199,8 +189,8 @@
splash.appendChild(activityDiv);
// part: side bar (only when opening workspace/folder)
// folder or workspace -> status bar color, sidebar
if (configuration.workspace) {
// folder or workspace -> status bar color, sidebar
const sideDiv = document.createElement('div');
sideDiv.setAttribute('style', `position: absolute; height: calc(100% - ${layoutInfo.titleBarHeight}px); top: ${layoutInfo.titleBarHeight}px; ${layoutInfo.sideBarSide}: ${layoutInfo.activityBarWidth}px; width: ${layoutInfo.sideBarWidth}px; background-color: ${colorInfo.sideBarBackground};`);
splash.appendChild(sideDiv);