From d399128c23a902064766352707239e17d884425f Mon Sep 17 00:00:00 2001 From: David Michon <dmichon-msft@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:01:49 -0700 Subject: [PATCH] Add more comments --- .../TypeScriptPlugin/TypeScriptBuilder.ts | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/heft/src/plugins/TypeScriptPlugin/TypeScriptBuilder.ts b/apps/heft/src/plugins/TypeScriptPlugin/TypeScriptBuilder.ts index 30b7d361891..a918def6328 100644 --- a/apps/heft/src/plugins/TypeScriptPlugin/TypeScriptBuilder.ts +++ b/apps/heft/src/plugins/TypeScriptPlugin/TypeScriptBuilder.ts @@ -131,6 +131,10 @@ const OLDEST_SUPPORTED_TS_MINOR_VERSION: number = 9; const NEWEST_SUPPORTED_TS_MAJOR_VERSION: number = 5; const NEWEST_SUPPORTED_TS_MINOR_VERSION: number = 0; +// symbols for attaching hidden metadata to ts.Program instances. +const INNER_GET_COMPILER_OPTIONS_SYMBOL: unique symbol = Symbol('getCompilerOptions'); +const INNER_EMIT_SYMBOL: unique symbol = Symbol('emit'); + export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderConfiguration> { private _typescriptVersion!: string; private _typescriptParsedVersion!: semver.SemVer; @@ -414,20 +418,24 @@ export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderCo ts: ExtendedTypeScript ): { changedFiles: Set<IExtendedSourceFile> } { interface IProgramWithMultiEmit extends TTypescript.Program { - __innerGetCompilerOptions?: TTypescript.Program['getCompilerOptions']; - __innerEmit?: TTypescript.Program['emit']; + // Attach the originals to the Program instance to avoid modifying the same Program twice. + // Don't use WeakMap because this Program could theoretically get a { ... } applied to it. + [INNER_GET_COMPILER_OPTIONS_SYMBOL]?: TTypescript.Program['getCompilerOptions']; + [INNER_EMIT_SYMBOL]?: TTypescript.Program['emit']; } const program: IProgramWithMultiEmit = innerProgram; - let { __innerEmit: innerEmit, __innerGetCompilerOptions: innerGetCompilerOptions } = program; + // Check to see if this Program has already been modified. + let { [INNER_EMIT_SYMBOL]: innerEmit, [INNER_GET_COMPILER_OPTIONS_SYMBOL]: innerGetCompilerOptions } = + program; if (!innerGetCompilerOptions) { - program.__innerGetCompilerOptions = innerGetCompilerOptions = program.getCompilerOptions; + program[INNER_GET_COMPILER_OPTIONS_SYMBOL] = innerGetCompilerOptions = program.getCompilerOptions; } if (!innerEmit) { - program.__innerEmit = innerEmit = program.emit; + program[INNER_EMIT_SYMBOL] = innerEmit = program.emit; } let foundPrimary: boolean = false; @@ -474,7 +482,7 @@ export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderCo customTransformers?: TTypescript.CustomTransformers ) => { if (emitOnlyDtsFiles) { - return program.__innerEmit!( + return program[INNER_EMIT_SYMBOL]!( targetSourceFile, writeFile, cancellationToken, @@ -487,7 +495,8 @@ export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderCo changedFiles.add(targetSourceFile as IExtendedSourceFile); } - const originalCompilerOptions: TTypescript.CompilerOptions = program.__innerGetCompilerOptions!(); + const originalCompilerOptions: TTypescript.CompilerOptions = + program[INNER_GET_COMPILER_OPTIONS_SYMBOL]!(); let defaultModuleKindResult: TTypescript.EmitResult; const diagnostics: TTypescript.Diagnostic[] = []; @@ -498,7 +507,7 @@ export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderCo // Need to mutate the compiler options for the `module` field specifically, because emitWorker() captures // options in the closure and passes it to `ts.getTransformers()` originalCompilerOptions.module = moduleKindToEmit.moduleKind; - const flavorResult: TTypescript.EmitResult = program.__innerEmit!( + const flavorResult: TTypescript.EmitResult = program[INNER_EMIT_SYMBOL]!( targetSourceFile, writeFile && wrapWriteFile(writeFile, moduleKindToEmit.jsExtensionOverride), cancellationToken, @@ -507,6 +516,7 @@ export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderCo ); emitSkipped = emitSkipped || flavorResult.emitSkipped; + // Need to aggregate diagnostics because some are impacted by the target module type for (const diagnostic of flavorResult.diagnostics) { diagnostics.push(diagnostic); } @@ -514,7 +524,6 @@ export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderCo if (moduleKindToEmit.moduleKind === defaultModuleKind) { defaultModuleKindResult = flavorResult; } - // Should results be aggregated, in case for whatever reason the diagnostics are not the same? } const mergedDiagnostics: readonly TTypescript.Diagnostic[] = @@ -527,7 +536,8 @@ export class TypeScriptBuilder extends SubprocessRunnerBase<ITypeScriptBuilderCo emitSkipped }; } finally { - program.getCompilerOptions = program.__innerGetCompilerOptions!; + // Restore the original compiler options and module kind for future calls + program.getCompilerOptions = program[INNER_GET_COMPILER_OPTIONS_SYMBOL]!; originalCompilerOptions.module = defaultModuleKind; } };