From 82acd7372343c7b749dd6035aa04ea00c0d3e475 Mon Sep 17 00:00:00 2001 From: Bharat Middha <5100938+bmiddha@users.noreply.github.com> Date: Wed, 19 Aug 2026 14:14:34 -0700 Subject: [PATCH 1/3] refactor: private fields in heft/webpack pkgs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14 --- .../src/ApiExtractorPlugin.ts | 28 +-- .../heft-jest-plugin/src/HeftJestReporter.ts | 54 ++--- .../heft-jest-plugin/src/JestPlugin.ts | 62 +++--- .../src/TerminalWritableStream.ts | 6 +- heft-plugins/heft-lint-plugin/src/Eslint.ts | 64 +++--- .../heft-lint-plugin/src/LintPlugin.ts | 42 ++-- .../heft-lint-plugin/src/LinterBase.ts | 6 +- heft-plugins/heft-lint-plugin/src/Tslint.ts | 40 ++-- .../src/DeferredWatchFileSystem.ts | 18 +- .../heft-rspack-plugin/src/RspackPlugin.ts | 92 ++++---- .../heft-sass-plugin/src/SassProcessor.ts | 92 ++++---- .../src/ServerlessStackPlugin.ts | 20 +- .../src/TypeScriptBuilder.ts | 184 ++++++++-------- .../fileSystem/TypeScriptCachedFileSystem.ts | 30 +-- .../src/DeferredWatchFileSystem.ts | 18 +- .../src/Webpack4Plugin.ts | 94 ++++---- .../src/DeferredWatchFileSystem.ts | 18 +- .../src/Webpack5Plugin.ts | 92 ++++---- .../src/HashedFolderDependency.ts | 8 +- .../src/SetPublicPathPlugin.ts | 8 +- .../src/SetPublicPathPluginBase.ts | 8 +- .../src/DeepImportsPlugin.ts | 26 +-- .../src/EmbeddedDependenciesWebpackPlugin.ts | 30 +-- .../src/KnownDescriptionFilePlugin.ts | 12 +- .../src/KnownPackageDependenciesPlugin.ts | 6 +- .../src/WorkspaceLayoutCache.ts | 28 +-- .../src/WorkspaceResolvePlugin.ts | 12 +- .../src/LocalizationPlugin.ts | 204 +++++++++--------- .../src/AsyncImportCompressionPlugin.ts | 8 +- .../src/ModuleMinifierPlugin.ts | 26 +-- .../src/PortableMinifierIdsPlugin.ts | 10 +- .../src/LocalizationPlugin.ts | 104 ++++----- .../src/TrueHashPlugin.ts | 6 +- .../src/test/LocalizedRuntimeTestBase.ts | 12 +- .../src/test/MemFSPlugin.ts | 10 +- .../src/ModuleMinifierPlugin.ts | 22 +- 36 files changed, 749 insertions(+), 751 deletions(-) diff --git a/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts b/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts index 8ab77d46808..01a995933ed 100644 --- a/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts +++ b/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts @@ -63,9 +63,9 @@ export interface IApiExtractorTaskConfiguration { } export default class ApiExtractorPlugin implements IHeftTaskPlugin { - private _apiExtractor: typeof TApiExtractor | undefined; - private _apiExtractorConfigurationFilePath: string | undefined | typeof UNINITIALIZED = UNINITIALIZED; - private _printedWatchWarning: boolean = false; + #apiExtractor: typeof TApiExtractor | undefined; + #apiExtractorConfigurationFilePath: string | undefined | typeof UNINITIALIZED = UNINITIALIZED; + #printedWatchWarning: boolean = false; public apply(taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration): void { const runAsync = async ( @@ -92,15 +92,15 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { - if (this._apiExtractorConfigurationFilePath === UNINITIALIZED) { - this._apiExtractorConfigurationFilePath = + if (this.#apiExtractorConfigurationFilePath === UNINITIALIZED) { + this.#apiExtractorConfigurationFilePath = await heftConfiguration.rigConfig.tryResolveConfigFilePathAsync(EXTRACTOR_CONFIG_RELATIVE_PATH); - if (this._apiExtractorConfigurationFilePath === undefined) { - this._apiExtractorConfigurationFilePath = + if (this.#apiExtractorConfigurationFilePath === undefined) { + this.#apiExtractorConfigurationFilePath = await heftConfiguration.rigConfig.tryResolveConfigFilePathAsync( LEGACY_EXTRACTOR_CONFIG_RELATIVE_PATH ); - if (this._apiExtractorConfigurationFilePath !== undefined) { + if (this.#apiExtractorConfigurationFilePath !== undefined) { taskSession.logger.emitWarning( new Error( `The "${LEGACY_EXTRACTOR_CONFIG_RELATIVE_PATH}" configuration file path is not supported ` + @@ -110,7 +110,7 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { } } } - return this._apiExtractorConfigurationFilePath; + return this.#apiExtractorConfigurationFilePath; } private async _getApiExtractorConfigurationAsync( @@ -153,14 +153,14 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { - if (!this._apiExtractor) { + if (!this.#apiExtractor) { const apiExtractorPackagePath: string = await heftConfiguration.rigPackageResolver.resolvePackageAsync( '@microsoft/api-extractor', taskSession.logger.terminal ); - this._apiExtractor = (await import(apiExtractorPackagePath)) as typeof TApiExtractor; + this.#apiExtractor = (await import(apiExtractorPackagePath)) as typeof TApiExtractor; } - return this._apiExtractor; + return this.#apiExtractor; } private async _runApiExtractorAsync( @@ -181,8 +181,8 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { if (runOptions.requestRun) { if (!runInWatchMode) { - if (!this._printedWatchWarning) { - this._printedWatchWarning = true; + if (!this.#printedWatchWarning) { + this.#printedWatchWarning = true; taskSession.logger.terminal.writeWarningLine( "API Extractor isn't currently enabled in watch mode." ); diff --git a/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts b/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts index 3f4e7089c3c..3233729a3d5 100644 --- a/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts +++ b/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts @@ -35,19 +35,19 @@ export interface IHeftJestReporterOptions { * https://github.com/facebook/jest/blob/main/packages/jest-reporters/src/default_reporter.ts */ export default class HeftJestReporter implements Reporter { - private _terminal: ITerminal; - private _buildFolderPath: string; - private _debugMode: boolean; + #terminal: ITerminal; + #buildFolderPath: string; + #debugMode: boolean; public constructor(jestConfig: Config.GlobalConfig, options: IHeftJestReporterOptions) { - this._terminal = options.logger.terminal; - this._buildFolderPath = options.heftConfiguration.buildFolderPath; - this._debugMode = options.debugMode; + this.#terminal = options.logger.terminal; + this.#buildFolderPath = options.heftConfiguration.buildFolderPath; + this.#debugMode = options.debugMode; } // eslint-disable-next-line @typescript-eslint/naming-convention public async onTestStart(test: Test): Promise { - this._terminal.writeLine( + this.#terminal.writeLine( Colorize.whiteBackground(Colorize.black('START')), ` ${this._getTestPath(test.path)}` ); @@ -84,34 +84,34 @@ export default class HeftJestReporter implements Reporter { `(duration: ${duration}, ${numPassingTests} passed, ${numFailingTests} failed${memUsage})`; if (numFailingTests > 0) { - this._terminal.writeLine(Colorize.redBackground(Colorize.black('FAIL')), message); + this.#terminal.writeLine(Colorize.redBackground(Colorize.black('FAIL')), message); } else if (testExecError) { - this._terminal.writeLine( + this.#terminal.writeLine( Colorize.redBackground(Colorize.black(`FAIL (${testExecError.type})`)), message ); } else { - this._terminal.writeLine(Colorize.greenBackground(Colorize.black('PASS')), message); + this.#terminal.writeLine(Colorize.greenBackground(Colorize.black('PASS')), message); } if (failureMessage) { - this._terminal.writeErrorLine(failureMessage); + this.#terminal.writeErrorLine(failureMessage); } if (updatedSnapshots) { - this._terminal.writeErrorLine( + this.#terminal.writeErrorLine( `Updated ${this._formatWithPlural(updatedSnapshots, 'snapshot', 'snapshots')}` ); } if (addedSnapshots) { - this._terminal.writeErrorLine( + this.#terminal.writeErrorLine( `Added ${this._formatWithPlural(addedSnapshots, 'snapshot', 'snapshots')}` ); } if (uncheckedSnapshots) { - this._terminal.writeWarningLine( + this.#terminal.writeWarningLine( `${this._formatWithPlural(uncheckedSnapshots, 'snapshot was', 'snapshots were')} not checked` ); } @@ -143,7 +143,7 @@ export default class HeftJestReporter implements Reporter { break; case 'groupCollapsed': - if (this._debugMode) { + if (this.#debugMode) { // The "groupCollapsed" name is too long this._writeConsoleOutputWithLabel('collapsed', logEntry.message); } @@ -155,7 +155,7 @@ export default class HeftJestReporter implements Reporter { case 'dirxml': case 'group': case 'time': - if (this._debugMode) { + if (this.#debugMode) { this._writeConsoleOutputWithLabel( logEntry.type, `(${logEntry.type}) ${logEntry.message}`, @@ -185,7 +185,7 @@ export default class HeftJestReporter implements Reporter { const prefix: string = debug ? Colorize.yellow(paddedLabel) : Colorize.cyan(paddedLabel); for (const line of lines) { - this._terminal.writeLine(prefix, ' ' + line); + this.#terminal.writeLine(prefix, ' ' + line); } } @@ -196,8 +196,8 @@ export default class HeftJestReporter implements Reporter { ): Promise { // Jest prints some text that changes the console's color without a newline, so we reset the console's color here // and print a newline. - this._terminal.writeLine('\u001b[0m'); - this._terminal.writeLine( + this.#terminal.writeLine('\u001b[0m'); + this.#terminal.writeLine( `Run start. ${this._formatWithPlural(aggregatedResult.numTotalTestSuites, 'test suite', 'test suites')}` ); } @@ -212,26 +212,26 @@ export default class HeftJestReporter implements Reporter { snapshot: { uncheckedKeysByFile: uncheckedSnapshotsByFile } } = results; - this._terminal.writeLine(); - this._terminal.writeLine('Tests finished:'); + this.#terminal.writeLine(); + this.#terminal.writeLine('Tests finished:'); const successesText: string = ` Successes: ${numPassedTests}`; - this._terminal.writeLine(numPassedTests > 0 ? Colorize.green(successesText) : successesText); + this.#terminal.writeLine(numPassedTests > 0 ? Colorize.green(successesText) : successesText); const failText: string = ` Failures: ${numFailedTests}`; - this._terminal.writeLine(numFailedTests > 0 ? Colorize.red(failText) : failText); + this.#terminal.writeLine(numFailedTests > 0 ? Colorize.red(failText) : failText); if (numRuntimeErrorTestSuites) { - this._terminal.writeLine(Colorize.red(` Failed test suites: ${numRuntimeErrorTestSuites}`)); + this.#terminal.writeLine(Colorize.red(` Failed test suites: ${numRuntimeErrorTestSuites}`)); } if (uncheckedSnapshotsByFile.length > 0) { - this._terminal.writeWarningLine( + this.#terminal.writeWarningLine( ` Test suites with unchecked snapshots: ${uncheckedSnapshotsByFile.length}` ); } - this._terminal.writeLine(` Total: ${numTotalTests}`); + this.#terminal.writeLine(` Total: ${numTotalTests}`); } public getLastError(): void { @@ -239,7 +239,7 @@ export default class HeftJestReporter implements Reporter { } private _getTestPath(fullTestPath: string): string { - return path.relative(this._buildFolderPath, fullTestPath); + return path.relative(this.#buildFolderPath, fullTestPath); } private _formatWithPlural(num: number, singular: string, plural: string): string { diff --git a/heft-plugins/heft-jest-plugin/src/JestPlugin.ts b/heft-plugins/heft-jest-plugin/src/JestPlugin.ts index 6ad53a10a48..168d7a06181 100644 --- a/heft-plugins/heft-jest-plugin/src/JestPlugin.ts +++ b/heft-plugins/heft-jest-plugin/src/JestPlugin.ts @@ -142,21 +142,21 @@ interface IPendingTestRun { * @internal */ export default class JestPlugin implements IHeftTaskPlugin { - private _jestPromise: Promise | undefined; - private _pendingTestRuns: Set = new Set(); - private _executing: boolean = false; + #jestPromise: Promise | undefined; + #pendingTestRuns: Set = new Set(); + #executing: boolean = false; - private _jestOutputStream: TerminalWritableStream | undefined; - private _changedFiles: Set = new Set(); - private _requestRun!: () => void; - private _nodeEnvSet: boolean | undefined; + #jestOutputStream: TerminalWritableStream | undefined; + #changedFiles: Set = new Set(); + #requestRun!: () => void; + #nodeEnvSet: boolean | undefined; - private _resolveFirstRunQueued!: () => void; - private _firstRunQueuedPromise: Promise; + #resolveFirstRunQueued!: () => void; + #firstRunQueuedPromise: Promise; public constructor() { - this._firstRunQueuedPromise = new Promise((resolve) => { - this._resolveFirstRunQueued = resolve; + this.#firstRunQueuedPromise = new Promise((resolve) => { + this.#resolveFirstRunQueued = resolve; }); } @@ -310,10 +310,10 @@ export default class JestPlugin implements IHeftTaskPlugin { const logger: IScopedLogger = taskSession.logger; const terminal: ITerminal = logger.terminal; - const pendingTestRuns: Set = this._pendingTestRuns; - this._requestRun = requestRun; + const pendingTestRuns: Set = this.#pendingTestRuns; + this.#requestRun = requestRun; - if (!this._jestPromise) { + if (!this.#jestPromise) { // Monkey-patch Jest's watch mode so that we can orchestrate it. const jestCoreDir: string = path.dirname(require.resolve('@jest/core')); @@ -349,7 +349,7 @@ export default class JestPlugin implements IHeftTaskPlugin { }); const wrappedStdOut: TerminalWritableStream = new TerminalWritableStream(terminal); - this._jestOutputStream = wrappedStdOut; + this.#jestOutputStream = wrappedStdOut; // Shim watch so that we can intercept the output stream const watchModulePath: string = path.resolve(jestCoreDir, 'watch.js'); @@ -381,7 +381,7 @@ export default class JestPlugin implements IHeftTaskPlugin { hasteMap.on('change', ({ eventsQueue }: { eventsQueue: { filePath: string }[] }) => { for (const file of eventsQueue) { // Record all changed files for the next test run - host._changedFiles.add(file.filePath); + host.#changedFiles.add(file.filePath); } }); }); @@ -389,7 +389,7 @@ export default class JestPlugin implements IHeftTaskPlugin { return originalWatch( initialGlobalConfig, contexts, - host._jestOutputStream as unknown as NodeJS.WriteStream, + host.#jestOutputStream as unknown as NodeJS.WriteStream, hasteMapInstances, stdin, hooks, @@ -418,23 +418,23 @@ export default class JestPlugin implements IHeftTaskPlugin { throw new Error(`Patched Jest expected JestPlugin on globalConfig`); } - if (!host._executing) { - host._requestRun(); + if (!host.#executing) { + host.#requestRun(); } return new Promise((resolve: () => void, reject: (err: Error) => void) => { - host._pendingTestRuns.add(async (): Promise => { + host.#pendingTestRuns.add(async (): Promise => { let result: AggregatedResult | undefined; const { onComplete } = params; - const findRelatedTests: boolean = params.globalConfig.onlyChanged && host._changedFiles.size > 0; + const findRelatedTests: boolean = params.globalConfig.onlyChanged && host.#changedFiles.size > 0; const globalConfig: IRunJestParams['globalConfig'] = Object.freeze({ ...params.globalConfig, // Use the knowledge of changed files to implement the "onlyChanged" behavior via // findRelatedTests and the list of changed files findRelatedTests, - nonFlagArgs: findRelatedTests ? Array.from(host._changedFiles) : [], + nonFlagArgs: findRelatedTests ? Array.from(host.#changedFiles) : [], // This property can only be true when the files are tracked directly by Git // Since we run tests on compiled files, this is not the case. onlyChanged: false @@ -457,7 +457,7 @@ export default class JestPlugin implements IHeftTaskPlugin { return result; }); - host._resolveFirstRunQueued(); + host.#resolveFirstRunQueued(); }); }; @@ -478,22 +478,22 @@ export default class JestPlugin implements IHeftTaskPlugin { true ); if (!jestArgv) { - this._jestPromise = Promise.resolve(); + this.#jestPromise = Promise.resolve(); return; } - this._jestPromise = runCLI(jestArgv, [buildFolderPath]); + this.#jestPromise = runCLI(jestArgv, [buildFolderPath]); } // Wait for the initial run to be queued. - await this._firstRunQueuedPromise; + await this.#firstRunQueuedPromise; // Explicitly wait an async tick for any file watchers await Promise.resolve(); if (pendingTestRuns.size > 0) { this._setNodeEnvIfRequested(options, logger); - this._executing = true; + this.#executing = true; for (const pendingTestRun of pendingTestRuns) { pendingTestRuns.delete(pendingTestRun); const jestResults: AggregatedResult | undefined = await pendingTestRun(); @@ -524,9 +524,9 @@ export default class JestPlugin implements IHeftTaskPlugin { // If we ran tests and they succeeded, consider the files to no longer be changed. // This might be overly-permissive, but there isn't a great way to identify if the changes // are no longer relevant, unfortunately. - this._changedFiles.clear(); + this.#changedFiles.clear(); } - this._executing = false; + this.#executing = false; } else { terminal.writeLine(`No pending test runs.`); } @@ -807,14 +807,14 @@ export default class JestPlugin implements IHeftTaskPlugin { } } else { process.env.NODE_ENV = 'test'; - this._nodeEnvSet = true; + this.#nodeEnvSet = true; } } } private _resetNodeEnv(): void { // unset the NODE_ENV only if we have set it - if (this._nodeEnvSet) { + if (this.#nodeEnvSet) { delete process.env.NODE_ENV; } } diff --git a/heft-plugins/heft-jest-plugin/src/TerminalWritableStream.ts b/heft-plugins/heft-jest-plugin/src/TerminalWritableStream.ts index 285bd520478..75acf1f6040 100644 --- a/heft-plugins/heft-jest-plugin/src/TerminalWritableStream.ts +++ b/heft-plugins/heft-jest-plugin/src/TerminalWritableStream.ts @@ -12,7 +12,7 @@ import type { ITerminal } from '@rushstack/terminal'; const FILTER_REGEX: RegExp = /\x1B\[2J\x1B\[0f|\x1B\[2J\x1B\[3J\x1B\[H/g; export class TerminalWritableStream extends Writable { - private readonly _terminal: ITerminal; + readonly #terminal: ITerminal; public constructor(terminal: ITerminal) { super({ @@ -21,14 +21,14 @@ export class TerminalWritableStream extends Writable { defaultEncoding: 'utf-8' }); - this._terminal = terminal; + this.#terminal = terminal; } // eslint-disable-next-line @typescript-eslint/no-explicit-any public _write(chunk: any, encoding: string, callback: (error?: Error | undefined) => void): void { const stringified: string = typeof chunk === 'string' ? chunk : chunk.toString(encoding); const filtered: string = stringified.replace(FILTER_REGEX, ''); - this._terminal.write(filtered); + this.#terminal.write(filtered); callback(); } } diff --git a/heft-plugins/heft-lint-plugin/src/Eslint.ts b/heft-plugins/heft-lint-plugin/src/Eslint.ts index aea83cbee8d..e767a174921 100644 --- a/heft-plugins/heft-lint-plugin/src/Eslint.ts +++ b/heft-plugins/heft-lint-plugin/src/Eslint.ts @@ -83,18 +83,18 @@ const ESLINT_LEGACY_CONFIG_FILENAMES: Set = new Set([ ]); export class Eslint extends LinterBase { - private readonly _eslintPackage: typeof TEslint | typeof TEslintLegacy; - private readonly _eslintPackageVersion: semver.SemVer; - private readonly _linter: TEslint.ESLint | TEslintLegacy.ESLint; - private readonly _eslintTimings: Map = new Map(); - private readonly _currentFixMessages: (TEslint.Linter.LintMessage | TEslintLegacy.Linter.LintMessage)[] = + readonly #eslintPackage: typeof TEslint | typeof TEslintLegacy; + readonly #eslintPackageVersion: semver.SemVer; + readonly #linter: TEslint.ESLint | TEslintLegacy.ESLint; + readonly #eslintTimings: Map = new Map(); + readonly #currentFixMessages: (TEslint.Linter.LintMessage | TEslintLegacy.Linter.LintMessage)[] = []; - private readonly _fixMessagesByResult: Map< + readonly #fixMessagesByResult: Map< TEslint.ESLint.LintResult | TEslintLegacy.ESLint.LintResult, (TEslint.Linter.LintMessage | TEslintLegacy.Linter.LintMessage)[] > = new Map(); - private readonly _sarifLogPath: string | undefined; - private readonly _configHashMap: WeakMap = new WeakMap(); + readonly #sarifLogPath: string | undefined; + readonly #configHashMap: WeakMap = new WeakMap(); protected constructor(options: IEslintOptions) { super('eslint', options); @@ -108,16 +108,16 @@ export class Eslint extends LinterBase= 9 && + this.#eslintPackageVersion.major >= 9 && ESLINT_LEGACY_CONFIG_FILENAMES.has(linterConfigFileName) ) { throw new Error( @@ -127,7 +127,7 @@ export class Eslint extends LinterBase; @@ -137,10 +137,10 @@ export class Eslint extends LinterBase { - this._currentFixMessages.push(message); + this.#currentFixMessages.push(message); return true; }; - } else if (this._eslintPackageVersion.major <= 8) { + } else if (this.#eslintPackageVersion.major <= 8) { // The @typescript-eslint/parser package allows providing an existing TypeScript program to avoid needing // to reparse. However, fixers in ESLint run in multiple passes against the underlying code until the // fix fully succeeds. This conflicts with providing an existing program as the code no longer maps to @@ -161,7 +161,7 @@ export class Eslint extends LinterBase { - return `${this._eslintPackageVersion.version}_${process.version}`; + return `${this.#eslintPackageVersion.version}_${process.version}`; } protected override async getSourceFileHashAsync(sourceFile: IExtendedSourceFile): Promise { - const sourceFileEslintConfiguration: TEslint.Linter.Config = await this._linter.calculateConfigForFile( + const sourceFileEslintConfiguration: TEslint.Linter.Config = await this.#linter.calculateConfigForFile( sourceFile.fileName ); @@ -275,15 +275,15 @@ export class Eslint extends LinterBase { const lintResults: TEslint.ESLint.LintResult[] | TEslintLegacy.ESLint.LintResult[] = - await this._linter.lintText(sourceFile.text, { filePath: sourceFile.fileName }); + await this.#linter.lintText(sourceFile.text, { filePath: sourceFile.fileName }); // Map the fix messages to the results. This API should only return one result per file, so we can be sure // that the fix messages belong to the returned result. If we somehow receive multiple results, we will // drop the messages on the floor, but since they are only used for logging, this should not be a problem. const fixMessages: (TEslint.Linter.LintMessage | TEslintLegacy.Linter.LintMessage)[] = - this._currentFixMessages.splice(0); + this.#currentFixMessages.splice(0); if (lintResults.length === 1) { - this._fixMessagesByResult.set(lintResults[0], fixMessages); + this.#fixMessagesByResult.set(lintResults[0], fixMessages); } this._fixesPossible ||= @@ -297,7 +297,7 @@ export class Eslint extends LinterBase { let omittedRuleCount: number = 0; - const timings: [string, number][] = Array.from(this._eslintTimings).sort( + const timings: [string, number][] = Array.from(this.#eslintTimings).sort( (x: [string, number], y: [string, number]) => { return y[1] - x[1]; } @@ -314,14 +314,14 @@ export class Eslint extends LinterBase 0) { - await this._eslintPackage.ESLint.outputFixes(lintResults); + if (this._fix && this.#fixMessagesByResult.size > 0) { + await this.#eslintPackage.ESLint.outputFixes(lintResults); } for (const lintResult of lintResults) { // Report linter fixes to the logger. These will only be returned when the underlying failure was fixed const fixMessages: TEslint.Linter.LintMessage[] | TEslintLegacy.Linter.LintMessage[] | undefined = - this._fixMessagesByResult.get(lintResult); + this.#fixMessagesByResult.get(lintResult); if (fixMessages) { for (const fixMessage of fixMessages) { const formattedMessage: string = `[FIXED] ${getFormattedErrorMessage(fixMessage)}`; @@ -347,15 +347,15 @@ export class Eslint extends LinterBase { - return await this._linter.isPathIgnored(filePath); + return await this.#linter.isPathIgnored(filePath); } protected override hasLintFailures( diff --git a/heft-plugins/heft-lint-plugin/src/LintPlugin.ts b/heft-plugins/heft-lint-plugin/src/LintPlugin.ts index 74a4e384d97..07ce96eb861 100644 --- a/heft-plugins/heft-lint-plugin/src/LintPlugin.ts +++ b/heft-plugins/heft-lint-plugin/src/LintPlugin.ts @@ -70,11 +70,11 @@ function getSarifLogPath( export default class LintPlugin implements IHeftTaskPlugin { // These are initliazed by _initAsync - private _initPromise!: Promise; - private _eslintToolPath: string | undefined; - private _eslintConfigFilePath: string | undefined; - private _tslintToolPath: string | undefined; - private _tslintConfigFilePath: string | undefined; + #initPromise!: Promise; + #eslintToolPath: string | undefined; + #eslintConfigFilePath: string | undefined; + #tslintToolPath: string | undefined; + #tslintConfigFilePath: string | undefined; public apply( taskSession: IHeftTaskSession, @@ -192,27 +192,27 @@ export default class LintPlugin implements IHeftTaskPlugin { heftConfiguration: HeftConfiguration ): Promise { // Make sure that we only ever init once by memoizing the init promise - if (!this._initPromise) { - this._initPromise = this._initInnerAsync(heftConfiguration, taskSession.logger); + if (!this.#initPromise) { + this.#initPromise = this._initInnerAsync(heftConfiguration, taskSession.logger); } - await this._initPromise; + await this.#initPromise; } private async _initInnerAsync(heftConfiguration: HeftConfiguration, logger: IScopedLogger): Promise { // Locate the tslint linter if enabled - this._tslintConfigFilePath = await Tslint.resolveTslintConfigFilePathAsync(heftConfiguration); - if (this._tslintConfigFilePath) { - this._tslintToolPath = await heftConfiguration.rigPackageResolver.resolvePackageAsync( + this.#tslintConfigFilePath = await Tslint.resolveTslintConfigFilePathAsync(heftConfiguration); + if (this.#tslintConfigFilePath) { + this.#tslintToolPath = await heftConfiguration.rigPackageResolver.resolvePackageAsync( 'tslint', logger.terminal ); } // Locate the eslint linter if enabled - this._eslintConfigFilePath = await Eslint.resolveEslintConfigFilePathAsync(heftConfiguration); - if (this._eslintConfigFilePath) { - logger.terminal.writeVerboseLine(`ESLint config file path: ${this._eslintConfigFilePath}`); - this._eslintToolPath = await heftConfiguration.rigPackageResolver.resolvePackageAsync( + this.#eslintConfigFilePath = await Eslint.resolveEslintConfigFilePathAsync(heftConfiguration); + if (this.#eslintConfigFilePath) { + logger.terminal.writeVerboseLine(`ESLint config file path: ${this.#eslintConfigFilePath}`); + this.#eslintToolPath = await heftConfiguration.rigPackageResolver.resolvePackageAsync( 'eslint', logger.terminal ); @@ -229,27 +229,27 @@ export default class LintPlugin implements IHeftTaskPlugin { await this._ensureInitializedAsync(taskSession, heftConfiguration); const linters: LinterBase[] = []; - if (this._eslintConfigFilePath && this._eslintToolPath) { + if (this.#eslintConfigFilePath && this.#eslintToolPath) { const eslintLinter: Eslint = await Eslint.initializeAsync({ tsProgram, fix, sarifLogPath, scopedLogger: taskSession.logger, - linterToolPath: this._eslintToolPath, - linterConfigFilePath: this._eslintConfigFilePath, + linterToolPath: this.#eslintToolPath, + linterConfigFilePath: this.#eslintConfigFilePath, buildFolderPath: heftConfiguration.buildFolderPath, buildMetadataFolderPath: taskSession.tempFolderPath }); linters.push(eslintLinter); } - if (this._tslintConfigFilePath && this._tslintToolPath) { + if (this.#tslintConfigFilePath && this.#tslintToolPath) { const tslintLinter: Tslint = await Tslint.initializeAsync({ tsProgram, fix, scopedLogger: taskSession.logger, - linterToolPath: this._tslintToolPath, - linterConfigFilePath: this._tslintConfigFilePath, + linterToolPath: this.#tslintToolPath, + linterConfigFilePath: this.#tslintConfigFilePath, buildFolderPath: heftConfiguration.buildFolderPath, buildMetadataFolderPath: taskSession.tempFolderPath }); diff --git a/heft-plugins/heft-lint-plugin/src/LinterBase.ts b/heft-plugins/heft-lint-plugin/src/LinterBase.ts index f6c473754c7..6e3404e5433 100644 --- a/heft-plugins/heft-lint-plugin/src/LinterBase.ts +++ b/heft-plugins/heft-lint-plugin/src/LinterBase.ts @@ -71,7 +71,7 @@ export abstract class LinterBase { protected _fixesPossible: boolean = false; - private readonly _linterName: string; + readonly #linterName: string; protected constructor(linterName: string, options: ILinterBaseOptions) { this._scopedLogger = options.scopedLogger; @@ -79,7 +79,7 @@ export abstract class LinterBase { this._buildFolderPath = options.buildFolderPath; this._buildMetadataFolderPath = options.buildMetadataFolderPath; this._linterConfigFilePath = options.linterConfigFilePath; - this._linterName = linterName; + this.#linterName = linterName; this._fix = options.fix || false; } @@ -131,7 +131,7 @@ export abstract class LinterBase { const linterCacheVersion: string = await this.getCacheVersionAsync(); const linterCacheFilePath: string = path.resolve( this._buildMetadataFolderPath, - `_${this._linterName}-${hashSuffix}.json` + `_${this.#linterName}-${hashSuffix}.json` ); let linterCacheData: ILinterCacheData | undefined; diff --git a/heft-plugins/heft-lint-plugin/src/Tslint.ts b/heft-plugins/heft-lint-plugin/src/Tslint.ts index 52a15677ad7..77025ac9ad0 100644 --- a/heft-plugins/heft-lint-plugin/src/Tslint.ts +++ b/heft-plugins/heft-lint-plugin/src/Tslint.ts @@ -26,32 +26,32 @@ function getFormattedErrorMessage(tslintFailure: TTslint.RuleFailure): string { const TSLINT_CONFIG_FILE_NAME: string = 'tslint.json'; export class Tslint extends LinterBase { - private readonly _tslintPackage: typeof TTslint; - private readonly _tslintConfiguration: TTslint.Configuration.IConfigurationFile; - private readonly _linter: IExtendedLinter; - private readonly _enabledRules: TTslint.IRule[]; - private readonly _ruleSeverityMap: Map; + readonly #tslintPackage: typeof TTslint; + readonly #tslintConfiguration: TTslint.Configuration.IConfigurationFile; + readonly #linter: IExtendedLinter; + readonly #enabledRules: TTslint.IRule[]; + readonly #ruleSeverityMap: Map; public constructor(options: ITslintOptions) { super('tslint', options); const { tslintPackage, tsProgram } = options; - this._tslintPackage = tslintPackage; - this._tslintConfiguration = options.tslintConfiguration; - this._linter = new tslintPackage.Linter( + this.#tslintPackage = tslintPackage; + this.#tslintConfiguration = options.tslintConfiguration; + this.#linter = new tslintPackage.Linter( { // This is not handled by the linter in the way that we use it, so we will manually apply // fixes later fix: false, - rulesDirectory: this._tslintConfiguration.rulesDirectory + rulesDirectory: this.#tslintConfiguration.rulesDirectory }, tsProgram ) as unknown as IExtendedLinter; - this._enabledRules = this._linter.getEnabledRules(this._tslintConfiguration, false); + this.#enabledRules = this.#linter.getEnabledRules(this.#tslintConfiguration, false); - this._ruleSeverityMap = new Map( - this._enabledRules.map((rule): [string, TTslint.RuleSeverity] => [ + this.#ruleSeverityMap = new Map( + this.#enabledRules.map((rule): [string, TTslint.RuleSeverity] => [ rule.getOptions().ruleName, rule.getOptions().ruleSeverity ]) @@ -131,7 +131,7 @@ export class Tslint extends LinterBase { } public printVersionHeader(): void { - this._terminal.writeLine(`Using TSLint version ${this._tslintPackage.Linter.VERSION}`); + this._terminal.writeLine(`Using TSLint version ${this.#tslintPackage.Linter.VERSION}`); } protected async getCacheVersionAsync(): Promise { @@ -139,7 +139,7 @@ export class Tslint extends LinterBase { this._linterConfigFilePath, this._terminal ); - const tslintConfigVersion: string = `${this._tslintPackage.Linter.VERSION}_${tslintConfigHash.digest( + const tslintConfigVersion: string = `${this.#tslintPackage.Linter.VERSION}_${tslintConfigHash.digest( 'hex' )}`; @@ -150,18 +150,18 @@ export class Tslint extends LinterBase { // Some of this code comes from here: // https://github.com/palantir/tslint/blob/24d29e421828348f616bf761adb3892bcdf51662/src/linter.ts#L161-L179 // Modified to only lint files that have changed and that we care about - let failures: TTslint.RuleFailure[] = this._linter.getAllFailures(sourceFile, this._enabledRules); + let failures: TTslint.RuleFailure[] = this.#linter.getAllFailures(sourceFile, this.#enabledRules); const hasFixableIssue: boolean = failures.some((f) => f.hasFix()); if (hasFixableIssue) { if (this._fix) { - failures = this._linter.applyAllFixes(this._enabledRules, failures, sourceFile, sourceFile.fileName); + failures = this.#linter.applyAllFixes(this.#enabledRules, failures, sourceFile, sourceFile.fileName); } else { this._fixesPossible = true; } } for (const failure of failures) { - const severity: TTslint.RuleSeverity | undefined = this._ruleSeverityMap.get(failure.getRuleName()); + const severity: TTslint.RuleSeverity | undefined = this.#ruleSeverityMap.get(failure.getRuleName()); if (severity === undefined) { throw new Error(`Severity for rule '${failure.getRuleName()}' not found`); } @@ -173,8 +173,8 @@ export class Tslint extends LinterBase { } protected async lintingFinishedAsync(failures: TTslint.RuleFailure[]): Promise { - this._linter.failures = failures; - const lintResult: TTslint.LintResult = this._linter.getResult(); + this.#linter.failures = failures; + const lintResult: TTslint.LintResult = this.#linter.getResult(); // Report linter fixes to the logger. These will only be returned when the underlying failure was fixed if (lintResult.fixes?.length) { @@ -203,7 +203,7 @@ export class Tslint extends LinterBase { } protected async isFileExcludedAsync(filePath: string): Promise { - return this._tslintPackage.Configuration.isFileExcluded(filePath, this._tslintConfiguration); + return this.#tslintPackage.Configuration.isFileExcluded(filePath, this.#tslintConfiguration); } protected hasLintFailures(lintResults: TTslint.RuleFailure[]): boolean { diff --git a/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts b/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts index 1b7a437c21d..2649cbad420 100644 --- a/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts +++ b/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts @@ -52,8 +52,8 @@ export class DeferredWatchFileSystem implements WatchFileSystem { public readonly watcherOptions: WatchOptions; public watcher: Watchpack | undefined; - private readonly _onChange: () => void; - private _state: IWatchState | undefined; + readonly #onChange: () => void; + #state: IWatchState | undefined; public constructor(inputFileSystem: InputFileSystem, onChange: () => void) { this.inputFileSystem = inputFileSystem; @@ -61,11 +61,11 @@ export class DeferredWatchFileSystem implements WatchFileSystem { aggregateTimeout: 0 }; this.watcher = new Watchpack(this.watcherOptions); - this._onChange = onChange; + this.#onChange = onChange; } public flush(): boolean { - const state: IWatchState | undefined = this._state; + const state: IWatchState | undefined = this.#state; if (!state) { return false; @@ -121,7 +121,7 @@ export class DeferredWatchFileSystem implements WatchFileSystem { const changes: Set = new Set(); const removals: Set = new Set(); - this._state = { + this.#state = { changes, removals, @@ -138,7 +138,7 @@ export class DeferredWatchFileSystem implements WatchFileSystem { removals.add(removal); } - this._onChange(); + this.#onChange(); }); this.watcher.watch({ @@ -213,10 +213,10 @@ export class DeferredWatchFileSystem implements WatchFileSystem { export class OverrideNodeWatchFSPlugin implements RspackPluginInstance { public readonly fileSystems: Set = new Set(); - private readonly _onChange: () => void; + readonly #onChange: () => void; public constructor(onChange: () => void) { - this._onChange = onChange; + this.#onChange = onChange; } public apply(compiler: Compiler): void { @@ -227,7 +227,7 @@ export class OverrideNodeWatchFSPlugin implements RspackPluginInstance { const watchFileSystem: DeferredWatchFileSystem = new DeferredWatchFileSystem( inputFileSystem, - this._onChange + this.#onChange ); this.fileSystems.add(watchFileSystem); compiler.watchFileSystem = watchFileSystem; diff --git a/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts b/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts index 67546a3e345..877c2844e05 100644 --- a/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts +++ b/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts @@ -42,28 +42,28 @@ const WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME: 'webpack-dev-middleware' = 'webpack-d * @internal */ export default class RspackPlugin implements IHeftTaskPlugin { - private _accessor: IRspackPluginAccessor | undefined; - private _isServeMode: boolean = false; - private _rspack: RspackCoreImport | undefined; - private _rspackCompiler: TRspack.Compiler | TRspack.MultiCompiler | undefined; - private _rspackConfiguration: IRspackConfiguration | undefined | false = false; - private _rspackCompilationDonePromise: Promise | undefined; - private _rspackCompilationDonePromiseResolveFn: (() => void) | undefined; - private _watchFileSystems: Set | undefined; - - private _warnings: Error[] = []; - private _errors: Error[] = []; + #accessor: IRspackPluginAccessor | undefined; + #isServeMode: boolean = false; + #rspack: RspackCoreImport | undefined; + #rspackCompiler: TRspack.Compiler | TRspack.MultiCompiler | undefined; + #rspackConfiguration: IRspackConfiguration | undefined | false = false; + #rspackCompilationDonePromise: Promise | undefined; + #rspackCompilationDonePromiseResolveFn: (() => void) | undefined; + #watchFileSystems: Set | undefined; + + #warnings: Error[] = []; + #errors: Error[] = []; public get accessor(): IRspackPluginAccessor { - if (!this._accessor) { - this._accessor = { + if (!this.#accessor) { + this.#accessor = { hooks: _createAccessorHooks(), parameters: { - isServeMode: this._isServeMode + isServeMode: this.#isServeMode } }; } - return this._accessor; + return this.#accessor; } public apply( @@ -71,8 +71,8 @@ export default class RspackPlugin implements IHeftTaskPlugin void ): Promise { - if (this._rspackConfiguration === false) { + if (this.#rspackConfiguration === false) { const rspackConfiguration: IRspackConfiguration | undefined = await tryLoadRspackConfigurationAsync( { taskSession, heftConfiguration, hooks: this.accessor.hooks, - serveMode: this._isServeMode, + serveMode: this.#isServeMode, loadRspackAsyncFn: this._loadRspackAsync.bind(this, taskSession, heftConfiguration) }, options @@ -114,7 +114,7 @@ export default class RspackPlugin implements IHeftTaskPlugin { - if (!this._rspack) { + if (!this.#rspack) { try { const rspackPackagePath: string = await heftConfiguration.rigPackageResolver.resolvePackageAsync( RSPACK_PACKAGE_NAME, taskSession.logger.terminal ); - this._rspack = await import(rspackPackagePath); + this.#rspack = await import(rspackPackagePath); taskSession.logger.terminal.writeDebugLine(`Using Rspack from rig package at "${rspackPackagePath}"`); } catch (e) { // Fallback to bundled version if not found in rig. - this._rspack = await import(RSPACK_PACKAGE_NAME); + this.#rspack = await import(RSPACK_PACKAGE_NAME); taskSession.logger.terminal.writeDebugLine(`Using Rspack from built-in "${RSPACK_PACKAGE_NAME}"`); } } - return this._rspack!; + return this.#rspack!; } private async _getRspackCompilerAsync( @@ -158,14 +158,14 @@ export default class RspackPlugin implements IHeftTaskPlugin { - if (!this._rspackCompiler) { + if (!this.#rspackCompiler) { const rspack: RspackCoreImport = await this._loadRspackAsync(taskSession, heftConfiguration); taskSession.logger.terminal.writeLine(`Using Rspack version ${rspack.version}`); - this._rspackCompiler = Array.isArray(rspackConfiguration) + this.#rspackCompiler = Array.isArray(rspackConfiguration) ? rspack.default(rspackConfiguration) /* (rspack.Compilation[]) => MultiCompiler */ : rspack.default(rspackConfiguration); /* (rspack.Compilation) => Compiler */ } - return this._rspackCompiler; + return this.#rspackCompiler; } private async _runRspackAsync( @@ -174,7 +174,7 @@ export default class RspackPlugin implements IHeftTaskPlugin { this._validateEnvironmentVariable(taskSession); - if (taskSession.parameters.watch || this._isServeMode) { + if (taskSession.parameters.watch || this.#isServeMode) { // Should never happen, but just in case throw new InternalError('Cannot run Rspack in compilation mode when watch mode is enabled'); } @@ -224,11 +224,11 @@ export default class RspackPlugin implements IHeftTaskPlugin { // Save a handle to the original promise, since the this-scoped promise will be replaced whenever // the compilation completes. - let rspackCompilationDonePromise: Promise | undefined = this._rspackCompilationDonePromise; + let rspackCompilationDonePromise: Promise | undefined = this.#rspackCompilationDonePromise; let isInitial: boolean = false; - if (!this._rspackCompiler) { + if (!this.#rspackCompiler) { isInitial = true; this._validateEnvironmentVariable(taskSession); if (!taskSession.parameters.watch) { @@ -256,14 +256,14 @@ export default class RspackPlugin implements IHeftTaskPlugin void) => { - this._rspackCompilationDonePromiseResolveFn = resolve; + this.#rspackCompilationDonePromise = new Promise((resolve: () => void) => { + this.#rspackCompilationDonePromiseResolveFn = resolve; }); - rspackCompilationDonePromise = this._rspackCompilationDonePromise; + rspackCompilationDonePromise = this.#rspackCompilationDonePromise; compiler.hooks.done.tap(PLUGIN_NAME, (stats?: TRspack.Stats | TRspack.MultiStats) => { - this._rspackCompilationDonePromiseResolveFn!(); - this._rspackCompilationDonePromise = new Promise((resolve: () => void) => { - this._rspackCompilationDonePromiseResolveFn = resolve; + this.#rspackCompilationDonePromiseResolveFn!(); + this.#rspackCompilationDonePromise = new Promise((resolve: () => void) => { + this.#rspackCompilationDonePromiseResolveFn = resolve; }); if (stats) { @@ -273,7 +273,7 @@ export default class RspackPlugin implements IHeftTaskPlugin record - private readonly _fileInfo: Map; - private readonly _resolutions: Map; + readonly #fileInfo: Map; + readonly #resolutions: Map; - private readonly _isFileModule: (filePath: string) => boolean; - private readonly _options: ISassProcessorOptions; - private readonly _realpathSync: (path: string) => string; - private readonly _scssOptions: Options<'async'>; + readonly #isFileModule: (filePath: string) => boolean; + readonly #options: ISassProcessorOptions; + readonly #realpathSync: (path: string) => string; + readonly #scssOptions: Options<'async'>; - private _configFilePath: string | undefined; + #configFilePath: string | undefined; public constructor(options: ISassProcessorOptions) { const { silenceDeprecations, excludeFiles } = options; @@ -255,13 +255,13 @@ export class SassProcessor { this.inputFileGlob = `**/*+(${allFileExtensions.join('|')})`; this.sourceFolderPath = options.srcFolder; - this._configFilePath = undefined; - this._fileInfo = new Map(); - this._isFileModule = isFileModule; - this._resolutions = new Map(); - this._options = options; - this._realpathSync = new RealNodeModulePathResolver().realNodeModulePath; - this._scssOptions = { + this.#configFilePath = undefined; + this.#fileInfo = new Map(); + this.#isFileModule = isFileModule; + this.#resolutions = new Map(); + this.#options = options; + this.#realpathSync = new RealNodeModulePathResolver().realNodeModulePath; + this.#scssOptions = { style: 'expanded', // leave minification to clean-css importers: [ { @@ -276,23 +276,23 @@ export class SassProcessor { } public async loadCacheAsync(tempFolderPath: string): Promise { - const configHash: string = getContentsHash('sass.json', JSON.stringify(this._options)).slice(0, 8); + const configHash: string = getContentsHash('sass.json', JSON.stringify(this.#options)).slice(0, 8); - this._configFilePath = path.join(tempFolderPath, `sass_${configHash}.json`); + this.#configFilePath = path.join(tempFolderPath, `sass_${configHash}.json`); try { - const serializedConfig: string = await FileSystem.readFileAsync(this._configFilePath); + const serializedConfig: string = await FileSystem.readFileAsync(this.#configFilePath); this._cache = serializedConfig; } catch (err) { if (!FileSystem.isNotExistError(err)) { - this._options.logger.terminal.writeVerboseLine(`Error reading cache file: ${err}`); + this.#options.logger.terminal.writeVerboseLine(`Error reading cache file: ${err}`); } } } public async compileFilesAsync(filepaths: Set): Promise { // Incremental resolve is complicated, so just clear it for now - this._resolutions.clear(); + this.#resolutions.clear(); // Expand affected files using dependency graph // If this is the initial compilation, the graph will be empty, so this will no-op' @@ -306,7 +306,7 @@ export class SassProcessor { const { concurrency, logger: { terminal } - } = this._options; + } = this.#options; terminal.writeVerboseLine(`Checking for changes to ${filepaths.size} files...`); for (const record of affectedRecords) { @@ -367,9 +367,9 @@ export class SassProcessor { affectedRecords, async (record, i) => { try { - await this._compileFileAsync(compilers[i % compilerCount], record, this._scssOptions); + await this._compileFileAsync(compilers[i % compilerCount], record, this.#scssOptions); } catch (err) { - this._options.logger.emitError(err); + this.#options.logger.emitError(err); } }, { @@ -383,7 +383,7 @@ export class SassProcessor { // Find all newly-referenced files and update the incremental build state data. const newRecords: Set = new Set(); - for (const record of this._fileInfo.values()) { + for (const record of this.#fileInfo.values()) { if (!record.version) { newRecords.add(record); } @@ -403,10 +403,10 @@ export class SassProcessor { } ); - if (this._configFilePath) { + if (this.#configFilePath) { const serializedConfig: string = this._cache; try { - await FileSystem.writeFileAsync(this._configFilePath, serializedConfig, { + await FileSystem.writeFileAsync(this.#configFilePath, serializedConfig, { ensureFolderExists: true }); } catch (err) { @@ -424,10 +424,10 @@ export class SassProcessor { private async _canonicalizeFileAsync(url: string, context: CanonicalizeContext): AsyncResolution { // The logic between `this._resolutions.get()` and `this._resolutions.set()` must be 100% synchronous // Otherwise we could end up with multiple promises for the same URL - let resolution: SyncOrAsyncResolution | undefined = this._resolutions.get(url); + let resolution: SyncOrAsyncResolution | undefined = this.#resolutions.get(url); if (resolution === undefined) { resolution = this._canonicalizeFileInnerAsync(url, context); - this._resolutions.set(url, resolution); + this.#resolutions.set(url, resolution); } return await resolution; } @@ -484,12 +484,12 @@ export class SassProcessor { const cacheKey: string = `${containingUrl.href}\0${url}`; // The logic between `this._resolutions.get()` and `this._resolutions.set()` must be 100% synchronous // Otherwise we could end up with multiple promises for the same URL - let resolution: SyncOrAsyncResolution | undefined = this._resolutions.get(cacheKey); + let resolution: SyncOrAsyncResolution | undefined = this.#resolutions.get(cacheKey); if (resolution === undefined) { // Since the cache doesn't have an entry, get the promise for the resolution // and inject it into the cache before other callers have a chance to try resolution = this._canonicalizePackageInnerAsync(url, context); - this._resolutions.set(cacheKey, resolution); + this.#resolutions.set(cacheKey, resolution); } return await resolution; } @@ -522,7 +522,7 @@ export class SassProcessor { const resolvedPackagePath: string = await Import.resolvePackageAsync({ packageName, baseFolderPath, - getRealPath: this._realpathSync + getRealPath: this.#realpathSync }); const modulePath: string = nodeModulesQuery.slice(linkEnd); const resolvedPath: string = `${resolvedPackagePath}${modulePath}`; @@ -538,12 +538,12 @@ export class SassProcessor { */ private async _canonicalizeHeftUrlAsync(url: string, context: CanonicalizeContext): AsyncResolution { // The logic between `this._resolutions.get()` and `this._resolutions.set()` must be 100% synchronous - let resolution: SyncOrAsyncResolution | undefined = this._resolutions.get(url); + let resolution: SyncOrAsyncResolution | undefined = this.#resolutions.get(url); if (resolution === undefined) { // Since the cache doesn't have an entry, get the promise for the resolution // and inject it into the cache before other callers have a chance to try resolution = this._canonicalizeHeftInnerAsync(url, context); - this._resolutions.set(url, resolution); + this.#resolutions.set(url, resolution); } return await resolution; @@ -611,7 +611,7 @@ export class SassProcessor { } private get _cache(): string { - const serializedRecords: ISerializedFileRecord[] = Array.from(this._fileInfo.values(), (record) => { + const serializedRecords: ISerializedFileRecord[] = Array.from(this.#fileInfo.values(), (record) => { return { relativePath: record.relativePath, version: record.version, @@ -628,11 +628,11 @@ export class SassProcessor { * @param cacheFileContent - The contents of the cache file */ private set _cache(cacheFileContent: string) { - this._fileInfo.clear(); + this.#fileInfo.clear(); const serializedRecords: ISerializedFileRecord[] = JSON.parse(cacheFileContent); const records: IFileRecord[] = []; - const buildFolder: string = this._options.buildFolder; + const buildFolder: string = this.#options.buildFolder; for (const record of serializedRecords) { const { relativePath, version, cssVersion } = record; // relativePath may start with `../` or similar, so need to use a library join function. @@ -641,7 +641,7 @@ export class SassProcessor { const isPartial: boolean = isSassPartial(absolutePath); // SCSS partials are not modules, insofar as they cannot be imported directly. - const isModule: boolean = isPartial ? false : this._isFileModule(absolutePath); + const isModule: boolean = isPartial ? false : this.#isFileModule(absolutePath); const fileRecord: IFileRecord = { absolutePath, @@ -657,8 +657,8 @@ export class SassProcessor { dependencies: new Set() }; records.push(fileRecord); - this._fileInfo.set(absolutePath, fileRecord); - this._resolutions.set(absolutePath, url); + this.#fileInfo.set(absolutePath, fileRecord); + this.#resolutions.set(absolutePath, url); } for (let i: number = 0, len: number = serializedRecords.length; i < len; i++) { @@ -701,26 +701,26 @@ export class SassProcessor { */ private _getOrCreateRecord(filePath: string): IFileRecord { filePath = path.resolve(filePath); - let record: IFileRecord | undefined = this._fileInfo.get(filePath); + let record: IFileRecord | undefined = this.#fileInfo.get(filePath); if (!record) { const isPartial: boolean = isSassPartial(filePath); - const isModule: boolean = isPartial ? false : this._isFileModule(filePath); + const isModule: boolean = isPartial ? false : this.#isFileModule(filePath); const url: URL = pathToHeftUrl(filePath); record = { absolutePath: filePath, url, isPartial, isModule, - index: this._fileInfo.size, - relativePath: Path.convertToSlashes(path.relative(this._options.buildFolder, filePath)), + index: this.#fileInfo.size, + relativePath: Path.convertToSlashes(path.relative(this.#options.buildFolder, filePath)), version: '', content: undefined, cssVersion: undefined, consumers: new Set(), dependencies: new Set() }; - this._resolutions.set(filePath, record.url); - this._fileInfo.set(filePath, record); + this.#resolutions.set(filePath, record.url); + this.#fileInfo.set(filePath, record); } return record; } @@ -751,7 +751,7 @@ export class SassProcessor { absolutePath: span.url ? heftUrlToPath(span.url.href ?? span.url) : 'unknown', // This property should always be present line: span.start.line, column: span.start.column, - projectFolder: this._options.buildFolder + projectFolder: this.#options.buildFolder }); } @@ -781,7 +781,7 @@ export class SassProcessor { postProcessCssAsync, preserveIcssExports, sourceMap - } = this._options; + } = this.#options; // Handle CSS modules let moduleMap: JsonObject | undefined; diff --git a/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts b/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts index 3dd5368e47a..cb8fdf9e581 100644 --- a/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts +++ b/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts @@ -30,10 +30,10 @@ const WEBPACK5_PLUGIN_NAME: typeof Webpack5PluginName = 'webpack5-plugin'; const SST_CLI_PACKAGE_NAME: string = '@serverless-stack/cli'; export default class ServerlessStackPlugin implements IHeftTaskPlugin { - private _logger!: IScopedLogger; + #logger!: IScopedLogger; public apply(taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration): void { - this._logger = taskSession.logger; + this.#logger = taskSession.logger; // Once https://github.com/serverless-stack/serverless-stack/issues/1537 is fixed, we may be // eliminate the need for this parameter. @@ -44,7 +44,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { // Only tap if the --sst flag is set. if (sstParameter.value) { const configureWebpackTap: () => Promise = async () => { - this._logger.terminal.writeLine( + this.#logger.terminal.writeLine( 'The command line includes "--sst", redirecting Webpack to Serverless Stack' ); return false; @@ -89,7 +89,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { useNodeJSResolver: true }); } catch (e) { - this._logger.emitError( + this.#logger.emitError( new Error( `The ${options.taskSession.taskName} task cannot start because your project does not seem to have ` + `a dependency on the "${SST_CLI_PACKAGE_NAME}" package: ` + @@ -101,7 +101,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { const sstCliEntryPoint: string = this._getSstCliEntryPoint(sstCliPackagePath); - this._logger.terminal.writeVerboseLine('Found SST package in' + sstCliPackagePath); + this.#logger.terminal.writeVerboseLine('Found SST package in' + sstCliPackagePath); const sstCommandArgs: string[] = []; sstCommandArgs.push(sstCliEntryPoint); @@ -119,7 +119,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { sstCommandArgs.push(options.sstStage); } - this._logger.terminal.writeVerboseLine('Launching child process: ' + JSON.stringify(sstCommandArgs)); + this.#logger.terminal.writeVerboseLine('Launching child process: ' + JSON.stringify(sstCommandArgs)); const sstCommandEnv: NodeJS.ProcessEnv = this._getWorkaroundEnvironment(sstCliPackagePath); @@ -145,20 +145,20 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { }); sstCommandResult.stdout?.on('data', (chunk: Buffer) => { - this._writeOutput(chunk.toString(), (x) => this._logger.terminal.write(x)); + this._writeOutput(chunk.toString(), (x) => this.#logger.terminal.write(x)); }); sstCommandResult.stderr?.on('data', (chunk: Buffer) => { - this._writeOutput(chunk.toString(), (x) => this._logger.terminal.writeError(x)); + this._writeOutput(chunk.toString(), (x) => this.#logger.terminal.writeError(x)); }); sstCommandResult.on('exit', (code: number | null) => { if (options.serveMode) { // The child process is not supposed to terminate in watch mode - this._logger.terminal.writeErrorLine(`SST process terminated with exit code ${code}`); + this.#logger.terminal.writeErrorLine(`SST process terminated with exit code ${code}`); // TODO: Provide a Heft facility for this process.exit(1); } else { - this._logger.terminal.writeVerboseLine(`SST process terminated with exit code ${code}`); + this.#logger.terminal.writeVerboseLine(`SST process terminated with exit code ${code}`); if (!code) { completionResolve(); } else { diff --git a/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts b/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts index b819d050c3b..5958c3e2eca 100644 --- a/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts +++ b/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts @@ -131,33 +131,33 @@ interface ITypeScriptTool extends IBaseTypeScriptTool { } export class TypeScriptBuilder { - private readonly _configuration: ITypeScriptBuilderConfiguration; - private readonly _typescriptLogger: IScopedLogger; - private readonly _typescriptTerminal: ITerminal; + readonly #configuration: ITypeScriptBuilderConfiguration; + readonly #typescriptLogger: IScopedLogger; + readonly #typescriptTerminal: ITerminal; - private _useSolutionBuilder!: boolean; + #useSolutionBuilder!: boolean; - private _moduleKindsToEmit!: ICachedEmitModuleKind[]; - private readonly _suppressedDiagnosticCodes: Set = new Set(); + #moduleKindsToEmit!: ICachedEmitModuleKind[]; + readonly #suppressedDiagnosticCodes: Set = new Set(); - private __tsCacheFilePath: string | undefined; + #_tsCacheFilePath: string | undefined; - private _tool: ITypeScriptTool | undefined = undefined; + #tool: ITypeScriptTool | undefined = undefined; - private _nextRequestId: number = 0; + #nextRequestId: number = 0; private get _tsCacheFilePath(): string { - if (!this.__tsCacheFilePath) { + if (!this.#_tsCacheFilePath) { // TypeScript internally handles if the tsconfig options have changed from when the tsbuildinfo file was created. // We only need to hash our additional Heft configuration. const configHash: crypto.Hash = crypto.createHash('sha1'); // Relativize the outFolderName paths before hashing to ensure portability across different machines const normalizedConfig: IEmitModuleKind[] = - this._configuration.additionalModuleKindsToEmit?.map((emitKind) => ({ + this.#configuration.additionalModuleKindsToEmit?.map((emitKind) => ({ ...emitKind, outFolderName: Path.convertToSlashes( - path.relative(this._configuration.buildFolderPath, emitKind.outFolderName) + path.relative(this.#configuration.buildFolderPath, emitKind.outFolderName) ) })) || []; @@ -168,31 +168,31 @@ export class TypeScriptBuilder { // using only '/' as the directory separator so that incremental builds don't break on Windows. // TypeScript will normalize to '/' when serializing, but not on the direct input, and uses exact string equality. const normalizedCacheFolderPath: string = Path.convertToSlashes( - this._configuration.buildMetadataFolderPath + this.#configuration.buildMetadataFolderPath ); - this.__tsCacheFilePath = `${normalizedCacheFolderPath}/ts_${serializedConfigHash}.json`; + this.#_tsCacheFilePath = `${normalizedCacheFolderPath}/ts_${serializedConfigHash}.json`; } - return this.__tsCacheFilePath; + return this.#_tsCacheFilePath; } public constructor(configuration: ITypeScriptBuilderConfiguration) { - this._configuration = configuration; - this._typescriptLogger = configuration.scopedLogger; - this._typescriptTerminal = configuration.scopedLogger.terminal; + this.#configuration = configuration; + this.#typescriptLogger = configuration.scopedLogger; + this.#typescriptTerminal = configuration.scopedLogger.terminal; } public async invokeAsync(onChangeDetected?: () => void): Promise { - if (!this._tool) { + if (!this.#tool) { const { tool: { ts, system: baseSystem, typeScriptToolPath } } = await loadTypeScriptToolAsync({ - terminal: this._typescriptTerminal, - heftConfiguration: this._configuration.heftConfiguration, - buildProjectReferences: this._configuration.buildProjectReferences, - onlyResolveSymlinksInNodeModules: this._configuration.onlyResolveSymlinksInNodeModules + terminal: this.#typescriptTerminal, + heftConfiguration: this.#configuration.heftConfiguration, + buildProjectReferences: this.#configuration.buildProjectReferences, + onlyResolveSymlinksInNodeModules: this.#configuration.onlyResolveSymlinksInNodeModules }); - this._useSolutionBuilder = !!this._configuration.buildProjectReferences; + this.#useSolutionBuilder = !!this.#configuration.buildProjectReferences; ts.performance.enable(); @@ -204,7 +204,7 @@ export class TypeScriptBuilder { ]; for (const code of suppressedCodes) { if (code !== undefined) { - this._suppressedDiagnosticCodes.add(code); + this.#suppressedDiagnosticCodes.add(code); } } @@ -225,7 +225,7 @@ export class TypeScriptBuilder { }; }; - this._typescriptTerminal.writeLine(`Using TypeScript version ${ts.version}`); + this.#typescriptTerminal.writeLine(`Using TypeScript version ${ts.version}`); const rawDiagnostics: TTypescript.Diagnostic[] = []; @@ -244,13 +244,13 @@ export class TypeScriptBuilder { fn(...args); }; pendingOperations.add(timeout); - if (!this._tool?.executing && onChangeDetected) { + if (!this.#tool?.executing && onChangeDetected) { onChangeDetected(); } return timeout; }; - const getCurrentDirectory: () => string = () => this._configuration.buildFolderPath; + const getCurrentDirectory: () => string = () => this.#configuration.buildFolderPath; // Need to also update watchFile and watchDirectory const system: ITypeScriptNodeSystem = { @@ -279,7 +279,7 @@ export class TypeScriptBuilder { }; } - this._tool = { + this.#tool = { typeScriptToolPath, ts, system, @@ -308,17 +308,17 @@ export class TypeScriptBuilder { }; } - const { performance } = this._tool.ts; + const { performance } = this.#tool.ts; // Reset the performance counters to 0 to avoid contamination from previous runs performance.disable(); performance.enable(); if (onChangeDetected !== undefined) { - await this._runWatchAsync(this._tool); - } else if (this._useSolutionBuilder) { - await this._runSolutionBuildAsync(this._tool); + await this._runWatchAsync(this.#tool); + } else if (this.#useSolutionBuilder) { + await this._runSolutionBuildAsync(this.#tool); } else { - await this._runBuildAsync(this._tool); + await this._runBuildAsync(this.#tool); } } @@ -336,7 +336,7 @@ export class TypeScriptBuilder { const { duration: configureDurationMs, tsconfig } = measureTsPerformance('Configure', () => { const _tsconfig: TTypescript.ParsedCommandLine = loadTsconfig({ tool, - tsconfigPath: this._configuration.tsconfigPath, + tsconfigPath: this.#configuration.tsconfigPath, tsCacheFilePath: this._tsCacheFilePath }); this._validateTsconfig(ts, _tsconfig); @@ -345,13 +345,13 @@ export class TypeScriptBuilder { tsconfig: _tsconfig }; }); - this._typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`); + this.#typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`); //#endregion - if (this._useSolutionBuilder) { + if (this.#useSolutionBuilder) { const solutionHost: TWatchSolutionHost = this._buildWatchSolutionBuilderHost(tool); const builder: TTypescript.SolutionBuilder = - ts.createSolutionBuilderWithWatch(solutionHost, [this._configuration.tsconfigPath], {}); + ts.createSolutionBuilderWithWatch(solutionHost, [this.#configuration.tsconfigPath], {}); tool.solutionBuilder = builder as IExtendedSolutionBuilder; @@ -380,7 +380,7 @@ export class TypeScriptBuilder { // eslint-disable-next-line require-atomic-updates tool.executing = false; } - this._logDiagnostics(ts, rawDiagnostics, this._useSolutionBuilder); + this._logDiagnostics(ts, rawDiagnostics, this.#useSolutionBuilder); } public async _runBuildAsync(tool: ITypeScriptTool): Promise { @@ -394,7 +394,7 @@ export class TypeScriptBuilder { } = measureTsPerformance('Configure', () => { const _tsconfig: TTypescript.ParsedCommandLine = loadTsconfig({ tool, - tsconfigPath: this._configuration.tsconfigPath, + tsconfigPath: this.#configuration.tsconfigPath, tsCacheFilePath: this._tsCacheFilePath }); this._validateTsconfig(ts, _tsconfig); @@ -406,7 +406,7 @@ export class TypeScriptBuilder { compilerHost: _compilerHost }; }); - this._typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`); + this.#typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`); //#endregion //#region PROGRAM @@ -415,7 +415,7 @@ export class TypeScriptBuilder { let innerProgram: TTypescript.Program; const isolatedModules: boolean = - !!this._configuration.useTranspilerWorker && !!tsconfig.options.isolatedModules; + !!this.#configuration.useTranspilerWorker && !!tsconfig.options.isolatedModules; const mode: 'both' | 'declaration' = isolatedModules ? 'declaration' : 'both'; let filesToTranspile: Map | undefined; @@ -472,11 +472,11 @@ export class TypeScriptBuilder { return { diagnostics: rawDiagnostics }; } ); - this._typescriptTerminal.writeVerboseLine(`Analyze: ${diagnosticsDurationMs}ms`); + this.#typescriptTerminal.writeVerboseLine(`Analyze: ${diagnosticsDurationMs}ms`); //#endregion //#region EMIT - const { changedFiles } = configureProgramForMultiEmit(innerProgram, ts, this._moduleKindsToEmit, mode); + const { changedFiles } = configureProgramForMultiEmit(innerProgram, ts, this.#moduleKindsToEmit, mode); const emitResult: TTypescript.EmitResult = genericProgram.emit( undefined, @@ -498,7 +498,7 @@ export class TypeScriptBuilder { const rawDiagnostics: TTypescript.Diagnostic[] = [...preDiagnostics, ...emitResult.diagnostics]; //#endregion - this._configuration.emitChangedFilesCallback(innerProgram, changedFiles); + this.#configuration.emitChangedFilesCallback(innerProgram, changedFiles); if (pendingTranspilePromises.size) { const emitResults: TTypescript.EmitResult[] = await Promise.all(pendingTranspilePromises.values()); @@ -516,7 +516,7 @@ export class TypeScriptBuilder { } public async _runSolutionBuildAsync(tool: ITypeScriptTool): Promise { - this._typescriptTerminal.writeVerboseLine(`Using solution mode`); + this.#typescriptTerminal.writeVerboseLine(`Using solution mode`); const { ts, measureSync, rawDiagnostics, pendingTranspilePromises } = tool; rawDiagnostics.length = 0; @@ -526,7 +526,7 @@ export class TypeScriptBuilder { const { duration: configureDurationMs, solutionBuilderHost } = measureSync('Configure', () => { const _tsconfig: TTypescript.ParsedCommandLine = loadTsconfig({ tool, - tsconfigPath: this._configuration.tsconfigPath, + tsconfigPath: this.#configuration.tsconfigPath, tsCacheFilePath: this._tsCacheFilePath }); this._validateTsconfig(ts, _tsconfig); @@ -537,12 +537,12 @@ export class TypeScriptBuilder { solutionBuilderHost: _solutionBuilderHost }; }); - this._typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`); + this.#typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`); //#endregion tool.solutionBuilder = ts.createSolutionBuilder( solutionBuilderHost, - [this._configuration.tsconfigPath], + [this.#configuration.tsconfigPath], {} ) as IExtendedSolutionBuilder; } else { @@ -583,7 +583,7 @@ export class TypeScriptBuilder { let warningCount: number = 0; let hasError: boolean = false; - this._typescriptTerminal.writeLine( + this.#typescriptTerminal.writeLine( `Encountered ${diagnostics.length} TypeScript issue${diagnostics.length > 1 ? 's' : ''}:` ); for (const diagnostic of diagnostics) { @@ -602,7 +602,7 @@ export class TypeScriptBuilder { } if (isSolutionMode && warningCount > 0 && !hasError) { - this._typescriptLogger.emitError( + this.#typescriptLogger.emitError( new Error( `TypeScript encountered ${warningCount} warning${warningCount === 1 ? '' : 's'} ` + `and is configured to build project references. As a result, no files were emitted. Please fix the reported warnings to proceed.` @@ -613,20 +613,20 @@ export class TypeScriptBuilder { } private _logEmitPerformance(ts: ExtendedTypeScript): void { - this._typescriptTerminal.writeVerboseLine(`Bind: ${ts.performance.getDuration('Bind')}ms`); - this._typescriptTerminal.writeVerboseLine(`Check: ${ts.performance.getDuration('Check')}ms`); - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine(`Bind: ${ts.performance.getDuration('Bind')}ms`); + this.#typescriptTerminal.writeVerboseLine(`Check: ${ts.performance.getDuration('Check')}ms`); + this.#typescriptTerminal.writeVerboseLine( `Transform: ${ts.performance.getDuration('transformTime')}ms ` + `(${ts.performance.getCount('beforeTransform')} files)` ); - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `Print: ${ts.performance.getDuration('printTime')}ms ` + `(${ts.performance.getCount('beforePrint')} files) (Includes Transform)` ); - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `Emit: ${ts.performance.getDuration('Emit')}ms (Includes Print)` ); - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `I/O Write: ${ts.performance.getDuration('I/O Write')}ms (${ts.performance.getCount( 'beforeIOWrite' )} files)` @@ -634,15 +634,15 @@ export class TypeScriptBuilder { } private _logReadPerformance(ts: ExtendedTypeScript): void { - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `I/O Read: ${ts.performance.getDuration('I/O Read')}ms (${ts.performance.getCount( 'beforeIORead' )} files)` ); - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `Parse: ${ts.performance.getDuration('Parse')}ms (${ts.performance.getCount('beforeParse')} files)` ); - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `Program (includes Read + Parse): ${ts.performance.getDuration('Program')}ms` ); } @@ -661,7 +661,7 @@ export class TypeScriptBuilder { const formattedMessage: string = `(TS${diagnostic.code}) ${message}`; errorObject = new FileError(formattedMessage, { absolutePath: diagnostic.file.fileName, - projectFolder: this._configuration.buildFolderPath, + projectFolder: this.#configuration.buildFolderPath, line: line + 1, column: character + 1 }); @@ -673,17 +673,17 @@ export class TypeScriptBuilder { switch (diagnosticCategory) { case ts.DiagnosticCategory.Error: { - this._typescriptLogger.emitError(errorObject); + this.#typescriptLogger.emitError(errorObject); break; } case ts.DiagnosticCategory.Warning: { - this._typescriptLogger.emitWarning(errorObject); + this.#typescriptLogger.emitWarning(errorObject); break; } default: { - this._typescriptTerminal.writeLine(...diagnosticMessage); + this.#typescriptTerminal.writeLine(...diagnosticMessage); break; } } @@ -705,7 +705,7 @@ export class TypeScriptBuilder { } // These pedantic checks also should not be treated as hard errors - if (this._suppressedDiagnosticCodes.has(diagnostic.code)) { + if (this.#suppressedDiagnosticCodes.has(diagnostic.code)) { return ts.DiagnosticCategory.Warning; } @@ -722,7 +722,7 @@ export class TypeScriptBuilder { ); } - this._moduleKindsToEmit = []; + this.#moduleKindsToEmit = []; const specifiedKinds: Map = new Map(); const specifiedOutDirs: Map = new Map(); @@ -733,7 +733,7 @@ export class TypeScriptBuilder { ); } - if (this._configuration.emitCjsExtensionForCommonJS) { + if (this.#configuration.emitCjsExtensionForCommonJS) { this._addModuleKindToEmit( ts.ModuleKind.CommonJS, tsconfig.options.outDir!, @@ -753,7 +753,7 @@ export class TypeScriptBuilder { specifiedOutDirs.set(`${tsconfig.options.outDir!}:.cjs`, cjsReason); } - if (this._configuration.emitMjsExtensionForESModule) { + if (this.#configuration.emitMjsExtensionForESModule) { this._addModuleKindToEmit( ts.ModuleKind.ESNext, tsconfig.options.outDir!, @@ -793,9 +793,9 @@ export class TypeScriptBuilder { specifiedOutDirs.set(`${tsconfig.options.outDir!}:.js`, tsConfigReason); } - if (this._configuration.additionalModuleKindsToEmit) { + if (this.#configuration.additionalModuleKindsToEmit) { for (const { moduleKind: moduleKindString, outFolderName, emitModulePackageJson = false } of this - ._configuration.additionalModuleKindsToEmit) { + .#configuration.additionalModuleKindsToEmit) { const moduleKind: TTypescript.ModuleKind = this._parseModuleKind(ts, moduleKindString); const outDirKey: string = `${outFolderName}:.js`; @@ -844,16 +844,16 @@ export class TypeScriptBuilder { ): string | undefined { let outFolderName: string; if (path.isAbsolute(outFolderPath)) { - outFolderName = path.relative(this._configuration.buildFolderPath, outFolderPath); + outFolderName = path.relative(this.#configuration.buildFolderPath, outFolderPath); } else { outFolderName = outFolderPath; - outFolderPath = path.resolve(this._configuration.buildFolderPath, outFolderPath); + outFolderPath = path.resolve(this.#configuration.buildFolderPath, outFolderPath); } outFolderPath = Path.convertToSlashes(outFolderPath); outFolderPath = outFolderPath.replace(/\/*$/, '/'); // Ensure the outFolderPath ends with a slash - for (const existingModuleKindToEmit of this._moduleKindsToEmit) { + for (const existingModuleKindToEmit of this.#moduleKindsToEmit) { let errorText: string | undefined; if (existingModuleKindToEmit.outFolderPath === outFolderPath) { @@ -882,12 +882,12 @@ export class TypeScriptBuilder { } if (errorText) { - this._typescriptLogger.emitError(new Error(errorText)); + this.#typescriptLogger.emitError(new Error(errorText)); return undefined; } } - this._moduleKindsToEmit.push({ + this.#moduleKindsToEmit.push({ outFolderPath, moduleKind, jsExtensionOverride, @@ -901,9 +901,7 @@ export class TypeScriptBuilder { private _getCreateBuilderProgram( ts: ExtendedTypeScript ): TTypescript.CreateProgram { - const { - _configuration: { emitChangedFilesCallback } - } = this; + const { emitChangedFilesCallback } = this.#configuration; const createMultiEmitBuilderProgram: TTypescript.CreateProgram< TTypescript.EmitAndSemanticDiagnosticsBuilderProgram @@ -919,7 +917,7 @@ export class TypeScriptBuilder { ts.performance.disable(); ts.performance.enable(); - this._typescriptTerminal.writeVerboseLine(`Reading program "${compilerOptions!.configFilePath}"`); + this.#typescriptTerminal.writeVerboseLine(`Reading program "${compilerOptions!.configFilePath}"`); const newProgram: TTypescript.EmitAndSemanticDiagnosticsBuilderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram( @@ -934,13 +932,13 @@ export class TypeScriptBuilder { this._logReadPerformance(ts); const isolatedModules: boolean = - !!this._configuration.useTranspilerWorker && !!compilerOptions!.isolatedModules; + !!this.#configuration.useTranspilerWorker && !!compilerOptions!.isolatedModules; const mode: 'both' | 'declaration' = isolatedModules ? 'declaration' : 'both'; if (isolatedModules) { // Kick the transpilation worker. const filesToTranspile: Map = getFilesToTranspileFromBuilderProgram(newProgram); - this._queueTranspileInWorker(this._tool!, compilerOptions!, filesToTranspile); + this._queueTranspileInWorker(this.#tool!, compilerOptions!, filesToTranspile); } const { emit: originalEmit } = newProgram; @@ -959,7 +957,7 @@ export class TypeScriptBuilder { const { changedFiles } = configureProgramForMultiEmit( innerProgram, ts, - this._moduleKindsToEmit, + this.#moduleKindsToEmit, mode ); @@ -974,7 +972,7 @@ export class TypeScriptBuilder { (result as IExtendedEmitResult).changedSourceFiles = changedFiles; - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `Emitting program "${innerCompilerOptions!.configFilePath}"` ); @@ -1019,7 +1017,7 @@ export class TypeScriptBuilder { program: TTypescript.EmitAndSemanticDiagnosticsBuilderProgram ) => { // Use the native metric since we aren't overwriting the writer - this._typescriptTerminal.writeVerboseLine( + this.#typescriptTerminal.writeVerboseLine( `I/O Write: ${ts.performance.getDuration('I/O Write')}ms (${ts.performance.getCount( 'beforeIOWrite' )} files)` @@ -1084,7 +1082,7 @@ export class TypeScriptBuilder { return; } - compilerHost.getCurrentDirectory = () => this._configuration.buildFolderPath; + compilerHost.getCurrentDirectory = () => this.#configuration.buildFolderPath; // Enable source file persistence const getSourceFile: typeof innerGetSourceFile & { @@ -1141,7 +1139,7 @@ export class TypeScriptBuilder { * interprets `.js` files in the output folder. */ private _emitModulePackageJsonFiles(ts: ExtendedTypeScript): void { - for (const { emitModulePackageJson, moduleKind, outFolderPath } of this._moduleKindsToEmit) { + for (const { emitModulePackageJson, moduleKind, outFolderPath } of this.#moduleKindsToEmit) { if (!emitModulePackageJson) { continue; } @@ -1176,7 +1174,7 @@ export class TypeScriptBuilder { const packageJsonContent: string = `{\n "type": "${moduleType}"\n}\n`; ts.sys.writeFile(packageJsonPath, packageJsonContent); - this._typescriptTerminal.writeVerboseLine(`Wrote ${packageJsonPath} with "type": "${moduleType}"`); + this.#typescriptTerminal.writeVerboseLine(`Wrote ${packageJsonPath} with "type": "${moduleType}"`); } else { throw new Error( `Unsupported module kind ${ts.ModuleKind[moduleKind]} for package.json generation. ` + @@ -1235,14 +1233,14 @@ export class TypeScriptBuilder { if (signal) { signal.reject(error); } else { - this._typescriptTerminal.writeErrorLine( + this.#typescriptTerminal.writeErrorLine( `Unexpected worker rejection for request with id ${resolvingRequestId}: ${error}` ); } } else if (signal) { signal.resolve(result); } else { - this._typescriptTerminal.writeErrorLine( + this.#typescriptTerminal.writeErrorLine( `Unexpected worker resolution for request with id ${resolvingRequestId}` ); } @@ -1272,16 +1270,16 @@ export class TypeScriptBuilder { // make linter happy const worker: Worker = maybeWorker; - const requestId: number = ++this._nextRequestId; + const requestId: number = ++this.#nextRequestId; const transpilePromise: Promise = new Promise( (resolve: (result: TTypescript.EmitResult) => void, reject: (err: Error) => void) => { pendingTranspileSignals.set(requestId, { resolve, reject }); - this._typescriptTerminal.writeLine(`Asynchronously transpiling ${compilerOptions.configFilePath}`); + this.#typescriptTerminal.writeLine(`Asynchronously transpiling ${compilerOptions.configFilePath}`); const request: ITranspilationRequestMessage = { compilerOptions, filesToTranspile, - moduleKindsToEmit: this._moduleKindsToEmit, + moduleKindsToEmit: this.#moduleKindsToEmit, requestId }; @@ -1293,7 +1291,7 @@ export class TypeScriptBuilder { } private _cleanupWorker(): void { - const tool: ITypeScriptTool | undefined = this._tool; + const tool: ITypeScriptTool | undefined = this.#tool; if (!tool) { return; } diff --git a/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts b/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts index ca76573d285..9eb87333209 100644 --- a/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts +++ b/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts @@ -33,10 +33,10 @@ interface ICacheEntry { * instance. */ export class TypeScriptCachedFileSystem { - private _statsCache: Map> = new Map(); - private _readFolderCache: Map> = new Map(); - private _readFileCache: Map> = new Map(); - private _realPathCache: Map> = new Map(); + #statsCache: Map> = new Map(); + #readFolderCache: Map> = new Map(); + #readFileCache: Map> = new Map(); + #realPathCache: Map> = new Map(); public exists: (path: string) => boolean = (path: string) => { try { @@ -65,18 +65,18 @@ export class TypeScriptCachedFileSystem { }; public getStatistics: (path: string) => FileSystemStats = (path: string) => { - return this._withCaching(path, FileSystem.getStatistics, this._statsCache); + return this._withCaching(path, FileSystem.getStatistics, this.#statsCache); }; public ensureFolder: (folderPath: string) => void = (folderPath: string) => { - if (!this._readFolderCache.get(folderPath)?.entry && !this._statsCache.get(folderPath)?.entry) { + if (!this.#readFolderCache.get(folderPath)?.entry && !this.#statsCache.get(folderPath)?.entry) { FileSystem.ensureFolder(folderPath); this._invalidateCacheEntry(folderPath); } }; public ensureFolderAsync: (folderPath: string) => Promise = async (folderPath: string) => { - if (!this._readFolderCache.get(folderPath)?.entry && !this._statsCache.get(folderPath)?.entry) { + if (!this.#readFolderCache.get(folderPath)?.entry && !this.#statsCache.get(folderPath)?.entry) { await FileSystem.ensureFolderAsync(folderPath); this._invalidateCacheEntry(folderPath); } @@ -108,7 +108,7 @@ export class TypeScriptCachedFileSystem { }; public readFileToBuffer: (filePath: string) => Buffer = (filePath: string) => { - return this._withCaching(filePath, FileSystem.readFileToBuffer, this._readFileCache); + return this._withCaching(filePath, FileSystem.readFileToBuffer, this.#readFileCache); }; public copyFileAsync: (options: IFileSystemCopyFileOptions) => Promise = async ( @@ -122,7 +122,7 @@ export class TypeScriptCachedFileSystem { filePath: string, options?: IFileSystemDeleteFileOptions | undefined ) => { - const cachedError: Error | undefined = this._statsCache.get(filePath)?.error; + const cachedError: Error | undefined = this.#statsCache.get(filePath)?.error; if (!cachedError || !FileSystem.isFileDoesNotExistError(cachedError)) { FileSystem.deleteFile(filePath); this._invalidateCacheEntry(filePath); @@ -153,7 +153,7 @@ export class TypeScriptCachedFileSystem { } } }, - this._realPathCache + this.#realPathCache ); }; @@ -166,7 +166,7 @@ export class TypeScriptCachedFileSystem { const folderEntries: FolderItem[] = FileSystem.readFolderItems(path); return this._sortFolderEntries(folderEntries); }, - this._readFolderCache + this.#readFolderCache ); }; @@ -212,9 +212,9 @@ export class TypeScriptCachedFileSystem { } private _invalidateCacheEntry(path: string): void { - this._statsCache.delete(path); - this._readFolderCache.delete(path); - this._readFileCache.delete(path); - this._realPathCache.delete(path); + this.#statsCache.delete(path); + this.#readFolderCache.delete(path); + this.#readFileCache.delete(path); + this.#realPathCache.delete(path); } } diff --git a/heft-plugins/heft-webpack4-plugin/src/DeferredWatchFileSystem.ts b/heft-plugins/heft-webpack4-plugin/src/DeferredWatchFileSystem.ts index e3032c9a541..d0f719a2041 100644 --- a/heft-plugins/heft-webpack4-plugin/src/DeferredWatchFileSystem.ts +++ b/heft-plugins/heft-webpack4-plugin/src/DeferredWatchFileSystem.ts @@ -67,8 +67,8 @@ export class DeferredWatchFileSystem implements IWatchFileSystem { public readonly watcherOptions: WatchOptions; public watcher: Watchpack | undefined; - private readonly _onChange: () => void; - private _state: IWatchState | undefined; + readonly #onChange: () => void; + #state: IWatchState | undefined; public constructor(inputFileSystem: IPurgeable, onChange: () => void) { this.inputFileSystem = inputFileSystem; @@ -76,11 +76,11 @@ export class DeferredWatchFileSystem implements IWatchFileSystem { aggregateTimeout: 0 }; this.watcher = new Watchpack(this.watcherOptions); - this._onChange = onChange; + this.#onChange = onChange; } public flush(): boolean { - const state: IWatchState | undefined = this._state; + const state: IWatchState | undefined = this.#state; if (!state) { return false; @@ -136,7 +136,7 @@ export class DeferredWatchFileSystem implements IWatchFileSystem { const changes: Set = new Set(); const removals: Set = new Set(); - this._state = { + this.#state = { files: new Set(files), dirs: new Set(directories), missing: new Set(missing), @@ -158,7 +158,7 @@ export class DeferredWatchFileSystem implements IWatchFileSystem { removals.add(removal); } - this._onChange(); + this.#onChange(); }); watcher.watch({ @@ -198,16 +198,16 @@ export class DeferredWatchFileSystem implements IWatchFileSystem { export class OverrideNodeWatchFSPlugin implements Plugin { public readonly fileSystems: Set = new Set(); - private readonly _onChange: () => void; + readonly #onChange: () => void; public constructor(onChange: () => void) { - this._onChange = onChange; + this.#onChange = onChange; } public apply(compiler: Compiler): void { const watchFileSystem: DeferredWatchFileSystem = new DeferredWatchFileSystem( compiler.inputFileSystem, - this._onChange + this.#onChange ); this.fileSystems.add(watchFileSystem); (compiler as { watchFileSystem?: IWatchFileSystem }).watchFileSystem = watchFileSystem; diff --git a/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts b/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts index 644f585c8e8..0dceb475040 100644 --- a/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts +++ b/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts @@ -74,28 +74,28 @@ const WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME: 'webpack-dev-middleware' = 'webpack-d * @internal */ export default class Webpack4Plugin implements IHeftTaskPlugin { - private _accessor: IWebpackPluginAccessor | undefined; - private _isServeMode: boolean = false; - private _webpack: typeof TWebpack | undefined; - private _webpackCompiler: ExtendedCompiler | ExtendedMultiCompiler | undefined; - private _webpackConfiguration: IWebpackConfiguration | undefined | false = false; - private _webpackCompilationDonePromise: Promise | undefined; - private _webpackCompilationDonePromiseResolveFn: (() => void) | undefined; - private _watchFileSystems: Set | undefined; - - private _warnings: Error[] = []; - private _errors: Error[] = []; + #accessor: IWebpackPluginAccessor | undefined; + #isServeMode: boolean = false; + #webpack: typeof TWebpack | undefined; + #webpackCompiler: ExtendedCompiler | ExtendedMultiCompiler | undefined; + #webpackConfiguration: IWebpackConfiguration | undefined | false = false; + #webpackCompilationDonePromise: Promise | undefined; + #webpackCompilationDonePromiseResolveFn: (() => void) | undefined; + #watchFileSystems: Set | undefined; + + #warnings: Error[] = []; + #errors: Error[] = []; public get accessor(): IWebpackPluginAccessor { - if (!this._accessor) { - this._accessor = { + if (!this.#accessor) { + this.#accessor = { hooks: _createAccessorHooks(), parameters: { - isServeMode: this._isServeMode + isServeMode: this.#isServeMode } }; } - return this._accessor; + return this.#accessor; } public apply( @@ -103,8 +103,8 @@ export default class Webpack4Plugin implements IHeftTaskPlugin void ): Promise { - if (this._webpackConfiguration === false) { + if (this.#webpackConfiguration === false) { const webpackConfiguration: IWebpackConfiguration | undefined = await tryLoadWebpackConfigurationAsync( { taskSession, heftConfiguration, hooks: this.accessor.hooks, - serveMode: this._isServeMode, + serveMode: this.#isServeMode, loadWebpackAsyncFn: this._loadWebpackAsync.bind(this) }, options @@ -144,7 +144,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { - if (!this._webpack) { + if (!this.#webpack) { // Allow this to fail if webpack is not installed - this._webpack = await import(WEBPACK_PACKAGE_NAME); + this.#webpack = await import(WEBPACK_PACKAGE_NAME); } - return this._webpack!; + return this.#webpack!; } private async _getWebpackCompilerAsync( taskSession: IHeftTaskSession, webpackConfiguration: IWebpackConfiguration ): Promise { - if (!this._webpackCompiler) { + if (!this.#webpackCompiler) { const webpack: typeof TWebpack = await this._loadWebpackAsync(); taskSession.logger.terminal.writeLine(`Using Webpack version ${webpack.version}`); - this._webpackCompiler = Array.isArray(webpackConfiguration) + this.#webpackCompiler = Array.isArray(webpackConfiguration) ? (webpack.default( webpackConfiguration ) as ExtendedMultiCompiler) /* (webpack.Compilation[]) => MultiCompiler */ : (webpack.default(webpackConfiguration) as ExtendedCompiler); /* (webpack.Compilation) => Compiler */ } - return this._webpackCompiler; + return this.#webpackCompiler; } private async _runWebpackAsync( @@ -192,7 +192,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { this._validateEnvironmentVariable(taskSession); - if (taskSession.parameters.watch || this._isServeMode) { + if (taskSession.parameters.watch || this.#isServeMode) { // Should never happen, but just in case throw new InternalError('Cannot run Webpack in compilation mode when watch mode is enabled'); } @@ -240,11 +240,11 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { // Save a handle to the original promise, since the this-scoped promise will be replaced whenever // the compilation completes. - let webpackCompilationDonePromise: Promise | undefined = this._webpackCompilationDonePromise; + let webpackCompilationDonePromise: Promise | undefined = this.#webpackCompilationDonePromise; let isInitial: boolean = false; - if (!this._webpackCompiler) { + if (!this.#webpackCompiler) { isInitial = true; this._validateEnvironmentVariable(taskSession); if (!taskSession.parameters.watch) { @@ -267,14 +267,14 @@ export default class Webpack4Plugin implements IHeftTaskPlugin void) => { - this._webpackCompilationDonePromiseResolveFn = resolve; + this.#webpackCompilationDonePromise = new Promise((resolve: () => void) => { + this.#webpackCompilationDonePromiseResolveFn = resolve; }); - webpackCompilationDonePromise = this._webpackCompilationDonePromise; + webpackCompilationDonePromise = this.#webpackCompilationDonePromise; compiler.hooks.done.tap(PLUGIN_NAME, (stats?: TWebpack.Stats | TWebpack.MultiStats) => { - this._webpackCompilationDonePromiseResolveFn!(); - this._webpackCompilationDonePromise = new Promise((resolve: () => void) => { - this._webpackCompilationDonePromiseResolveFn = resolve; + this.#webpackCompilationDonePromiseResolveFn!(); + this.#webpackCompilationDonePromise = new Promise((resolve: () => void) => { + this.#webpackCompilationDonePromiseResolveFn = resolve; }); if (stats) { this._recordErrors(stats); @@ -283,7 +283,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin void; - private _state: IWatchState | undefined; + readonly #onChange: () => void; + #state: IWatchState | undefined; public constructor(inputFileSystem: InputFileSystem, onChange: () => void) { this.inputFileSystem = inputFileSystem; @@ -45,11 +45,11 @@ export class DeferredWatchFileSystem implements WatchFileSystem { aggregateTimeout: 0 }; this.watcher = new Watchpack(this.watcherOptions); - this._onChange = onChange; + this.#onChange = onChange; } public flush(): boolean { - const state: IWatchState | undefined = this._state; + const state: IWatchState | undefined = this.#state; if (!state) { return false; @@ -105,7 +105,7 @@ export class DeferredWatchFileSystem implements WatchFileSystem { const changes: Set = new Set(); const removals: Set = new Set(); - this._state = { + this.#state = { changes, removals, @@ -122,7 +122,7 @@ export class DeferredWatchFileSystem implements WatchFileSystem { removals.add(removal); } - this._onChange(); + this.#onChange(); }); this.watcher.watch({ @@ -197,10 +197,10 @@ export class DeferredWatchFileSystem implements WatchFileSystem { export class OverrideNodeWatchFSPlugin implements WebpackPluginInstance { public readonly fileSystems: Set = new Set(); - private readonly _onChange: () => void; + readonly #onChange: () => void; public constructor(onChange: () => void) { - this._onChange = onChange; + this.#onChange = onChange; } public apply(compiler: Compiler): void { @@ -211,7 +211,7 @@ export class OverrideNodeWatchFSPlugin implements WebpackPluginInstance { const watchFileSystem: DeferredWatchFileSystem = new DeferredWatchFileSystem( inputFileSystem, - this._onChange + this.#onChange ); this.fileSystems.add(watchFileSystem); compiler.watchFileSystem = watchFileSystem; diff --git a/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts b/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts index 59bf0c4b725..e5bfed6d903 100644 --- a/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts +++ b/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts @@ -41,28 +41,28 @@ const WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME: 'webpack-dev-middleware' = 'webpack-d * @internal */ export default class Webpack5Plugin implements IHeftTaskPlugin { - private _accessor: IWebpackPluginAccessor | undefined; - private _isServeMode: boolean = false; - private _webpack: typeof TWebpack | undefined; - private _webpackCompiler: TWebpack.Compiler | TWebpack.MultiCompiler | undefined; - private _webpackConfiguration: IWebpackConfiguration | undefined | false = false; - private _webpackCompilationDonePromise: Promise | undefined; - private _webpackCompilationDonePromiseResolveFn: (() => void) | undefined; - private _watchFileSystems: Set | undefined; - - private _warnings: Error[] = []; - private _errors: Error[] = []; + #accessor: IWebpackPluginAccessor | undefined; + #isServeMode: boolean = false; + #webpack: typeof TWebpack | undefined; + #webpackCompiler: TWebpack.Compiler | TWebpack.MultiCompiler | undefined; + #webpackConfiguration: IWebpackConfiguration | undefined | false = false; + #webpackCompilationDonePromise: Promise | undefined; + #webpackCompilationDonePromiseResolveFn: (() => void) | undefined; + #watchFileSystems: Set | undefined; + + #warnings: Error[] = []; + #errors: Error[] = []; public get accessor(): IWebpackPluginAccessor { - if (!this._accessor) { - this._accessor = { + if (!this.#accessor) { + this.#accessor = { hooks: _createAccessorHooks(), parameters: { - isServeMode: this._isServeMode + isServeMode: this.#isServeMode } }; } - return this._accessor; + return this.#accessor; } public apply( @@ -70,8 +70,8 @@ export default class Webpack5Plugin implements IHeftTaskPlugin void ): Promise { - if (this._webpackConfiguration === false) { + if (this.#webpackConfiguration === false) { const webpackConfiguration: IWebpackConfiguration | undefined = await tryLoadWebpackConfigurationAsync( { taskSession, heftConfiguration, hooks: this.accessor.hooks, - serveMode: this._isServeMode, + serveMode: this.#isServeMode, loadWebpackAsyncFn: this._loadWebpackAsync.bind(this, taskSession, heftConfiguration) }, options @@ -113,7 +113,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { - if (!this._webpack) { + if (!this.#webpack) { try { const webpackPackagePath: string = await heftConfiguration.rigPackageResolver.resolvePackageAsync( WEBPACK_PACKAGE_NAME, taskSession.logger.terminal ); - this._webpack = await import(webpackPackagePath); + this.#webpack = await import(webpackPackagePath); taskSession.logger.terminal.writeDebugLine(`Using Webpack from rig package at "${webpackPackagePath}"`); } catch (e) { // Fallback to bundled version if not found in rig. - this._webpack = await import(WEBPACK_PACKAGE_NAME); + this.#webpack = await import(WEBPACK_PACKAGE_NAME); taskSession.logger.terminal.writeDebugLine(`Using Webpack from built-in "${WEBPACK_PACKAGE_NAME}"`); } } - return this._webpack!; + return this.#webpack!; } private async _getWebpackCompilerAsync( @@ -157,14 +157,14 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { - if (!this._webpackCompiler) { + if (!this.#webpackCompiler) { const webpack: typeof TWebpack = await this._loadWebpackAsync(taskSession, heftConfiguration); taskSession.logger.terminal.writeLine(`Using Webpack version ${webpack.version}`); - this._webpackCompiler = Array.isArray(webpackConfiguration) + this.#webpackCompiler = Array.isArray(webpackConfiguration) ? webpack.default(webpackConfiguration) /* (webpack.Compilation[]) => MultiCompiler */ : webpack.default(webpackConfiguration); /* (webpack.Compilation) => Compiler */ } - return this._webpackCompiler; + return this.#webpackCompiler; } private async _runWebpackAsync( @@ -173,7 +173,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { this._validateEnvironmentVariable(taskSession); - if (taskSession.parameters.watch || this._isServeMode) { + if (taskSession.parameters.watch || this.#isServeMode) { // Should never happen, but just in case throw new InternalError('Cannot run Webpack in compilation mode when watch mode is enabled'); } @@ -223,11 +223,11 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { // Save a handle to the original promise, since the this-scoped promise will be replaced whenever // the compilation completes. - let webpackCompilationDonePromise: Promise | undefined = this._webpackCompilationDonePromise; + let webpackCompilationDonePromise: Promise | undefined = this.#webpackCompilationDonePromise; let isInitial: boolean = false; - if (!this._webpackCompiler) { + if (!this.#webpackCompiler) { isInitial = true; this._validateEnvironmentVariable(taskSession); if (!taskSession.parameters.watch) { @@ -251,14 +251,14 @@ export default class Webpack5Plugin implements IHeftTaskPlugin void) => { - this._webpackCompilationDonePromiseResolveFn = resolve; + this.#webpackCompilationDonePromise = new Promise((resolve: () => void) => { + this.#webpackCompilationDonePromiseResolveFn = resolve; }); - webpackCompilationDonePromise = this._webpackCompilationDonePromise; + webpackCompilationDonePromise = this.#webpackCompilationDonePromise; compiler.hooks.done.tap(PLUGIN_NAME, (stats?: TWebpack.Stats | TWebpack.MultiStats) => { - this._webpackCompilationDonePromiseResolveFn!(); - this._webpackCompilationDonePromise = new Promise((resolve: () => void) => { - this._webpackCompilationDonePromiseResolveFn = resolve; + this.#webpackCompilationDonePromiseResolveFn!(); + this.#webpackCompilationDonePromise = new Promise((resolve: () => void) => { + this.#webpackCompilationDonePromiseResolveFn = resolve; }); if (stats) { @@ -268,7 +268,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { + compiler.hooks.thisCompilation.tap(this.#pluginName, (compilation: webpack.Compilation) => { if (initialOutputPublicPathSetting) { compilation.warnings.push( new compiler.webpack.WebpackError( @@ -41,7 +41,7 @@ export abstract class SetPublicPathPluginBase implements webpack.WebpackPluginIn ); } else { compilation.hooks.runtimeRequirementInTree.for(thisWebpack.RuntimeGlobals.publicPath).intercept({ - name: this._pluginName, + name: this.#pluginName, register: (tap) => { if (tap.name === 'RuntimePlugin') { // Disable the default public path runtime plugin diff --git a/webpack/webpack-deep-imports-plugin/src/DeepImportsPlugin.ts b/webpack/webpack-deep-imports-plugin/src/DeepImportsPlugin.ts index 6525b360259..e1ffcaf9788 100644 --- a/webpack/webpack-deep-imports-plugin/src/DeepImportsPlugin.ts +++ b/webpack/webpack-deep-imports-plugin/src/DeepImportsPlugin.ts @@ -66,10 +66,10 @@ function countSlashes(str: string): number { * @public */ export class DeepImportsPlugin extends DllPlugin { - private readonly _inFolderName: string; - private readonly _outFolderName: string; - private readonly _pathsToIgnoreWithoutExtensions: Set; - private readonly _dTsFilesInputFolderName: string | undefined; + readonly #inFolderName: string; + readonly #outFolderName: string; + readonly #pathsToIgnoreWithoutExtensions: Set; + readonly #dTsFilesInputFolderName: string | undefined; public constructor(options: IDeepImportsPluginOptions) { const superOptions: DllPluginOptions = { @@ -114,10 +114,10 @@ export class DeepImportsPlugin extends DllPlugin { pathsToIgnoreWithoutExtensions.add(normalizedPathToIgnore); } - this._inFolderName = options.inFolderName; - this._outFolderName = options.outFolderName; - this._pathsToIgnoreWithoutExtensions = pathsToIgnoreWithoutExtensions; - this._dTsFilesInputFolderName = dTsFilesInputFolderName; + this.#inFolderName = options.inFolderName; + this.#outFolderName = options.outFolderName; + this.#pathsToIgnoreWithoutExtensions = pathsToIgnoreWithoutExtensions; + this.#dTsFilesInputFolderName = dTsFilesInputFolderName; } public override apply(compiler: Compiler): void { @@ -153,8 +153,8 @@ export class DeepImportsPlugin extends DllPlugin { exportsInfo: IExportsInfo; } - const pathsToIgnoreWithoutExtension: Set = this._pathsToIgnoreWithoutExtensions; - const resolvedLibInFolder: string = path.join(compiler.context, this._inFolderName); + const pathsToIgnoreWithoutExtension: Set = this.#pathsToIgnoreWithoutExtensions; + const resolvedLibInFolder: string = path.join(compiler.context, this.#inFolderName); const libModulesByChunk: Map = new Map(); const encounteredLibPaths: Set = new Set(); for (const runtimeChunk of runtimeChunks) { @@ -199,13 +199,13 @@ export class DeepImportsPlugin extends DllPlugin { libModulesByChunk.set(runtimeChunk, libModules); } - const resolvedLibOutFolder: string = path.join(compiler.context, this._outFolderName); + const resolvedLibOutFolder: string = path.join(compiler.context, this.#outFolderName); const outputPathRelativeLibOutFolder: string = Path.convertToSlashes( path.relative(outputPath, resolvedLibOutFolder) ); - const resolvedDtsFilesInputFolderName: string | undefined = this._dTsFilesInputFolderName - ? path.join(compiler.context, this._dTsFilesInputFolderName) + const resolvedDtsFilesInputFolderName: string | undefined = this.#dTsFilesInputFolderName + ? path.join(compiler.context, this.#dTsFilesInputFolderName) : undefined; for (const [chunk, libModules] of libModulesByChunk) { diff --git a/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts b/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts index 103d2e859ad..caf972bc15b 100644 --- a/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts +++ b/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts @@ -148,19 +148,19 @@ type DefaultLicenseTemplate = `
${string}

${string}`; * and their licenses. */ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginInstance { - private readonly _outputFileName: string; - private readonly _generateLicenseFile: boolean; - private readonly _generateLicenseFileFunction: LicenseFileGeneratorFunction; - private readonly _generatedLicenseFilename: LicenseFileName; - private readonly _packageFilterFunction: (packageJson: IPackageData, filePath: string) => boolean; + readonly #outputFileName: string; + readonly #generateLicenseFile: boolean; + readonly #generateLicenseFileFunction: LicenseFileGeneratorFunction; + readonly #generatedLicenseFilename: LicenseFileName; + readonly #packageFilterFunction: (packageJson: IPackageData, filePath: string) => boolean; public constructor(options?: IEmbeddedDependenciesWebpackPluginOptions) { - this._outputFileName = options?.outputFileName || DEFAULT_EMBEDDED_DEPENDENCIES_FILE_NAME; - this._generateLicenseFile = options?.generateLicenseFile || false; - this._generateLicenseFileFunction = + this.#outputFileName = options?.outputFileName || DEFAULT_EMBEDDED_DEPENDENCIES_FILE_NAME; + this.#generateLicenseFile = options?.generateLicenseFile || false; + this.#generateLicenseFileFunction = options?.generateLicenseFileFunction || this._defaultLicenseFileGenerator; - this._generatedLicenseFilename = options?.generatedLicenseFilename || DEFAULT_GENERATED_LICENSE_FILE_NAME; - this._packageFilterFunction = options?.packageFilterPredicate || DEFAULT_PACKAGE_FILTER_FUNCTION; + this.#generatedLicenseFilename = options?.generatedLicenseFilename || DEFAULT_GENERATED_LICENSE_FILE_NAME; + this.#packageFilterFunction = options?.packageFilterPredicate || DEFAULT_PACKAGE_FILTER_FUNCTION; } /** @@ -188,7 +188,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI if ( pkg && filePath && - this._packageFilterFunction(pkg, filePath) && + this.#packageFilterFunction(pkg, filePath) && filePath?.includes('node_modules') ) { const key: PackageNameAndVersion = makePackageMapKeyForPackage(pkg); @@ -247,14 +247,14 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI embeddedDependencies: packages }; - compilation.emitAsset(this._outputFileName, new sources.RawSource(JSON.stringify(dataToStringify))); + compilation.emitAsset(this.#outputFileName, new sources.RawSource(JSON.stringify(dataToStringify))); - if (this._generateLicenseFile) { + if (this.#generateLicenseFile) { // We should try catch here because generator function can be output from user config try { compilation.emitAsset( - this._generatedLicenseFilename, - new sources.RawSource(this._generateLicenseFileFunction(packages)) + this.#generatedLicenseFilename, + new sources.RawSource(this.#generateLicenseFileFunction(packages)) ); } catch (error: unknown) { this._emitWebpackError(compilation, 'Failed to generate license file', error); diff --git a/webpack/webpack-workspace-resolve-plugin/src/KnownDescriptionFilePlugin.ts b/webpack/webpack-workspace-resolve-plugin/src/KnownDescriptionFilePlugin.ts index 30b26319570..44327dbacad 100644 --- a/webpack/webpack-workspace-resolve-plugin/src/KnownDescriptionFilePlugin.ts +++ b/webpack/webpack-workspace-resolve-plugin/src/KnownDescriptionFilePlugin.ts @@ -18,8 +18,8 @@ export class KnownDescriptionFilePlugin { public readonly source: string; public readonly target: string; - private readonly _skipForContext: boolean; - private readonly _cache: WorkspaceLayoutCache; + readonly #skipForContext: boolean; + readonly #cache: WorkspaceLayoutCache; /** * Constructs a new instance of `KnownDescriptionFilePlugin`. @@ -31,12 +31,12 @@ export class KnownDescriptionFilePlugin { public constructor(cache: WorkspaceLayoutCache, source: string, target: string, skipForContext?: boolean) { this.source = source; this.target = target; - this._cache = cache; - this._skipForContext = !!skipForContext; + this.#cache = cache; + this.#skipForContext = !!skipForContext; } public apply(resolver: Resolver): void { - if (this._skipForContext && resolver.options.resolveToContext) { + if (this.#skipForContext && resolver.options.resolveToContext) { return; } @@ -71,7 +71,7 @@ export class KnownDescriptionFilePlugin { return callback(); } - const cache: WorkspaceLayoutCache = this._cache; + const cache: WorkspaceLayoutCache = this.#cache; const match: IPrefixMatch | undefined = cache.contextLookup.findLongestPrefixMatch(path); diff --git a/webpack/webpack-workspace-resolve-plugin/src/KnownPackageDependenciesPlugin.ts b/webpack/webpack-workspace-resolve-plugin/src/KnownPackageDependenciesPlugin.ts index 2f721e018fb..fc48fe7df99 100644 --- a/webpack/webpack-workspace-resolve-plugin/src/KnownPackageDependenciesPlugin.ts +++ b/webpack/webpack-workspace-resolve-plugin/src/KnownPackageDependenciesPlugin.ts @@ -19,7 +19,7 @@ export class KnownPackageDependenciesPlugin { public readonly source: string; public readonly target: string; - private readonly _cache: WorkspaceLayoutCache; + readonly #cache: WorkspaceLayoutCache; /** * Constructs a new instance of `KnownPackageDependenciesPlugin`. @@ -30,7 +30,7 @@ export class KnownPackageDependenciesPlugin { public constructor(cache: WorkspaceLayoutCache, source: string, target: string) { this.source = source; this.target = target; - this._cache = cache; + this.#cache = cache; } public apply(resolver: Resolver): void { @@ -53,7 +53,7 @@ export class KnownPackageDependenciesPlugin { return callback(new Error(`Expected descriptionFileData for ${path}`)); } - const cache: WorkspaceLayoutCache = this._cache; + const cache: WorkspaceLayoutCache = this.#cache; let scope: IPrefixMatch | undefined = cache.contextForPackage.get(descriptionFileData); diff --git a/webpack/webpack-workspace-resolve-plugin/src/WorkspaceLayoutCache.ts b/webpack/webpack-workspace-resolve-plugin/src/WorkspaceLayoutCache.ts index 0f2d988b634..671e43de4a8 100644 --- a/webpack/webpack-workspace-resolve-plugin/src/WorkspaceLayoutCache.ts +++ b/webpack/webpack-workspace-resolve-plugin/src/WorkspaceLayoutCache.ts @@ -138,30 +138,30 @@ export class WorkspaceLayoutCache { // Internal class due to coupling to `resolveContexts` class ResolveContext implements IResolveContext { - private readonly _serialized: ISerializedResolveContext; - private _descriptionFileRoot: string | undefined; - private _dependencies: LookupByPath | undefined; + readonly #serialized: ISerializedResolveContext; + #descriptionFileRoot: string | undefined; + #dependencies: LookupByPath | undefined; public constructor(serialized: ISerializedResolveContext) { - this._serialized = serialized; - this._descriptionFileRoot = undefined; - this._dependencies = undefined; + this.#serialized = serialized; + this.#descriptionFileRoot = undefined; + this.#dependencies = undefined; } public get descriptionFileRoot(): string { - if (!this._descriptionFileRoot) { - const merged: string = `${basePath}${this._serialized.root}`; - this._descriptionFileRoot = normalizeToPlatform?.(merged) ?? merged; + if (!this.#descriptionFileRoot) { + const merged: string = `${basePath}${this.#serialized.root}`; + this.#descriptionFileRoot = normalizeToPlatform?.(merged) ?? merged; } - return this._descriptionFileRoot; + return this.#descriptionFileRoot; } public findDependency(request: string): IPrefixMatch | undefined { - if (!this._dependencies) { + if (!this.#dependencies) { // Lazy initialize this object since most packages won't be requested. const dependencies: LookupByPath = new LookupByPath(undefined, '/'); - const { name, deps } = this._serialized; + const { name, deps } = this.#serialized; // Handle the self-reference scenario dependencies.setItem(name, this); @@ -171,10 +171,10 @@ export class WorkspaceLayoutCache { dependencies.setItem(key, resolveContexts[ordinal]); } } - this._dependencies = dependencies; + this.#dependencies = dependencies; } - return this._dependencies.findLongestPrefixMatch(request); + return this.#dependencies.findLongestPrefixMatch(request); } } diff --git a/webpack/webpack-workspace-resolve-plugin/src/WorkspaceResolvePlugin.ts b/webpack/webpack-workspace-resolve-plugin/src/WorkspaceResolvePlugin.ts index a68a97aa5db..ec9225764fe 100644 --- a/webpack/webpack-workspace-resolve-plugin/src/WorkspaceResolvePlugin.ts +++ b/webpack/webpack-workspace-resolve-plugin/src/WorkspaceResolvePlugin.ts @@ -31,16 +31,16 @@ export interface IWorkspaceResolvePluginOptions { * @beta */ export class WorkspaceResolvePlugin implements WebpackPluginInstance { - private readonly _cache: WorkspaceLayoutCache; - private readonly _resolverNames: Set; + readonly #cache: WorkspaceLayoutCache; + readonly #resolverNames: Set; public constructor(options: IWorkspaceResolvePluginOptions) { - this._cache = options.cache; - this._resolverNames = new Set(options.resolverNames ?? ['normal', 'context', 'loader']); + this.#cache = options.cache; + this.#resolverNames = new Set(options.resolverNames ?? ['normal', 'context', 'loader']); } public apply(compiler: Compiler): void { - const cache: WorkspaceLayoutCache = this._cache; + const cache: WorkspaceLayoutCache = this.#cache; function handler(resolveOptions: ResolveOptions): ResolveOptions { // Omit default `node_modules` @@ -75,7 +75,7 @@ export class WorkspaceResolvePlugin implements WebpackPluginInstance { return resolveOptions; } - for (const resolverName of this._resolverNames) { + for (const resolverName of this.#resolverNames) { compiler.resolverFactory.hooks.resolveOptions .for(resolverName) .tap(WorkspaceResolvePlugin.name, handler); diff --git a/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts b/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts index 2e4a05b7c06..5bbe57c226d 100644 --- a/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts +++ b/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts @@ -98,32 +98,32 @@ export class LocalizationPlugin implements Webpack.Plugin { */ public stringKeys: Map = new Map(); - private _options: ILocalizationPluginOptions; - private _resolvedTranslatedStringsFromOptions!: ILocalizedStrings; - private _globsToIgnore: string[] | undefined; - private _stringPlaceholderCounter: number = 0; - private _stringPlaceholderMap: Map = new Map< + #options: ILocalizationPluginOptions; + #resolvedTranslatedStringsFromOptions!: ILocalizedStrings; + #globsToIgnore: string[] | undefined; + #stringPlaceholderCounter: number = 0; + #stringPlaceholderMap: Map = new Map< string, IStringSerialNumberData >(); - private _locales: Set = new Set(); - private _passthroughLocaleName!: string; - private _defaultLocale!: string; - private _noStringsLocaleName!: string; - private _fillMissingTranslationStrings!: boolean; - private _pseudolocalizers: Map string> = new Map< + #locales: Set = new Set(); + #passthroughLocaleName!: string; + #defaultLocale!: string; + #noStringsLocaleName!: string; + #fillMissingTranslationStrings!: boolean; + #pseudolocalizers: Map string> = new Map< string, (str: string) => string >(); - private _resxNewlineNormalization: NewlineKind | undefined; - private _ignoreMissingResxComments: boolean | undefined; + #resxNewlineNormalization: NewlineKind | undefined; + #ignoreMissingResxComments: boolean | undefined; /** * The outermost map's keys are the locale names. * The middle map's keys are the resolved, file names. * The innermost map's keys are the string identifiers and its values are the string values. */ - private _resolvedLocalizedStrings: Map>> = new Map< + #resolvedLocalizedStrings: Map>> = new Map< string, Map> >(); @@ -140,7 +140,7 @@ export class LocalizationPlugin implements Webpack.Plugin { ); } - this._options = options; + this.#options = options; } public apply(compiler: Webpack.Compiler): void { @@ -150,29 +150,29 @@ export class LocalizationPlugin implements Webpack.Plugin { throw new Error(`The ${LocalizationPlugin.name} plugin requires Webpack 4`); } - if (this._options.typingsOptions && compiler.context) { + if (this.#options.typingsOptions && compiler.context) { if ( - this._options.typingsOptions.generatedTsFolder && - !path.isAbsolute(this._options.typingsOptions.generatedTsFolder) + this.#options.typingsOptions.generatedTsFolder && + !path.isAbsolute(this.#options.typingsOptions.generatedTsFolder) ) { - this._options.typingsOptions.generatedTsFolder = path.resolve( + this.#options.typingsOptions.generatedTsFolder = path.resolve( compiler.context, - this._options.typingsOptions.generatedTsFolder + this.#options.typingsOptions.generatedTsFolder ); } if ( - this._options.typingsOptions.sourceRoot && - !path.isAbsolute(this._options.typingsOptions.sourceRoot) + this.#options.typingsOptions.sourceRoot && + !path.isAbsolute(this.#options.typingsOptions.sourceRoot) ) { - this._options.typingsOptions.sourceRoot = path.resolve( + this.#options.typingsOptions.sourceRoot = path.resolve( compiler.context, - this._options.typingsOptions.sourceRoot + this.#options.typingsOptions.sourceRoot ); } const secondaryGeneratedTsFolders: string[] | undefined = - this._options.typingsOptions.secondaryGeneratedTsFolders; + this.#options.typingsOptions.secondaryGeneratedTsFolders; if (secondaryGeneratedTsFolders) { for (let i: number = 0; i < secondaryGeneratedTsFolders.length; i++) { const secondaryGeneratedTsFolder: string = secondaryGeneratedTsFolders[i]; @@ -189,15 +189,15 @@ export class LocalizationPlugin implements Webpack.Plugin { const { errors, warnings } = this._initializeAndValidateOptions(compiler.options, isWebpackDevServer); let typingsPreprocessor: TypingsGenerator | undefined; - if (this._options.typingsOptions) { + if (this.#options.typingsOptions) { typingsPreprocessor = new TypingsGenerator({ - srcFolder: this._options.typingsOptions.sourceRoot || compiler.context, - generatedTsFolder: this._options.typingsOptions.generatedTsFolder, - secondaryGeneratedTsFolders: this._options.typingsOptions.secondaryGeneratedTsFolders, - exportAsDefault: this._options.typingsOptions.exportAsDefault, - globsToIgnore: this._options.globsToIgnore, - ignoreString: this._options.ignoreString, - processComment: this._options.typingsOptions.processComment + srcFolder: this.#options.typingsOptions.sourceRoot || compiler.context, + generatedTsFolder: this.#options.typingsOptions.generatedTsFolder, + secondaryGeneratedTsFolders: this.#options.typingsOptions.secondaryGeneratedTsFolders, + exportAsDefault: this.#options.typingsOptions.exportAsDefault, + globsToIgnore: this.#options.globsToIgnore, + ignoreString: this.#options.ignoreString, + processComment: this.#options.typingsOptions.processComment }); } else { typingsPreprocessor = undefined; @@ -206,11 +206,11 @@ export class LocalizationPlugin implements Webpack.Plugin { const webpackConfigurationUpdaterOptions: IWebpackConfigurationUpdaterOptions = { pluginInstance: this, configuration: compiler.options, - globsToIgnore: this._globsToIgnore, + globsToIgnore: this.#globsToIgnore, localeNameOrPlaceholder: Constants.LOCALE_NAME_PLACEHOLDER, - resxNewlineNormalization: this._resxNewlineNormalization, - ignoreMissingResxComments: this._ignoreMissingResxComments, - ignoreString: this._options.ignoreString + resxNewlineNormalization: this.#resxNewlineNormalization, + ignoreMissingResxComments: this.#ignoreMissingResxComments, + ignoreString: this.#options.ignoreString }; if (errors.length > 0 || warnings.length > 0) { @@ -238,7 +238,7 @@ export class LocalizationPlugin implements Webpack.Plugin { } compiler.options.plugins.push( - new Webpack.WatchIgnorePlugin([this._options.typingsOptions!.generatedTsFolder]) + new Webpack.WatchIgnorePlugin([this.#options.typingsOptions!.generatedTsFolder]) ); } @@ -336,7 +336,7 @@ export class LocalizationPlugin implements Webpack.Plugin { // Change the chunk's name to include either the locale name or the locale name for chunks without strings const replacementValue: string = localizedChunk ? Constants.LOCALE_NAME_PLACEHOLDER - : this._noStringsLocaleName; + : this.#noStringsLocaleName; if (chunk.hasRuntime()) { chunk.filenameTemplate = (compilation.options.output!.filename as string).replace( Constants.LOCALE_FILENAME_TOKEN_REGEX, @@ -405,10 +405,10 @@ export class LocalizationPlugin implements Webpack.Plugin { asset, chunk, chunkHasLocalizedModules: this._chunkHasLocalizedModules.bind(this), - locales: this._locales, - noStringsLocaleName: this._noStringsLocaleName, - fillMissingTranslationStrings: this._fillMissingTranslationStrings, - defaultLocale: this._defaultLocale + locales: this.#locales, + noStringsLocaleName: this.#noStringsLocaleName, + fillMissingTranslationStrings: this.#fillMissingTranslationStrings, + defaultLocale: this.#defaultLocale }); // Delete the existing asset because it's been renamed @@ -448,7 +448,7 @@ export class LocalizationPlugin implements Webpack.Plugin { assetName: chunkFilename, asset, chunk, - noStringsLocaleName: this._noStringsLocaleName, + noStringsLocaleName: this.#noStringsLocaleName, chunkHasLocalizedModules: this._chunkHasLocalizedModules.bind(this) }); @@ -464,20 +464,20 @@ export class LocalizationPlugin implements Webpack.Plugin { chunk.files = Array.from(chunkFilesSet); } - if (this._options.localizationStats) { - if (this._options.localizationStats.dropPath) { + if (this.#options.localizationStats) { + if (this.#options.localizationStats.dropPath) { const resolvedLocalizationStatsDropPath: string = path.resolve( compiler.outputPath, - this._options.localizationStats.dropPath + this.#options.localizationStats.dropPath ); JsonFile.save(localizationStats, resolvedLocalizationStatsDropPath, { ensureFolderExists: true }); } - if (this._options.localizationStats.callback) { + if (this.#options.localizationStats.callback) { try { - this._options.localizationStats.callback(localizationStats); + this.#options.localizationStats.callback(localizationStats); } catch (e) { /* swallow errors from the callback */ } @@ -502,7 +502,7 @@ export class LocalizationPlugin implements Webpack.Plugin { const errors: Error[] = []; const locFileData: ILocaleFileData = this._convertLocalizationFileToLocData(localizedResourceData); - this._addLocFile(this._defaultLocale, localizedResourcePath, locFileData); + this._addLocFile(this.#defaultLocale, localizedResourcePath, locFileData); const normalizeLocalizedData: (localizedData: ILocaleFileData | string) => ILocaleFileData = ( localizedData @@ -513,8 +513,8 @@ export class LocalizationPlugin implements Webpack.Plugin { filePath: localizedData, content: FileSystem.readFile(localizedData), terminal: terminal, - resxNewlineNormalization: this._resxNewlineNormalization, - ignoreMissingResxComments: this._ignoreMissingResxComments + resxNewlineNormalization: this.#resxNewlineNormalization, + ignoreMissingResxComments: this.#ignoreMissingResxComments }); return this._convertLocalizationFileToLocData(localizationFile); @@ -525,7 +525,7 @@ export class LocalizationPlugin implements Webpack.Plugin { const missingLocales: string[] = []; for (const [translatedLocaleName, translatedStrings] of Object.entries( - this._resolvedTranslatedStringsFromOptions + this.#resolvedTranslatedStringsFromOptions )) { const translatedLocFileFromOptions: ILocaleFileData | string | undefined = translatedStrings[localizedResourcePath]; @@ -537,10 +537,10 @@ export class LocalizationPlugin implements Webpack.Plugin { } } - if (missingLocales.length > 0 && this._options.localizedData.resolveMissingTranslatedStrings) { + if (missingLocales.length > 0 && this.#options.localizedData.resolveMissingTranslatedStrings) { let resolvedTranslatedData: IResolvedMissingTranslations | undefined = undefined; try { - resolvedTranslatedData = this._options.localizedData.resolveMissingTranslatedStrings( + resolvedTranslatedData = this.#options.localizedData.resolveMissingTranslatedStrings( missingLocales, localizedResourcePath ); @@ -558,7 +558,7 @@ export class LocalizationPlugin implements Webpack.Plugin { } } - this._pseudolocalizers.forEach((pseudolocalizer: (str: string) => string, pseudolocaleName: string) => { + this.#pseudolocalizers.forEach((pseudolocalizer: (str: string) => string, pseudolocaleName: string) => { const pseudolocFileData: ILocaleFileData = {}; for (const [stringName, stringValue] of Object.entries(locFileData)) { @@ -575,7 +575,7 @@ export class LocalizationPlugin implements Webpack.Plugin { * @internal */ public getDataForSerialNumber(serialNumber: string): IStringSerialNumberData | undefined { - return this._stringPlaceholderMap.get(serialNumber); + return this.#stringPlaceholderMap.get(serialNumber); } private _addLocFile( @@ -583,7 +583,7 @@ export class LocalizationPlugin implements Webpack.Plugin { localizedFilePath: string, localizedFileData: ILocaleFileData ): void { - const filesMap: Map> = this._resolvedLocalizedStrings.get(localeName)!; + const filesMap: Map> = this.#resolvedLocalizedStrings.get(localeName)!; const stringsMap: Map = new Map(); filesMap.set(localizedFilePath, stringsMap); @@ -596,17 +596,17 @@ export class LocalizationPlugin implements Webpack.Plugin { } const placeholder: IStringPlaceholder = this.stringKeys.get(stringKey)!; - if (!this._stringPlaceholderMap.has(placeholder.suffix)) { - this._stringPlaceholderMap.set(placeholder.suffix, { + if (!this.#stringPlaceholderMap.has(placeholder.suffix)) { + this.#stringPlaceholderMap.set(placeholder.suffix, { values: { - [this._passthroughLocaleName]: stringName + [this.#passthroughLocaleName]: stringName }, locFilePath: localizedFilePath, stringName: stringName }); } - this._stringPlaceholderMap.get(placeholder.suffix)!.values[localeName] = stringValue; + this.#stringPlaceholderMap.get(placeholder.suffix)!.values[localeName] = stringValue; stringsMap.set(stringName, stringValue); } @@ -650,31 +650,31 @@ export class LocalizationPlugin implements Webpack.Plugin { // START misc options // eslint-disable-next-line no-lone-blocks { - this._globsToIgnore = this._options.globsToIgnore; + this.#globsToIgnore = this.#options.globsToIgnore; } // END misc options // START options.localizedData - if (this._options.localizedData) { - this._ignoreMissingResxComments = this._options.localizedData.ignoreMissingResxComments; + if (this.#options.localizedData) { + this.#ignoreMissingResxComments = this.#options.localizedData.ignoreMissingResxComments; // START options.localizedData.passthroughLocale - if (this._options.localizedData.passthroughLocale) { + if (this.#options.localizedData.passthroughLocale) { const { usePassthroughLocale, passthroughLocaleName = 'passthrough' } = - this._options.localizedData.passthroughLocale; + this.#options.localizedData.passthroughLocale; if (usePassthroughLocale) { - this._passthroughLocaleName = passthroughLocaleName; - this._locales.add(passthroughLocaleName); + this.#passthroughLocaleName = passthroughLocaleName; + this.#locales.add(passthroughLocaleName); } } // END options.localizedData.passthroughLocale // START options.localizedData.translatedStrings - const { translatedStrings } = this._options.localizedData; - this._resolvedTranslatedStringsFromOptions = {}; + const { translatedStrings } = this.#options.localizedData; + this.#resolvedTranslatedStringsFromOptions = {}; if (translatedStrings) { for (const [localeName, locale] of Object.entries(translatedStrings)) { - if (this._locales.has(localeName)) { + if (this.#locales.has(localeName)) { errors.push( Error( `The locale "${localeName}" appears multiple times. ` + @@ -688,9 +688,9 @@ export class LocalizationPlugin implements Webpack.Plugin { return { errors, warnings }; } - this._locales.add(localeName); - this._resolvedLocalizedStrings.set(localeName, new Map>()); - this._resolvedTranslatedStringsFromOptions[localeName] = {}; + this.#locales.add(localeName); + this.#resolvedLocalizedStrings.set(localeName, new Map>()); + this.#resolvedTranslatedStringsFromOptions[localeName] = {}; const locFilePathsInLocale: Set = new Set(); @@ -715,7 +715,7 @@ export class LocalizationPlugin implements Webpack.Plugin { ? path.resolve(configuration.context!, locFileDataFromOptions) : locFileDataFromOptions; - this._resolvedTranslatedStringsFromOptions[localeName][normalizedLocFilePath] = + this.#resolvedTranslatedStringsFromOptions[localeName][normalizedLocFilePath] = normalizedLocFileDataFromOptions; } } @@ -724,20 +724,20 @@ export class LocalizationPlugin implements Webpack.Plugin { // END options.localizedData.translatedStrings // START options.localizedData.defaultLocale - if (this._options.localizedData.defaultLocale) { - const { localeName, fillMissingTranslationStrings } = this._options.localizedData.defaultLocale; - if (this._options.localizedData.defaultLocale.localeName) { - if (this._locales.has(localeName)) { + if (this.#options.localizedData.defaultLocale) { + const { localeName, fillMissingTranslationStrings } = this.#options.localizedData.defaultLocale; + if (this.#options.localizedData.defaultLocale.localeName) { + if (this.#locales.has(localeName)) { errors.push(new Error('The default locale is also specified in the translated strings.')); return { errors, warnings }; } else if (!ensureValidLocaleName(localeName)) { return { errors, warnings }; } - this._locales.add(localeName); - this._resolvedLocalizedStrings.set(localeName, new Map>()); - this._defaultLocale = localeName; - this._fillMissingTranslationStrings = !!fillMissingTranslationStrings; + this.#locales.add(localeName); + this.#resolvedLocalizedStrings.set(localeName, new Map>()); + this.#defaultLocale = localeName; + this.#fillMissingTranslationStrings = !!fillMissingTranslationStrings; } else { errors.push(new Error('Missing default locale name')); return { errors, warnings }; @@ -749,18 +749,18 @@ export class LocalizationPlugin implements Webpack.Plugin { // END options.localizedData.defaultLocale // START options.localizedData.pseudoLocales - if (this._options.localizedData.pseudolocales) { + if (this.#options.localizedData.pseudolocales) { for (const [pseudolocaleName, pseudoLocaleOpts] of Object.entries( - this._options.localizedData.pseudolocales + this.#options.localizedData.pseudolocales )) { - if (this._defaultLocale === pseudolocaleName) { + if (this.#defaultLocale === pseudolocaleName) { errors.push( new Error(`A pseudolocale (${pseudolocaleName}) name is also the default locale name.`) ); return { errors, warnings }; } - if (this._locales.has(pseudolocaleName)) { + if (this.#locales.has(pseudolocaleName)) { errors.push( new Error( `A pseudolocale (${pseudolocaleName}) name is also specified in the translated strings.` @@ -769,30 +769,30 @@ export class LocalizationPlugin implements Webpack.Plugin { return { errors, warnings }; } - this._pseudolocalizers.set(pseudolocaleName, getPseudolocalizer(pseudoLocaleOpts)); - this._locales.add(pseudolocaleName); - this._resolvedLocalizedStrings.set(pseudolocaleName, new Map>()); + this.#pseudolocalizers.set(pseudolocaleName, getPseudolocalizer(pseudoLocaleOpts)); + this.#locales.add(pseudolocaleName); + this.#resolvedLocalizedStrings.set(pseudolocaleName, new Map>()); } } // END options.localizedData.pseudoLocales // START options.localizedData.normalizeResxNewlines - if (this._options.localizedData.normalizeResxNewlines) { - switch (this._options.localizedData.normalizeResxNewlines) { + if (this.#options.localizedData.normalizeResxNewlines) { + switch (this.#options.localizedData.normalizeResxNewlines) { case 'crlf': { - this._resxNewlineNormalization = NewlineKind.CrLf; + this.#resxNewlineNormalization = NewlineKind.CrLf; break; } case 'lf': { - this._resxNewlineNormalization = NewlineKind.Lf; + this.#resxNewlineNormalization = NewlineKind.Lf; break; } default: { errors.push( new Error( - `Unexpected value "${this._options.localizedData.normalizeResxNewlines}" for option ` + + `Unexpected value "${this.#options.localizedData.normalizeResxNewlines}" for option ` + '"localizedData.normalizeResxNewlines"' ) ); @@ -808,13 +808,13 @@ export class LocalizationPlugin implements Webpack.Plugin { // START options.noStringsLocaleName if ( - this._options.noStringsLocaleName === undefined || - this._options.noStringsLocaleName === null || - !ensureValidLocaleName(this._options.noStringsLocaleName) + this.#options.noStringsLocaleName === undefined || + this.#options.noStringsLocaleName === null || + !ensureValidLocaleName(this.#options.noStringsLocaleName) ) { - this._noStringsLocaleName = 'none'; + this.#noStringsLocaleName = 'none'; } else { - this._noStringsLocaleName = this._options.noStringsLocaleName; + this.#noStringsLocaleName = this.#options.noStringsLocaleName; } // END options.noStringsLocaleName @@ -822,7 +822,7 @@ export class LocalizationPlugin implements Webpack.Plugin { } private _getPlaceholderString(): IStringPlaceholder { - const suffix: string = (this._stringPlaceholderCounter++).toString(); + const suffix: string = (this.#stringPlaceholderCounter++).toString(); return { value: `${Constants.STRING_PLACEHOLDER_PREFIX}_\\_${Constants.STRING_PLACEHOLDER_LABEL}_${suffix}`, suffix: suffix diff --git a/webpack/webpack4-module-minifier-plugin/src/AsyncImportCompressionPlugin.ts b/webpack/webpack4-module-minifier-plugin/src/AsyncImportCompressionPlugin.ts index 6bae5be94cc..1a6ef0942dc 100644 --- a/webpack/webpack4-module-minifier-plugin/src/AsyncImportCompressionPlugin.ts +++ b/webpack/webpack4-module-minifier-plugin/src/AsyncImportCompressionPlugin.ts @@ -102,10 +102,10 @@ function needChunkOnDemandLoadingCode(chunk: webpack.compilation.Chunk): boolean * Also ensures that the code seen by the minifier does not contain chunk ids, and is therefore portable across chunks/compilations. */ export class AsyncImportCompressionPlugin implements Plugin { - private readonly _minifierHooks: IModuleMinifierPluginHooks; + readonly #minifierHooks: IModuleMinifierPluginHooks; public constructor(minifierHooks: IModuleMinifierPluginHooks) { - this._minifierHooks = minifierHooks; + this.#minifierHooks = minifierHooks; } public apply(compiler: Compiler): void { @@ -113,7 +113,7 @@ export class AsyncImportCompressionPlugin implements Plugin { const asyncImportGroups: Map = new Map(); let rankedImportGroups: IAsyncImportMetadata[] | undefined; - this._minifierHooks.postProcessCodeFragment.tap( + this.#minifierHooks.postProcessCodeFragment.tap( { name: PLUGIN_NAME, stage: -1 @@ -157,7 +157,7 @@ export class AsyncImportCompressionPlugin implements Plugin { const chunkExpression: string = meta.index < 0 ? JSON.stringify(meta.chunkIds) : `${meta.index}`; - const mapped: string | number | undefined = this._minifierHooks.finalModuleId.call( + const mapped: string | number | undefined = this.#minifierHooks.finalModuleId.call( module.id!, context.compilation ); diff --git a/webpack/webpack4-module-minifier-plugin/src/ModuleMinifierPlugin.ts b/webpack/webpack4-module-minifier-plugin/src/ModuleMinifierPlugin.ts index 40716e76ee6..2687e53237c 100644 --- a/webpack/webpack4-module-minifier-plugin/src/ModuleMinifierPlugin.ts +++ b/webpack/webpack4-module-minifier-plugin/src/ModuleMinifierPlugin.ts @@ -163,10 +163,10 @@ export class ModuleMinifierPlugin implements webpack.Plugin { public readonly hooks: IModuleMinifierPluginHooks; public minifier: IModuleMinifier; - private readonly _enhancers: webpack.Plugin[]; - private readonly _sourceMap: boolean | undefined; + readonly #enhancers: webpack.Plugin[]; + readonly #sourceMap: boolean | undefined; - private readonly _optionsForHash: IOptionsForHash; + readonly #optionsForHash: IOptionsForHash; public constructor(options: IModuleMinifierPluginOptions) { this.hooks = { @@ -179,26 +179,26 @@ export class ModuleMinifierPlugin implements webpack.Plugin { const { minifier, sourceMap, usePortableModules = false, compressAsyncImports = false } = options; - this._optionsForHash = { + this.#optionsForHash = { ...options, minifier: undefined, revision: CODE_GENERATION_REVISION }; - this._enhancers = []; + this.#enhancers = []; if (usePortableModules) { - this._enhancers.push(new PortableMinifierModuleIdsPlugin(this.hooks)); + this.#enhancers.push(new PortableMinifierModuleIdsPlugin(this.hooks)); } if (compressAsyncImports) { - this._enhancers.push(new AsyncImportCompressionPlugin(this.hooks)); + this.#enhancers.push(new AsyncImportCompressionPlugin(this.hooks)); } this.hooks.rehydrateAssets.tap(PLUGIN_NAME, defaultRehydrateAssets); this.minifier = minifier; - this._sourceMap = sourceMap; + this.#sourceMap = sourceMap; } public static getCompilationStatistics( @@ -208,7 +208,7 @@ export class ModuleMinifierPlugin implements webpack.Plugin { } public apply(compiler: webpack.Compiler): void { - for (const enhancer of this._enhancers) { + for (const enhancer of this.#enhancers) { enhancer.apply(compiler); } @@ -217,14 +217,14 @@ export class ModuleMinifierPlugin implements webpack.Plugin { } = compiler; // The explicit setting is preferred due to accuracy, but try to guess based on devtool const useSourceMaps: boolean = - typeof this._sourceMap === 'boolean' - ? this._sourceMap + typeof this.#sourceMap === 'boolean' + ? this.#sourceMap : typeof devtool === 'string' ? devtool.endsWith('source-map') : mode === 'production' && devtool !== false; - this._optionsForHash.sourceMap = useSourceMaps; - const binaryConfig: Uint8Array = Buffer.from(JSON.stringify(this._optionsForHash), 'utf-8'); + this.#optionsForHash.sourceMap = useSourceMaps; + const binaryConfig: Uint8Array = Buffer.from(JSON.stringify(this.#optionsForHash), 'utf-8'); compiler.hooks.thisCompilation.tap( PLUGIN_NAME, diff --git a/webpack/webpack4-module-minifier-plugin/src/PortableMinifierIdsPlugin.ts b/webpack/webpack4-module-minifier-plugin/src/PortableMinifierIdsPlugin.ts index d52230ee6b1..9b467280a19 100644 --- a/webpack/webpack4-module-minifier-plugin/src/PortableMinifierIdsPlugin.ts +++ b/webpack/webpack4-module-minifier-plugin/src/PortableMinifierIdsPlugin.ts @@ -40,10 +40,10 @@ const STABLE_MODULE_ID_REGEX: RegExp = /(? = new Map(); - this._minifierHooks.finalModuleId.tap(PLUGIN_NAME, (id: string | number | undefined) => { + this.#minifierHooks.finalModuleId.tap(PLUGIN_NAME, (id: string | number | undefined) => { return id === undefined ? id : stableIdToFinalId.get(id); }); - this._minifierHooks.postProcessCodeFragment.tap( + this.#minifierHooks.postProcessCodeFragment.tap( PLUGIN_NAME, (source: ReplaceSource, context: IPostProcessFragmentContext) => { const code: string = source.original().source() as string; @@ -83,7 +83,7 @@ export class PortableMinifierModuleIdsPlugin implements Plugin { let match: RegExpExecArray | null = null; while ((match = STABLE_MODULE_ID_REGEX.exec(code))) { const id: string = match[1]; - const mapped: string | number | undefined = this._minifierHooks.finalModuleId.call( + const mapped: string | number | undefined = this.#minifierHooks.finalModuleId.call( id, context.compilation ); diff --git a/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts b/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts index e5a54496bad..e3e8ddbcc97 100644 --- a/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts +++ b/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts @@ -112,35 +112,35 @@ export function getPluginInstance(compiler: Compiler | undefined): LocalizationP * @public */ export class LocalizationPlugin implements WebpackPluginInstance { - private readonly _locFiles: Map = new Map(); + readonly #locFiles: Map = new Map(); /** * @internal */ public readonly _options: ILocalizationPluginOptions; - private readonly _resolvedTranslatedStringsFromOptions: Map< + readonly #resolvedTranslatedStringsFromOptions: Map< string, Map> > = new Map(); - private readonly _stringPlaceholderBySuffix: Map = new Map(); - private readonly _customDataPlaceholderBySuffix: Map = new Map(); - private readonly _customDataPlaceholderByUniqueId: Map = new Map(); - private _passthroughLocaleName!: string; - private _defaultLocale!: string; - private _noStringsLocaleName!: string; - private _fillMissingTranslationStrings!: boolean; + readonly #stringPlaceholderBySuffix: Map = new Map(); + readonly #customDataPlaceholderBySuffix: Map = new Map(); + readonly #customDataPlaceholderByUniqueId: Map = new Map(); + #passthroughLocaleName!: string; + #defaultLocale!: string; + #noStringsLocaleName!: string; + #fillMissingTranslationStrings!: boolean; /** * @remarks * Include the `chunk` parameter so that the functions arity is the same as the * `ValueForLocaleFn` type. */ - private _formatLocaleForFilename!: (loc: string, chunk: unknown) => string; - private readonly _pseudolocalizers: Map string> = new Map(); + #formatLocaleForFilename!: (loc: string, chunk: unknown) => string; + readonly #pseudolocalizers: Map string> = new Map(); /** * The set of locales that have translations provided. */ - private _translatedLocales: Set = new Set(); + #translatedLocales: Set = new Set(); public constructor(options: ILocalizationPluginOptions) { this._options = options; @@ -278,7 +278,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { } if (chunkIdsWithStrings.size === 0) { - return this._formatLocaleForFilename(this._noStringsLocaleName, undefined); + return this.#formatLocaleForFilename(this.#noStringsLocaleName, undefined); } else if (chunkIdsWithoutStrings.size === 0) { return `" + ${localeExpression} + "`; } else { @@ -301,7 +301,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { } const noLocaleExpression: string = JSON.stringify( - this._formatLocaleForFilename(this._noStringsLocaleName, undefined) + this.#formatLocaleForFilename(this.#noStringsLocaleName, undefined) ); return `" + (${JSON.stringify(chunkMapping)}[chunkId]?${ @@ -318,11 +318,11 @@ export class LocalizationPlugin implements WebpackPluginInstance { runtimeLocaleExpression ); // Ensure that the initial name maps to a file that should exist in the final output - locale = isLocalized ? this._defaultLocale : this._noStringsLocaleName; + locale = isLocalized ? this.#defaultLocale : this.#noStringsLocaleName; } return assetPath.replace( Constants.LOCALE_FILENAME_TOKEN_REGEX, - this._formatLocaleForFilename(locale, undefined) + this.#formatLocaleForFilename(locale, undefined) ); } } else { @@ -341,7 +341,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING - 1 }, async (): Promise => { - const locales: Set = this._translatedLocales; + const locales: Set = this.#translatedLocales; const { chunkGraph, chunks } = compilation; const { localizationStats: statsOptions } = this._options; @@ -391,10 +391,10 @@ export class LocalizationPlugin implements WebpackPluginInstance { compilation, cache, locales, - defaultLocale: this._defaultLocale, - passthroughLocaleName: this._passthroughLocaleName, - fillMissingTranslationStrings: this._fillMissingTranslationStrings, - formatLocaleForFilenameFn: this._formatLocaleForFilename, + defaultLocale: this.#defaultLocale, + passthroughLocaleName: this.#passthroughLocaleName, + fillMissingTranslationStrings: this.#fillMissingTranslationStrings, + formatLocaleForFilenameFn: this.#formatLocaleForFilename, // Chunk-specific values chunk, asset, @@ -412,8 +412,8 @@ export class LocalizationPlugin implements WebpackPluginInstance { compilation, cache, hasUrlGenerator: chunksWithUrlGenerators.has(chunk), - noStringsLocaleName: this._noStringsLocaleName, - formatLocaleForFilenameFn: this._formatLocaleForFilename, + noStringsLocaleName: this.#noStringsLocaleName, + formatLocaleForFilenameFn: this.#formatLocaleForFilename, // Chunk-specific values chunk, asset, @@ -493,13 +493,13 @@ export class LocalizationPlugin implements WebpackPluginInstance { ): Promise> { const locFileData: ReadonlyMap = convertLocalizationFileToLocData(localizedResourceData); const fileInfo: IFileTranslationInfo = this._addLocFileAndGetPlaceholders( - this._defaultLocale, + this.#defaultLocale, localizedFileKey, locFileData ); const missingLocales: string[] = []; - for (const [translatedLocaleName, translatedStrings] of this._resolvedTranslatedStringsFromOptions) { + for (const [translatedLocaleName, translatedStrings] of this.#resolvedTranslatedStringsFromOptions) { const translatedLocFileFromOptions: ILocaleFileData | undefined = translatedStrings.get(localizedFileKey); @@ -545,7 +545,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { } } - for (const [pseudolocaleName, pseudolocalizer] of this._pseudolocalizers) { + for (const [pseudolocaleName, pseudolocalizer] of this.#pseudolocalizers) { const pseudolocFileData: Map = new Map(); for (const [stringName, stringValue] of locFileData) { @@ -564,7 +564,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { * @public */ public getPlaceholder(localizedFileKey: string, stringName: string): IStringPlaceholder | undefined { - const file: IFileTranslationInfo | undefined = this._locFiles.get(localizedFileKey); + const file: IFileTranslationInfo | undefined = this.#locFiles.get(localizedFileKey); if (!file) { return undefined; } @@ -579,7 +579,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { placeholderUniqueId: string ): string { let placeholder: ICustomDataPlaceholder | undefined = - this._customDataPlaceholderByUniqueId.get(placeholderUniqueId); + this.#customDataPlaceholderByUniqueId.get(placeholderUniqueId); if (!placeholder) { // Get a hash of the unique ID to make sure its value doesn't interfere with our placeholder tokens const suffix: string = Buffer.from(placeholderUniqueId, 'utf-8').toString('hex'); @@ -588,8 +588,8 @@ export class LocalizationPlugin implements WebpackPluginInstance { suffix, valueForLocaleFn }; - this._customDataPlaceholderBySuffix.set(suffix, placeholder); - this._customDataPlaceholderByUniqueId.set(placeholderUniqueId, placeholder); + this.#customDataPlaceholderBySuffix.set(suffix, placeholder); + this.#customDataPlaceholderByUniqueId.set(placeholderUniqueId, placeholder); } else if (placeholder.valueForLocaleFn !== valueForLocaleFn) { throw new Error( `${this.getCustomDataPlaceholderForValueFunction.name} has already been called with "${placeholderUniqueId}" ` + @@ -604,14 +604,14 @@ export class LocalizationPlugin implements WebpackPluginInstance { * @internal */ public _getStringDataForSerialNumber(suffix: string): IStringPlaceholder | undefined { - return this._stringPlaceholderBySuffix.get(suffix); + return this.#stringPlaceholderBySuffix.get(suffix); } /** * @internal */ public _getCustomDataForSerialNumber(suffix: string): ICustomDataPlaceholder | undefined { - return this._customDataPlaceholderBySuffix.get(suffix); + return this.#customDataPlaceholderBySuffix.get(suffix); } private _addLocFileAndGetPlaceholders( @@ -619,14 +619,14 @@ export class LocalizationPlugin implements WebpackPluginInstance { localizedFileKey: string, localizedFileData: ReadonlyMap ): IFileTranslationInfo { - let fileInfo: IFileTranslationInfo | undefined = this._locFiles.get(localizedFileKey); + let fileInfo: IFileTranslationInfo | undefined = this.#locFiles.get(localizedFileKey); if (!fileInfo) { fileInfo = { placeholders: new Map(), translations: new Map(), renderedPlaceholders: {} }; - this._locFiles.set(localizedFileKey, fileInfo); + this.#locFiles.set(localizedFileKey, fileInfo); } const { placeholders, translations } = fileInfo; const locFilePrefix: string = Buffer.from(localizedFileKey, 'utf-8').toString('hex') + '$'; @@ -646,7 +646,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { }; placeholders.set(stringName, placeholder); - this._stringPlaceholderBySuffix.set(suffix, placeholder); + this.#stringPlaceholderBySuffix.set(suffix, placeholder); } resultObject[stringName] = placeholder.value; @@ -707,8 +707,8 @@ export class LocalizationPlugin implements WebpackPluginInstance { if (passthroughLocale) { const { usePassthroughLocale, passthroughLocaleName = 'passthrough' } = passthroughLocale; if (usePassthroughLocale) { - this._passthroughLocaleName = passthroughLocaleName; - this._translatedLocales.add(passthroughLocaleName); + this.#passthroughLocaleName = passthroughLocaleName; + this.#translatedLocales.add(passthroughLocaleName); } } // END options.localizedData.passthroughLocale @@ -718,10 +718,10 @@ export class LocalizationPlugin implements WebpackPluginInstance { configuration.context?.startsWith('/') ? path.posix.resolve : path.resolve ).bind(0, configuration.context!); const { translatedStrings } = localizedData; - this._resolvedTranslatedStringsFromOptions.clear(); + this.#resolvedTranslatedStringsFromOptions.clear(); if (translatedStrings) { for (const [localeName, locale] of Object.entries(translatedStrings)) { - if (this._translatedLocales.has(localeName)) { + if (this.#translatedLocales.has(localeName)) { errors.push( new WebpackError( `The locale "${localeName}" appears multiple times. ` + @@ -735,9 +735,9 @@ export class LocalizationPlugin implements WebpackPluginInstance { return { errors, warnings }; } - this._translatedLocales.add(localeName); + this.#translatedLocales.add(localeName); const resolvedFromOptionsForLocale: Map = new Map(); - this._resolvedTranslatedStringsFromOptions.set(localeName, resolvedFromOptionsForLocale); + this.#resolvedTranslatedStringsFromOptions.set(localeName, resolvedFromOptionsForLocale); for (const [locFilePath, locFileDataFromOptions] of Object.entries(locale)) { const normalizedLocFilePath: string = resolveRelativeToContext(locFilePath); @@ -768,16 +768,16 @@ export class LocalizationPlugin implements WebpackPluginInstance { if (defaultLocale) { const { localeName, fillMissingTranslationStrings } = defaultLocale; if (localeName) { - if (this._translatedLocales.has(localeName)) { + if (this.#translatedLocales.has(localeName)) { errors.push(new WebpackError('The default locale is also specified in the translated strings.')); return { errors, warnings }; } else if (!ensureValidLocaleName(localeName)) { return { errors, warnings }; } - this._translatedLocales.add(localeName); - this._defaultLocale = localeName; - this._fillMissingTranslationStrings = !!fillMissingTranslationStrings; + this.#translatedLocales.add(localeName); + this.#defaultLocale = localeName; + this.#fillMissingTranslationStrings = !!fillMissingTranslationStrings; } else { errors.push(new WebpackError('Missing default locale name')); return { errors, warnings }; @@ -792,14 +792,14 @@ export class LocalizationPlugin implements WebpackPluginInstance { const { pseudolocales } = localizedData; if (pseudolocales) { for (const [pseudolocaleName, pseudoLocaleOpts] of Object.entries(pseudolocales)) { - if (this._defaultLocale === pseudolocaleName) { + if (this.#defaultLocale === pseudolocaleName) { errors.push( new WebpackError(`A pseudolocale (${pseudolocaleName}) name is also the default locale name.`) ); return { errors, warnings }; } - if (this._translatedLocales.has(pseudolocaleName)) { + if (this.#translatedLocales.has(pseudolocaleName)) { errors.push( new WebpackError( `A pseudolocale (${pseudolocaleName}) name is also specified in the translated strings.` @@ -808,8 +808,8 @@ export class LocalizationPlugin implements WebpackPluginInstance { return { errors, warnings }; } - this._pseudolocalizers.set(pseudolocaleName, getPseudolocalizer(pseudoLocaleOpts)); - this._translatedLocales.add(pseudolocaleName); + this.#pseudolocalizers.set(pseudolocaleName, getPseudolocalizer(pseudoLocaleOpts)); + this.#translatedLocales.add(pseudolocaleName); } } // END options.localizedData.pseudoLocales @@ -825,15 +825,15 @@ export class LocalizationPlugin implements WebpackPluginInstance { noStringsLocaleName === null || !ensureValidLocaleName(noStringsLocaleName) ) { - this._noStringsLocaleName = 'none'; + this.#noStringsLocaleName = 'none'; } else { - this._noStringsLocaleName = noStringsLocaleName; + this.#noStringsLocaleName = noStringsLocaleName; } // END options.noStringsLocaleName // START options.formatLocaleForFilename const { formatLocaleForFilename = (localeName: string) => localeName } = this._options; - this._formatLocaleForFilename = formatLocaleForFilename; + this.#formatLocaleForFilename = formatLocaleForFilename; // END options.formatLocaleForFilename return { errors, warnings }; } diff --git a/webpack/webpack5-localization-plugin/src/TrueHashPlugin.ts b/webpack/webpack5-localization-plugin/src/TrueHashPlugin.ts index 2c208ffce1b..0bd0921524d 100644 --- a/webpack/webpack5-localization-plugin/src/TrueHashPlugin.ts +++ b/webpack/webpack5-localization-plugin/src/TrueHashPlugin.ts @@ -26,17 +26,17 @@ export interface ITrueHashPluginOptions { * @public */ export class TrueHashPlugin implements WebpackPluginInstance { - private readonly _options: ITrueHashPluginOptions; + readonly #options: ITrueHashPluginOptions; public constructor(options: ITrueHashPluginOptions = {}) { - this._options = options; + this.#options = options; } public apply(compiler: Compiler): void { compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation: Compilation) => { const { webpack: thisWebpack } = compiler; const { hashFunction, stageOverride = thisWebpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING - 1 } = - this._options; + this.#options; const hashFn: HashFn = hashFunction ?? getHashFunction({ diff --git a/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts b/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts index bb8af0ad213..26cbe8ad36b 100644 --- a/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts +++ b/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts @@ -14,15 +14,15 @@ import { type ITrueHashPluginOptions, TrueHashPlugin } from '../TrueHashPlugin'; import { markEntity } from '../utilities/EntityMarker'; class InjectCustomPlaceholderPlugin implements webpack.WebpackPluginInstance { - private readonly _localizationPlugin: LocalizationPlugin; - private readonly _localizedChunkNameByLocaleName: Map>; + readonly #localizationPlugin: LocalizationPlugin; + readonly #localizedChunkNameByLocaleName: Map>; public constructor( localizationPlugin: LocalizationPlugin, localizedChunkNameByLocaleName: Map> ) { - this._localizationPlugin = localizationPlugin; - this._localizedChunkNameByLocaleName = localizedChunkNameByLocaleName; + this.#localizationPlugin = localizationPlugin; + this.#localizedChunkNameByLocaleName = localizedChunkNameByLocaleName; } public apply(compiler: Compiler): void { @@ -30,9 +30,9 @@ class InjectCustomPlaceholderPlugin implements webpack.WebpackPluginInstance { const printLocalizedChunkName: 'printLocalizedChunkName' = 'printLocalizedChunkName'; const { runtime, RuntimeModule, Template, RuntimeGlobals } = compiler.webpack; - const localizationPlugin: LocalizationPlugin = this._localizationPlugin; + const localizationPlugin: LocalizationPlugin = this.#localizationPlugin; const localizedChunkNameByLocaleName: Map> = this - ._localizedChunkNameByLocaleName; + .#localizedChunkNameByLocaleName; function getLocalizedChunkNamesString(locale: string): string { return `/* ${locale} */ ${JSON.stringify(localizedChunkNameByLocaleName.get(locale))}`; diff --git a/webpack/webpack5-localization-plugin/src/test/MemFSPlugin.ts b/webpack/webpack5-localization-plugin/src/test/MemFSPlugin.ts index 5cc4e0508d8..12e77b2e79b 100644 --- a/webpack/webpack5-localization-plugin/src/test/MemFSPlugin.ts +++ b/webpack/webpack5-localization-plugin/src/test/MemFSPlugin.ts @@ -8,10 +8,10 @@ type IntermediateFileSystem = Compiler['intermediateFileSystem']; const PLUGIN_NAME: 'MemFSPlugin' = 'MemFSPlugin'; export class MemFSPlugin implements WebpackPluginInstance { - private readonly _memfs: Volume; + readonly #memfs: Volume; public constructor(memfs: Volume) { - this._memfs = memfs; + this.#memfs = memfs; } public apply(compiler: Compiler): void { @@ -19,9 +19,9 @@ export class MemFSPlugin implements WebpackPluginInstance { if (!nodeFileSystem) { throw new Error('MemFSPlugin requires compiler.inputFileSystem to be defined'); } - compiler.inputFileSystem = this._memfs as unknown as InputFileSystem; - compiler.intermediateFileSystem = this._memfs as unknown as IntermediateFileSystem; - compiler.outputFileSystem = this._memfs as unknown as OutputFileSystem; + compiler.inputFileSystem = this.#memfs as unknown as InputFileSystem; + compiler.intermediateFileSystem = this.#memfs as unknown as IntermediateFileSystem; + compiler.outputFileSystem = this.#memfs as unknown as OutputFileSystem; compiler.resolverFactory.hooks.resolveOptions.for('loader').tap( { stage: 10, diff --git a/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts b/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts index b98be12b188..61774c4fe2d 100644 --- a/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts +++ b/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts @@ -176,10 +176,10 @@ export class ModuleMinifierPlugin implements WebpackPluginInstance { public readonly hooks: IModuleMinifierPluginHooks; public minifier: IModuleMinifier; - private readonly _enhancers: WebpackPluginInstance[]; - private readonly _sourceMap: boolean | undefined; + readonly #enhancers: WebpackPluginInstance[]; + readonly #sourceMap: boolean | undefined; - private readonly _optionsForHash: IOptionsForHash; + readonly #optionsForHash: IOptionsForHash; public constructor(options: IModuleMinifierPluginOptions) { this.hooks = { @@ -190,18 +190,18 @@ export class ModuleMinifierPlugin implements WebpackPluginInstance { const { minifier, sourceMap } = options; - this._optionsForHash = { + this.#optionsForHash = { ...options, minifier: undefined, revision: CODE_GENERATION_REVISION }; - this._enhancers = []; + this.#enhancers = []; this.hooks.rehydrateAssets.tap(PLUGIN_NAME, defaultRehydrateAssets); this.minifier = minifier; - this._sourceMap = sourceMap; + this.#sourceMap = sourceMap; } public static getCompilationStatistics(compilation: Compilation): IModuleMinifierPluginStats | undefined { @@ -209,7 +209,7 @@ export class ModuleMinifierPlugin implements WebpackPluginInstance { } public apply(compiler: Compiler): void { - for (const enhancer of this._enhancers) { + for (const enhancer of this.#enhancers) { enhancer.apply(compiler); } @@ -223,14 +223,14 @@ export class ModuleMinifierPlugin implements WebpackPluginInstance { const { CachedSource, ConcatSource, RawSource, ReplaceSource, SourceMapSource } = webpack.sources; // The explicit setting is preferred due to accuracy, but try to guess based on devtool const useSourceMaps: boolean = - typeof this._sourceMap === 'boolean' - ? this._sourceMap + typeof this.#sourceMap === 'boolean' + ? this.#sourceMap : typeof devtool === 'string' ? devtool.endsWith('source-map') : mode === 'production' && devtool !== false; - this._optionsForHash.sourceMap = useSourceMaps; - const binaryConfig: Buffer = Buffer.from(JSON.stringify(this._optionsForHash), 'utf-8'); + this.#optionsForHash.sourceMap = useSourceMaps; + const binaryConfig: Buffer = Buffer.from(JSON.stringify(this.#optionsForHash), 'utf-8'); compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation, compilationData) => { const { normalModuleFactory } = compilationData; From 946d39a0c7e9f25443e720ad8e37436ebaa53449 Mon Sep 17 00:00:00 2001 From: Bharat Middha <5100938+bmiddha@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:27:37 -0700 Subject: [PATCH 2/3] refactor: convert private methods/accessors to # syntax Extend the earlier private-fields conversion to also cover private methods and get/set accessors across the heft and webpack plugin scopes, using the same AST-driven tool. Two candidates in SassProcessor.ts (the _cache get/set accessor pair) were left as private because the tool's per-declaration reference tracking cannot safely disambiguate the shared accessor symbol. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14 --- .../src/ApiExtractorPlugin.ts | 16 +-- .../heft-jest-plugin/src/HeftJestReporter.ts | 36 +++--- .../heft-jest-plugin/src/JestPlugin.ts | 26 ++--- heft-plugins/heft-lint-plugin/src/Eslint.ts | 6 +- .../heft-lint-plugin/src/LintPlugin.ts | 20 ++-- heft-plugins/heft-lint-plugin/src/Tslint.ts | 6 +- .../src/DeferredWatchFileSystem.ts | 16 +-- .../heft-rspack-plugin/src/RspackPlugin.ts | 50 ++++---- .../heft-sass-plugin/src/SassProcessor.ts | 60 +++++----- .../src/ServerlessStackPlugin.ts | 18 +-- .../src/TypeScriptBuilder.ts | 110 +++++++++--------- .../src/TypeScriptPlugin.ts | 16 +-- .../fileSystem/TypeScriptCachedFileSystem.ts | 28 ++--- .../src/Webpack4Plugin.ts | 44 +++---- .../src/DeferredWatchFileSystem.ts | 16 +-- .../src/Webpack5Plugin.ts | 50 ++++---- .../src/HashedFolderDependency.ts | 4 +- .../src/EmbeddedDependenciesWebpackPlugin.ts | 18 +-- .../src/LocalizationPlugin.ts | 36 +++--- .../src/LocalizationPlugin.ts | 8 +- 20 files changed, 292 insertions(+), 292 deletions(-) diff --git a/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts b/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts index 01a995933ed..fb15b8008f8 100644 --- a/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts +++ b/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts @@ -72,9 +72,9 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { runOptions: IHeftTaskRunHookOptions & Partial ): Promise => { const result: IApiExtractorConfigurationResult | undefined = - await this._getApiExtractorConfigurationAsync(taskSession, heftConfiguration); + await this.#getApiExtractorConfigurationAsync(taskSession, heftConfiguration); if (result) { - await this._runApiExtractorAsync( + await this.#runApiExtractorAsync( taskSession, heftConfiguration, runOptions, @@ -88,7 +88,7 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { taskSession.hooks.runIncremental.tapPromise(PLUGIN_NAME, runAsync); } - private async _getApiExtractorConfigurationFilePathAsync( + async #getApiExtractorConfigurationFilePathAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { @@ -113,7 +113,7 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { return this.#apiExtractorConfigurationFilePath; } - private async _getApiExtractorConfigurationAsync( + async #getApiExtractorConfigurationAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, ignoreMissingEntryPoint?: boolean @@ -122,14 +122,14 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { // including support for rig.json. However, Heft does not load the @microsoft/api-extractor package at all // unless it sees a config/api-extractor.json file. Thus we need to do our own lookup here. const apiExtractorConfigurationFilePath: string | undefined = - await this._getApiExtractorConfigurationFilePathAsync(taskSession, heftConfiguration); + await this.#getApiExtractorConfigurationFilePathAsync(taskSession, heftConfiguration); if (!apiExtractorConfigurationFilePath) { return undefined; } // Since the config file exists, we can assume that API Extractor is available. Attempt to resolve // and import the package. If the resolution fails, a helpful error is thrown. - const apiExtractorPackage: typeof TApiExtractor = await this._getApiExtractorPackageAsync( + const apiExtractorPackage: typeof TApiExtractor = await this.#getApiExtractorPackageAsync( taskSession, heftConfiguration ); @@ -149,7 +149,7 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { return { apiExtractorPackage, apiExtractorConfiguration }; } - private async _getApiExtractorPackageAsync( + async #getApiExtractorPackageAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { @@ -163,7 +163,7 @@ export default class ApiExtractorPlugin implements IHeftTaskPlugin { return this.#apiExtractor; } - private async _runApiExtractorAsync( + async #runApiExtractorAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, runOptions: IHeftTaskRunHookOptions & Partial, diff --git a/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts b/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts index 3233729a3d5..7d32a4c9ca8 100644 --- a/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts +++ b/heft-plugins/heft-jest-plugin/src/HeftJestReporter.ts @@ -49,7 +49,7 @@ export default class HeftJestReporter implements Reporter { public async onTestStart(test: Test): Promise { this.#terminal.writeLine( Colorize.whiteBackground(Colorize.black('START')), - ` ${this._getTestPath(test.path)}` + ` ${this.#getTestPath(test.path)}` ); } @@ -59,7 +59,7 @@ export default class HeftJestReporter implements Reporter { testResult: TestResult, aggregatedResult: AggregatedResult ): Promise { - this._writeConsoleOutput(testResult); + this.#writeConsoleOutput(testResult); const { numPassingTests, numFailingTests, @@ -80,7 +80,7 @@ export default class HeftJestReporter implements Reporter { const memUsage: string = memoryUsage ? `, ${Math.floor(memoryUsage / 1000000)}MB heap size` : ''; const message: string = - ` ${this._getTestPath(test.path)} ` + + ` ${this.#getTestPath(test.path)} ` + `(duration: ${duration}, ${numPassingTests} passed, ${numFailingTests} failed${memUsage})`; if (numFailingTests > 0) { @@ -100,19 +100,19 @@ export default class HeftJestReporter implements Reporter { if (updatedSnapshots) { this.#terminal.writeErrorLine( - `Updated ${this._formatWithPlural(updatedSnapshots, 'snapshot', 'snapshots')}` + `Updated ${this.#formatWithPlural(updatedSnapshots, 'snapshot', 'snapshots')}` ); } if (addedSnapshots) { this.#terminal.writeErrorLine( - `Added ${this._formatWithPlural(addedSnapshots, 'snapshot', 'snapshots')}` + `Added ${this.#formatWithPlural(addedSnapshots, 'snapshot', 'snapshots')}` ); } if (uncheckedSnapshots) { this.#terminal.writeWarningLine( - `${this._formatWithPlural(uncheckedSnapshots, 'snapshot was', 'snapshots were')} not checked` + `${this.#formatWithPlural(uncheckedSnapshots, 'snapshot was', 'snapshots were')} not checked` ); } } @@ -122,30 +122,30 @@ export default class HeftJestReporter implements Reporter { // a build failure and searching its log output for errors. To reduce confusion, we add a prefix // like "|console.error|" to each output line, to clearly distinguish test logging from regular // task output. You can suppress test logging entirely using the "--silent" CLI parameter. - private _writeConsoleOutput(testResult: TestResult): void { + #writeConsoleOutput(testResult: TestResult): void { if (testResult.console) { for (const logEntry of testResult.console) { switch (logEntry.type) { case 'debug': - this._writeConsoleOutputWithLabel('console.debug', logEntry.message); + this.#writeConsoleOutputWithLabel('console.debug', logEntry.message); break; case 'log': - this._writeConsoleOutputWithLabel('console.log', logEntry.message); + this.#writeConsoleOutputWithLabel('console.log', logEntry.message); break; case 'warn': - this._writeConsoleOutputWithLabel('console.warn', logEntry.message); + this.#writeConsoleOutputWithLabel('console.warn', logEntry.message); break; case 'error': - this._writeConsoleOutputWithLabel('console.error', logEntry.message); + this.#writeConsoleOutputWithLabel('console.error', logEntry.message); break; case 'info': - this._writeConsoleOutputWithLabel('console.info', logEntry.message); + this.#writeConsoleOutputWithLabel('console.info', logEntry.message); break; case 'groupCollapsed': if (this.#debugMode) { // The "groupCollapsed" name is too long - this._writeConsoleOutputWithLabel('collapsed', logEntry.message); + this.#writeConsoleOutputWithLabel('collapsed', logEntry.message); } break; @@ -156,7 +156,7 @@ export default class HeftJestReporter implements Reporter { case 'group': case 'time': if (this.#debugMode) { - this._writeConsoleOutputWithLabel( + this.#writeConsoleOutputWithLabel( logEntry.type, `(${logEntry.type}) ${logEntry.message}`, true @@ -172,7 +172,7 @@ export default class HeftJestReporter implements Reporter { } } - private _writeConsoleOutputWithLabel(label: string, message: string, debug?: boolean): void { + #writeConsoleOutputWithLabel(label: string, message: string, debug?: boolean): void { if (message === '') { return; } @@ -198,7 +198,7 @@ export default class HeftJestReporter implements Reporter { // and print a newline. this.#terminal.writeLine('\u001b[0m'); this.#terminal.writeLine( - `Run start. ${this._formatWithPlural(aggregatedResult.numTotalTestSuites, 'test suite', 'test suites')}` + `Run start. ${this.#formatWithPlural(aggregatedResult.numTotalTestSuites, 'test suite', 'test suites')}` ); } @@ -238,11 +238,11 @@ export default class HeftJestReporter implements Reporter { // This reporter doesn't have any errors to throw } - private _getTestPath(fullTestPath: string): string { + #getTestPath(fullTestPath: string): string { return path.relative(this.#buildFolderPath, fullTestPath); } - private _formatWithPlural(num: number, singular: string, plural: string): string { + #formatWithPlural(num: number, singular: string, plural: string): string { return `${num} ${num === 1 ? singular : plural}`; } } diff --git a/heft-plugins/heft-jest-plugin/src/JestPlugin.ts b/heft-plugins/heft-jest-plugin/src/JestPlugin.ts index 168d7a06181..32eefb41729 100644 --- a/heft-plugins/heft-jest-plugin/src/JestPlugin.ts +++ b/heft-plugins/heft-jest-plugin/src/JestPlugin.ts @@ -228,13 +228,13 @@ export default class JestPlugin implements IHeftTaskPlugin { }; taskSession.hooks.run.tapPromise(PLUGIN_NAME, async (runOptions: IHeftTaskRunHookOptions) => { - await this._runJestAsync(taskSession, heftConfiguration, options); + await this.#runJestAsync(taskSession, heftConfiguration, options); }); taskSession.hooks.runIncremental.tapPromise( PLUGIN_NAME, async (runIncrementalOptions: IHeftTaskRunIncrementalHookOptions) => { - await this._runJestWatchAsync( + await this.#runJestWatchAsync( taskSession, heftConfiguration, options, @@ -247,7 +247,7 @@ export default class JestPlugin implements IHeftTaskPlugin { /** * Runs Jest using the provided options. */ - private async _runJestAsync( + async #runJestAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, options: IJestPluginOptions @@ -255,13 +255,13 @@ export default class JestPlugin implements IHeftTaskPlugin { const logger: IScopedLogger = taskSession.logger; const terminal: ITerminal = logger.terminal; - this._setNodeEnvIfRequested(options, logger); + this.#setNodeEnvIfRequested(options, logger); const { getVersion, runCLI } = await import(`@jest/core`); terminal.writeLine(`Using Jest version ${getVersion()}`); const buildFolderPath: string = heftConfiguration.buildFolderPath; - const jestArgv: Config.Argv | undefined = await this._createJestArgvAsync( + const jestArgv: Config.Argv | undefined = await this.#createJestArgvAsync( taskSession, heftConfiguration, options, @@ -279,7 +279,7 @@ export default class JestPlugin implements IHeftTaskPlugin { results: jestResults } = await runCLI(jestArgv, [buildFolderPath]); - this._resetNodeEnv(); + this.#resetNodeEnv(); if (jestResults.numFailedTests > 0) { logger.emitError( @@ -301,7 +301,7 @@ export default class JestPlugin implements IHeftTaskPlugin { /** * Runs Jest using the provided options. */ - private async _runJestWatchAsync( + async #runJestWatchAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, options: IJestPluginOptions, @@ -471,7 +471,7 @@ export default class JestPlugin implements IHeftTaskPlugin { terminal.writeLine(`Using Jest version ${getVersion()}`); const buildFolderPath: string = heftConfiguration.buildFolderPath; - const jestArgv: Config.Argv | undefined = await this._createJestArgvAsync( + const jestArgv: Config.Argv | undefined = await this.#createJestArgvAsync( taskSession, heftConfiguration, options, @@ -491,7 +491,7 @@ export default class JestPlugin implements IHeftTaskPlugin { await Promise.resolve(); if (pendingTestRuns.size > 0) { - this._setNodeEnvIfRequested(options, logger); + this.#setNodeEnvIfRequested(options, logger); this.#executing = true; for (const pendingTestRun of pendingTestRuns) { @@ -518,7 +518,7 @@ export default class JestPlugin implements IHeftTaskPlugin { } } - this._resetNodeEnv(); + this.#resetNodeEnv(); if (!logger.hasErrors) { // If we ran tests and they succeeded, consider the files to no longer be changed. @@ -532,7 +532,7 @@ export default class JestPlugin implements IHeftTaskPlugin { } } - private async _createJestArgvAsync( + async #createJestArgvAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, options: IJestPluginOptions, @@ -796,7 +796,7 @@ export default class JestPlugin implements IHeftTaskPlugin { return _jestConfigurationFileLoader; } - private _setNodeEnvIfRequested(options: IJestPluginOptions, logger: IScopedLogger): void { + #setNodeEnvIfRequested(options: IJestPluginOptions, logger: IScopedLogger): void { if (options.enableNodeEnvManagement) { if (process.env.NODE_ENV) { if (process.env.NODE_ENV !== 'test') { @@ -812,7 +812,7 @@ export default class JestPlugin implements IHeftTaskPlugin { } } - private _resetNodeEnv(): void { + #resetNodeEnv(): void { // unset the NODE_ENV only if we have set it if (this.#nodeEnvSet) { delete process.env.NODE_ENV; diff --git a/heft-plugins/heft-lint-plugin/src/Eslint.ts b/heft-plugins/heft-lint-plugin/src/Eslint.ts index e767a174921..81ca9c87ac9 100644 --- a/heft-plugins/heft-lint-plugin/src/Eslint.ts +++ b/heft-plugins/heft-lint-plugin/src/Eslint.ts @@ -325,14 +325,14 @@ export class Eslint extends LinterBase { // If we are not in the typescript phase, we need to create a typescript program // from the tsconfig file if (!inTypescriptPhase) { - const tsProgram: IExtendedProgram = await this._createTypescriptProgramAsync( + const tsProgram: IExtendedProgram = await this.#createTypescriptProgramAsync( heftConfiguration, taskSession ); @@ -136,7 +136,7 @@ export default class LintPlugin implements IHeftTaskPlugin { // Run the linters to completion. Linters emit errors and warnings to the logger. for (const [tsProgram, changedFiles] of typescriptChangedFiles) { try { - await this._lintAsync({ + await this.#lintAsync({ taskSession, heftConfiguration, tsProgram, @@ -163,7 +163,7 @@ export default class LintPlugin implements IHeftTaskPlugin { }); } - private async _createTypescriptProgramAsync( + async #createTypescriptProgramAsync( heftConfiguration: HeftConfiguration, taskSession: IHeftTaskSession ): Promise { @@ -187,18 +187,18 @@ export default class LintPlugin implements IHeftTaskPlugin { return program; } - private async _ensureInitializedAsync( + async #ensureInitializedAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { // Make sure that we only ever init once by memoizing the init promise if (!this.#initPromise) { - this.#initPromise = this._initInnerAsync(heftConfiguration, taskSession.logger); + this.#initPromise = this.#initInnerAsync(heftConfiguration, taskSession.logger); } await this.#initPromise; } - private async _initInnerAsync(heftConfiguration: HeftConfiguration, logger: IScopedLogger): Promise { + async #initInnerAsync(heftConfiguration: HeftConfiguration, logger: IScopedLogger): Promise { // Locate the tslint linter if enabled this.#tslintConfigFilePath = await Tslint.resolveTslintConfigFilePathAsync(heftConfiguration); if (this.#tslintConfigFilePath) { @@ -221,12 +221,12 @@ export default class LintPlugin implements IHeftTaskPlugin { } } - private async _lintAsync(options: ILintOptions): Promise { + async #lintAsync(options: ILintOptions): Promise { const { taskSession, heftConfiguration, tsProgram, changedFiles, fix, sarifLogPath } = options; // Ensure that we have initialized. This promise is cached, so calling init // multiple times will only init once. - await this._ensureInitializedAsync(taskSession, heftConfiguration); + await this.#ensureInitializedAsync(taskSession, heftConfiguration); const linters: LinterBase[] = []; if (this.#eslintConfigFilePath && this.#eslintToolPath) { @@ -257,10 +257,10 @@ export default class LintPlugin implements IHeftTaskPlugin { } // Now that we know we have initialized properly, run the linter(s) - await Promise.all(linters.map((linter) => this._runLinterAsync(linter, tsProgram, changedFiles))); + await Promise.all(linters.map((linter) => this.#runLinterAsync(linter, tsProgram, changedFiles))); } - private async _runLinterAsync( + async #runLinterAsync( linter: LinterBase, tsProgram: IExtendedProgram, changedFiles?: ReadonlySet | undefined diff --git a/heft-plugins/heft-lint-plugin/src/Tslint.ts b/heft-plugins/heft-lint-plugin/src/Tslint.ts index 77025ac9ad0..cff4ab79a71 100644 --- a/heft-plugins/heft-lint-plugin/src/Tslint.ts +++ b/heft-plugins/heft-lint-plugin/src/Tslint.ts @@ -180,14 +180,14 @@ export class Tslint extends LinterBase { if (lintResult.fixes?.length) { for (const fixedTslintFailure of lintResult.fixes) { const formattedMessage: string = `[FIXED] ${getFormattedErrorMessage(fixedTslintFailure)}`; - const errorObject: FileError = this._getLintFileError(fixedTslintFailure, formattedMessage); + const errorObject: FileError = this.#getLintFileError(fixedTslintFailure, formattedMessage); this._scopedLogger.emitWarning(errorObject); } } // Report linter errors and warnings to the logger for (const tslintFailure of lintResult.failures) { - const errorObject: FileError = this._getLintFileError(tslintFailure); + const errorObject: FileError = this.#getLintFileError(tslintFailure); switch (tslintFailure.getRuleSeverity()) { case 'error': { this._scopedLogger.emitError(errorObject); @@ -210,7 +210,7 @@ export class Tslint extends LinterBase { return lintResults.length > 0; } - private _getLintFileError(tslintFailure: TTslint.RuleFailure, message?: string): FileError { + #getLintFileError(tslintFailure: TTslint.RuleFailure, message?: string): FileError { if (!message) { message = getFormattedErrorMessage(tslintFailure); } diff --git a/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts b/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts index 2649cbad420..6b57c2d3fda 100644 --- a/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts +++ b/heft-plugins/heft-rspack-plugin/src/DeferredWatchFileSystem.ts @@ -91,9 +91,9 @@ export class DeferredWatchFileSystem implements WatchFileSystem { } if (changes.size > 0 || removals.size > 0) { - this._purge(removals, changes); + this.#purge(removals, changes); - const { fileTimeInfoEntries, contextTimeInfoEntries } = this._fetchTimeInfo(); + const { fileTimeInfoEntries, contextTimeInfoEntries } = this.#fetchTimeInfo(); callback(null, fileTimeInfoEntries, contextTimeInfoEntries, changes, removals); @@ -167,8 +167,8 @@ export class DeferredWatchFileSystem implements WatchFileSystem { getInfo: () => { const newRemovals: Set | undefined = this.watcher?.aggregatedRemovals; const newChanges: Set | undefined = this.watcher?.aggregatedChanges; - this._purge(newRemovals, newChanges); - const { fileTimeInfoEntries, contextTimeInfoEntries } = this._fetchTimeInfo(); + this.#purge(newRemovals, newChanges); + const { fileTimeInfoEntries, contextTimeInfoEntries } = this.#fetchTimeInfo(); return { changes: newChanges!, removals: newRemovals!, @@ -177,24 +177,24 @@ export class DeferredWatchFileSystem implements WatchFileSystem { }; }, getContextTimeInfoEntries: () => { - const { contextTimeInfoEntries } = this._fetchTimeInfo(); + const { contextTimeInfoEntries } = this.#fetchTimeInfo(); return contextTimeInfoEntries; }, getFileTimeInfoEntries: () => { - const { fileTimeInfoEntries } = this._fetchTimeInfo(); + const { fileTimeInfoEntries } = this.#fetchTimeInfo(); return fileTimeInfoEntries; } }; } - private _fetchTimeInfo(): ITimeInfoEntries { + #fetchTimeInfo(): ITimeInfoEntries { const fileTimeInfoEntries: IRawFileSystemMap = new Map(); const contextTimeInfoEntries: IRawFileSystemMap = new Map(); this.watcher?.collectTimeInfoEntries(fileTimeInfoEntries, contextTimeInfoEntries); return { fileTimeInfoEntries, contextTimeInfoEntries }; } - private _purge(removals: Set | undefined, changes: Set | undefined): void { + #purge(removals: Set | undefined, changes: Set | undefined): void { const fs: InputFileSystem = this.inputFileSystem; if (fs.purge) { if (removals) { diff --git a/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts b/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts index 877c2844e05..06ca57fae65 100644 --- a/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts +++ b/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts @@ -83,18 +83,18 @@ export default class RspackPlugin implements IHeftTaskPlugin { - await this._runRspackAsync(taskSession, heftConfiguration, options); + await this.#runRspackAsync(taskSession, heftConfiguration, options); }); taskSession.hooks.runIncremental.tapPromise( PLUGIN_NAME, async (runOptions: IHeftTaskRunIncrementalHookOptions) => { - await this._runRspackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun); + await this.#runRspackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun); } ); } - private async _getRspackConfigurationAsync( + async #getRspackConfigurationAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, options: IRspackPluginOptions, @@ -107,7 +107,7 @@ export default class RspackPlugin implements IHeftTaskPlugin { @@ -153,13 +153,13 @@ export default class RspackPlugin implements IHeftTaskPlugin { if (!this.#rspackCompiler) { - const rspack: RspackCoreImport = await this._loadRspackAsync(taskSession, heftConfiguration); + const rspack: RspackCoreImport = await this.#loadRspackAsync(taskSession, heftConfiguration); taskSession.logger.terminal.writeLine(`Using Rspack version ${rspack.version}`); this.#rspackCompiler = Array.isArray(rspackConfiguration) ? rspack.default(rspackConfiguration) /* (rspack.Compilation[]) => MultiCompiler */ @@ -168,19 +168,19 @@ export default class RspackPlugin implements IHeftTaskPlugin { - this._validateEnvironmentVariable(taskSession); + this.#validateEnvironmentVariable(taskSession); if (taskSession.parameters.watch || this.#isServeMode) { // Should never happen, but just in case throw new InternalError('Cannot run Rspack in compilation mode when watch mode is enabled'); } // Load the config and compiler, and return if there is no config found - const rspackConfiguration: IRspackConfiguration | undefined = await this._getRspackConfigurationAsync( + const rspackConfiguration: IRspackConfiguration | undefined = await this.#getRspackConfigurationAsync( taskSession, heftConfiguration, options @@ -188,7 +188,7 @@ export default class RspackPlugin implements IHeftTaskPlugin { - return await this._canonicalizeAsync(url, context); + return await this.#canonicalizeAsync(url, context); }; const loadAsync: (url: URL) => Promise = async (url) => { const absolutePath: string = heftUrlToPath(url.href); - const record: IFileRecord = this._getOrCreateRecord(absolutePath); + const record: IFileRecord = this.#getOrCreateRecord(absolutePath); if (record.content === undefined) { - const { content, version } = await this._readFileContentAsync(absolutePath); + const { content, version } = await this.#readFileContentAsync(absolutePath); record.version = version; record.content = content; } @@ -299,7 +299,7 @@ export class SassProcessor { const affectedRecords: Set = new Set(); for (const file of filepaths) { - const record: IFileRecord = this._getOrCreateRecord(file); + const record: IFileRecord = this.#getOrCreateRecord(file); affectedRecords.add(record); } @@ -319,7 +319,7 @@ export class SassProcessor { await Async.forEachAsync( affectedRecords, async (record: IFileRecord) => { - const contentAndVersion: IFileContentAndVersion = await this._readFileContentAsync( + const contentAndVersion: IFileContentAndVersion = await this.#readFileContentAsync( record.absolutePath ); const { version } = contentAndVersion; @@ -367,7 +367,7 @@ export class SassProcessor { affectedRecords, async (record, i) => { try { - await this._compileFileAsync(compilers[i % compilerCount], record, this.#scssOptions); + await this.#compileFileAsync(compilers[i % compilerCount], record, this.#scssOptions); } catch (err) { this.#options.logger.emitError(err); } @@ -392,7 +392,7 @@ export class SassProcessor { await Async.forEachAsync( newRecords, async (record: IFileRecord) => { - const { content, version } = await this._readFileContentAsync(record.absolutePath); + const { content, version } = await this.#readFileContentAsync(record.absolutePath); // eslint-disable-next-line require-atomic-updates record.content = content; // eslint-disable-next-line require-atomic-updates @@ -421,26 +421,26 @@ export class SassProcessor { * @param context - The context in which the canonicalization is being performed * @returns The canonical URL of the target file, or null if it does not resolve */ - private async _canonicalizeFileAsync(url: string, context: CanonicalizeContext): AsyncResolution { + async #canonicalizeFileAsync(url: string, context: CanonicalizeContext): AsyncResolution { // The logic between `this._resolutions.get()` and `this._resolutions.set()` must be 100% synchronous // Otherwise we could end up with multiple promises for the same URL let resolution: SyncOrAsyncResolution | undefined = this.#resolutions.get(url); if (resolution === undefined) { - resolution = this._canonicalizeFileInnerAsync(url, context); + resolution = this.#canonicalizeFileInnerAsync(url, context); this.#resolutions.set(url, resolution); } return await resolution; } - private async _canonicalizeFileInnerAsync(url: string, context: CanonicalizeContext): AsyncResolution { + async #canonicalizeFileInnerAsync(url: string, context: CanonicalizeContext): AsyncResolution { const absolutePath: string = heftUrlToPath(url); const lastSlash: number = url.lastIndexOf('/'); const basename: string = url.slice(lastSlash + 1); // Does this file exist? try { - const contentAndVersion: IFileContentAndVersion = await this._readFileContentAsync(absolutePath); - const record: IFileRecord = this._getOrCreateRecord(absolutePath); + const contentAndVersion: IFileContentAndVersion = await this.#readFileContentAsync(absolutePath); + const record: IFileRecord = this.#getOrCreateRecord(absolutePath); const { version } = contentAndVersion; if (version !== record.version) { record.content = contentAndVersion.content; @@ -464,7 +464,7 @@ export class SassProcessor { // Try again with the partial const dirname: string = url.slice(0, lastSlash); const partialUrl: string = `${dirname}/_${basename}`; - const result: SyncResolution = await this._canonicalizeFileAsync(partialUrl, context); + const result: SyncResolution = await this.#canonicalizeFileAsync(partialUrl, context); return result; } @@ -474,7 +474,7 @@ export class SassProcessor { * @param context - The context in which the canonicalization is being performed * @returns The canonical URL of the target file, or null if it does not resolve */ - private async _canonicalizePackageAsync(url: string, context: CanonicalizeContext): AsyncResolution { + async #canonicalizePackageAsync(url: string, context: CanonicalizeContext): AsyncResolution { // We rewrite any of the old form `~` imports to `pkg:` const { containingUrl } = context; if (!containingUrl) { @@ -488,7 +488,7 @@ export class SassProcessor { if (resolution === undefined) { // Since the cache doesn't have an entry, get the promise for the resolution // and inject it into the cache before other callers have a chance to try - resolution = this._canonicalizePackageInnerAsync(url, context); + resolution = this.#canonicalizePackageInnerAsync(url, context); this.#resolutions.set(cacheKey, resolution); } return await resolution; @@ -500,7 +500,7 @@ export class SassProcessor { * @param context - The context in which the canonicalization is being performed * @returns The canonical URL of the target file, or null if it does not resolve */ - private async _canonicalizePackageInnerAsync(url: string, context: CanonicalizeContext): AsyncResolution { + async #canonicalizePackageInnerAsync(url: string, context: CanonicalizeContext): AsyncResolution { const containingUrl: string | undefined = context.containingUrl?.href; if (containingUrl === undefined) { throw new Error(`Cannot resolve ${url} without a containing URL`); @@ -527,7 +527,7 @@ export class SassProcessor { const modulePath: string = nodeModulesQuery.slice(linkEnd); const resolvedPath: string = `${resolvedPackagePath}${modulePath}`; const heftUrl: string = pathToHeftUrl(resolvedPath).href; - return await this._canonicalizeHeftUrlAsync(heftUrl, context); + return await this.#canonicalizeHeftUrlAsync(heftUrl, context); } /** @@ -536,13 +536,13 @@ export class SassProcessor { * @param context - The context in which the canonicalization is being performed * @returns The canonical URL of the target file, or null if it does not resolve */ - private async _canonicalizeHeftUrlAsync(url: string, context: CanonicalizeContext): AsyncResolution { + async #canonicalizeHeftUrlAsync(url: string, context: CanonicalizeContext): AsyncResolution { // The logic between `this._resolutions.get()` and `this._resolutions.set()` must be 100% synchronous let resolution: SyncOrAsyncResolution | undefined = this.#resolutions.get(url); if (resolution === undefined) { // Since the cache doesn't have an entry, get the promise for the resolution // and inject it into the cache before other callers have a chance to try - resolution = this._canonicalizeHeftInnerAsync(url, context); + resolution = this.#canonicalizeHeftInnerAsync(url, context); this.#resolutions.set(url, resolution); } @@ -556,18 +556,18 @@ export class SassProcessor { * @param context - The context in which the canonicalization is being performed * @returns The canonical URL of the target file, or null if it does not resolve */ - private async _canonicalizeAsync(url: string, context: CanonicalizeContext): AsyncResolution { + async #canonicalizeAsync(url: string, context: CanonicalizeContext): AsyncResolution { if (url.startsWith('~')) { throw new Error(`Unexpected tilde in URL: ${url} in context: ${context.containingUrl?.href}`); } if (url.startsWith('pkg:')) { - return await this._canonicalizePackageAsync(url, context); + return await this.#canonicalizePackageAsync(url, context); } // Check the cache first, and exit early if previously resolved if (url.startsWith('heft:')) { - return await this._canonicalizeHeftUrlAsync(url, context); + return await this.#canonicalizeHeftUrlAsync(url, context); } const { containingUrl } = context; @@ -576,7 +576,7 @@ export class SassProcessor { } const resolvedUrl: string = new URL(url, containingUrl.toString()).toString(); - return await this._canonicalizeHeftUrlAsync(resolvedUrl, context); + return await this.#canonicalizeHeftUrlAsync(resolvedUrl, context); } /** @@ -585,10 +585,10 @@ export class SassProcessor { * @param context - The context in which the canonicalization is being performed * @returns The canonical URL of the target file, or null if it does not resolve */ - private async _canonicalizeHeftInnerAsync(url: string, context: CanonicalizeContext): AsyncResolution { + async #canonicalizeHeftInnerAsync(url: string, context: CanonicalizeContext): AsyncResolution { if (url.endsWith('.sass') || url.endsWith('.scss') || url.endsWith('.css')) { // Extension is already present, so only try the exact URL or the corresponding partial - return await this._canonicalizeFileAsync(url, context); + return await this.#canonicalizeFileAsync(url, context); } // Spec says prefer .sass, but we don't use that extension. @@ -601,7 +601,7 @@ export class SassProcessor { `${url}/index.sass`, `${url}/index.css` ]) { - const result: SyncResolution = await this._canonicalizeFileAsync(candidate, context); + const result: SyncResolution = await this.#canonicalizeFileAsync(candidate, context); if (result) { return result; } @@ -678,7 +678,7 @@ export class SassProcessor { * @param absolutePath - The absolute path to the file * @returns A promise for an object that can be used to access the text and hash of the file. */ - private async _readFileContentAsync(absolutePath: string): Promise { + async #readFileContentAsync(absolutePath: string): Promise { const content: Buffer = await FileSystem.readFileToBufferAsync(absolutePath); let version: string | undefined; let contentString: string | undefined; @@ -699,7 +699,7 @@ export class SassProcessor { * @param filePath - The file path to get or create a record for * @returns The tracking record for the specified file */ - private _getOrCreateRecord(filePath: string): IFileRecord { + #getOrCreateRecord(filePath: string): IFileRecord { filePath = path.resolve(filePath); let record: IFileRecord | undefined = this.#fileInfo.get(filePath); if (!record) { @@ -725,7 +725,7 @@ export class SassProcessor { return record; } - private async _compileFileAsync( + async #compileFileAsync( compiler: Pick, record: IFileRecord, scssOptions: Options<'async'> @@ -759,7 +759,7 @@ export class SassProcessor { record.dependencies.clear(); for (const dependency of result.loadedUrls) { const dependencyPath: string = heftUrlToPath(dependency.href); - const dependencyRecord: IFileRecord = this._getOrCreateRecord(dependencyPath); + const dependencyRecord: IFileRecord = this.#getOrCreateRecord(dependencyPath); record.dependencies.add(dependencyRecord); dependencyRecord.consumers.add(record); } diff --git a/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts b/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts index cb8fdf9e581..5468fff3370 100644 --- a/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts +++ b/heft-plugins/heft-serverless-stack-plugin/src/ServerlessStackPlugin.ts @@ -66,7 +66,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { taskSession.hooks.run.tapPromise(PLUGIN_NAME, async (runOptions: IHeftTaskRunHookOptions) => { // TODO: Handle watch / serve mode - await this._runServerlessStackAsync({ + await this.#runServerlessStackAsync({ taskSession, heftConfiguration, sstStage: sstStageParameter.value @@ -75,7 +75,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { } } - private async _runServerlessStackAsync(options: { + async #runServerlessStackAsync(options: { taskSession: IHeftTaskSession; heftConfiguration: HeftConfiguration; sstStage?: string; @@ -99,7 +99,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { return; } - const sstCliEntryPoint: string = this._getSstCliEntryPoint(sstCliPackagePath); + const sstCliEntryPoint: string = this.#getSstCliEntryPoint(sstCliPackagePath); this.#logger.terminal.writeVerboseLine('Found SST package in' + sstCliPackagePath); @@ -121,7 +121,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { this.#logger.terminal.writeVerboseLine('Launching child process: ' + JSON.stringify(sstCommandArgs)); - const sstCommandEnv: NodeJS.ProcessEnv = this._getWorkaroundEnvironment(sstCliPackagePath); + const sstCommandEnv: NodeJS.ProcessEnv = this.#getWorkaroundEnvironment(sstCliPackagePath); const sstCommandResult: child_process.ChildProcess = child_process.spawn( process.execPath, @@ -145,10 +145,10 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { }); sstCommandResult.stdout?.on('data', (chunk: Buffer) => { - this._writeOutput(chunk.toString(), (x) => this.#logger.terminal.write(x)); + this.#writeOutput(chunk.toString(), (x) => this.#logger.terminal.write(x)); }); sstCommandResult.stderr?.on('data', (chunk: Buffer) => { - this._writeOutput(chunk.toString(), (x) => this.#logger.terminal.writeError(x)); + this.#writeOutput(chunk.toString(), (x) => this.#logger.terminal.writeError(x)); }); sstCommandResult.on('exit', (code: number | null) => { @@ -170,7 +170,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { return completionPromise; } - private _writeOutput(chunk: string, write: (message: string) => void): void { + #writeOutput(chunk: string, write: (message: string) => void): void { const lines: string[] = chunk.split('\n'); const lastLine: string = lines.pop() || ''; @@ -180,7 +180,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { } } - private _getSstCliEntryPoint(sstCliPackagePath: string): string { + #getSstCliEntryPoint(sstCliPackagePath: string): string { // Entry point for SST prior to v1.2.0 let sstCliEntryPoint: string = path.join(sstCliPackagePath, 'bin/scripts.js'); if (FileSystem.exists(sstCliEntryPoint)) { @@ -208,7 +208,7 @@ export default class ServerlessStackPlugin implements IHeftTaskPlugin { // // Since we're invoking the "@serverless-stack/cli/bin/scripts.js" entry point directly, we need to // reproduce this workaround. - private _getWorkaroundEnvironment(sstCliPackagePath: string): NodeJS.ProcessEnv { + #getWorkaroundEnvironment(sstCliPackagePath: string): NodeJS.ProcessEnv { const sstCommandEnv: NodeJS.ProcessEnv = { ...process.env }; diff --git a/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts b/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts index 5958c3e2eca..6b6e758434b 100644 --- a/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts +++ b/heft-plugins/heft-typescript-plugin/src/TypeScriptBuilder.ts @@ -146,7 +146,7 @@ export class TypeScriptBuilder { #nextRequestId: number = 0; - private get _tsCacheFilePath(): string { + get #tsCacheFilePath(): string { if (!this.#_tsCacheFilePath) { // TypeScript internally handles if the tsconfig options have changed from when the tsbuildinfo file was created. // We only need to hash our additional Heft configuration. @@ -337,9 +337,9 @@ export class TypeScriptBuilder { const _tsconfig: TTypescript.ParsedCommandLine = loadTsconfig({ tool, tsconfigPath: this.#configuration.tsconfigPath, - tsCacheFilePath: this._tsCacheFilePath + tsCacheFilePath: this.#tsCacheFilePath }); - this._validateTsconfig(ts, _tsconfig); + this.#validateTsconfig(ts, _tsconfig); return { tsconfig: _tsconfig @@ -349,7 +349,7 @@ export class TypeScriptBuilder { //#endregion if (this.#useSolutionBuilder) { - const solutionHost: TWatchSolutionHost = this._buildWatchSolutionBuilderHost(tool); + const solutionHost: TWatchSolutionHost = this.#buildWatchSolutionBuilderHost(tool); const builder: TTypescript.SolutionBuilder = ts.createSolutionBuilderWithWatch(solutionHost, [this.#configuration.tsconfigPath], {}); @@ -357,7 +357,7 @@ export class TypeScriptBuilder { builder.build(); } else { - const compilerHost: TWatchCompilerHost = this._buildWatchCompilerHost(tool, tsconfig); + const compilerHost: TWatchCompilerHost = this.#buildWatchCompilerHost(tool, tsconfig); tool.watchProgram = ts.createWatchProgram(compilerHost); } } @@ -380,7 +380,7 @@ export class TypeScriptBuilder { // eslint-disable-next-line require-atomic-updates tool.executing = false; } - this._logDiagnostics(ts, rawDiagnostics, this.#useSolutionBuilder); + this.#logDiagnostics(ts, rawDiagnostics, this.#useSolutionBuilder); } public async _runBuildAsync(tool: ITypeScriptTool): Promise { @@ -395,11 +395,11 @@ export class TypeScriptBuilder { const _tsconfig: TTypescript.ParsedCommandLine = loadTsconfig({ tool, tsconfigPath: this.#configuration.tsconfigPath, - tsCacheFilePath: this._tsCacheFilePath + tsCacheFilePath: this.#tsCacheFilePath }); - this._validateTsconfig(ts, _tsconfig); + this.#validateTsconfig(ts, _tsconfig); - const _compilerHost: TTypescript.CompilerHost = this._buildIncrementalCompilerHost(tool, _tsconfig); + const _compilerHost: TTypescript.CompilerHost = this.#buildIncrementalCompilerHost(tool, _tsconfig); return { tsconfig: _tsconfig, @@ -450,12 +450,12 @@ export class TypeScriptBuilder { // Prefer the builder program, since it is what gives us incremental builds const genericProgram: TTypescript.BuilderProgram | TTypescript.Program = builderProgram || innerProgram; - this._logReadPerformance(ts); + this.#logReadPerformance(ts); //#endregion if (isolatedModules) { // Kick the transpilation worker. - this._queueTranspileInWorker(tool, genericProgram.getCompilerOptions(), filesToTranspile); + this.#queueTranspileInWorker(tool, genericProgram.getCompilerOptions(), filesToTranspile); } //#region ANALYSIS @@ -487,11 +487,11 @@ export class TypeScriptBuilder { undefined ); - this._cleanupWorker(); + this.#cleanupWorker(); //#endregion - this._emitModulePackageJsonFiles(ts); - this._logEmitPerformance(ts); + this.#emitModulePackageJsonFiles(ts); + this.#logEmitPerformance(ts); //#region FINAL_ANALYSIS // Need to ensure that we include emit diagnostics, since they might not be part of the other sets @@ -509,7 +509,7 @@ export class TypeScriptBuilder { } } - this._logDiagnostics(ts, rawDiagnostics); + this.#logDiagnostics(ts, rawDiagnostics); // Reset performance counters in case any are used in the callback ts.performance.disable(); ts.performance.enable(); @@ -527,11 +527,11 @@ export class TypeScriptBuilder { const _tsconfig: TTypescript.ParsedCommandLine = loadTsconfig({ tool, tsconfigPath: this.#configuration.tsconfigPath, - tsCacheFilePath: this._tsCacheFilePath + tsCacheFilePath: this.#tsCacheFilePath }); - this._validateTsconfig(ts, _tsconfig); + this.#validateTsconfig(ts, _tsconfig); - const _solutionBuilderHost: TSolutionHost = this._buildSolutionBuilderHost(tool); + const _solutionBuilderHost: TSolutionHost = this.#buildSolutionBuilderHost(tool); return { solutionBuilderHost: _solutionBuilderHost @@ -555,10 +555,10 @@ export class TypeScriptBuilder { //#region EMIT // Ignoring the exit status because we only care about presence of diagnostics tool.solutionBuilder.build(); - this._cleanupWorker(); + this.#cleanupWorker(); //#endregion - this._emitModulePackageJsonFiles(ts); + this.#emitModulePackageJsonFiles(ts); if (pendingTranspilePromises.size) { const emitResults: TTypescript.EmitResult[] = await Promise.all(pendingTranspilePromises.values()); @@ -569,10 +569,10 @@ export class TypeScriptBuilder { } } - this._logDiagnostics(ts, rawDiagnostics, true); + this.#logDiagnostics(ts, rawDiagnostics, true); } - private _logDiagnostics( + #logDiagnostics( ts: ExtendedTypeScript, rawDiagnostics: TTypescript.Diagnostic[], isSolutionMode?: boolean @@ -587,7 +587,7 @@ export class TypeScriptBuilder { `Encountered ${diagnostics.length} TypeScript issue${diagnostics.length > 1 ? 's' : ''}:` ); for (const diagnostic of diagnostics) { - const diagnosticCategory: TTypescript.DiagnosticCategory = this._getAdjustedDiagnosticCategory( + const diagnosticCategory: TTypescript.DiagnosticCategory = this.#getAdjustedDiagnosticCategory( diagnostic, ts ); @@ -598,7 +598,7 @@ export class TypeScriptBuilder { hasError = true; } - this._printDiagnosticMessage(ts, diagnostic, diagnosticCategory); + this.#printDiagnosticMessage(ts, diagnostic, diagnosticCategory); } if (isSolutionMode && warningCount > 0 && !hasError) { @@ -612,7 +612,7 @@ export class TypeScriptBuilder { } } - private _logEmitPerformance(ts: ExtendedTypeScript): void { + #logEmitPerformance(ts: ExtendedTypeScript): void { this.#typescriptTerminal.writeVerboseLine(`Bind: ${ts.performance.getDuration('Bind')}ms`); this.#typescriptTerminal.writeVerboseLine(`Check: ${ts.performance.getDuration('Check')}ms`); this.#typescriptTerminal.writeVerboseLine( @@ -633,7 +633,7 @@ export class TypeScriptBuilder { ); } - private _logReadPerformance(ts: ExtendedTypeScript): void { + #logReadPerformance(ts: ExtendedTypeScript): void { this.#typescriptTerminal.writeVerboseLine( `I/O Read: ${ts.performance.getDuration('I/O Read')}ms (${ts.performance.getCount( 'beforeIORead' @@ -647,10 +647,10 @@ export class TypeScriptBuilder { ); } - private _printDiagnosticMessage( + #printDiagnosticMessage( ts: ExtendedTypeScript, diagnostic: TTypescript.Diagnostic, - diagnosticCategory: TTypescript.DiagnosticCategory = this._getAdjustedDiagnosticCategory(diagnostic, ts) + diagnosticCategory: TTypescript.DiagnosticCategory = this.#getAdjustedDiagnosticCategory(diagnostic, ts) ): void { // Code taken from reference example let diagnosticMessage: string; @@ -689,7 +689,7 @@ export class TypeScriptBuilder { } } - private _getAdjustedDiagnosticCategory( + #getAdjustedDiagnosticCategory( diagnostic: TTypescript.Diagnostic, ts: ExtendedTypeScript ): TTypescript.DiagnosticCategory { @@ -712,7 +712,7 @@ export class TypeScriptBuilder { return diagnostic.category; } - private _validateTsconfig(ts: ExtendedTypeScript, tsconfig: TTypescript.ParsedCommandLine): void { + #validateTsconfig(ts: ExtendedTypeScript, tsconfig: TTypescript.ParsedCommandLine): void { if ( (tsconfig.options.module && !tsconfig.options.outDir) || (!tsconfig.options.module && tsconfig.options.outDir) @@ -734,7 +734,7 @@ export class TypeScriptBuilder { } if (this.#configuration.emitCjsExtensionForCommonJS) { - this._addModuleKindToEmit( + this.#addModuleKindToEmit( ts.ModuleKind.CommonJS, tsconfig.options.outDir!, /* isPrimary */ tsconfig.options.module === ts.ModuleKind.CommonJS, @@ -754,7 +754,7 @@ export class TypeScriptBuilder { } if (this.#configuration.emitMjsExtensionForESModule) { - this._addModuleKindToEmit( + this.#addModuleKindToEmit( ts.ModuleKind.ESNext, tsconfig.options.outDir!, /* isPrimary */ tsconfig.options.module === ts.ModuleKind.ESNext, @@ -774,7 +774,7 @@ export class TypeScriptBuilder { } if (!specifiedKinds.has(tsconfig.options.module)) { - this._addModuleKindToEmit( + this.#addModuleKindToEmit( tsconfig.options.module, tsconfig.options.outDir!, /* isPrimary */ true, @@ -796,7 +796,7 @@ export class TypeScriptBuilder { if (this.#configuration.additionalModuleKindsToEmit) { for (const { moduleKind: moduleKindString, outFolderName, emitModulePackageJson = false } of this .#configuration.additionalModuleKindsToEmit) { - const moduleKind: TTypescript.ModuleKind = this._parseModuleKind(ts, moduleKindString); + const moduleKind: TTypescript.ModuleKind = this.#parseModuleKind(ts, moduleKindString); const outDirKey: string = `${outFolderName}:.js`; const moduleKindReason: IModuleKindReason = { @@ -818,7 +818,7 @@ export class TypeScriptBuilder { `Output folder "${outFolderName}" already contains module kind ${existingDir.kind} with extension '${existingDir.extension}', specified by option ${existingDir.reason}.` ); } else { - const outFolderKey: string | undefined = this._addModuleKindToEmit( + const outFolderKey: string | undefined = this.#addModuleKindToEmit( moduleKind, outFolderName, /* isPrimary */ false, @@ -835,7 +835,7 @@ export class TypeScriptBuilder { } } - private _addModuleKindToEmit( + #addModuleKindToEmit( moduleKind: TTypescript.ModuleKind, outFolderPath: string, isPrimary: boolean, @@ -898,7 +898,7 @@ export class TypeScriptBuilder { return `${outFolderName}:${jsExtensionOverride || '.js'}`; } - private _getCreateBuilderProgram( + #getCreateBuilderProgram( ts: ExtendedTypeScript ): TTypescript.CreateProgram { const { emitChangedFilesCallback } = this.#configuration; @@ -929,7 +929,7 @@ export class TypeScriptBuilder { projectReferences ); - this._logReadPerformance(ts); + this.#logReadPerformance(ts); const isolatedModules: boolean = !!this.#configuration.useTranspilerWorker && !!compilerOptions!.isolatedModules; @@ -938,7 +938,7 @@ export class TypeScriptBuilder { if (isolatedModules) { // Kick the transpilation worker. const filesToTranspile: Map = getFilesToTranspileFromBuilderProgram(newProgram); - this._queueTranspileInWorker(this.#tool!, compilerOptions!, filesToTranspile); + this.#queueTranspileInWorker(this.#tool!, compilerOptions!, filesToTranspile); } const { emit: originalEmit } = newProgram; @@ -976,8 +976,8 @@ export class TypeScriptBuilder { `Emitting program "${innerCompilerOptions!.configFilePath}"` ); - this._emitModulePackageJsonFiles(ts); - this._logEmitPerformance(ts); + this.#emitModulePackageJsonFiles(ts); + this.#logEmitPerformance(ts); // Reset performance counters ts.performance.disable(); @@ -996,7 +996,7 @@ export class TypeScriptBuilder { return createMultiEmitBuilderProgram; } - private _buildSolutionBuilderHost(tool: ITypeScriptTool): TSolutionHost { + #buildSolutionBuilderHost(tool: ITypeScriptTool): TSolutionHost { const reportSolutionBuilderStatus: TTypescript.DiagnosticReporter = tool.reportDiagnostic; const reportEmitErrorSummary: TTypescript.ReportEmitErrorSummary = (errorCount: number): void => { // Do nothing @@ -1007,7 +1007,7 @@ export class TypeScriptBuilder { const solutionBuilderHost: TTypescript.SolutionBuilderHost = ts.createSolutionBuilderHost( system, - this._getCreateBuilderProgram(ts), + this.#getCreateBuilderProgram(ts), tool.reportDiagnostic, reportSolutionBuilderStatus, reportEmitErrorSummary @@ -1027,7 +1027,7 @@ export class TypeScriptBuilder { return solutionBuilderHost; } - private _buildIncrementalCompilerHost( + #buildIncrementalCompilerHost( tool: ITypeScriptTool, tsconfig: TTypescript.ParsedCommandLine ): TTypescript.CompilerHost { @@ -1045,26 +1045,26 @@ export class TypeScriptBuilder { ); } - this._changeCompilerHostToUseCache(compilerHost, tool); + this.#changeCompilerHostToUseCache(compilerHost, tool); return compilerHost; } - private _buildWatchCompilerHost( + #buildWatchCompilerHost( tool: ITypeScriptTool, tsconfig: TTypescript.ParsedCommandLine ): TWatchCompilerHost { const { ts, system } = tool; const reportWatchStatus: TTypescript.DiagnosticReporter = (diagnostic: TTypescript.Diagnostic): void => { - this._printDiagnosticMessage(ts, diagnostic); + this.#printDiagnosticMessage(ts, diagnostic); }; const compilerHost: TWatchCompilerHost = ts.createWatchCompilerHost( tsconfig.fileNames, tsconfig.options, system, - this._getCreateBuilderProgram(ts), + this.#getCreateBuilderProgram(ts), tool.reportDiagnostic, reportWatchStatus, tsconfig.projectReferences, @@ -1074,7 +1074,7 @@ export class TypeScriptBuilder { return compilerHost; } - private _changeCompilerHostToUseCache(compilerHost: TTypescript.CompilerHost, tool: ITypeScriptTool): void { + #changeCompilerHostToUseCache(compilerHost: TTypescript.CompilerHost, tool: ITypeScriptTool): void { const { sourceFileCache } = tool; const { getSourceFile: innerGetSourceFile } = compilerHost; @@ -1119,12 +1119,12 @@ export class TypeScriptBuilder { compilerHost.getSourceFile = getSourceFile; } - private _buildWatchSolutionBuilderHost(tool: ITypeScriptTool): TWatchSolutionHost { + #buildWatchSolutionBuilderHost(tool: ITypeScriptTool): TWatchSolutionHost { const { reportDiagnostic, ts, system } = tool; const host: TWatchSolutionHost = ts.createSolutionBuilderWithWatchHost( system, - this._getCreateBuilderProgram(ts), + this.#getCreateBuilderProgram(ts), reportDiagnostic, reportDiagnostic, reportDiagnostic @@ -1138,7 +1138,7 @@ export class TypeScriptBuilder { * `package.json` with the appropriate `"type"` field to ensure Node.js correctly * interprets `.js` files in the output folder. */ - private _emitModulePackageJsonFiles(ts: ExtendedTypeScript): void { + #emitModulePackageJsonFiles(ts: ExtendedTypeScript): void { for (const { emitModulePackageJson, moduleKind, outFolderPath } of this.#moduleKindsToEmit) { if (!emitModulePackageJson) { continue; @@ -1184,7 +1184,7 @@ export class TypeScriptBuilder { } } - private _parseModuleKind(ts: ExtendedTypeScript, moduleKindName: string): TTypescript.ModuleKind { + #parseModuleKind(ts: ExtendedTypeScript, moduleKindName: string): TTypescript.ModuleKind { switch (moduleKindName.toLowerCase()) { case 'commonjs': return ts.ModuleKind.CommonJS; @@ -1209,7 +1209,7 @@ export class TypeScriptBuilder { } } - private _queueTranspileInWorker( + #queueTranspileInWorker( tool: ITypeScriptTool, compilerOptions: TTypescript.CompilerOptions, filesToTranspile: Map @@ -1290,7 +1290,7 @@ export class TypeScriptBuilder { pendingTranspilePromises.set(requestId, transpilePromise); } - private _cleanupWorker(): void { + #cleanupWorker(): void { const tool: ITypeScriptTool | undefined = this.#tool; if (!tool) { return; diff --git a/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts b/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts index 6fb6eb72647..32dff7658e2 100644 --- a/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts +++ b/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts @@ -259,7 +259,7 @@ export default class TypeScriptPlugin implements IHeftTaskPlugin { // all source files to this set of static assets. This would allow us to avoid // having to copy the static assets multiple times, increasing build times and // package size. - for (const copyOperation of await this._getStaticAssetCopyOperationsAsync( + for (const copyOperation of await this.#getStaticAssetCopyOperationsAsync( taskSession, heftConfiguration )) { @@ -271,7 +271,7 @@ export default class TypeScriptPlugin implements IHeftTaskPlugin { ); taskSession.hooks.run.tapPromise(PLUGIN_NAME, async (runOptions: IHeftTaskRunHookOptions) => { - const builder: TypeScriptBuilder | false = await this._getTypeScriptBuilderAsync( + const builder: TypeScriptBuilder | false = await this.#getTypeScriptBuilderAsync( taskSession, heftConfiguration ); @@ -286,7 +286,7 @@ export default class TypeScriptPlugin implements IHeftTaskPlugin { async (runIncrementalOptions: IHeftTaskRunIncrementalHookOptions) => { if (incrementalBuilder === undefined) { // eslint-disable-next-line require-atomic-updates - incrementalBuilder = await this._getTypeScriptBuilderAsync(taskSession, heftConfiguration); + incrementalBuilder = await this.#getTypeScriptBuilderAsync(taskSession, heftConfiguration); } if (incrementalBuilder) { @@ -296,11 +296,11 @@ export default class TypeScriptPlugin implements IHeftTaskPlugin { ); } - private async _getStaticAssetCopyOperationsAsync( + async #getStaticAssetCopyOperationsAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { - const { typeScriptConfigurationJson, partialTsconfigFile } = await this._loadConfigAsync( + const { typeScriptConfigurationJson, partialTsconfigFile } = await this.#loadConfigAsync( taskSession, heftConfiguration ); @@ -341,11 +341,11 @@ export default class TypeScriptPlugin implements IHeftTaskPlugin { return copyOperations; } - private async _getTypeScriptBuilderAsync( + async #getTypeScriptBuilderAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { - const { typeScriptConfigurationJson, partialTsconfigFile } = await this._loadConfigAsync( + const { typeScriptConfigurationJson, partialTsconfigFile } = await this.#loadConfigAsync( taskSession, heftConfiguration ); @@ -391,7 +391,7 @@ export default class TypeScriptPlugin implements IHeftTaskPlugin { return typeScriptBuilder; } - private async _loadConfigAsync( + async #loadConfigAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration ): Promise { diff --git a/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts b/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts index 9eb87333209..a3039343bd4 100644 --- a/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts +++ b/heft-plugins/heft-typescript-plugin/src/fileSystem/TypeScriptCachedFileSystem.ts @@ -65,20 +65,20 @@ export class TypeScriptCachedFileSystem { }; public getStatistics: (path: string) => FileSystemStats = (path: string) => { - return this._withCaching(path, FileSystem.getStatistics, this.#statsCache); + return this.#withCaching(path, FileSystem.getStatistics, this.#statsCache); }; public ensureFolder: (folderPath: string) => void = (folderPath: string) => { if (!this.#readFolderCache.get(folderPath)?.entry && !this.#statsCache.get(folderPath)?.entry) { FileSystem.ensureFolder(folderPath); - this._invalidateCacheEntry(folderPath); + this.#invalidateCacheEntry(folderPath); } }; public ensureFolderAsync: (folderPath: string) => Promise = async (folderPath: string) => { if (!this.#readFolderCache.get(folderPath)?.entry && !this.#statsCache.get(folderPath)?.entry) { await FileSystem.ensureFolderAsync(folderPath); - this._invalidateCacheEntry(folderPath); + this.#invalidateCacheEntry(folderPath); } }; @@ -92,7 +92,7 @@ export class TypeScriptCachedFileSystem { options?: IFileSystemWriteFileOptions | undefined ) => { FileSystem.writeFile(filePath, contents, options); - this._invalidateCacheEntry(filePath); + this.#invalidateCacheEntry(filePath); }; public readFile: (filePath: string, options?: IFileSystemReadFileOptions | undefined) => string = ( @@ -108,14 +108,14 @@ export class TypeScriptCachedFileSystem { }; public readFileToBuffer: (filePath: string) => Buffer = (filePath: string) => { - return this._withCaching(filePath, FileSystem.readFileToBuffer, this.#readFileCache); + return this.#withCaching(filePath, FileSystem.readFileToBuffer, this.#readFileCache); }; public copyFileAsync: (options: IFileSystemCopyFileOptions) => Promise = async ( options: IFileSystemCopyFileOptions ) => { await FileSystem.copyFileAsync(options); - this._invalidateCacheEntry(options.destinationPath); + this.#invalidateCacheEntry(options.destinationPath); }; public deleteFile: (filePath: string, options?: IFileSystemDeleteFileOptions | undefined) => void = ( @@ -125,7 +125,7 @@ export class TypeScriptCachedFileSystem { const cachedError: Error | undefined = this.#statsCache.get(filePath)?.error; if (!cachedError || !FileSystem.isFileDoesNotExistError(cachedError)) { FileSystem.deleteFile(filePath); - this._invalidateCacheEntry(filePath); + this.#invalidateCacheEntry(filePath); } else if (options?.throwIfNotExists) { throw cachedError; } @@ -135,11 +135,11 @@ export class TypeScriptCachedFileSystem { options: IFileSystemCreateLinkOptions ) => { await FileSystem.createHardLinkAsync(options); - this._invalidateCacheEntry(options.newLinkPath); + this.#invalidateCacheEntry(options.newLinkPath); }; public getRealPath: (linkPath: string) => string = (linkPath: string) => { - return this._withCaching( + return this.#withCaching( linkPath, (path: string) => { try { @@ -160,17 +160,17 @@ export class TypeScriptCachedFileSystem { public readFolderFilesAndDirectories: (folderPath: string) => IReadFolderFilesAndDirectoriesResult = ( folderPath: string ) => { - return this._withCaching( + return this.#withCaching( folderPath, (path: string) => { const folderEntries: FolderItem[] = FileSystem.readFolderItems(path); - return this._sortFolderEntries(folderEntries); + return this.#sortFolderEntries(folderEntries); }, this.#readFolderCache ); }; - private _sortFolderEntries(folderEntries: FolderItem[]): IReadFolderFilesAndDirectoriesResult { + #sortFolderEntries(folderEntries: FolderItem[]): IReadFolderFilesAndDirectoriesResult { // TypeScript expects entries sorted ordinally by name // In practice this might not matter folderEntries.sort((a, b) => Sort.compareByValue(a, b)); @@ -188,7 +188,7 @@ export class TypeScriptCachedFileSystem { return { files, directories }; } - private _withCaching( + #withCaching( path: string, fn: (path: string) => TResult, cache: Map> @@ -211,7 +211,7 @@ export class TypeScriptCachedFileSystem { } } - private _invalidateCacheEntry(path: string): void { + #invalidateCacheEntry(path: string): void { this.#statsCache.delete(path); this.#readFolderCache.delete(path); this.#readFileCache.delete(path); diff --git a/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts b/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts index 0dceb475040..c8d9fc7cff7 100644 --- a/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts +++ b/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts @@ -113,18 +113,18 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { - await this._runWebpackAsync(taskSession, heftConfiguration, options); + await this.#runWebpackAsync(taskSession, heftConfiguration, options); }); taskSession.hooks.runIncremental.tapPromise( PLUGIN_NAME, async (runOptions: IHeftTaskRunIncrementalHookOptions) => { - await this._runWebpackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun); + await this.#runWebpackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun); } ); } - private async _getWebpackConfigurationAsync( + async #getWebpackConfigurationAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, options: IWebpackPluginOptions, @@ -137,7 +137,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { + async #loadWebpackAsync(): Promise { if (!this.#webpack) { // Allow this to fail if webpack is not installed this.#webpack = await import(WEBPACK_PACKAGE_NAME); @@ -170,12 +170,12 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { if (!this.#webpackCompiler) { - const webpack: typeof TWebpack = await this._loadWebpackAsync(); + const webpack: typeof TWebpack = await this.#loadWebpackAsync(); taskSession.logger.terminal.writeLine(`Using Webpack version ${webpack.version}`); this.#webpackCompiler = Array.isArray(webpackConfiguration) ? (webpack.default( @@ -186,19 +186,19 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { - this._validateEnvironmentVariable(taskSession); + this.#validateEnvironmentVariable(taskSession); if (taskSession.parameters.watch || this.#isServeMode) { // Should never happen, but just in case throw new InternalError('Cannot run Webpack in compilation mode when watch mode is enabled'); } // Load the config and compiler, and return if there is no config found - const webpackConfiguration: IWebpackConfiguration | undefined = await this._getWebpackConfigurationAsync( + const webpackConfiguration: IWebpackConfiguration | undefined = await this.#getWebpackConfigurationAsync( taskSession, heftConfiguration, options @@ -206,7 +206,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin 0 || removals.size > 0) { - this._purge(removals, changes); + this.#purge(removals, changes); - const { fileTimeInfoEntries, contextTimeInfoEntries } = this._fetchTimeInfo(); + const { fileTimeInfoEntries, contextTimeInfoEntries } = this.#fetchTimeInfo(); callback(null, fileTimeInfoEntries, contextTimeInfoEntries, changes, removals); @@ -151,8 +151,8 @@ export class DeferredWatchFileSystem implements WatchFileSystem { getInfo: () => { const newRemovals: Set | undefined = this.watcher?.aggregatedRemovals; const newChanges: Set | undefined = this.watcher?.aggregatedChanges; - this._purge(newRemovals, newChanges); - const { fileTimeInfoEntries, contextTimeInfoEntries } = this._fetchTimeInfo(); + this.#purge(newRemovals, newChanges); + const { fileTimeInfoEntries, contextTimeInfoEntries } = this.#fetchTimeInfo(); return { changes: newChanges!, removals: newRemovals!, @@ -161,24 +161,24 @@ export class DeferredWatchFileSystem implements WatchFileSystem { }; }, getContextTimeInfoEntries: () => { - const { contextTimeInfoEntries } = this._fetchTimeInfo(); + const { contextTimeInfoEntries } = this.#fetchTimeInfo(); return contextTimeInfoEntries; }, getFileTimeInfoEntries: () => { - const { fileTimeInfoEntries } = this._fetchTimeInfo(); + const { fileTimeInfoEntries } = this.#fetchTimeInfo(); return fileTimeInfoEntries; } }; } - private _fetchTimeInfo(): ITimeInfoEntries { + #fetchTimeInfo(): ITimeInfoEntries { const fileTimeInfoEntries: IRawFileSystemMap = new Map(); const contextTimeInfoEntries: IRawFileSystemMap = new Map(); this.watcher?.collectTimeInfoEntries(fileTimeInfoEntries, contextTimeInfoEntries); return { fileTimeInfoEntries, contextTimeInfoEntries }; } - private _purge(removals: Set | undefined, changes: Set | undefined): void { + #purge(removals: Set | undefined, changes: Set | undefined): void { const fs: InputFileSystem = this.inputFileSystem; if (fs.purge) { if (removals) { diff --git a/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts b/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts index e5bfed6d903..bfa7e1e0dde 100644 --- a/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts +++ b/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts @@ -82,18 +82,18 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { - await this._runWebpackAsync(taskSession, heftConfiguration, options); + await this.#runWebpackAsync(taskSession, heftConfiguration, options); }); taskSession.hooks.runIncremental.tapPromise( PLUGIN_NAME, async (runOptions: IHeftTaskRunIncrementalHookOptions) => { - await this._runWebpackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun); + await this.#runWebpackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun); } ); } - private async _getWebpackConfigurationAsync( + async #getWebpackConfigurationAsync( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, options: IWebpackPluginOptions, @@ -106,7 +106,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { @@ -152,13 +152,13 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { if (!this.#webpackCompiler) { - const webpack: typeof TWebpack = await this._loadWebpackAsync(taskSession, heftConfiguration); + const webpack: typeof TWebpack = await this.#loadWebpackAsync(taskSession, heftConfiguration); taskSession.logger.terminal.writeLine(`Using Webpack version ${webpack.version}`); this.#webpackCompiler = Array.isArray(webpackConfiguration) ? webpack.default(webpackConfiguration) /* (webpack.Compilation[]) => MultiCompiler */ @@ -167,19 +167,19 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { - this._validateEnvironmentVariable(taskSession); + this.#validateEnvironmentVariable(taskSession); if (taskSession.parameters.watch || this.#isServeMode) { // Should never happen, but just in case throw new InternalError('Cannot run Webpack in compilation mode when watch mode is enabled'); } // Load the config and compiler, and return if there is no config found - const webpackConfiguration: IWebpackConfiguration | undefined = await this._getWebpackConfigurationAsync( + const webpackConfiguration: IWebpackConfiguration | undefined = await this.#getWebpackConfigurationAsync( taskSession, heftConfiguration, options @@ -187,7 +187,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { if (!this.expression) { - this.expression = await this._collectAssetsAndGetExpressionAsync(compilation, globFs); + this.expression = await this.#collectAssetsAndGetExpressionAsync(compilation, globFs); } } - private async _collectAssetsAndGetExpressionAsync( + async #collectAssetsAndGetExpressionAsync( compilation: webpack.Compilation, globFs: glob.FileSystemAdapter ): Promise { diff --git a/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts b/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts index caf972bc15b..b2cee495800 100644 --- a/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts +++ b/webpack/webpack-embedded-dependencies-plugin/src/EmbeddedDependenciesWebpackPlugin.ts @@ -158,7 +158,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI this.#outputFileName = options?.outputFileName || DEFAULT_EMBEDDED_DEPENDENCIES_FILE_NAME; this.#generateLicenseFile = options?.generateLicenseFile || false; this.#generateLicenseFileFunction = - options?.generateLicenseFileFunction || this._defaultLicenseFileGenerator; + options?.generateLicenseFileFunction || this.#defaultLicenseFileGenerator; this.#generatedLicenseFilename = options?.generatedLicenseFilename || DEFAULT_GENERATED_LICENSE_FILE_NAME; this.#packageFilterFunction = options?.packageFilterPredicate || DEFAULT_PACKAGE_FILTER_FUNCTION; } @@ -210,12 +210,12 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI const { name, version } = data; let licenseSource: string | undefined; const license: string | undefined = parseLicense(data); - const licensePath: string | undefined = await this._getLicenseFilePathAsync(dir, compiler); + const licensePath: string | undefined = await this.#getLicenseFilePathAsync(dir, compiler); if (licensePath) { licenseSource = await FileSystem.readFileAsync(licensePath); const copyright: string | undefined = - this._parseCopyright(licenseSource) || parsePackageAuthor(data); + this.#parseCopyright(licenseSource) || parsePackageAuthor(data); packages.push({ name, @@ -238,7 +238,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI } ); } catch (error) { - this._emitWebpackError(compilation, 'Failed to process embedded dependencies', error); + this.#emitWebpackError(compilation, 'Failed to process embedded dependencies', error); } finally { Sort.sortBy(packages, (pkg) => pkg.name); } @@ -257,7 +257,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI new sources.RawSource(this.#generateLicenseFileFunction(packages)) ); } catch (error: unknown) { - this._emitWebpackError(compilation, 'Failed to generate license file', error); + this.#emitWebpackError(compilation, 'Failed to generate license file', error); } } @@ -287,7 +287,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI * } * ``` */ - private _emitWebpackError(compilation: Compilation, errorMessage: string, error: unknown): void { + #emitWebpackError(compilation: Compilation, errorMessage: string, error: unknown): void { let emittedError: WebpackError; const { WebpackError } = compilation.compiler.webpack; // If the error is a string, we can just emit it as is with message prefix and error message @@ -311,7 +311,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI /** * Searches a third party package directory for a license file. */ - private async _getLicenseFilePathAsync( + async #getLicenseFilePathAsync( modulePath: string, compiler: Compiler ): Promise { @@ -344,7 +344,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI /** * Given a module path, try to parse the module's copyright attribution. */ - private _parseCopyright(licenseSource: string): string | undefined { + #parseCopyright(licenseSource: string): string | undefined { const match: RegExpMatchArray | null = licenseSource.match(COPYRIGHT_REGEX); if (match) { @@ -354,7 +354,7 @@ export default class EmbeddedDependenciesWebpackPlugin implements WebpackPluginI return undefined; } - private _defaultLicenseFileGenerator(packages: IPackageData[]): string { + #defaultLicenseFileGenerator(packages: IPackageData[]): string { const licenseContent = (pkg: IPackageData): string => pkg.licenseSource || pkg.copyright || 'License or Copyright not found'; diff --git a/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts b/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts index 5bbe57c226d..5048eafb45f 100644 --- a/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts +++ b/webpack/webpack4-localization-plugin/src/LocalizationPlugin.ts @@ -186,7 +186,7 @@ export class LocalizationPlugin implements Webpack.Plugin { // https://github.com/webpack/webpack-dev-server/pull/1929/files#diff-15fb51940da53816af13330d8ce69b4eR66 const isWebpackDevServer: boolean = process.env.WEBPACK_DEV_SERVER === 'true'; - const { errors, warnings } = this._initializeAndValidateOptions(compiler.options, isWebpackDevServer); + const { errors, warnings } = this.#initializeAndValidateOptions(compiler.options, isWebpackDevServer); let typingsPreprocessor: TypingsGenerator | undefined; if (this.#options.typingsOptions) { @@ -331,7 +331,7 @@ export class LocalizationPlugin implements Webpack.Plugin { for (const chunk of chunks) { // See if the chunk contains any localized modules or loads any localized chunks - const localizedChunk: boolean = this._chunkHasLocalizedModules(chunk); + const localizedChunk: boolean = this.#chunkHasLocalizedModules(chunk); // Change the chunk's name to include either the locale name or the locale name for chunks without strings const replacementValue: string = localizedChunk @@ -387,7 +387,7 @@ export class LocalizationPlugin implements Webpack.Plugin { } } - if (this._chunkHasLocalizedModules(chunk)) { + if (this.#chunkHasLocalizedModules(chunk)) { processChunkJsFile((chunkFilename) => { if (chunkFilename.indexOf(Constants.LOCALE_NAME_PLACEHOLDER) === -1) { throw new Error( @@ -404,7 +404,7 @@ export class LocalizationPlugin implements Webpack.Plugin { assetName: chunkFilename, asset, chunk, - chunkHasLocalizedModules: this._chunkHasLocalizedModules.bind(this), + chunkHasLocalizedModules: this.#chunkHasLocalizedModules.bind(this), locales: this.#locales, noStringsLocaleName: this.#noStringsLocaleName, fillMissingTranslationStrings: this.#fillMissingTranslationStrings, @@ -449,7 +449,7 @@ export class LocalizationPlugin implements Webpack.Plugin { asset, chunk, noStringsLocaleName: this.#noStringsLocaleName, - chunkHasLocalizedModules: this._chunkHasLocalizedModules.bind(this) + chunkHasLocalizedModules: this.#chunkHasLocalizedModules.bind(this) }); // Delete the existing asset because it's been renamed @@ -501,8 +501,8 @@ export class LocalizationPlugin implements Webpack.Plugin { const additionalLoadedFilePaths: string[] = []; const errors: Error[] = []; - const locFileData: ILocaleFileData = this._convertLocalizationFileToLocData(localizedResourceData); - this._addLocFile(this.#defaultLocale, localizedResourcePath, locFileData); + const locFileData: ILocaleFileData = this.#convertLocalizationFileToLocData(localizedResourceData); + this.#addLocFile(this.#defaultLocale, localizedResourcePath, locFileData); const normalizeLocalizedData: (localizedData: ILocaleFileData | string) => ILocaleFileData = ( localizedData @@ -517,7 +517,7 @@ export class LocalizationPlugin implements Webpack.Plugin { ignoreMissingResxComments: this.#ignoreMissingResxComments }); - return this._convertLocalizationFileToLocData(localizationFile); + return this.#convertLocalizationFileToLocData(localizationFile); } else { return localizedData; } @@ -533,7 +533,7 @@ export class LocalizationPlugin implements Webpack.Plugin { missingLocales.push(translatedLocaleName); } else { const translatedLocFileData: ILocaleFileData = normalizeLocalizedData(translatedLocFileFromOptions); - this._addLocFile(translatedLocaleName, localizedResourcePath, translatedLocFileData); + this.#addLocFile(translatedLocaleName, localizedResourcePath, translatedLocFileData); } } @@ -552,7 +552,7 @@ export class LocalizationPlugin implements Webpack.Plugin { for (const [resolvedLocaleName, resolvedLocaleData] of Object.entries(resolvedTranslatedData)) { if (resolvedLocaleData) { const translatedLocFileData: ILocaleFileData = normalizeLocalizedData(resolvedLocaleData); - this._addLocFile(resolvedLocaleName, localizedResourcePath, translatedLocFileData); + this.#addLocFile(resolvedLocaleName, localizedResourcePath, translatedLocFileData); } } } @@ -565,7 +565,7 @@ export class LocalizationPlugin implements Webpack.Plugin { pseudolocFileData[stringName] = pseudolocalizer(stringValue); } - this._addLocFile(pseudolocaleName, localizedResourcePath, pseudolocFileData); + this.#addLocFile(pseudolocaleName, localizedResourcePath, pseudolocFileData); }); return { additionalLoadedFilePaths, errors }; @@ -578,7 +578,7 @@ export class LocalizationPlugin implements Webpack.Plugin { return this.#stringPlaceholderMap.get(serialNumber); } - private _addLocFile( + #addLocFile( localeName: string, localizedFilePath: string, localizedFileData: ILocaleFileData @@ -591,7 +591,7 @@ export class LocalizationPlugin implements Webpack.Plugin { for (const [stringName, stringValue] of Object.entries(localizedFileData)) { const stringKey: string = `${localizedFilePath}?${stringName}`; if (!this.stringKeys.has(stringKey)) { - const placeholder: IStringPlaceholder = this._getPlaceholderString(); + const placeholder: IStringPlaceholder = this.#getPlaceholderString(); this.stringKeys.set(stringKey, placeholder); } @@ -612,7 +612,7 @@ export class LocalizationPlugin implements Webpack.Plugin { } } - private _initializeAndValidateOptions( + #initializeAndValidateOptions( configuration: Webpack.Configuration, isWebpackDevServer: boolean ): { errors: Error[]; warnings: Error[] } { @@ -821,7 +821,7 @@ export class LocalizationPlugin implements Webpack.Plugin { return { errors, warnings }; } - private _getPlaceholderString(): IStringPlaceholder { + #getPlaceholderString(): IStringPlaceholder { const suffix: string = (this.#stringPlaceholderCounter++).toString(); return { value: `${Constants.STRING_PLACEHOLDER_PREFIX}_\\_${Constants.STRING_PLACEHOLDER_LABEL}_${suffix}`, @@ -829,7 +829,7 @@ export class LocalizationPlugin implements Webpack.Plugin { }; } - private _chunkHasLocalizedModules(chunk: Webpack.compilation.Chunk): boolean { + #chunkHasLocalizedModules(chunk: Webpack.compilation.Chunk): boolean { let chunkHasAnyLocModules: boolean | undefined = EntityMarker.getMark(chunk); if (chunkHasAnyLocModules === undefined) { chunkHasAnyLocModules = false; @@ -847,7 +847,7 @@ export class LocalizationPlugin implements Webpack.Plugin { // the locale name. if (!chunkHasAnyLocModules && chunk.hasRuntime()) { for (const asyncChunk of chunk.getAllAsyncChunks()) { - if (this._chunkHasLocalizedModules(asyncChunk)) { + if (this.#chunkHasLocalizedModules(asyncChunk)) { chunkHasAnyLocModules = true; break; } @@ -860,7 +860,7 @@ export class LocalizationPlugin implements Webpack.Plugin { return chunkHasAnyLocModules; } - private _convertLocalizationFileToLocData(locFile: ILocalizationFile): ILocaleFileData { + #convertLocalizationFileToLocData(locFile: ILocalizationFile): ILocaleFileData { const locFileData: ILocaleFileData = {}; for (const [stringName, locFileEntry] of Object.entries(locFile)) { locFileData[stringName] = locFileEntry.value; diff --git a/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts b/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts index e3e8ddbcc97..44b84f34a52 100644 --- a/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts +++ b/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts @@ -155,7 +155,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { // https://github.com/webpack/webpack-dev-server/pull/1929/files#diff-15fb51940da53816af13330d8ce69b4eR66 const isWebpackDevServer: boolean = process.env.WEBPACK_DEV_SERVER === 'true'; - const { errors, warnings } = this._initializeAndValidateOptions(compiler, isWebpackDevServer); + const { errors, warnings } = this.#initializeAndValidateOptions(compiler, isWebpackDevServer); if (errors.length > 0 || warnings.length > 0) { compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation: Compilation) => { @@ -492,7 +492,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { localizedResourceData: ILocalizationFile ): Promise> { const locFileData: ReadonlyMap = convertLocalizationFileToLocData(localizedResourceData); - const fileInfo: IFileTranslationInfo = this._addLocFileAndGetPlaceholders( + const fileInfo: IFileTranslationInfo = this.#addLocFileAndGetPlaceholders( this.#defaultLocale, localizedFileKey, locFileData @@ -614,7 +614,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { return this.#customDataPlaceholderBySuffix.get(suffix); } - private _addLocFileAndGetPlaceholders( + #addLocFileAndGetPlaceholders( localeName: string, localizedFileKey: string, localizedFileData: ReadonlyMap @@ -658,7 +658,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { return fileInfo; } - private _initializeAndValidateOptions( + #initializeAndValidateOptions( compiler: Compiler, isWebpackDevServer: boolean ): { errors: WebpackError[]; warnings: WebpackError[] } { From 65244f24834a9bd3eb904fb80a95cf4cc6530fc8 Mon Sep 17 00:00:00 2001 From: Bharat Middha <5100938+bmiddha@users.noreply.github.com> Date: Wed, 19 Aug 2026 15:33:33 -0700 Subject: [PATCH 3/3] refactor: convert SassProcessor _cache accessor pair to # syntax Manually convert the get/set _cache accessor pair the codemod left as private, since both declarations and all 2 usages are plain 'this._cache' property access within SassProcessor's own instance methods, with no subclassing, bracket/reflection access, or external test references in the package. The tool's skip was a limitation of its per-declaration reference tracking (shared accessor symbol), not a real semantic hazard. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14 --- heft-plugins/heft-sass-plugin/src/SassProcessor.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/heft-plugins/heft-sass-plugin/src/SassProcessor.ts b/heft-plugins/heft-sass-plugin/src/SassProcessor.ts index 9863361148b..1ac502077a9 100644 --- a/heft-plugins/heft-sass-plugin/src/SassProcessor.ts +++ b/heft-plugins/heft-sass-plugin/src/SassProcessor.ts @@ -282,7 +282,7 @@ export class SassProcessor { try { const serializedConfig: string = await FileSystem.readFileAsync(this.#configFilePath); - this._cache = serializedConfig; + this.#cache = serializedConfig; } catch (err) { if (!FileSystem.isNotExistError(err)) { this.#options.logger.terminal.writeVerboseLine(`Error reading cache file: ${err}`); @@ -404,7 +404,7 @@ export class SassProcessor { ); if (this.#configFilePath) { - const serializedConfig: string = this._cache; + const serializedConfig: string = this.#cache; try { await FileSystem.writeFileAsync(this.#configFilePath, serializedConfig, { ensureFolderExists: true @@ -610,7 +610,7 @@ export class SassProcessor { return null; } - private get _cache(): string { + get #cache(): string { const serializedRecords: ISerializedFileRecord[] = Array.from(this.#fileInfo.values(), (record) => { return { relativePath: record.relativePath, @@ -627,7 +627,7 @@ export class SassProcessor { * Configures the state of this processor using the specified cache file content. * @param cacheFileContent - The contents of the cache file */ - private set _cache(cacheFileContent: string) { + set #cache(cacheFileContent: string) { this.#fileInfo.clear(); const serializedRecords: ISerializedFileRecord[] = JSON.parse(cacheFileContent);