From 22c7a7bc50ac8a2b7358b032b0b758a470f70cfd Mon Sep 17 00:00:00 2001 From: gasnier Date: Sun, 28 Mar 2021 00:49:09 +0100 Subject: [PATCH 01/12] buildSolutionReferences with instance transformers --- src/index.ts | 1 - src/instances.ts | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 95e53e301..7c9a15a4b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,7 +43,6 @@ function loader(this: webpack.loader.LoaderContext, contents: string) { return; } const instance = instanceOrError.instance!; - buildSolutionReferences(instance, this); successLoader(this, contents, callback, instance); } diff --git a/src/instances.ts b/src/instances.ts index 3d7c299c5..0acc06656 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -405,6 +405,7 @@ export function initializeInstance( : instance.compiler.createProgram([], instance.compilerOptions)); instance.transformers = getCustomTransformers(program); + buildSolutionReferences(instance, loader);//build references after setting transformers // Setup watch run for solution building if (instance.solutionBuilderHost) { addAssetHooks(loader, instance); @@ -454,7 +455,7 @@ export function initializeInstance( instance.languageService!.getProgram() ); } - + buildSolutionReferences(instance, loader);//build references after setting transformers addAssetHooks(loader, instance); loader._compiler.hooks.watchRun.tapAsync( @@ -535,6 +536,19 @@ export function buildSolutionReferences( instance.configParseResult.projectReferences!.map(ref => ref.path), { verbose: true } ); + + //build invalidated references with the instance transformers + let invalidatedProject = solutionBuilder.getNextInvalidatedProject(); + while (invalidatedProject) { + invalidatedProject.emit( + void 0, + void 0, + void 0, + void 0, + instance.transformers); + invalidatedProject = solutionBuilder.getNextInvalidatedProject(); + } + solutionBuilder.build(); instance.solutionBuilderHost.ensureAllReferenceTimestamps(); instancesBySolutionBuilderConfigs.set( From 8967f6f78c0dda5a5ffaf65b705a52639559341b Mon Sep 17 00:00:00 2001 From: gasnier Date: Sun, 28 Mar 2021 01:11:35 +0100 Subject: [PATCH 02/12] fix build --- src/index.ts | 1 - src/instances.ts | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 7c9a15a4b..958129b02 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,6 @@ import * as webpack from 'webpack'; import * as constants from './constants'; import { - buildSolutionReferences, getEmitOutput, getInputFileNameFromOutput, getTypeScriptInstance, diff --git a/src/instances.ts b/src/instances.ts index 0acc06656..509f16653 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -540,12 +540,14 @@ export function buildSolutionReferences( //build invalidated references with the instance transformers let invalidatedProject = solutionBuilder.getNextInvalidatedProject(); while (invalidatedProject) { - invalidatedProject.emit( + if(invalidatedProject.kind === typescript.InvalidatedProjectKind.Build){ + invalidatedProject.emit( void 0, void 0, void 0, void 0, instance.transformers); + } invalidatedProject = solutionBuilder.getNextInvalidatedProject(); } From 9b65d9e3cd1d1db735b68635f44e055c8100d99e Mon Sep 17 00:00:00 2001 From: gasnier Date: Sun, 28 Mar 2021 01:21:18 +0100 Subject: [PATCH 03/12] fix prettier problems --- src/instances.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/instances.ts b/src/instances.ts index 509f16653..cbcd76e97 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -405,7 +405,7 @@ export function initializeInstance( : instance.compiler.createProgram([], instance.compilerOptions)); instance.transformers = getCustomTransformers(program); - buildSolutionReferences(instance, loader);//build references after setting transformers + buildSolutionReferences(instance, loader); //build references after setting transformers // Setup watch run for solution building if (instance.solutionBuilderHost) { addAssetHooks(loader, instance); @@ -455,7 +455,7 @@ export function initializeInstance( instance.languageService!.getProgram() ); } - buildSolutionReferences(instance, loader);//build references after setting transformers + buildSolutionReferences(instance, loader); //build references after setting transformers addAssetHooks(loader, instance); loader._compiler.hooks.watchRun.tapAsync( @@ -540,15 +540,16 @@ export function buildSolutionReferences( //build invalidated references with the instance transformers let invalidatedProject = solutionBuilder.getNextInvalidatedProject(); while (invalidatedProject) { - if(invalidatedProject.kind === typescript.InvalidatedProjectKind.Build){ - invalidatedProject.emit( - void 0, - void 0, - void 0, - void 0, - instance.transformers); - } - invalidatedProject = solutionBuilder.getNextInvalidatedProject(); + if (invalidatedProject.kind === typescript.InvalidatedProjectKind.Build) { + invalidatedProject.emit( + void 0, + void 0, + void 0, + void 0, + instance.transformers + ); + } + invalidatedProject = solutionBuilder.getNextInvalidatedProject(); } solutionBuilder.build(); From da7143705305d62b6f3255e0a59cd5028ad5e97c Mon Sep 17 00:00:00 2001 From: gasnier Date: Sun, 28 Mar 2021 03:25:53 +0200 Subject: [PATCH 04/12] handle all kinds of invalidatedProject --- src/instances.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/instances.ts b/src/instances.ts index cbcd76e97..bc8bb4a8f 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -542,12 +542,21 @@ export function buildSolutionReferences( while (invalidatedProject) { if (invalidatedProject.kind === typescript.InvalidatedProjectKind.Build) { invalidatedProject.emit( - void 0, - void 0, - void 0, - void 0, + undefined, + undefined, + undefined, + undefined, instance.transformers ); + } else if ( + invalidatedProject.kind === + typescript.InvalidatedProjectKind.UpdateBundle + ) { + invalidatedProject.emit(undefined, instance.transformers); + } else if (invalidatedProject.updateOutputFileStatmps) { + invalidatedProject.updateOutputFileStatmps(); + } else { + invalidatedProject.done(undefined, undefined, instance.transformers); } invalidatedProject = solutionBuilder.getNextInvalidatedProject(); } From 2f8bb310f83984817aa4b3ba0ee897fb1a05f033 Mon Sep 17 00:00:00 2001 From: gasnier Date: Sun, 28 Mar 2021 12:35:00 +0200 Subject: [PATCH 05/12] let invalidatedProject 'done' function do the job --- src/instances.ts | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/instances.ts b/src/instances.ts index bc8bb4a8f..c0f77cd08 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -540,24 +540,10 @@ export function buildSolutionReferences( //build invalidated references with the instance transformers let invalidatedProject = solutionBuilder.getNextInvalidatedProject(); while (invalidatedProject) { - if (invalidatedProject.kind === typescript.InvalidatedProjectKind.Build) { - invalidatedProject.emit( - undefined, - undefined, - undefined, - undefined, - instance.transformers - ); - } else if ( - invalidatedProject.kind === - typescript.InvalidatedProjectKind.UpdateBundle - ) { - invalidatedProject.emit(undefined, instance.transformers); - } else if (invalidatedProject.updateOutputFileStatmps) { - invalidatedProject.updateOutputFileStatmps(); - } else { - invalidatedProject.done(undefined, undefined, instance.transformers); - } + //done will emit files or updateOutputTimestamps before calling doneInvalidatedProject that will allow us to go to next invalidated project + invalidatedProject.done(undefined, undefined, instance.transformers); + + //go to next invalidatedProject = solutionBuilder.getNextInvalidatedProject(); } From bdd8cc927994bfd207c1bc7be0ff28ca46fe7fc7 Mon Sep 17 00:00:00 2001 From: gasnier Date: Sun, 28 Mar 2021 16:19:29 +0200 Subject: [PATCH 06/12] code simplification --- src/index.ts | 2 ++ src/instances.ts | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 713305788..d353be8f2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import * as webpack from 'webpack'; import * as constants from './constants'; import { + buildSolutionReferences, getEmitOutput, getInputFileNameFromOutput, getTypeScriptInstance, @@ -52,6 +53,7 @@ function successLoader( instance: TSInstance ) { initializeInstance(loaderContext, instance); + buildSolutionReferences(instance, loaderContext); //build references after setting transformers and hooks reportTranspileErrors(instance, loaderContext); const rawFilePath = path.normalize(loaderContext.resourcePath); diff --git a/src/instances.ts b/src/instances.ts index c619c4a16..b0f0166e0 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -405,7 +405,6 @@ export function initializeInstance( : instance.compiler.createProgram([], instance.compilerOptions)); instance.transformers = getCustomTransformers(program); - buildSolutionReferences(instance, loader); //build references after setting transformers // Setup watch run for solution building if (instance.solutionBuilderHost) { addAssetHooks(loader, instance); @@ -455,7 +454,7 @@ export function initializeInstance( instance.languageService!.getProgram() ); } - buildSolutionReferences(instance, loader); //build references after setting transformers + addAssetHooks(loader, instance); loader._compiler.hooks.watchRun.tapAsync( From 9c5cc499cece8387c1d0b222bda710eace53cb4c Mon Sep 17 00:00:00 2001 From: gasnier Date: Mon, 29 Mar 2021 23:01:29 +0200 Subject: [PATCH 07/12] override program.emit to always pass transformers --- src/index.ts | 2 + src/instances.ts | 49 +++++---------------- src/transformers.ts | 105 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 38 deletions(-) create mode 100644 src/transformers.ts diff --git a/src/index.ts b/src/index.ts index d353be8f2..235f80535 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,6 +20,7 @@ import { LogLevel, TSInstance, } from './interfaces'; +import { installTransformers } from './transformers'; import { appendSuffixesIfMatch, arrify, @@ -36,6 +37,7 @@ function loader(this: webpack.loader.LoaderContext, contents: string) { this.cacheable && this.cacheable(); const callback = this.async() as webpack.loader.loaderCallback; const options = getLoaderOptions(this); + installTransformers(options); const instanceOrError = getTypeScriptInstance(options, this); if (instanceOrError.error !== undefined) { diff --git a/src/instances.ts b/src/instances.ts index b0f0166e0..4ea335ece 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -23,6 +23,7 @@ import { makeSolutionBuilderHost, makeWatchHost, } from './servicesHost'; +import { getCustomTransformers } from './transformers'; import { appendSuffixesIfMatch, ensureProgram, @@ -369,31 +370,6 @@ export function initializeInstance( instance.initialSetupPending = false; - // same strategy as https://github.com/s-panferov/awesome-typescript-loader/pull/531/files - let { getCustomTransformers: customerTransformers } = instance.loaderOptions; - let getCustomTransformers = Function.prototype; - - if (typeof customerTransformers === 'function') { - getCustomTransformers = customerTransformers; - } else if (typeof customerTransformers === 'string') { - try { - customerTransformers = require(customerTransformers); - } catch (err) { - throw new Error( - `Failed to load customTransformers from "${instance.loaderOptions.getCustomTransformers}": ${err.message}` - ); - } - - if (typeof customerTransformers !== 'function') { - throw new Error( - `Custom transformers in "${ - instance.loaderOptions.getCustomTransformers - }" should export a function, got ${typeof getCustomTransformers}` - ); - } - getCustomTransformers = customerTransformers; - } - if (instance.loaderOptions.transpileOnly) { const program = (instance.program = instance.configParseResult.projectReferences !== undefined @@ -404,7 +380,10 @@ export function initializeInstance( }) : instance.compiler.createProgram([], instance.compilerOptions)); - instance.transformers = getCustomTransformers(program); + instance.transformers = getCustomTransformers( + instance.loaderOptions, + program + ); // Setup watch run for solution building if (instance.solutionBuilderHost) { addAssetHooks(loader, instance); @@ -436,7 +415,10 @@ export function initializeInstance( instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram(); instance.program = instance.builderProgram.getProgram(); - instance.transformers = getCustomTransformers(instance.program); + instance.transformers = getCustomTransformers( + instance.loaderOptions, + instance.program + ); } else { instance.servicesHost = makeServicesHost( getScriptRegexp(instance), @@ -451,7 +433,8 @@ export function initializeInstance( ); instance.transformers = getCustomTransformers( - instance.languageService!.getProgram() + instance.loaderOptions, + instance.languageService!.getProgram()! ); } @@ -536,16 +519,6 @@ export function buildSolutionReferences( { verbose: true } ); - //build invalidated references with the instance transformers - let invalidatedProject = solutionBuilder.getNextInvalidatedProject(); - while (invalidatedProject) { - //done will emit files or updateOutputTimestamps before calling doneInvalidatedProject that will allow us to go to next invalidated project - invalidatedProject.done(undefined, undefined, instance.transformers); - - //go to next - invalidatedProject = solutionBuilder.getNextInvalidatedProject(); - } - solutionBuilder.build(); instance.solutionBuilderHost.ensureAllReferenceTimestamps(); instancesBySolutionBuilderConfigs.set( diff --git a/src/transformers.ts b/src/transformers.ts new file mode 100644 index 000000000..1d1624c03 --- /dev/null +++ b/src/transformers.ts @@ -0,0 +1,105 @@ +import * as ts from 'typescript'; +import { LoaderOptions } from './interfaces'; + +export function getCustomTransformers( + loaderOptions: LoaderOptions, + program: ts.Program +) { + // same strategy as https://github.com/s-panferov/awesome-typescript-loader/pull/531/files + let { getCustomTransformers: customerTransformers } = loaderOptions; + let getCustomTransformers = Function.prototype; + + if (typeof customerTransformers === 'function') { + getCustomTransformers = customerTransformers; + } else if (typeof customerTransformers === 'string') { + try { + customerTransformers = require(customerTransformers); + } catch (err) { + throw new Error( + `Failed to load customTransformers from "${loaderOptions.getCustomTransformers}": ${err.message}` + ); + } + + if (typeof customerTransformers !== 'function') { + throw new Error( + `Custom transformers in "${ + loaderOptions.getCustomTransformers + }" should export a function, got ${typeof getCustomTransformers}` + ); + } + getCustomTransformers = customerTransformers; + } + return getCustomTransformers(program); +} + +/** + * For now we need to patch typescript to force transformers passed to the program.emit function. + * We will be able to remove this code once typescript will add customTransformers to SolutionBuilder + * SolutionBuilder is used when watch is enabled + */ +let patched = false; +export function installTransformers(loaderOptions: LoaderOptions) { + if (!loaderOptions.getCustomTransformers) { + return; //no need to patch if there is no transformer + } + if (patched) { + return; //do not patch twice + } + patched = true; + const originalCreateProgram = ts.createProgram; + + //override createProgram in order to override emit function and use overrideTransformers + function createProgram( + rootNamesOrOptions: ReadonlyArray | ts.CreateProgramOptions, + options?: ts.CompilerOptions, + host?: ts.CompilerHost, + oldProgram?: ts.Program, + configFileParsingDiagnostics?: ReadonlyArray + ): ts.Program { + let program: ts.Program; + if (Array.isArray(rootNamesOrOptions)) { + program = originalCreateProgram( + rootNamesOrOptions as ReadonlyArray, + options!, + host, + oldProgram, + configFileParsingDiagnostics + ); + } else { + program = originalCreateProgram( + rootNamesOrOptions as ts.CreateProgramOptions + ); + } + + const transformers: + | ts.CustomTransformers + | undefined = getCustomTransformers(loaderOptions, program); + + const originalEmit = program.emit; + + function newEmit( + targetSourceFile?: ts.SourceFile, + writeFile?: ts.WriteFileCallback, + cancellationToken?: ts.CancellationToken, + emitOnlyDtsFiles?: boolean, + customTransformers?: ts.CustomTransformers + ): ts.EmitResult { + /* Invoke TS emit */ + const result: ts.EmitResult = originalEmit( + targetSourceFile, + writeFile, + cancellationToken, + emitOnlyDtsFiles, + transformers ? transformers : customTransformers + ); + + return result; + } + + program.emit = newEmit; + + return program; + } + + Object.assign(ts, { createProgram }); +} From 6f3f2033d6833219a5ae740879c87e8a1ed9e23f Mon Sep 17 00:00:00 2001 From: gasnier Date: Mon, 19 Apr 2021 09:59:24 +0200 Subject: [PATCH 08/12] handle transformers in a single place merge transformers in case additional transformers were added somewhere --- src/instances.ts | 18 ++---------------- src/transformers.ts | 44 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/instances.ts b/src/instances.ts index 34eeeb754..edae6f29f 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -23,7 +23,6 @@ import { makeSolutionBuilderHost, makeWatchHost, } from './servicesHost'; -import { getCustomTransformers } from './transformers'; import { appendSuffixesIfMatch, ensureProgram, @@ -345,19 +344,15 @@ export function initializeInstance( instance.initialSetupPending = false; if (instance.loaderOptions.transpileOnly) { - const program = (instance.program = + instance.program = instance.configParseResult.projectReferences !== undefined ? instance.compiler.createProgram({ rootNames: instance.configParseResult.fileNames, options: instance.configParseResult.options, projectReferences: instance.configParseResult.projectReferences, }) - : instance.compiler.createProgram([], instance.compilerOptions)); + : instance.compiler.createProgram([], instance.compilerOptions); - instance.transformers = getCustomTransformers( - instance.loaderOptions, - program - ); // Setup watch run for solution building if (instance.solutionBuilderHost) { addAssetHooks(loader, instance); @@ -389,10 +384,6 @@ export function initializeInstance( instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram(); instance.program = instance.builderProgram.getProgram(); - instance.transformers = getCustomTransformers( - instance.loaderOptions, - instance.program - ); } else { instance.servicesHost = makeServicesHost( getScriptRegexp(instance), @@ -405,11 +396,6 @@ export function initializeInstance( instance.servicesHost, instance.compiler.createDocumentRegistry() ); - - instance.transformers = getCustomTransformers( - instance.loaderOptions, - instance.languageService!.getProgram()! - ); } addAssetHooks(loader, instance); diff --git a/src/transformers.ts b/src/transformers.ts index 1d1624c03..ba1e26abb 100644 --- a/src/transformers.ts +++ b/src/transformers.ts @@ -32,6 +32,44 @@ export function getCustomTransformers( return getCustomTransformers(program); } +/** + * @returns a ts.CustomTransformers merged from tr1 and tr2 (does not check for duplicates) + */ +function mergeTransformers(tr1: ts.CustomTransformers | undefined, tr2: ts.CustomTransformers | undefined ):ts.CustomTransformers | undefined{ + if(tr1){ + const result:ts.CustomTransformers = { + after : [], + before :[], + afterDeclarations:[] + }; + //add tr1 values in result + if(tr1.after){ + result.after!.push(...tr1.after); + } + if(tr1.before){ + result.before!.push(...tr1.before); + } + if(tr1.afterDeclarations){ + result.afterDeclarations!.push(...tr1.afterDeclarations); + } + + //add tr2 values + if(tr2?.after){ + result.after!.push(...tr2.after); + } + if(tr2?.before){ + result.before!.push(...tr2.before); + } + if(tr2?.afterDeclarations){ + result.afterDeclarations!.push(...tr2.afterDeclarations); + } + + return result; + }else{ + return tr2; + } +} + /** * For now we need to patch typescript to force transformers passed to the program.emit function. * We will be able to remove this code once typescript will add customTransformers to SolutionBuilder @@ -71,9 +109,7 @@ export function installTransformers(loaderOptions: LoaderOptions) { ); } - const transformers: - | ts.CustomTransformers - | undefined = getCustomTransformers(loaderOptions, program); + const transformers: ts.CustomTransformers | undefined = getCustomTransformers(loaderOptions, program); const originalEmit = program.emit; @@ -90,7 +126,7 @@ export function installTransformers(loaderOptions: LoaderOptions) { writeFile, cancellationToken, emitOnlyDtsFiles, - transformers ? transformers : customTransformers + mergeTransformers(transformers, customTransformers) ); return result; From 010d85994d309b33064db1b43153a704ccc6ed17 Mon Sep 17 00:00:00 2001 From: gasnier Date: Mon, 19 Apr 2021 11:19:14 +0200 Subject: [PATCH 09/12] revert move buildSolutionReferences (because unit tests do not pass and it is no longer needed for transformers) --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 915f57c81..84f96cdc0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -46,6 +46,7 @@ function loader(this: WebpackLoaderContext, contents: string) { return; } const instance = instanceOrError.instance!; + buildSolutionReferences(instance, this); // Warning: references are built before hooks are set in initializeInstance successLoader(this, contents, callback, instance); } @@ -56,7 +57,6 @@ function successLoader( instance: TSInstance ) { initializeInstance(loaderContext, instance); - buildSolutionReferences(instance, loaderContext); //build references after setting transformers and hooks reportTranspileErrors(instance, loaderContext); const rawFilePath = path.normalize(loaderContext.resourcePath); From 093ef04bbb5ae72084c73101d6027f677c203730 Mon Sep 17 00:00:00 2001 From: gasnier Date: Wed, 5 May 2021 21:49:59 +0200 Subject: [PATCH 10/12] cleanup code --- src/index.ts | 42 ++++++++++++++++------------------ src/instances.ts | 56 +++++++++++++++++++++------------------------ src/interfaces.ts | 17 +++++++------- src/servicesHost.ts | 40 +++++++++++++++----------------- src/transformers.ts | 33 +++++++++++++------------- 5 files changed, 89 insertions(+), 99 deletions(-) diff --git a/src/index.ts b/src/index.ts index 427c83ac0..a2070c664 100644 --- a/src/index.ts +++ b/src/index.ts @@ -61,14 +61,14 @@ function successLoader( const filePath = instance.loaderOptions.appendTsSuffixTo.length > 0 || - instance.loaderOptions.appendTsxSuffixTo.length > 0 + instance.loaderOptions.appendTsxSuffixTo.length > 0 ? appendSuffixesIfMatch( - { - '.ts': instance.loaderOptions.appendTsSuffixTo, - '.tsx': instance.loaderOptions.appendTsxSuffixTo, - }, - rawFilePath - ) + { + '.ts': instance.loaderOptions.appendTsSuffixTo, + '.tsx': instance.loaderOptions.appendTsxSuffixTo, + }, + rawFilePath + ) : rawFilePath; const fileVersion = updateFileInCache( @@ -109,10 +109,10 @@ function makeSourceMapAndFinish( ? ' The most common cause for this is having errors when building referenced projects.' : !instance.loaderOptions.allowTsInNodeModules && filePath.indexOf('node_modules') !== -1 - ? ' By default, ts-loader will not compile .ts files in node_modules.\n' + + ? ' By default, ts-loader will not compile .ts files in node_modules.\n' + 'You should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option.\n' + 'See: https://github.com/Microsoft/TypeScript/issues/12358' - : ''; + : ''; callback( new Error( @@ -274,7 +274,6 @@ function makeLoaderOptions(instanceName: string, loaderOptions: LoaderOptions) { compilerOptions: {}, appendTsSuffixTo: [], appendTsxSuffixTo: [], - transformers: {}, happyPackMode: false, colors: true, onlyCompileBundledFiles: false, @@ -428,7 +427,7 @@ function getEmit( // the real dependency that webpack should watch is the JS output file. addDependency( getInputFileNameFromOutput(instance, path.resolve(resolvedFileName)) || - originalFileName + originalFileName ); } } @@ -441,16 +440,16 @@ function getEmit( '@' + (isReferencedFile(instance, defFilePath) ? instance - .solutionBuilderHost!.getInputFileStamp(defFilePath) - .toString() + .solutionBuilderHost!.getInputFileStamp(defFilePath) + .toString() : ( - instance.files.get(instance.filePathKeyMapper(defFilePath)) || - instance.otherFiles.get( - instance.filePathKeyMapper(defFilePath) - ) || { - version: '?', - } - ).version) + instance.files.get(instance.filePathKeyMapper(defFilePath)) || + instance.otherFiles.get( + instance.filePathKeyMapper(defFilePath) + ) || { + version: '?', + } + ).version) ); return getOutputAndSourceMapFromOutputFiles(outputFiles); @@ -604,7 +603,6 @@ function getTranspilationEmit( diagnostics, } = instance.compiler.transpileModule(contents, { compilerOptions: { ...instance.compilerOptions, rootDir: undefined }, - transformers: instance.transformers, reportDiagnostics: true, fileName, }); @@ -660,5 +658,5 @@ export = loader; // eslint-disable-next-line @typescript-eslint/no-namespace namespace loader { // eslint-disable-next-line @typescript-eslint/no-empty-interface - export interface Options extends LoaderOptions {} + export interface Options extends LoaderOptions { } } diff --git a/src/instances.ts b/src/instances.ts index d047b09b8..a2a118ca6 100644 --- a/src/instances.ts +++ b/src/instances.ts @@ -108,8 +108,8 @@ function createFilePathKeyMapper( const filePathKey = pathResolve(filePath); cachedPath = fileNameLowerCaseRegExp.test(filePathKey) ? (filePathKey.replace(fileNameLowerCaseRegExp, ch => - ch.toLowerCase() - ) as FilePathKey) + ch.toLowerCase() + ) as FilePathKey) : filePathKey; filePathMapperCache.set(filePath, cachedPath); } @@ -197,15 +197,15 @@ function successfulTypeScriptInstance( const appendTsTsxSuffixesIfRequired = loaderOptions.appendTsSuffixTo.length > 0 || - loaderOptions.appendTsxSuffixTo.length > 0 + loaderOptions.appendTsxSuffixTo.length > 0 ? (filePath: string) => - appendSuffixesIfMatch( - { - '.ts': loaderOptions.appendTsSuffixTo, - '.tsx': loaderOptions.appendTsxSuffixTo, - }, - filePath - ) + appendSuffixesIfMatch( + { + '.ts': loaderOptions.appendTsSuffixTo, + '.tsx': loaderOptions.appendTsxSuffixTo, + }, + filePath + ) : (filePath: string) => filePath; if (loaderOptions.transpileOnly) { @@ -222,7 +222,6 @@ function successfulTypeScriptInstance( version: 0, program: undefined, // temporary, to be set later dependencyGraph: new Map(), - transformers: {} as typescript.CustomTransformers, // this is only set temporarily, custom transformers are created further down colors, initialSetupPending: true, reportTranspileErrors: true, @@ -245,8 +244,8 @@ function successfulTypeScriptInstance( try { const filesToLoad = loaderOptions.onlyCompileBundledFiles ? configParseResult.fileNames.filter(fileName => - dtsDtsxOrDtsDtsxMapRegex.test(fileName) - ) + dtsDtsxOrDtsDtsxMapRegex.test(fileName) + ) : configParseResult.fileNames; filesToLoad.forEach(filePath => { normalizedFilePath = path.normalize(filePath); @@ -279,7 +278,6 @@ function successfulTypeScriptInstance( otherFiles, languageService: null, version: 0, - transformers: {} as typescript.CustomTransformers, // this is only set temporarily, custom transformers are created further down dependencyGraph: new Map(), colors, initialSetupPending: true, @@ -349,10 +347,10 @@ export function initializeInstance( instance.program = instance.configParseResult.projectReferences !== undefined ? instance.compiler.createProgram({ - rootNames: instance.configParseResult.fileNames, - options: instance.configParseResult.options, - projectReferences: instance.configParseResult.projectReferences, - }) + rootNames: instance.configParseResult.fileNames, + options: instance.configParseResult.options, + projectReferences: instance.configParseResult.projectReferences, + }) : instance.compiler.createProgram([], instance.compilerOptions); // Setup watch run for solution building @@ -550,13 +548,13 @@ function getOutputPathWithoutChangingExt( ) { return outputDir ? (instance.compiler as any).resolvePath( - outputDir, - (instance.compiler as any).getRelativePathFromDirectory( - rootDirOfOptions(instance, configFile), - inputFileName, - ignoreCase - ) + outputDir, + (instance.compiler as any).getRelativePathFromDirectory( + rootDirOfOptions(instance, configFile), + inputFileName, + ignoreCase ) + ) : inputFileName; } @@ -582,8 +580,8 @@ function getOutputJSFileName( ? '.json' : fileExtensionIs(inputFileName, '.tsx') && configFile.options.jsx === instance.compiler.JsxEmit.Preserve - ? '.jsx' - : '.js' + ? '.jsx' + : '.js' ); return !isJsonFile || (instance.compiler as any).comparePaths( @@ -713,8 +711,7 @@ export function getEmitFromWatchHost(instance: TSInstance, filePath?: string) { const result = builderProgram.emitNextAffectedFile( writeFile, /*cancellationToken*/ undefined, - /*emitOnlyDtsFiles*/ false, - instance.transformers + /*emitOnlyDtsFiles*/ false ); if (!result) { break; @@ -762,8 +759,7 @@ export function getEmitOutput(instance: TSInstance, filePath: string) { sourceFile, writeFile, /*cancellationToken*/ undefined, - /*emitOnlyDtsFiles*/ false, - instance.transformers + /*emitOnlyDtsFiles*/ false ); return outputFiles; } else { diff --git a/src/interfaces.ts b/src/interfaces.ts index 41077a6b9..7c0cc124f 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -39,7 +39,7 @@ export interface CacheableHost extends HostMayBeCacheable { export interface ModuleResolutionHostMayBeCacheable extends typescript.ModuleResolutionHost, - HostMayBeCacheable { + HostMayBeCacheable { readFile(filePath: string, encoding?: string): string | undefined; trace: NonNullable; directoryExists: NonNullable< @@ -65,11 +65,11 @@ export interface ModuleResolutionHostMayBeCacheable export interface ServiceHostWhichMayBeCacheable extends typescript.LanguageServiceHost, - HostMayBeCacheable {} + HostMayBeCacheable { } export interface WatchHost extends typescript.WatchCompilerHostOfFilesAndCompilerOptions, - HostMayBeCacheable { + HostMayBeCacheable { invokeFileWatcher: WatchFactory['invokeFileWatcher']; updateRootFileNames(): void; outputFiles: Map; @@ -104,7 +104,7 @@ export type FilePathKey = string & { __filePathKeyBrand: any }; export interface SolutionBuilderWithWatchHost extends typescript.SolutionBuilderWithWatchHost, - WatchFactory { + WatchFactory { diagnostics: SolutionDiagnostics; writtenFiles: typescript.OutputFile[]; configFileInfo: Map; @@ -209,7 +209,6 @@ export interface TSInstance { version: number; dependencyGraph: DependencyGraph; filesWithErrors?: TSFiles; - transformers: typescript.CustomTransformers; colors: Chalk; otherFiles: TSFiles; @@ -282,10 +281,10 @@ export interface LoaderOptions { appendTsxSuffixTo: (RegExp | string)[]; happyPackMode: boolean; getCustomTransformers: - | string - | (( - program: typescript.Program - ) => typescript.CustomTransformers | undefined); + | string + | (( + program: typescript.Program + ) => typescript.CustomTransformers | undefined); experimentalWatchApi: boolean; allowTsInNodeModules: boolean; experimentalFileCaching: boolean; diff --git a/src/servicesHost.ts b/src/servicesHost.ts index 383d437a2..445e1db63 100644 --- a/src/servicesHost.ts +++ b/src/servicesHost.ts @@ -52,8 +52,8 @@ function makeResolversAndModuleResolutionHost( compilerOptions.newLine === constants.CarriageReturnLineFeedCode ? constants.CarriageReturnLineFeed : compilerOptions.newLine === constants.LineFeedCode - ? constants.LineFeed - : constants.EOL; + ? constants.LineFeed + : constants.EOL; // loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3 const getCurrentDirectory = () => loader.context; @@ -229,9 +229,7 @@ export function makeServicesHost( // used for (/// ) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329 resolveTypeReferenceDirectives, - resolveModuleNames, - - getCustomTransformers: () => instance.transformers, + resolveModuleNames }; return servicesHost; @@ -980,12 +978,12 @@ export function makeSolutionBuilderHost( configInfo.tsbuildInfoFile = instance.compiler .getTsBuildInfoEmitOutputFilePath ? instance.compiler.getTsBuildInfoEmitOutputFilePath( - configInfo.config.options - ) + configInfo.config.options + ) : // before api - (instance.compiler as any).getOutputPathForBuildInfo( - configInfo.config.options - ); + (instance.compiler as any).getOutputPathForBuildInfo( + configInfo.config.options + ); } function getOutputFileAndKeyFromReferencedProject( @@ -994,9 +992,9 @@ export function makeSolutionBuilderHost( const outputFile = ensureOutputFile(outputFileName); return outputFile !== undefined ? { - key: getOutputFileKeyFromReferencedProject(outputFileName)!, - outputFile, - } + key: getOutputFileKeyFromReferencedProject(outputFileName)!, + outputFile, + } : undefined; } @@ -1076,10 +1074,10 @@ export function makeSolutionBuilderHost( const text = compiler.sys.readFile(outputFileName); return text !== undefined ? { - name: outputFileName, - text, - writeByteOrderMark: false, - } + name: outputFileName, + text, + writeByteOrderMark: false, + } : undefined; } @@ -1125,8 +1123,8 @@ export function makeSolutionBuilderHost( existing == missingFileModifiedTime ? compiler.FileWatcherEventKind.Created : newTime === missingFileModifiedTime - ? compiler.FileWatcherEventKind.Deleted - : compiler.FileWatcherEventKind.Changed; + ? compiler.FileWatcherEventKind.Deleted + : compiler.FileWatcherEventKind.Changed; solutionBuilderHost.invokeFileWatcher(fileName, eventKind); } } @@ -1239,7 +1237,7 @@ function resolveModule( resolutionResult = { resolvedFileName, originalFileName }; } } - } catch (e) {} + } catch (e) { } const tsResolution = resolveModuleName( moduleName, @@ -1258,7 +1256,7 @@ function resolveModule( return resolutionResult! === undefined || resolutionResult.resolvedFileName === - tsResolutionResult.resolvedFileName || + tsResolutionResult.resolvedFileName || isJsImplementationOfTypings(resolutionResult!, tsResolutionResult) ? tsResolutionResult : resolutionResult!; diff --git a/src/transformers.ts b/src/transformers.ts index ba1e26abb..64e4bfffc 100644 --- a/src/transformers.ts +++ b/src/transformers.ts @@ -22,8 +22,7 @@ export function getCustomTransformers( if (typeof customerTransformers !== 'function') { throw new Error( - `Custom transformers in "${ - loaderOptions.getCustomTransformers + `Custom transformers in "${loaderOptions.getCustomTransformers }" should export a function, got ${typeof getCustomTransformers}` ); } @@ -35,44 +34,44 @@ export function getCustomTransformers( /** * @returns a ts.CustomTransformers merged from tr1 and tr2 (does not check for duplicates) */ -function mergeTransformers(tr1: ts.CustomTransformers | undefined, tr2: ts.CustomTransformers | undefined ):ts.CustomTransformers | undefined{ - if(tr1){ - const result:ts.CustomTransformers = { - after : [], - before :[], - afterDeclarations:[] +function mergeTransformers(tr1: ts.CustomTransformers | undefined, tr2: ts.CustomTransformers | undefined): ts.CustomTransformers | undefined { + if (tr1) { + const result: ts.CustomTransformers = { + after: [], + before: [], + afterDeclarations: [] }; //add tr1 values in result - if(tr1.after){ + if (tr1.after) { result.after!.push(...tr1.after); } - if(tr1.before){ + if (tr1.before) { result.before!.push(...tr1.before); } - if(tr1.afterDeclarations){ + if (tr1.afterDeclarations) { result.afterDeclarations!.push(...tr1.afterDeclarations); } //add tr2 values - if(tr2?.after){ + if (tr2?.after) { result.after!.push(...tr2.after); } - if(tr2?.before){ + if (tr2?.before) { result.before!.push(...tr2.before); } - if(tr2?.afterDeclarations){ + if (tr2?.afterDeclarations) { result.afterDeclarations!.push(...tr2.afterDeclarations); } return result; - }else{ + } else { return tr2; } } /** - * For now we need to patch typescript to force transformers passed to the program.emit function. - * We will be able to remove this code once typescript will add customTransformers to SolutionBuilder + * Patches typescript program to pass custom transformers to the program.emit function. + * In 2021, this is the only way since it is not possible to pass transformers to SolutionBuilder * SolutionBuilder is used when watch is enabled */ let patched = false; From e8b2bc8adfc99a15930078ba4aa41ed6b0cfc0b3 Mon Sep 17 00:00:00 2001 From: John Reilly Date: Thu, 6 May 2021 06:07:24 +0100 Subject: [PATCH 11/12] Explicitly check for undefined --- src/transformers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transformers.ts b/src/transformers.ts index 64e4bfffc..6c5649041 100644 --- a/src/transformers.ts +++ b/src/transformers.ts @@ -76,7 +76,7 @@ function mergeTransformers(tr1: ts.CustomTransformers | undefined, tr2: ts.Custo */ let patched = false; export function installTransformers(loaderOptions: LoaderOptions) { - if (!loaderOptions.getCustomTransformers) { + if (loaderOptions.getCustomTransformers === undefined) { return; //no need to patch if there is no transformer } if (patched) { From 2f951fc48fc4c5aab130133bb2e49f01ae87e58e Mon Sep 17 00:00:00 2001 From: John Reilly Date: Thu, 6 May 2021 06:09:41 +0100 Subject: [PATCH 12/12] Explicitly check for true --- src/transformers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transformers.ts b/src/transformers.ts index 6c5649041..66863a3fb 100644 --- a/src/transformers.ts +++ b/src/transformers.ts @@ -79,7 +79,7 @@ export function installTransformers(loaderOptions: LoaderOptions) { if (loaderOptions.getCustomTransformers === undefined) { return; //no need to patch if there is no transformer } - if (patched) { + if (patched === true) { return; //do not patch twice } patched = true;