Skip to content

Commit

Permalink
debt - prepare for property initialisation order changes #243049
Browse files Browse the repository at this point in the history
  • Loading branch information
bpasero committed Mar 11, 2025
1 parent acb986b commit 79af214
Show file tree
Hide file tree
Showing 19 changed files with 186 additions and 140 deletions.
16 changes: 0 additions & 16 deletions build/lib/propertyInitOrderChecker.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 0 additions & 16 deletions build/lib/propertyInitOrderChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,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',
Expand Down Expand Up @@ -182,11 +168,9 @@ const ignored = new Set([
'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',
Expand Down
15 changes: 11 additions & 4 deletions src/vs/base/parts/storage/node/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<IDatabaseConnection>;

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<Map<string, string>> {
const connection = await this.whenConnected;
Expand Down
53 changes: 33 additions & 20 deletions src/vs/code/browser/workbench/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface ISecretStorageCrypto {
}

class TransparentCrypto implements ISecretStorageCrypto {

async seal(data: string): Promise<string> {
return data;
}
Expand All @@ -44,6 +45,7 @@ const enum AESConstants {
}

class NetworkError extends Error {

constructor(inner: Error) {
super(inner.message);
this.name = inner.name;
Expand All @@ -52,9 +54,12 @@ class NetworkError extends Error {
}

class ServerKeyedAESCrypto implements ISecretStorageCrypto {
private _serverKey: Uint8Array | undefined;

/** Gets whether the algorithm is supported; requires a secure context */
private serverKey: Uint8Array | undefined;

/**
* Gets whether the algorithm is supported; requires a secure context
*/
public static supported() {
return !!crypto.subtle;
}
Expand Down Expand Up @@ -141,8 +146,8 @@ class ServerKeyedAESCrypto implements ISecretStorageCrypto {
}

private async getServerKeyPart(): Promise<Uint8Array> {
if (this._serverKey) {
return this._serverKey;
if (this.serverKey) {
return this.serverKey;
}

let attempt = 0;
Expand All @@ -158,8 +163,8 @@ class ServerKeyedAESCrypto implements ISecretStorageCrypto {
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++;
Expand All @@ -172,34 +177,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<Record<string, string>> = this.load();
private readonly storageKey = 'secrets.provider';

private secretsPromise: Promise<Record<string, string>>;

type: 'in-memory' | 'persisted' | 'unknown' = 'persisted';

constructor(
private readonly crypto: ISecretStorageCrypto,
) { }
) {
this.secretsPromise = this.load();
}

private async load(): Promise<Record<string, string>> {
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);
}
}
}
Expand Down Expand Up @@ -243,33 +253,35 @@ export class LocalStorageSecretStorageProvider implements ISecretStorageProvider
}

async get(key: string): Promise<string | undefined> {
const secrets = await this._secretsPromise;
const secrets = await this.secretsPromise;

return secrets[key];
}

async set(key: string, value: string): Promise<void> {
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<void> {
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<void> {
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;
Expand Down Expand Up @@ -485,6 +497,7 @@ class WorkspaceProvider implements IWorkspaceProvider {
return !!result;
}
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ 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,
Expand All @@ -44,6 +42,10 @@ export class LanguagePackCachedDataCleaner extends Disposable {
) {
super();

this.dataMaxAge = this.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) {
Expand Down Expand Up @@ -95,7 +97,7 @@ 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) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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();
}
Expand Down
5 changes: 3 additions & 2 deletions src/vs/platform/backup/electron-main/backupMainService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [];
Expand All @@ -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<void> {
Expand Down
6 changes: 4 additions & 2 deletions src/vs/platform/files/node/diskFileSystemProviderServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<IFileChange[] | string>,
private readonly logService: ILogService,
logService: ILogService,
private readonly environmentService: IEnvironmentService
) {
super();

this.fileWatcher = this._register(new DiskFileSystemProvider(logService));

this.registerListeners(sessionEmitter);
}

Expand Down
Loading

0 comments on commit 79af214

Please sign in to comment.