From 129f975fd4f4e71bef3f3a3272d81f909796eb23 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 11 Mar 2025 09:51:56 +0100 Subject: [PATCH] debt - prepare for property initialisation order changes #243049 (#243153) --- build/lib/propertyInitOrderChecker.js | 26 ----- build/lib/propertyInitOrderChecker.ts | 26 ----- src/vs/base/parts/storage/node/storage.ts | 15 ++- src/vs/code/browser/workbench/workbench.ts | 58 ++++++---- .../sharedProcess/contrib/codeCacheCleaner.ts | 16 +-- .../contrib/languagePackCachedDataCleaner.ts | 18 +-- .../electron-main/auxiliaryWindow.ts | 4 +- .../backup/electron-main/backupMainService.ts | 5 +- .../node/diskFileSystemProviderServer.ts | 6 +- .../node/watcher/nodejs/nodejsWatcherLib.ts | 17 ++- .../node/watcher/parcel/parcelWatcher.ts | 9 +- .../electron-main/menubarMainService.ts | 4 +- .../electron-main/nativeHostMainService.ts | 108 +++++++++++------- src/vs/platform/state/node/stateService.ts | 6 +- src/vs/platform/storage/common/storage.ts | 6 +- .../platform/storage/common/storageService.ts | 25 ++-- .../electron-main/storageMainService.ts | 8 +- .../utilityProcessWorkerMainService.ts | 10 +- .../windows/electron-main/windowImpl.ts | 8 +- .../electron-main/windowsMainService.ts | 6 +- .../electron-main/windowsStateHandler.ts | 4 +- src/vs/platform/workspace/common/workspace.ts | 28 +++-- .../electron-main/workspacesMainService.ts | 4 +- .../workspacesManagementMainService.ts | 4 +- .../common/extHostFileSystemEventService.ts | 8 +- .../api/node/extHostDiskFileSystemProvider.ts | 6 +- .../parts/auxiliarybar/auxiliaryBarPart.ts | 4 +- .../browser/parts/dialogs/dialogHandler.ts | 6 +- .../storage/browser/storageService.ts | 4 +- 29 files changed, 251 insertions(+), 198 deletions(-) diff --git a/build/lib/propertyInitOrderChecker.js b/build/lib/propertyInitOrderChecker.js index a0f03f7e8ab..622bbf2d7ac 100644 --- a/build/lib/propertyInitOrderChecker.js +++ b/build/lib/propertyInitOrderChecker.js @@ -55,24 +55,7 @@ const TS_CONFIG_PATH = path.join(__dirname, '../../', 'src', 'tsconfig.json'); // const ignored = new Set([ 'vs/base/common/arrays.ts', - 'vs/platform/workspace/common/workspace.ts', - 'vs/platform/files/node/watcher/nodejs/nodejsWatcherLib.ts', - 'vs/platform/storage/common/storage.ts', - 'vs/platform/state/node/stateService.ts', - 'vs/platform/workspaces/electron-main/workspacesManagementMainService.ts', - 'vs/platform/windows/electron-main/windowImpl.ts', - 'vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts', - 'vs/base/parts/storage/node/storage.ts', - 'vs/platform/storage/electron-main/storageMainService.ts', - 'vs/platform/backup/electron-main/backupMainService.ts', - 'vs/platform/files/node/diskFileSystemProviderServer.ts', - 'vs/platform/native/electron-main/nativeHostMainService.ts', - 'vs/platform/menubar/electron-main/menubarMainService.ts', - 'vs/platform/windows/electron-main/windowsStateHandler.ts', - 'vs/platform/windows/electron-main/windowsMainService.ts', - 'vs/platform/workspaces/electron-main/workspacesMainService.ts', 'vs/platform/extensionManagement/common/extensionsScannerService.ts', - 'vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts', 'vs/platform/configuration/common/configurations.ts', 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/tokenizer.ts', 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts', @@ -158,7 +141,6 @@ const ignored = new Set([ 'vs/workbench/browser/parts/editor/editorStatus.ts', 'vs/workbench/browser/parts/editor/editorPart.ts', 'vs/workbench/browser/parts/editor/editorParts.ts', - 'vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts', 'vs/workbench/services/textfile/common/textFileEditorModel.ts', 'vs/workbench/services/history/browser/historyService.ts', 'vs/workbench/services/notification/common/notificationService.ts', @@ -204,31 +186,23 @@ const ignored = new Set([ 'vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts', 'vs/workbench/contrib/accessibilitySignals/browser/editorTextPropertySignalsContribution.ts', 'vs/workbench/contrib/inlineCompletions/browser/inlineCompletionLanguageStatusBarContribution.ts', - 'vs/workbench/browser/parts/dialogs/dialogHandler.ts', 'vs/workbench/browser/parts/notifications/notificationsCenter.ts', 'vs/workbench/browser/parts/notifications/notificationsToasts.ts', - 'vs/workbench/services/storage/browser/storageService.ts', 'vs/workbench/services/textfile/common/textFileEditorModelManager.ts', 'vs/workbench/services/textfile/browser/textFileService.ts', 'vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts', 'vs/workbench/services/workingCopy/common/workingCopyBackupTracker.ts', 'vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts', - 'vs/code/browser/workbench/workbench.ts', 'vs/workbench/electron-sandbox/window.ts', - 'vs/platform/storage/common/storageService.ts', 'vs/workbench/services/files/electron-sandbox/diskFileSystemProvider.ts', - 'vs/code/electron-utility/sharedProcess/contrib/codeCacheCleaner.ts', 'vs/code/electron-utility/sharedProcess/contrib/languagePackCachedDataCleaner.ts', 'vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts', 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordInsertView.ts', - 'vs/platform/files/node/watcher/parcel/parcelWatcher.ts', 'vs/platform/terminal/node/ptyService.ts', 'vs/workbench/services/host/electron-sandbox/nativeHostService.ts', 'vs/workbench/services/integrity/electron-sandbox/integrityService.ts', 'vs/workbench/api/common/extHostLanguageFeatures.ts', - 'vs/workbench/api/common/extHostFileSystemEventService.ts', 'vs/workbench/api/common/extHostSearch.ts', - 'vs/workbench/api/node/extHostDiskFileSystemProvider.ts', 'vs/workbench/test/common/workbenchTestServices.ts', 'vs/workbench/test/browser/workbenchTestServices.ts', 'vs/workbench/contrib/testing/test/common/testStubs.ts', diff --git a/build/lib/propertyInitOrderChecker.ts b/build/lib/propertyInitOrderChecker.ts index 36f219ff25a..17cc0c1eb31 100644 --- a/build/lib/propertyInitOrderChecker.ts +++ b/build/lib/propertyInitOrderChecker.ts @@ -24,24 +24,7 @@ const TS_CONFIG_PATH = path.join(__dirname, '../../', 'src', 'tsconfig.json'); const ignored = new Set([ 'vs/base/common/arrays.ts', - 'vs/platform/workspace/common/workspace.ts', - 'vs/platform/files/node/watcher/nodejs/nodejsWatcherLib.ts', - 'vs/platform/storage/common/storage.ts', - 'vs/platform/state/node/stateService.ts', - 'vs/platform/workspaces/electron-main/workspacesManagementMainService.ts', - 'vs/platform/windows/electron-main/windowImpl.ts', - 'vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts', - 'vs/base/parts/storage/node/storage.ts', - 'vs/platform/storage/electron-main/storageMainService.ts', - 'vs/platform/backup/electron-main/backupMainService.ts', - 'vs/platform/files/node/diskFileSystemProviderServer.ts', - 'vs/platform/native/electron-main/nativeHostMainService.ts', - 'vs/platform/menubar/electron-main/menubarMainService.ts', - 'vs/platform/windows/electron-main/windowsStateHandler.ts', - 'vs/platform/windows/electron-main/windowsMainService.ts', - 'vs/platform/workspaces/electron-main/workspacesMainService.ts', 'vs/platform/extensionManagement/common/extensionsScannerService.ts', - 'vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts', 'vs/platform/configuration/common/configurations.ts', 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/tokenizer.ts', 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/bracketPairsTree.ts', @@ -127,7 +110,6 @@ const ignored = new Set([ 'vs/workbench/browser/parts/editor/editorStatus.ts', 'vs/workbench/browser/parts/editor/editorPart.ts', 'vs/workbench/browser/parts/editor/editorParts.ts', - 'vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts', 'vs/workbench/services/textfile/common/textFileEditorModel.ts', 'vs/workbench/services/history/browser/historyService.ts', 'vs/workbench/services/notification/common/notificationService.ts', @@ -173,31 +155,23 @@ const ignored = new Set([ 'vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts', 'vs/workbench/contrib/accessibilitySignals/browser/editorTextPropertySignalsContribution.ts', 'vs/workbench/contrib/inlineCompletions/browser/inlineCompletionLanguageStatusBarContribution.ts', - 'vs/workbench/browser/parts/dialogs/dialogHandler.ts', 'vs/workbench/browser/parts/notifications/notificationsCenter.ts', 'vs/workbench/browser/parts/notifications/notificationsToasts.ts', - 'vs/workbench/services/storage/browser/storageService.ts', 'vs/workbench/services/textfile/common/textFileEditorModelManager.ts', 'vs/workbench/services/textfile/browser/textFileService.ts', 'vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts', 'vs/workbench/services/workingCopy/common/workingCopyBackupTracker.ts', 'vs/workbench/contrib/welcomeDialog/browser/welcomeWidget.ts', - 'vs/code/browser/workbench/workbench.ts', 'vs/workbench/electron-sandbox/window.ts', - 'vs/platform/storage/common/storageService.ts', 'vs/workbench/services/files/electron-sandbox/diskFileSystemProvider.ts', - 'vs/code/electron-utility/sharedProcess/contrib/codeCacheCleaner.ts', 'vs/code/electron-utility/sharedProcess/contrib/languagePackCachedDataCleaner.ts', 'vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts', 'vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordInsertView.ts', - 'vs/platform/files/node/watcher/parcel/parcelWatcher.ts', 'vs/platform/terminal/node/ptyService.ts', 'vs/workbench/services/host/electron-sandbox/nativeHostService.ts', 'vs/workbench/services/integrity/electron-sandbox/integrityService.ts', 'vs/workbench/api/common/extHostLanguageFeatures.ts', - 'vs/workbench/api/common/extHostFileSystemEventService.ts', 'vs/workbench/api/common/extHostSearch.ts', - 'vs/workbench/api/node/extHostDiskFileSystemProvider.ts', 'vs/workbench/test/common/workbenchTestServices.ts', 'vs/workbench/test/browser/workbenchTestServices.ts', 'vs/workbench/contrib/testing/test/common/testStubs.ts', diff --git a/src/vs/base/parts/storage/node/storage.ts b/src/vs/base/parts/storage/node/storage.ts index 2def700f2b0..bf674966c0a 100644 --- a/src/vs/base/parts/storage/node/storage.ts +++ b/src/vs/base/parts/storage/node/storage.ts @@ -38,13 +38,20 @@ export class SQLiteStorageDatabase implements IStorageDatabase { private static readonly BUSY_OPEN_TIMEOUT = 2000; // timeout in ms to retry when opening DB fails with SQLITE_BUSY private static readonly MAX_HOST_PARAMETERS = 256; // maximum number of parameters within a statement - private readonly name = basename(this.path); + private readonly name: string; - private readonly logger = new SQLiteStorageDatabaseLogger(this.options.logging); + private readonly logger: SQLiteStorageDatabaseLogger; - private readonly whenConnected = this.connect(this.path); + private readonly whenConnected: Promise; - constructor(private readonly path: string, private readonly options: ISQLiteStorageDatabaseOptions = Object.create(null)) { } + constructor( + private readonly path: string, + options: ISQLiteStorageDatabaseOptions = Object.create(null) + ) { + this.name = basename(this.path); + this.logger = new SQLiteStorageDatabaseLogger(options.logging); + this.whenConnected = this.connect(this.path); + } async getItems(): Promise> { const connection = await this.whenConnected; diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index faa711a30c5..ab9671491fb 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -28,6 +28,7 @@ interface ISecretStorageCrypto { } class TransparentCrypto implements ISecretStorageCrypto { + async seal(data: string): Promise { return data; } @@ -44,6 +45,7 @@ const enum AESConstants { } class NetworkError extends Error { + constructor(inner: Error) { super(inner.message); this.name = inner.name; @@ -52,10 +54,13 @@ class NetworkError extends Error { } class ServerKeyedAESCrypto implements ISecretStorageCrypto { - private _serverKey: Uint8Array | undefined; - /** Gets whether the algorithm is supported; requires a secure context */ - public static supported() { + private serverKey: Uint8Array | undefined; + + /** + * Gets whether the algorithm is supported; requires a secure context + */ + static supported() { return !!crypto.subtle; } @@ -141,8 +146,8 @@ class ServerKeyedAESCrypto implements ISecretStorageCrypto { } private async getServerKeyPart(): Promise { - if (this._serverKey) { - return this._serverKey; + if (this.serverKey) { + return this.serverKey; } let attempt = 0; @@ -154,12 +159,15 @@ class ServerKeyedAESCrypto implements ISecretStorageCrypto { if (!res.ok) { throw new Error(res.statusText); } + const serverKey = new Uint8Array(await res.arrayBuffer()); if (serverKey.byteLength !== AESConstants.KEY_LENGTH / 8) { throw Error(`The key retrieved by the server is not ${AESConstants.KEY_LENGTH} bit long.`); } - this._serverKey = serverKey; - return this._serverKey; + + this.serverKey = serverKey; + + return this.serverKey; } catch (e) { lastError = e instanceof Error ? e : new Error(String(e)); attempt++; @@ -172,34 +180,39 @@ class ServerKeyedAESCrypto implements ISecretStorageCrypto { if (lastError) { throw new NetworkError(lastError); } + throw new Error('Unknown error'); } } export class LocalStorageSecretStorageProvider implements ISecretStorageProvider { - private readonly _storageKey = 'secrets.provider'; - private _secretsPromise: Promise> = this.load(); + private readonly storageKey = 'secrets.provider'; + + private secretsPromise: Promise>; type: 'in-memory' | 'persisted' | 'unknown' = 'persisted'; constructor( private readonly crypto: ISecretStorageCrypto, - ) { } + ) { + this.secretsPromise = this.load(); + } private async load(): Promise> { const record = this.loadAuthSessionFromElement(); - // Get the secrets from localStorage - const encrypted = localStorage.getItem(this._storageKey); + + const encrypted = localStorage.getItem(this.storageKey); if (encrypted) { try { const decrypted = JSON.parse(await this.crypto.unseal(encrypted)); + return { ...record, ...decrypted }; } catch (err) { // TODO: send telemetry console.error('Failed to decrypt secrets from localStorage', err); if (!(err instanceof NetworkError)) { - localStorage.removeItem(this._storageKey); + localStorage.removeItem(this.storageKey); } } } @@ -243,33 +256,35 @@ export class LocalStorageSecretStorageProvider implements ISecretStorageProvider } async get(key: string): Promise { - const secrets = await this._secretsPromise; + const secrets = await this.secretsPromise; + return secrets[key]; } + async set(key: string, value: string): Promise { - const secrets = await this._secretsPromise; + const secrets = await this.secretsPromise; secrets[key] = value; - this._secretsPromise = Promise.resolve(secrets); + this.secretsPromise = Promise.resolve(secrets); this.save(); } + async delete(key: string): Promise { - const secrets = await this._secretsPromise; + const secrets = await this.secretsPromise; delete secrets[key]; - this._secretsPromise = Promise.resolve(secrets); + this.secretsPromise = Promise.resolve(secrets); this.save(); } private async save(): Promise { try { - const encrypted = await this.crypto.seal(JSON.stringify(await this._secretsPromise)); - localStorage.setItem(this._storageKey, encrypted); + const encrypted = await this.crypto.seal(JSON.stringify(await this.secretsPromise)); + localStorage.setItem(this.storageKey, encrypted); } catch (err) { console.error(err); } } } - class LocalStorageURLCallbackProvider extends Disposable implements IURLCallbackProvider { private static REQUEST_ID = 0; @@ -485,6 +500,7 @@ class WorkspaceProvider implements IWorkspaceProvider { return !!result; } } + return false; } diff --git a/src/vs/code/electron-utility/sharedProcess/contrib/codeCacheCleaner.ts b/src/vs/code/electron-utility/sharedProcess/contrib/codeCacheCleaner.ts index 7560b8fac32..5e7ebeaee5d 100644 --- a/src/vs/code/electron-utility/sharedProcess/contrib/codeCacheCleaner.ts +++ b/src/vs/code/electron-utility/sharedProcess/contrib/codeCacheCleaner.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as fs from 'fs'; +import { promises } from 'fs'; import { RunOnceScheduler } from '../../../../base/common/async.js'; import { onUnexpectedError } from '../../../../base/common/errors.js'; import { Disposable } from '../../../../base/common/lifecycle.js'; @@ -14,17 +14,19 @@ import { IProductService } from '../../../../platform/product/common/productServ 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) + private readonly dataMaxAge: number; constructor( currentCodeCachePath: string | undefined, - @IProductService private readonly productService: IProductService, + @IProductService productService: IProductService, @ILogService private readonly logService: ILogService ) { super(); + this.dataMaxAge = productService.quality !== 'stable' + ? 1000 * 60 * 60 * 24 * 7 // roughly 1 week (insiders) + : 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months (stable) + // Cached data is stored as user data and we run a cleanup task every time // the editor starts. The strategy is to delete all files that are older than // 3 months (1 week respectively) @@ -55,8 +57,8 @@ export class CodeCacheCleaner extends Disposable { // Delete cache folder if old enough const codeCacheEntryPath = join(codeCacheRootPath, codeCache); - const codeCacheEntryStat = await fs.promises.stat(codeCacheEntryPath); - if (codeCacheEntryStat.isDirectory() && (now - codeCacheEntryStat.mtime.getTime()) > this._DataMaxAge) { + const codeCacheEntryStat = await promises.stat(codeCacheEntryPath); + if (codeCacheEntryStat.isDirectory() && (now - codeCacheEntryStat.mtime.getTime()) > this.dataMaxAge) { this.logService.trace(`[code cache cleanup]: Removing code cache folder ${codeCache}.`); return Promises.rm(codeCacheEntryPath); diff --git a/src/vs/code/electron-utility/sharedProcess/contrib/languagePackCachedDataCleaner.ts b/src/vs/code/electron-utility/sharedProcess/contrib/languagePackCachedDataCleaner.ts index 0c70b33f15c..f3f351ebaa4 100644 --- a/src/vs/code/electron-utility/sharedProcess/contrib/languagePackCachedDataCleaner.ts +++ b/src/vs/code/electron-utility/sharedProcess/contrib/languagePackCachedDataCleaner.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as fs from 'fs'; +import { promises } from 'fs'; import { RunOnceScheduler } from '../../../../base/common/async.js'; import { IStringDictionary } from '../../../../base/common/collections.js'; import { onUnexpectedError } from '../../../../base/common/errors.js'; @@ -33,17 +33,19 @@ interface ILanguagePackFile { export class LanguagePackCachedDataCleaner 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) + private readonly dataMaxAge: number; constructor( @INativeEnvironmentService private readonly environmentService: INativeEnvironmentService, @ILogService private readonly logService: ILogService, - @IProductService private readonly productService: IProductService + @IProductService productService: IProductService ) { super(); + this.dataMaxAge = productService.quality !== 'stable' + ? 1000 * 60 * 60 * 24 * 7 // roughly 1 week (insiders) + : 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months (stable) + // 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) { @@ -59,7 +61,7 @@ export class LanguagePackCachedDataCleaner extends Disposable { try { const installed: IStringDictionary = Object.create(null); - const metaData: ILanguagePackFile = JSON.parse(await fs.promises.readFile(join(this.environmentService.userDataPath, 'languagepacks.json'), 'utf8')); + const metaData: ILanguagePackFile = JSON.parse(await promises.readFile(join(this.environmentService.userDataPath, 'languagepacks.json'), 'utf8')); for (const locale of Object.keys(metaData)) { const entry = metaData[locale]; installed[`${entry.hash}.${locale}`] = true; @@ -94,8 +96,8 @@ export class LanguagePackCachedDataCleaner extends Disposable { } const candidate = join(folder, entry); - const stat = await fs.promises.stat(candidate); - if (stat.isDirectory() && (now - stat.mtime.getTime()) > this._DataMaxAge) { + const stat = await promises.stat(candidate); + if (stat.isDirectory() && (now - stat.mtime.getTime()) > this.dataMaxAge) { this.logService.trace(`[language pack cache cleanup]: Removing language pack cache folder: ${join(packEntry, entry)}`); await Promises.rm(candidate); diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts index 971d5cd6b2e..683ca26d49b 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts @@ -20,7 +20,7 @@ export interface IAuxiliaryWindow extends IBaseWindow { export class AuxiliaryWindow extends BaseWindow implements IAuxiliaryWindow { - readonly id = this.webContents.id; + readonly id: number; parentId = -1; override get win() { @@ -43,6 +43,8 @@ export class AuxiliaryWindow extends BaseWindow implements IAuxiliaryWindow { ) { super(configurationService, stateService, environmentMainService, logService); + this.id = this.webContents.id; + // Try to claim window this.tryClaimWindow(); } diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts index 36287ebc981..55b36989ae3 100644 --- a/src/vs/platform/backup/electron-main/backupMainService.ts +++ b/src/vs/platform/backup/electron-main/backupMainService.ts @@ -27,7 +27,7 @@ export class BackupMainService implements IBackupMainService { private static readonly backupWorkspacesMetadataStorageKey = 'backupWorkspaces'; - protected backupHome = this.environmentMainService.backupHome; + protected backupHome: string; private workspaces: IWorkspaceBackupInfo[] = []; private folders: IFolderBackupInfo[] = []; @@ -40,11 +40,12 @@ export class BackupMainService implements IBackupMainService { private readonly backupPathComparer = { isEqual: (pathA: string, pathB: string) => isEqual(pathA, pathB, !isLinux) }; constructor( - @IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService, + @IEnvironmentMainService environmentMainService: IEnvironmentMainService, @IConfigurationService private readonly configurationService: IConfigurationService, @ILogService private readonly logService: ILogService, @IStateService private readonly stateService: IStateService ) { + this.backupHome = environmentMainService.backupHome; } async initialize(): Promise { diff --git a/src/vs/platform/files/node/diskFileSystemProviderServer.ts b/src/vs/platform/files/node/diskFileSystemProviderServer.ts index d626904949e..e5a847eb635 100644 --- a/src/vs/platform/files/node/diskFileSystemProviderServer.ts +++ b/src/vs/platform/files/node/diskFileSystemProviderServer.ts @@ -272,16 +272,18 @@ export abstract class AbstractSessionFileWatcher extends Disposable implements I // This is important because we want to ensure that we only // forward events from the watched paths for this session and // not other clients that asked to watch other paths. - private readonly fileWatcher = this._register(new DiskFileSystemProvider(this.logService)); + private readonly fileWatcher: DiskFileSystemProvider; constructor( private readonly uriTransformer: IURITransformer, sessionEmitter: Emitter, - private readonly logService: ILogService, + logService: ILogService, private readonly environmentService: IEnvironmentService ) { super(); + this.fileWatcher = this._register(new DiskFileSystemProvider(logService)); + this.registerListeners(sessionEmitter); } diff --git a/src/vs/platform/files/node/watcher/nodejs/nodejsWatcherLib.ts b/src/vs/platform/files/node/watcher/nodejs/nodejsWatcherLib.ts index b016dde0a9f..3d92b0e3361 100644 --- a/src/vs/platform/files/node/watcher/nodejs/nodejsWatcherLib.ts +++ b/src/vs/platform/files/node/watcher/nodejs/nodejsWatcherLib.ts @@ -15,9 +15,10 @@ import { joinPath } from '../../../../../base/common/resources.js'; import { URI } from '../../../../../base/common/uri.js'; import { realpath } from '../../../../../base/node/extpath.js'; import { Promises } from '../../../../../base/node/pfs.js'; -import { FileChangeType, IFileChange } from '../../../common/files.js'; +import { FileChangeFilter, FileChangeType, IFileChange } from '../../../common/files.js'; import { ILogMessage, coalesceEvents, INonRecursiveWatchRequest, parseWatcherPatterns, IRecursiveWatcherWithSubscribe, isFiltered, isWatchRequestWithCorrelation } from '../../../common/watcher.js'; import { Lazy } from '../../../../../base/common/lazy.js'; +import { ParsedPattern } from '../../../../../base/common/glob.js'; export class NodeJSFileWatcherLibrary extends Disposable { @@ -50,9 +51,9 @@ export class NodeJSFileWatcherLibrary extends Disposable { // to coalesce events and reduce spam. private readonly fileChangesAggregator = this._register(new RunOnceWorker(events => this.handleFileChanges(events), NodeJSFileWatcherLibrary.FILE_CHANGES_HANDLER_DELAY)); - private readonly excludes = parseWatcherPatterns(this.request.path, this.request.excludes); - private readonly includes = this.request.includes ? parseWatcherPatterns(this.request.path, this.request.includes) : undefined; - private readonly filter = isWatchRequestWithCorrelation(this.request) ? this.request.filter : undefined; // filtering is only enabled when correlating because watchers are otherwise potentially reused + private readonly excludes: ParsedPattern[]; + private readonly includes: ParsedPattern[] | undefined; + private readonly filter: FileChangeFilter | undefined; private readonly cts = new CancellationTokenSource(); @@ -78,7 +79,7 @@ export class NodeJSFileWatcherLibrary extends Disposable { return result; }); - readonly ready = this.watch(); + readonly ready: Promise; private _isReusingRecursiveWatcher = false; get isReusingRecursiveWatcher(): boolean { return this._isReusingRecursiveWatcher; } @@ -95,6 +96,12 @@ export class NodeJSFileWatcherLibrary extends Disposable { private verboseLogging?: boolean ) { super(); + + this.excludes = parseWatcherPatterns(this.request.path, this.request.excludes); + this.includes = this.request.includes ? parseWatcherPatterns(this.request.path, this.request.includes) : undefined; + this.filter = isWatchRequestWithCorrelation(this.request) ? this.request.filter : undefined; // filtering is only enabled when correlating because watchers are otherwise potentially reused + + this.ready = this.watch(); } private async watch(): Promise { diff --git a/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts b/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts index a24ef066a5f..70a36d3be48 100644 --- a/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts +++ b/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts @@ -12,7 +12,7 @@ import { CancellationToken, CancellationTokenSource } from '../../../../../base/ import { toErrorMessage } from '../../../../../base/common/errorMessage.js'; import { Emitter, Event } from '../../../../../base/common/event.js'; import { randomPath, isEqual, isEqualOrParent } from '../../../../../base/common/extpath.js'; -import { GLOBSTAR, patternsEquals } from '../../../../../base/common/glob.js'; +import { GLOBSTAR, ParsedPattern, patternsEquals } from '../../../../../base/common/glob.js'; import { BaseWatcher } from '../baseWatcher.js'; import { TernarySearchTree } from '../../../../../base/common/ternarySearchTree.js'; import { normalizeNFC } from '../../../../../base/common/normalization.js'; @@ -37,8 +37,8 @@ export class ParcelWatcherInstance extends Disposable { private didStop = false; get stopped(): boolean { return this.didStop; } - private readonly includes = this.request.includes ? parseWatcherPatterns(this.request.path, this.request.includes) : undefined; - private readonly excludes = this.request.excludes ? parseWatcherPatterns(this.request.path, this.request.excludes) : undefined; + private readonly includes: ParsedPattern[] | undefined; + private readonly excludes: ParsedPattern[] | undefined; private readonly subscriptions = new Map void>>(); @@ -65,6 +65,9 @@ export class ParcelWatcherInstance extends Disposable { ) { super(); + this.includes = this.request.includes ? parseWatcherPatterns(this.request.path, this.request.includes) : undefined; + this.excludes = this.request.excludes ? parseWatcherPatterns(this.request.path, this.request.excludes) : undefined; + this._register(toDisposable(() => this.subscriptions.clear())); } diff --git a/src/vs/platform/menubar/electron-main/menubarMainService.ts b/src/vs/platform/menubar/electron-main/menubarMainService.ts index a80966d417a..b26f617df2f 100644 --- a/src/vs/platform/menubar/electron-main/menubarMainService.ts +++ b/src/vs/platform/menubar/electron-main/menubarMainService.ts @@ -20,7 +20,7 @@ export class MenubarMainService extends Disposable implements IMenubarMainServic declare readonly _serviceBrand: undefined; - private readonly menubar = this.installMenuBarAfterWindowOpen(); + private readonly menubar: Promise; constructor( @IInstantiationService private readonly instantiationService: IInstantiationService, @@ -28,6 +28,8 @@ export class MenubarMainService extends Disposable implements IMenubarMainServic @ILogService private readonly logService: ILogService ) { super(); + + this.menubar = this.installMenuBarAfterWindowOpen(); } private async installMenuBarAfterWindowOpen(): Promise { diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index c04dabc6785..6324e98e290 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -73,6 +73,60 @@ export class NativeHostMainService extends Disposable implements INativeHostMain @IInstantiationService private readonly instantiationService: IInstantiationService ) { super(); + + // Events + { + this.onDidOpenMainWindow = Event.map(this.windowsMainService.onDidOpenWindow, window => window.id); + + this.onDidTriggerWindowSystemContextMenu = Event.any( + Event.map(this.windowsMainService.onDidTriggerSystemContextMenu, ({ window, x, y }) => ({ windowId: window.id, x, y })), + Event.map(this.auxiliaryWindowsMainService.onDidTriggerSystemContextMenu, ({ window, x, y }) => ({ windowId: window.id, x, y })) + ); + + this.onDidMaximizeWindow = Event.any( + Event.map(this.windowsMainService.onDidMaximizeWindow, window => window.id), + Event.map(this.auxiliaryWindowsMainService.onDidMaximizeWindow, window => window.id) + ); + this.onDidUnmaximizeWindow = Event.any( + Event.map(this.windowsMainService.onDidUnmaximizeWindow, window => window.id), + Event.map(this.auxiliaryWindowsMainService.onDidUnmaximizeWindow, window => window.id) + ); + + this.onDidChangeWindowFullScreen = Event.any( + Event.map(this.windowsMainService.onDidChangeFullScreen, e => ({ windowId: e.window.id, fullscreen: e.fullscreen })), + Event.map(this.auxiliaryWindowsMainService.onDidChangeFullScreen, e => ({ windowId: e.window.id, fullscreen: e.fullscreen })) + ); + + this.onDidBlurMainWindow = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-blur', (event, window: BrowserWindow) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId)); + this.onDidFocusMainWindow = Event.any( + Event.map(Event.filter(Event.map(this.windowsMainService.onDidChangeWindowsCount, () => this.windowsMainService.getLastActiveWindow()), window => !!window), window => window!.id), + Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-focus', (event, window: BrowserWindow) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId)) + ); + + this.onDidBlurMainOrAuxiliaryWindow = Event.any( + this.onDidBlurMainWindow, + Event.map(Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-blur', (event, window: BrowserWindow) => this.auxiliaryWindowsMainService.getWindowByWebContents(window.webContents)), window => !!window), window => window!.id) + ); + this.onDidFocusMainOrAuxiliaryWindow = Event.any( + this.onDidFocusMainWindow, + Event.map(Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-focus', (event, window: BrowserWindow) => this.auxiliaryWindowsMainService.getWindowByWebContents(window.webContents)), window => !!window), window => window!.id) + ); + + this.onDidResumeOS = Event.fromNodeEventEmitter(powerMonitor, 'resume'); + + this.onDidChangeColorScheme = this.themeMainService.onDidChangeColorScheme; + + this.onDidChangeDisplay = Event.debounce(Event.any( + Event.filter(Event.fromNodeEventEmitter(screen, 'display-metrics-changed', (event: Electron.Event, display: Display, changedMetrics?: string[]) => changedMetrics), changedMetrics => { + // Electron will emit 'display-metrics-changed' events even when actually + // going fullscreen, because the dock hides. However, we do not want to + // react on this event as there is no change in display bounds. + return !(Array.isArray(changedMetrics) && changedMetrics.length === 1 && changedMetrics[0] === 'workArea'); + }), + Event.fromNodeEventEmitter(screen, 'display-added'), + Event.fromNodeEventEmitter(screen, 'display-removed') + ), () => { }, 100); + } } @@ -85,59 +139,29 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#region Events - readonly onDidOpenMainWindow = Event.map(this.windowsMainService.onDidOpenWindow, window => window.id); + readonly onDidOpenMainWindow: Event; - readonly onDidTriggerWindowSystemContextMenu = Event.any( - Event.map(this.windowsMainService.onDidTriggerSystemContextMenu, ({ window, x, y }) => ({ windowId: window.id, x, y })), - Event.map(this.auxiliaryWindowsMainService.onDidTriggerSystemContextMenu, ({ window, x, y }) => ({ windowId: window.id, x, y })) - ); + readonly onDidTriggerWindowSystemContextMenu: Event<{ windowId: number; x: number; y: number }>; - readonly onDidMaximizeWindow = Event.any( - Event.map(this.windowsMainService.onDidMaximizeWindow, window => window.id), - Event.map(this.auxiliaryWindowsMainService.onDidMaximizeWindow, window => window.id) - ); - readonly onDidUnmaximizeWindow = Event.any( - Event.map(this.windowsMainService.onDidUnmaximizeWindow, window => window.id), - Event.map(this.auxiliaryWindowsMainService.onDidUnmaximizeWindow, window => window.id) - ); + readonly onDidMaximizeWindow: Event; + readonly onDidUnmaximizeWindow: Event; - readonly onDidChangeWindowFullScreen = Event.any( - Event.map(this.windowsMainService.onDidChangeFullScreen, e => ({ windowId: e.window.id, fullscreen: e.fullscreen })), - Event.map(this.auxiliaryWindowsMainService.onDidChangeFullScreen, e => ({ windowId: e.window.id, fullscreen: e.fullscreen })) - ); + readonly onDidChangeWindowFullScreen: Event<{ readonly windowId: number; readonly fullscreen: boolean }>; - readonly onDidBlurMainWindow = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-blur', (event, window: BrowserWindow) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId)); - readonly onDidFocusMainWindow = Event.any( - Event.map(Event.filter(Event.map(this.windowsMainService.onDidChangeWindowsCount, () => this.windowsMainService.getLastActiveWindow()), window => !!window), window => window!.id), - Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-focus', (event, window: BrowserWindow) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId)) - ); + readonly onDidBlurMainWindow: Event; + readonly onDidFocusMainWindow: Event; - readonly onDidBlurMainOrAuxiliaryWindow = Event.any( - this.onDidBlurMainWindow, - Event.map(Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-blur', (event, window: BrowserWindow) => this.auxiliaryWindowsMainService.getWindowByWebContents(window.webContents)), window => !!window), window => window!.id) - ); - readonly onDidFocusMainOrAuxiliaryWindow = Event.any( - this.onDidFocusMainWindow, - Event.map(Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-focus', (event, window: BrowserWindow) => this.auxiliaryWindowsMainService.getWindowByWebContents(window.webContents)), window => !!window), window => window!.id) - ); + readonly onDidBlurMainOrAuxiliaryWindow: Event; + readonly onDidFocusMainOrAuxiliaryWindow: Event; - readonly onDidResumeOS = Event.fromNodeEventEmitter(powerMonitor, 'resume'); + readonly onDidResumeOS: Event; - readonly onDidChangeColorScheme = this.themeMainService.onDidChangeColorScheme; + readonly onDidChangeColorScheme: Event; private readonly _onDidChangePassword = this._register(new Emitter<{ account: string; service: string }>()); readonly onDidChangePassword = this._onDidChangePassword.event; - readonly onDidChangeDisplay = Event.debounce(Event.any( - Event.filter(Event.fromNodeEventEmitter(screen, 'display-metrics-changed', (event: Electron.Event, display: Display, changedMetrics?: string[]) => changedMetrics), changedMetrics => { - // Electron will emit 'display-metrics-changed' events even when actually - // going fullscreen, because the dock hides. However, we do not want to - // react on this event as there is no change in display bounds. - return !(Array.isArray(changedMetrics) && changedMetrics.length === 1 && changedMetrics[0] === 'workArea'); - }), - Event.fromNodeEventEmitter(screen, 'display-added'), - Event.fromNodeEventEmitter(screen, 'display-removed') - ), () => { }, 100); + readonly onDidChangeDisplay: Event; //#endregion diff --git a/src/vs/platform/state/node/stateService.ts b/src/vs/platform/state/node/stateService.ts index 77f7c45bc11..ef71d504bf6 100644 --- a/src/vs/platform/state/node/stateService.ts +++ b/src/vs/platform/state/node/stateService.ts @@ -25,18 +25,20 @@ export class FileStorage extends Disposable { private storage: StorageDatabase = Object.create(null); private lastSavedStorageContents = ''; - private readonly flushDelayer = this._register(new ThrottledDelayer(this.saveStrategy === SaveStrategy.IMMEDIATE ? 0 : 100 /* buffer saves over a short time */)); + private readonly flushDelayer: ThrottledDelayer; private initializing: Promise | undefined = undefined; private closing: Promise | undefined = undefined; constructor( private readonly storagePath: URI, - private readonly saveStrategy: SaveStrategy, + saveStrategy: SaveStrategy, private readonly logService: ILogService, private readonly fileService: IFileService, ) { super(); + + this.flushDelayer = this._register(new ThrottledDelayer(saveStrategy === SaveStrategy.IMMEDIATE ? 0 : 100 /* buffer saves over a short time */)); } init(): Promise { diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index b120f38a296..d67cdc47680 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -328,11 +328,13 @@ export abstract class AbstractStorageService extends Disposable implements IStor private initializationPromise: Promise | undefined; - private readonly flushWhenIdleScheduler = this._register(new RunOnceScheduler(() => this.doFlushWhenIdle(), this.options.flushInterval)); + private readonly flushWhenIdleScheduler: RunOnceScheduler; private readonly runFlushWhenIdle = this._register(new MutableDisposable()); - constructor(private readonly options: IStorageServiceOptions = { flushInterval: AbstractStorageService.DEFAULT_FLUSH_INTERVAL }) { + constructor(options: IStorageServiceOptions = { flushInterval: AbstractStorageService.DEFAULT_FLUSH_INTERVAL }) { super(); + + this.flushWhenIdleScheduler = this._register(new RunOnceScheduler(() => this.doFlushWhenIdle(), options.flushInterval)); } onDidChangeValue(scope: StorageScope.WORKSPACE, key: string | undefined, disposable: DisposableStore): Event; diff --git a/src/vs/platform/storage/common/storageService.ts b/src/vs/platform/storage/common/storageService.ts index c7181a89705..1b6d567fe3e 100644 --- a/src/vs/platform/storage/common/storageService.ts +++ b/src/vs/platform/storage/common/storageService.ts @@ -17,24 +17,33 @@ import { IAnyWorkspaceIdentifier } from '../../workspace/common/workspace.js'; export class RemoteStorageService extends AbstractStorageService { - private readonly applicationStorageProfile = this.initialProfiles.defaultProfile; - private readonly applicationStorage = this.createApplicationStorage(); + private readonly applicationStorageProfile: IUserDataProfile; + private readonly applicationStorage: IStorage; - private profileStorageProfile = this.initialProfiles.currentProfile; + private profileStorageProfile: IUserDataProfile; private readonly profileStorageDisposables = this._register(new DisposableStore()); - private profileStorage = this.createProfileStorage(this.profileStorageProfile); + private profileStorage: IStorage; - private workspaceStorageId = this.initialWorkspace?.id; + private workspaceStorageId: string | undefined; private readonly workspaceStorageDisposables = this._register(new DisposableStore()); - private workspaceStorage = this.createWorkspaceStorage(this.initialWorkspace); + private workspaceStorage: IStorage | undefined; constructor( - private readonly initialWorkspace: IAnyWorkspaceIdentifier | undefined, - private readonly initialProfiles: { defaultProfile: IUserDataProfile; currentProfile: IUserDataProfile }, + initialWorkspace: IAnyWorkspaceIdentifier | undefined, + initialProfiles: { defaultProfile: IUserDataProfile; currentProfile: IUserDataProfile }, private readonly remoteService: IRemoteService, private readonly environmentService: IEnvironmentService ) { super(); + + this.applicationStorageProfile = initialProfiles.defaultProfile; + this.applicationStorage = this.createApplicationStorage(); + + this.profileStorageProfile = initialProfiles.currentProfile; + this.profileStorage = this.createProfileStorage(this.profileStorageProfile); + + this.workspaceStorageId = initialWorkspace?.id; + this.workspaceStorage = this.createWorkspaceStorage(initialWorkspace); } private createApplicationStorage(): IStorage { diff --git a/src/vs/platform/storage/electron-main/storageMainService.ts b/src/vs/platform/storage/electron-main/storageMainService.ts index 94664c7eaef..d46df436862 100644 --- a/src/vs/platform/storage/electron-main/storageMainService.ts +++ b/src/vs/platform/storage/electron-main/storageMainService.ts @@ -91,6 +91,8 @@ export class StorageMainService extends Disposable implements IStorageMainServic ) { super(); + this.applicationStorage = this._register(this.createApplicationStorage()); + this.registerListeners(); } @@ -163,7 +165,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic //#region Application Storage - readonly applicationStorage = this._register(this.createApplicationStorage()); + readonly applicationStorage: IStorageMain; private createApplicationStorage(): IStorageMain { this.logService.trace(`StorageMainService: creating application storage`); @@ -332,13 +334,15 @@ export class ApplicationStorageMainService extends AbstractStorageService implem declare readonly _serviceBrand: undefined; - readonly whenReady = this.storageMainService.applicationStorage.whenInit; + readonly whenReady: Promise; constructor( @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService, @IStorageMainService private readonly storageMainService: IStorageMainService ) { super(); + + this.whenReady = this.storageMainService.applicationStorage.whenInit; } protected doInitialize(): Promise { diff --git a/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts b/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts index 9ab01b9be15..1ce3d5a18a5 100644 --- a/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts +++ b/src/vs/platform/utilityProcess/electron-main/utilityProcessWorkerMainService.ts @@ -99,17 +99,19 @@ class UtilityProcessWorker extends Disposable { private readonly _onDidTerminate = this._register(new Emitter()); readonly onDidTerminate = this._onDidTerminate.event; - private readonly utilityProcess = this._register(new WindowUtilityProcess(this.logService, this.windowsMainService, this.telemetryService, this.lifecycleMainService)); + private readonly utilityProcess: WindowUtilityProcess; constructor( - @ILogService private readonly logService: ILogService, + @ILogService logService: ILogService, @IWindowsMainService private readonly windowsMainService: IWindowsMainService, - @ITelemetryService private readonly telemetryService: ITelemetryService, - @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, + @ITelemetryService telemetryService: ITelemetryService, + @ILifecycleMainService lifecycleMainService: ILifecycleMainService, private readonly configuration: IUtilityProcessWorkerCreateConfiguration ) { super(); + this.utilityProcess = this._register(new WindowUtilityProcess(logService, windowsMainService, telemetryService, lifecycleMainService)); + this.registerListeners(); } diff --git a/src/vs/platform/windows/electron-main/windowImpl.ts b/src/vs/platform/windows/electron-main/windowImpl.ts index 7ea47d522f8..d7c6a41d986 100644 --- a/src/vs/platform/windows/electron-main/windowImpl.ts +++ b/src/vs/platform/windows/electron-main/windowImpl.ts @@ -26,7 +26,7 @@ import { IFileService } from '../../files/common/files.js'; import { ILifecycleMainService } from '../../lifecycle/electron-main/lifecycleMainService.js'; import { ILogService } from '../../log/common/log.js'; import { IProductService } from '../../product/common/productService.js'; -import { IProtocolMainService } from '../../protocol/electron-main/protocol.js'; +import { IIPCObjectUrl, IProtocolMainService } from '../../protocol/electron-main/protocol.js'; import { resolveMarketplaceHeaders } from '../../externalServices/common/marketplace.js'; import { IApplicationStorageMainService, IStorageMainService } from '../../storage/electron-main/storageMainService.js'; import { ITelemetryService } from '../../telemetry/common/telemetry.js'; @@ -536,7 +536,7 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { private customZoomLevel: number | undefined = undefined; - private readonly configObjectUrl = this._register(this.protocolMainService.createIPCObjectUrl()); + private readonly configObjectUrl: IIPCObjectUrl; private pendingLoadConfig: INativeWindowConfiguration | undefined; private wasLoaded = false; @@ -558,7 +558,7 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { @IDialogMainService private readonly dialogMainService: IDialogMainService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @IProductService private readonly productService: IProductService, - @IProtocolMainService private readonly protocolMainService: IProtocolMainService, + @IProtocolMainService protocolMainService: IProtocolMainService, @IWindowsMainService private readonly windowsMainService: IWindowsMainService, @IStateService stateService: IStateService, @IInstantiationService instantiationService: IInstantiationService @@ -567,6 +567,8 @@ export class CodeWindow extends BaseWindow implements ICodeWindow { //#region create browser window { + this.configObjectUrl = this._register(protocolMainService.createIPCObjectUrl()); + // Load window state const [state, hasMultipleDisplays] = this.restoreWindowState(config.state); this.windowState = state; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index d2ca2f8f6c7..594b8364353 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -210,7 +210,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic private readonly windows = new Map(); - private readonly windowsStateHandler = this._register(new WindowsStateHandler(this, this.stateService, this.lifecycleMainService, this.logService, this.configurationService)); + private readonly windowsStateHandler: WindowsStateHandler; constructor( private readonly machineId: string, @@ -219,7 +219,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic private readonly initialUserEnv: IProcessEnvironment, @ILogService private readonly logService: ILogService, @ILoggerMainService private readonly loggerService: ILoggerMainService, - @IStateService private readonly stateService: IStateService, + @IStateService stateService: IStateService, @IPolicyService private readonly policyService: IPolicyService, @IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService, @IUserDataProfilesMainService private readonly userDataProfilesMainService: IUserDataProfilesMainService, @@ -238,6 +238,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic ) { super(); + this.windowsStateHandler = this._register(new WindowsStateHandler(this, stateService, this.lifecycleMainService, this.logService, this.configurationService)); + this.registerListeners(); } diff --git a/src/vs/platform/windows/electron-main/windowsStateHandler.ts b/src/vs/platform/windows/electron-main/windowsStateHandler.ts index bd14cdbe3f4..1008f8217e5 100644 --- a/src/vs/platform/windows/electron-main/windowsStateHandler.ts +++ b/src/vs/platform/windows/electron-main/windowsStateHandler.ts @@ -55,7 +55,7 @@ export class WindowsStateHandler extends Disposable { private static readonly windowsStateStorageKey = 'windowsState'; get state() { return this._state; } - private readonly _state = restoreWindowsState(this.stateService.getItem(WindowsStateHandler.windowsStateStorageKey)); + private readonly _state: IWindowsState; private lastClosedState: IWindowState | undefined = undefined; @@ -70,6 +70,8 @@ export class WindowsStateHandler extends Disposable { ) { super(); + this._state = restoreWindowsState(this.stateService.getItem(WindowsStateHandler.windowsStateStorageKey)); + this.registerListeners(); } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index c6e7245ba7f..d46996a9210 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -329,16 +329,23 @@ export function isWorkspaceFolder(thing: unknown): thing is IWorkspaceFolder { export class Workspace implements IWorkspace { - private _foldersMap: TernarySearchTree = TernarySearchTree.forUris(this._ignorePathCasing, () => true); + private foldersMap: TernarySearchTree; + private _folders!: WorkspaceFolder[]; + get folders(): WorkspaceFolder[] { return this._folders; } + set folders(folders: WorkspaceFolder[]) { + this._folders = folders; + this.updateFoldersMap(); + } constructor( private _id: string, folders: WorkspaceFolder[], private _transient: boolean, private _configuration: URI | null, - private _ignorePathCasing: (key: URI) => boolean, + private ignorePathCasing: (key: URI) => boolean, ) { + this.foldersMap = TernarySearchTree.forUris(this.ignorePathCasing, () => true); this.folders = folders; } @@ -346,19 +353,10 @@ export class Workspace implements IWorkspace { this._id = workspace.id; this._configuration = workspace.configuration; this._transient = workspace.transient; - this._ignorePathCasing = workspace._ignorePathCasing; + this.ignorePathCasing = workspace.ignorePathCasing; this.folders = workspace.folders; } - get folders(): WorkspaceFolder[] { - return this._folders; - } - - set folders(folders: WorkspaceFolder[]) { - this._folders = folders; - this.updateFoldersMap(); - } - get id(): string { return this._id; } @@ -380,13 +378,13 @@ export class Workspace implements IWorkspace { return null; } - return this._foldersMap.findSubstr(resource) || null; + return this.foldersMap.findSubstr(resource) || null; } private updateFoldersMap(): void { - this._foldersMap = TernarySearchTree.forUris(this._ignorePathCasing, () => true); + this.foldersMap = TernarySearchTree.forUris(this.ignorePathCasing, () => true); for (const folder of this.folders) { - this._foldersMap.set(folder.uri, folder); + this.foldersMap.set(folder.uri, folder); } } diff --git a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts index b42bd3ad679..17374c47894 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesMainService.ts @@ -12,6 +12,7 @@ import { IWorkspaceIdentifier } from '../../workspace/common/workspace.js'; import { IWorkspacesHistoryMainService } from './workspacesHistoryMainService.js'; import { IWorkspacesManagementMainService } from './workspacesManagementMainService.js'; import { IWorkspaceBackupInfo, IFolderBackupInfo } from '../../backup/common/backup.js'; +import { Event } from '../../../base/common/event.js'; export class WorkspacesMainService implements AddFirstParameterToFunctions /* only methods, not events */, number /* window ID */> { @@ -23,6 +24,7 @@ export class WorkspacesMainService implements AddFirstParameterToFunctions; getRecentlyOpened(windowId: number): Promise { return this.workspacesHistoryMainService.getRecentlyOpened(); diff --git a/src/vs/platform/workspaces/electron-main/workspacesManagementMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesManagementMainService.ts index 33a585bd982..64835d8b0eb 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesManagementMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesManagementMainService.ts @@ -64,7 +64,7 @@ export class WorkspacesManagementMainService extends Disposable implements IWork private readonly _onDidEnterWorkspace = this._register(new Emitter()); readonly onDidEnterWorkspace: Event = this._onDidEnterWorkspace.event; - private readonly untitledWorkspacesHome = this.environmentMainService.untitledWorkspacesHome; // local URI that contains all untitled workspaces + private readonly untitledWorkspacesHome: URI; // local URI that contains all untitled workspaces private untitledWorkspaces: IUntitledWorkspaceInfo[] = []; @@ -76,6 +76,8 @@ export class WorkspacesManagementMainService extends Disposable implements IWork @IDialogMainService private readonly dialogMainService: IDialogMainService ) { super(); + + this.untitledWorkspacesHome = this.environmentMainService.untitledWorkspacesHome; } async initialize(): Promise { diff --git a/src/vs/workbench/api/common/extHostFileSystemEventService.ts b/src/vs/workbench/api/common/extHostFileSystemEventService.ts index 9bacc4ae0da..5fcd3c613d0 100644 --- a/src/vs/workbench/api/common/extHostFileSystemEventService.ts +++ b/src/vs/workbench/api/common/extHostFileSystemEventService.ts @@ -243,9 +243,7 @@ interface IExtensionListener { class LazyRevivedFileSystemEvents implements FileSystemEvents { - constructor(private readonly _events: FileSystemEvents) { } - - readonly session = this._events.session; + readonly session: number | undefined; private _created = new Lazy(() => this._events.created.map(URI.revive) as URI[]); get created(): URI[] { return this._created.value; } @@ -255,6 +253,10 @@ class LazyRevivedFileSystemEvents implements FileSystemEvents { private _deleted = new Lazy(() => this._events.deleted.map(URI.revive) as URI[]); get deleted(): URI[] { return this._deleted.value; } + + constructor(private readonly _events: FileSystemEvents) { + this.session = this._events.session; + } } export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServiceShape { diff --git a/src/vs/workbench/api/node/extHostDiskFileSystemProvider.ts b/src/vs/workbench/api/node/extHostDiskFileSystemProvider.ts index 2be6ba4652f..cb6a09dc96d 100644 --- a/src/vs/workbench/api/node/extHostDiskFileSystemProvider.ts +++ b/src/vs/workbench/api/node/extHostDiskFileSystemProvider.ts @@ -27,9 +27,11 @@ export class ExtHostDiskFileSystemProvider { class DiskFileSystemProviderAdapter implements vscode.FileSystemProvider { - private readonly impl = new DiskFileSystemProvider(this.logService); + private readonly impl: DiskFileSystemProvider; - constructor(private readonly logService: ILogService) { } + constructor(logService: ILogService) { + this.impl = new DiskFileSystemProvider(logService); + } async stat(uri: vscode.Uri): Promise { const stat = await this.impl.stat(uri); diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts index 508322d359f..75a3ce42d68 100644 --- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts +++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts @@ -80,7 +80,7 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart { readonly priority = LayoutPriority.Low; - private configuration = this.resolveConfiguration(); + private configuration: IAuxiliaryBarPartConfiguration; constructor( @INotificationService notificationService: INotificationService, @@ -125,6 +125,8 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart { menuService, ); + this.configuration = this.resolveConfiguration(); + this._register(configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(LayoutSettings.ACTIVITY_BAR_LOCATION)) { this.configuration = this.resolveConfiguration(); diff --git a/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts b/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts index 7563b30cd47..a7524ec4fe6 100644 --- a/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts +++ b/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts @@ -33,18 +33,20 @@ export class BrowserDialogHandler extends AbstractDialogHandler { 'editor.action.clipboardPasteAction' ]; - private readonly markdownRenderer = this.instantiationService.createInstance(MarkdownRenderer, {}); + private readonly markdownRenderer: MarkdownRenderer; constructor( @ILogService private readonly logService: ILogService, @ILayoutService private readonly layoutService: ILayoutService, @IKeybindingService private readonly keybindingService: IKeybindingService, - @IInstantiationService private readonly instantiationService: IInstantiationService, + @IInstantiationService instantiationService: IInstantiationService, @IProductService private readonly productService: IProductService, @IClipboardService private readonly clipboardService: IClipboardService, @IOpenerService private readonly openerService: IOpenerService ) { super(); + + this.markdownRenderer = instantiationService.createInstance(MarkdownRenderer, {}); } async prompt(prompt: IPrompt): Promise> { diff --git a/src/vs/workbench/services/storage/browser/storageService.ts b/src/vs/workbench/services/storage/browser/storageService.ts index 68573404c1e..ca10b6f7d95 100644 --- a/src/vs/workbench/services/storage/browser/storageService.ts +++ b/src/vs/workbench/services/storage/browser/storageService.ts @@ -29,7 +29,7 @@ export class BrowserStorageService extends AbstractStorageService { private profileStorage: IStorage | undefined; private profileStorageDatabase: IIndexedDBStorageDatabase | undefined; - private profileStorageProfile = this.userDataProfileService.currentProfile; + private profileStorageProfile: IUserDataProfile; private readonly profileStorageDisposables = this._register(new DisposableStore()); private workspaceStorage: IStorage | undefined; @@ -50,6 +50,8 @@ export class BrowserStorageService extends AbstractStorageService { ) { super({ flushInterval: BrowserStorageService.BROWSER_DEFAULT_FLUSH_INTERVAL }); + this.profileStorageProfile = this.userDataProfileService.currentProfile; + this.registerListeners(); }