From ee02eb60d8bd5f202f3c90b6d3b435ae45d731aa Mon Sep 17 00:00:00 2001 From: Ahn Date: Sat, 18 Apr 2020 13:12:20 +0200 Subject: [PATCH 1/2] chore: rename some files and methods in compiler area --- src/__helpers__/fakers.ts | 4 +-- .../language-service.spec.ts.snap | 14 +++++----- ...e.spec.ts.snap => transpiler.spec.ts.snap} | 28 +++++++++---------- src/compiler/instance.ts | 23 +++++++-------- src/compiler/language-service.spec.ts | 2 +- src/compiler/language-service.ts | 2 +- src/compiler/program.ts | 6 +++- ...pile-module.spec.ts => transpiler.spec.ts} | 2 +- .../{transpile-module.ts => transpiler.ts} | 16 +++++------ src/config/config-set.ts | 4 +-- 10 files changed, 53 insertions(+), 48 deletions(-) rename src/compiler/__snapshots__/{transpile-module.spec.ts.snap => transpiler.spec.ts.snap} (63%) rename src/compiler/{transpile-module.spec.ts => transpiler.spec.ts} (98%) rename src/compiler/{transpile-module.ts => transpiler.ts} (87%) diff --git a/src/__helpers__/fakers.ts b/src/__helpers__/fakers.ts index 8655284f4b..c1b5d49490 100644 --- a/src/__helpers__/fakers.ts +++ b/src/__helpers__/fakers.ts @@ -1,7 +1,7 @@ import { Config } from '@jest/types' import { resolve } from 'path' -import { createCompiler } from '../compiler/instance' +import { createCompilerInstance } from '../compiler/instance' import { ConfigSet } from '../config/config-set' import { BabelConfig, TsJestConfig, TsJestGlobalOptions } from '../types' import { ImportReasons } from '../util/messages' @@ -76,5 +76,5 @@ export function makeCompiler({ } const cs = new ConfigSet(getJestConfig(jestConfig, tsJestConfig), parentConfig) - return createCompiler(cs) + return createCompilerInstance(cs) } diff --git a/src/compiler/__snapshots__/language-service.spec.ts.snap b/src/compiler/__snapshots__/language-service.spec.ts.snap index f6ae9ebfe7..c6383bdc3c 100644 --- a/src/compiler/__snapshots__/language-service.spec.ts.snap +++ b/src/compiler/__snapshots__/language-service.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`language service should compile js file for allowJs true with outDir 1`] = ` +exports[`Language service should compile js file for allowJs true with outDir 1`] = ` ===[ FILE: test-allow-js-with-outDir.js ]======================================= "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); @@ -18,7 +18,7 @@ exports[`language service should compile js file for allowJs true with outDir 1` ================================================================================ `; -exports[`language service should compile js file for allowJs true without outDir 1`] = ` +exports[`Language service should compile js file for allowJs true without outDir 1`] = ` ===[ FILE: test-allow-js-no-outDir.js ]========================================= "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); @@ -36,7 +36,7 @@ exports[`language service should compile js file for allowJs true without outDir ================================================================================ `; -exports[`language service should compile tsx file for jsx preserve 1`] = ` +exports[`Language service should compile tsx file for jsx preserve 1`] = ` ===[ FILE: test-jsx-preserve.tsx ]============================================== "use strict"; var App = function () { @@ -60,7 +60,7 @@ exports[`language service should compile tsx file for jsx preserve 1`] = ` ================================================================================ `; -exports[`language service should compile tsx file for other jsx options 1`] = ` +exports[`Language service should compile tsx file for other jsx options 1`] = ` ===[ FILE: test-jsx-options.tsx ]=============================================== "use strict"; var App = function () { @@ -84,14 +84,14 @@ exports[`language service should compile tsx file for other jsx options 1`] = ` ================================================================================ `; -exports[`language service should report diagnostics related to typings with pathRegex config matches file name 1`] = `"test-match-regex-diagnostics.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."`; +exports[`Language service should report diagnostics related to typings with pathRegex config matches file name 1`] = `"test-match-regex-diagnostics.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."`; -exports[`language service should throw error when cannot compile 1`] = ` +exports[`Language service should throw error when cannot compile 1`] = ` "Unable to require \`.d.ts\` file for file: test-cannot-compile.d.ts. This is usually the result of a faulty configuration or import. Make sure there is a \`.js\`, \`.json\` or another executable extension available alongside \`test-cannot-compile.d.ts\`." `; -exports[`language service should use the cache 3`] = ` +exports[`Language service should use the cache 3`] = ` ===[ FILE: test-cache.ts ]====================================================== console.log("hello"); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1jYWNoZS50cyIsIm1hcHBpbmdzIjoiQUFBQSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbInRlc3QtY2FjaGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coXCJoZWxsb1wiKSJdLCJ2ZXJzaW9uIjozfQ== diff --git a/src/compiler/__snapshots__/transpile-module.spec.ts.snap b/src/compiler/__snapshots__/transpiler.spec.ts.snap similarity index 63% rename from src/compiler/__snapshots__/transpile-module.spec.ts.snap rename to src/compiler/__snapshots__/transpiler.spec.ts.snap index 0b2561b610..bf6af90209 100644 --- a/src/compiler/__snapshots__/transpile-module.spec.ts.snap +++ b/src/compiler/__snapshots__/transpiler.spec.ts.snap @@ -1,24 +1,24 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`transpile module with isolatedModule: true should compile js file for allowJs true 1`] = ` - ===[ FILE: src/compiler/transpile-module.spec.ts.test.js ]====================== +exports[`Transpiler should compile js file for allowJs true 1`] = ` + ===[ FILE: src/compiler/transpiler.spec.ts.test.js ]============================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = 42; - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiPGN3ZD4vc3JjL2NvbXBpbGVyL3RyYW5zcGlsZS1tb2R1bGUuc3BlYy50cy50ZXN0LmpzIiwibWFwcGluZ3MiOiI7O0FBQUEsa0JBQWUsRUFBRSxDQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIjxjd2Q+L3NyYy9jb21waWxlci90cmFuc3BpbGUtbW9kdWxlLnNwZWMudHMudGVzdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCA0MiJdLCJ2ZXJzaW9uIjozfQ== + //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiPGN3ZD4vc3JjL2NvbXBpbGVyL3RyYW5zcGlsZXIuc3BlYy50cy50ZXN0LmpzIiwibWFwcGluZ3MiOiI7O0FBQUEsa0JBQWUsRUFBRSxDQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIjxjd2Q+L3NyYy9jb21waWxlci90cmFuc3BpbGVyLnNwZWMudHMudGVzdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCA0MiJdLCJ2ZXJzaW9uIjozfQ== ===[ INLINE SOURCE MAPS ]======================================================= - file: /src/compiler/transpile-module.spec.ts.test.js + file: /src/compiler/transpiler.spec.ts.test.js mappings: ';;AAAA,kBAAe,EAAE,CAAA' names: [] sources: - - /src/compiler/transpile-module.spec.ts.test.js + - /src/compiler/transpiler.spec.ts.test.js sourcesContent: - export default 42 version: 3 ================================================================================ `; -exports[`transpile module with isolatedModule: true should compile tsx file for jsx preserve 1`] = ` +exports[`Transpiler should compile tsx file for jsx preserve 1`] = ` ===[ FILE: foo.tsx ]============================================================ "use strict"; var App = function () { @@ -42,7 +42,7 @@ exports[`transpile module with isolatedModule: true should compile tsx file for ================================================================================ `; -exports[`transpile module with isolatedModule: true should compile tsx file for other jsx options 1`] = ` +exports[`Transpiler should compile tsx file for other jsx options 1`] = ` ===[ FILE: foo.tsx ]============================================================ "use strict"; var App = function () { @@ -66,24 +66,24 @@ exports[`transpile module with isolatedModule: true should compile tsx file for ================================================================================ `; -exports[`transpile module with isolatedModule: true should compile using transpileModule and not use cache 1`] = ` - ===[ FILE: src/compiler/transpile-module.spec.ts ]============================== +exports[`Transpiler should compile using transpileModule and not use cache 1`] = ` + ===[ FILE: src/compiler/transpiler.spec.ts ]==================================== "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = 42; - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiPGN3ZD4vc3JjL2NvbXBpbGVyL3RyYW5zcGlsZS1tb2R1bGUuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLGtCQUFlLEVBQUUsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyI8Y3dkPi9zcmMvY29tcGlsZXIvdHJhbnNwaWxlLW1vZHVsZS5zcGVjLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IDQyIl0sInZlcnNpb24iOjN9 + //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiPGN3ZD4vc3JjL2NvbXBpbGVyL3RyYW5zcGlsZXIuc3BlYy50cyIsIm1hcHBpbmdzIjoiOztBQUFBLGtCQUFlLEVBQUUsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyI8Y3dkPi9zcmMvY29tcGlsZXIvdHJhbnNwaWxlci5zcGVjLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IDQyIl0sInZlcnNpb24iOjN9 ===[ INLINE SOURCE MAPS ]======================================================= - file: /src/compiler/transpile-module.spec.ts + file: /src/compiler/transpiler.spec.ts mappings: ';;AAAA,kBAAe,EAAE,CAAA' names: [] sources: - - /src/compiler/transpile-module.spec.ts + - /src/compiler/transpiler.spec.ts sourcesContent: - export default 42 version: 3 ================================================================================ `; -exports[`transpile module with isolatedModule: true should report diagnostics related to codes with pathRegex config is undefined 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; +exports[`Transpiler should report diagnostics related to codes with pathRegex config is undefined 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; -exports[`transpile module with isolatedModule: true should report diagnostics related to codes with pathRegex config matches file name 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; +exports[`Transpiler should report diagnostics related to codes with pathRegex config matches file name 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; diff --git a/src/compiler/instance.ts b/src/compiler/instance.ts index b991e97fb2..7150cf15cb 100644 --- a/src/compiler/instance.ts +++ b/src/compiler/instance.ts @@ -39,9 +39,9 @@ import { CompileFn, CompilerInstance, MemoryCache, TsCompiler } from '../types' import { sha1 } from '../util/sha1' import { getResolvedModulesCache } from './compiler-utils' -import { compileUsingLanguageService } from './language-service' -import { compileUsingProgram } from './program' -import { compileUsingTranspileModule } from './transpile-module' +import { initializeLanguageServiceInstance } from './language-service' +import { initializeProgramInstance } from './program' +import { initializeTranspilerInstance } from './transpiler' /** * Update the output remapping the source map. @@ -89,9 +89,10 @@ const isValidCacheContent = (contents: string): boolean => { } /** - * Wrap the function with caching. + * Compile files which are provided by jest via transform config and cache the result in file system if users run with + * cache mode */ -const readThrough = ( +const compileAndCacheResult = ( cachedir: string | undefined, memoryCache: MemoryCache, compileFn: CompileFn, @@ -150,10 +151,10 @@ const readThrough = ( } /** - * Register TypeScript compiler. + * Register TypeScript compiler instance. * @internal */ -export const createCompiler = (configs: ConfigSet): TsCompiler => { +export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { const logger = configs.logger.child({ namespace: 'ts-compiler' }) const { typescript: { options: compilerOptions, fileNames }, @@ -186,12 +187,12 @@ export const createCompiler = (configs: ConfigSet): TsCompiler => { if (!tsJest.isolatedModules) { // Use language services by default compilerInstance = !tsJest.compilerHost - ? compileUsingLanguageService(configs, logger, memoryCache) - : compileUsingProgram(configs, logger, memoryCache) + ? initializeLanguageServiceInstance(configs, logger, memoryCache) + : initializeProgramInstance(configs, logger, memoryCache) } else { - compilerInstance = compileUsingTranspileModule(configs, logger) + compilerInstance = initializeTranspilerInstance(configs, logger) } - const compile = readThrough(cachedir, memoryCache, compilerInstance.compileFn, getExtension, logger) + const compile = compileAndCacheResult(cachedir, memoryCache, compilerInstance.compileFn, getExtension, logger) return { cwd: configs.cwd, compile, program: compilerInstance.program } } diff --git a/src/compiler/language-service.spec.ts b/src/compiler/language-service.spec.ts index fb2550e05f..2607105a4b 100644 --- a/src/compiler/language-service.spec.ts +++ b/src/compiler/language-service.spec.ts @@ -11,7 +11,7 @@ import * as compilerUtils from './compiler-utils' const logTarget = logTargetMock() -describe('language service', () => { +describe('Language service', () => { beforeEach(() => { logTarget.clear() }) diff --git a/src/compiler/language-service.ts b/src/compiler/language-service.ts index ca4627467b..0add135448 100644 --- a/src/compiler/language-service.ts +++ b/src/compiler/language-service.ts @@ -22,7 +22,7 @@ function doTypeChecking(configs: ConfigSet, fileName: string, service: _ts.Langu /** * @internal */ -export const compileUsingLanguageService = ( +export const initializeLanguageServiceInstance = ( configs: ConfigSet, logger: Logger, memoryCache: MemoryCache, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2c04286a55..5b6de5b66f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -22,7 +22,11 @@ function doTypeChecking(configs: ConfigSet, fileName: string, program: _ts.Progr /** * @internal */ -export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCache: MemoryCache): CompilerInstance => { +export const initializeProgramInstance = ( + configs: ConfigSet, + logger: Logger, + memoryCache: MemoryCache, +): CompilerInstance => { logger.debug('compileUsingProgram(): create typescript compiler') const ts = configs.compilerModule diff --git a/src/compiler/transpile-module.spec.ts b/src/compiler/transpiler.spec.ts similarity index 98% rename from src/compiler/transpile-module.spec.ts rename to src/compiler/transpiler.spec.ts index 77e62cd9da..aaa5a92375 100644 --- a/src/compiler/transpile-module.spec.ts +++ b/src/compiler/transpiler.spec.ts @@ -8,7 +8,7 @@ import { TS_JEST_OUT_DIR } from '../config/config-set' const logTarget = logTargetMock() -describe('transpile module with isolatedModule: true', () => { +describe('Transpiler', () => { const baseTsJestConfig = { isolatedModules: true, } diff --git a/src/compiler/transpile-module.ts b/src/compiler/transpiler.ts similarity index 87% rename from src/compiler/transpile-module.ts rename to src/compiler/transpiler.ts index 7b25d610fc..9c49f184d4 100644 --- a/src/compiler/transpile-module.ts +++ b/src/compiler/transpiler.ts @@ -11,12 +11,12 @@ import { getAndCacheOutputJSFileName, getAndCacheProjectReference } from './comp /** * @internal */ -export const compileUsingTranspileModule = (configs: ConfigSet, logger: Logger): CompilerInstance => { +export const initializeTranspilerInstance = (configs: ConfigSet, logger: Logger): CompilerInstance => { logger.debug('compileUsingTranspileModule(): create typescript compiler') const { options, projectReferences, fileNames } = configs.typescript const files: TSFiles = new Map() - const compiler = configs.compilerModule + const ts = configs.compilerModule fileNames.forEach(filePath => { const normalizedFilePath = normalize(filePath) files.set(normalizedFilePath, { @@ -25,12 +25,12 @@ export const compileUsingTranspileModule = (configs: ConfigSet, logger: Logger): }) }) const program = projectReferences - ? compiler.createProgram({ + ? ts.createProgram({ rootNames: fileNames, options, projectReferences, }) - : compiler.createProgram([], options) + : ts.createProgram([], options) const updateFileInCache = (contents: string, filePath: string) => { const file = files.get(filePath) if (file && file.text !== contents) { @@ -62,7 +62,7 @@ export const compileUsingTranspileModule = (configs: ConfigSet, logger: Logger): const jsFileName = getAndCacheOutputJSFileName(normalizedFileName, referencedProject, files) const relativeJSFileName = configs.resolvePath(jsFileName) - if (!compiler.sys.fileExists(jsFileName)) { + if (!ts.sys.fileExists(jsFileName)) { throw new Error( // tslint:disable-next-line:prefer-template `Could not find output JavaScript file for input ` + @@ -75,12 +75,12 @@ export const compileUsingTranspileModule = (configs: ConfigSet, logger: Logger): } const mapFileName = `${jsFileName}.map` - const outputText = compiler.sys.readFile(jsFileName) - const sourceMapText = compiler.sys.readFile(mapFileName) + const outputText = ts.sys.readFile(jsFileName) + const sourceMapText = ts.sys.readFile(mapFileName) return [outputText!, sourceMapText!] } else { - const result: _ts.TranspileOutput = compiler.transpileModule(code, { + const result: _ts.TranspileOutput = ts.transpileModule(code, { fileName: normalizedFileName, transformers: configs.tsCustomTransformers, compilerOptions: options, diff --git a/src/config/config-set.ts b/src/config/config-set.ts index 96c299af46..c686560ff3 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -24,7 +24,7 @@ import { } from 'typescript' import { digest as MY_DIGEST, version as MY_VERSION } from '..' -import { createCompiler } from '../compiler/instance' +import { createCompilerInstance } from '../compiler/instance' import { internals as internalAstTransformers } from '../transformers' import { AstTransformerDesc, @@ -435,7 +435,7 @@ export class ConfigSet { @Memoize() get tsCompiler(): TsCompiler { - return createCompiler(this) + return createCompilerInstance(this) } /** From e525ec2a960a7cf01beee02b15e902364a8647aa Mon Sep 17 00:00:00 2001 From: Ahn Date: Sat, 18 Apr 2020 23:16:44 +0200 Subject: [PATCH 2/2] fix(compiler): make `projectReferences` work with `LanguageService` --- .../simple/dependency/package.json | 2 +- .../simple/with-dependency/package.json | 6 +- .../yarn-workspace-composite/.gitignore | 1 + .../yarn-workspace-composite/package.json | 8 +- .../yarn-workspace-composite/tsconfig.json | 1 + src/compiler/compiler-utils.spec.ts | 3 +- src/compiler/compiler-utils.ts | 48 ++++++- src/compiler/instance.ts | 18 ++- src/compiler/language-service.spec.ts | 30 +++- src/compiler/language-service.ts | 130 +++++++++++------- src/compiler/program.spec.ts | 2 +- src/compiler/program.ts | 8 +- src/compiler/transpiler.spec.ts | 72 +++++++--- src/compiler/transpiler.ts | 65 +++------ src/types.ts | 1 + 15 files changed, 254 insertions(+), 141 deletions(-) create mode 100644 e2e/__external-repos__/yarn-workspace-composite/.gitignore diff --git a/e2e/__external-repos__/simple/dependency/package.json b/e2e/__external-repos__/simple/dependency/package.json index 677e33b012..772ef01de1 100644 --- a/e2e/__external-repos__/simple/dependency/package.json +++ b/e2e/__external-repos__/simple/dependency/package.json @@ -2,7 +2,7 @@ "name": "dependency", "version": "0.0.1", "peerDependencies": { - "typescript": "^3.7.5" + "typescript": "^3.8.3" }, "main": "./index.ts" } diff --git a/e2e/__external-repos__/simple/with-dependency/package.json b/e2e/__external-repos__/simple/with-dependency/package.json index d0c64b6486..5b9df80d9c 100644 --- a/e2e/__external-repos__/simple/with-dependency/package.json +++ b/e2e/__external-repos__/simple/with-dependency/package.json @@ -36,12 +36,12 @@ } }, "devDependencies": { - "typescript": "^3.7.5" + "typescript": "^3.8.3" }, "dependencies": { - "@types/jest": "^25.1.2", + "@types/jest": "^25.2.1", "dependency": "file:../dependency", - "jest": "^25.1.0" + "jest": "^25.3.0" }, "main": "./index.ts" } diff --git a/e2e/__external-repos__/yarn-workspace-composite/.gitignore b/e2e/__external-repos__/yarn-workspace-composite/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/e2e/__external-repos__/yarn-workspace-composite/.gitignore @@ -0,0 +1 @@ +/target diff --git a/e2e/__external-repos__/yarn-workspace-composite/package.json b/e2e/__external-repos__/yarn-workspace-composite/package.json index c23b857449..fcf77af3b7 100644 --- a/e2e/__external-repos__/yarn-workspace-composite/package.json +++ b/e2e/__external-repos__/yarn-workspace-composite/package.json @@ -6,11 +6,11 @@ "packages/*" ], "scripts": { - "test": "jest --no-cache" + "test": "yarn tsc -b packages/my-app/tsconfig.json && jest --no-cache" }, "devDependencies": { - "@types/jest": "^25.1.2", - "jest": "^25.1.0", - "typescript": "~3.7.5" + "@types/jest": "^25.2.1", + "jest": "^25.3.0", + "typescript": "~3.8.3" } } diff --git a/e2e/__external-repos__/yarn-workspace-composite/tsconfig.json b/e2e/__external-repos__/yarn-workspace-composite/tsconfig.json index fff6928601..61da5551f7 100644 --- a/e2e/__external-repos__/yarn-workspace-composite/tsconfig.json +++ b/e2e/__external-repos__/yarn-workspace-composite/tsconfig.json @@ -9,6 +9,7 @@ "noImplicitAny": true, "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, + "outDir": "./target/", "lib": [ "dom", "es2018" ] diff --git a/src/compiler/compiler-utils.spec.ts b/src/compiler/compiler-utils.spec.ts index 9f4d9b88b9..e53f1687ee 100644 --- a/src/compiler/compiler-utils.spec.ts +++ b/src/compiler/compiler-utils.spec.ts @@ -4,7 +4,7 @@ import { resolve } from 'path' import { makeCompiler } from '../__helpers__/fakers' import { tempDir } from '../__helpers__/path' -import { MemoryCache } from '../types' +import { MemoryCache, TSFile } from '../types' import { cacheResolvedModules, getResolvedModulesCache } from './compiler-utils' @@ -13,6 +13,7 @@ const memoryCache: MemoryCache = { versions: Object.create(null), outputs: Object.create(null), resolvedModules: Object.create(null), + files: new Map(), } describe('cacheResolvedModules', () => { diff --git a/src/compiler/compiler-utils.ts b/src/compiler/compiler-utils.ts index 022e99ba7c..7685a9bee7 100644 --- a/src/compiler/compiler-utils.ts +++ b/src/compiler/compiler-utils.ts @@ -4,8 +4,9 @@ import micromatch = require('micromatch') import { dirname, join, normalize, relative, resolve } from 'path' import * as _ts from 'typescript' +import { ConfigSet } from '../config/config-set' import { EXTENSION_REGEX, JSON_REGEX, TS_TSX_REGEX } from '../constants' -import { MemoryCache, TSFiles } from '../types' +import { MemoryCache, SourceOutput, TSFiles } from '../types' import { sha1 } from '../util/sha1' /** @@ -145,12 +146,11 @@ function getOutputJavaScriptFileName(inputFileName: string, projectReference: _t } /** - * @internal * Gets the output JS file path for an input file governed by a composite project. * Pulls from the cache if it exists; computes and caches the result otherwise. */ /* istanbul ignore next (we leave this for e2e) */ -export function getAndCacheOutputJSFileName( +function getAndCacheOutputJSFileName( inputFileName: string, projectReference: _ts.ResolvedProjectReference, files: TSFiles, @@ -170,3 +170,45 @@ export function getAndCacheOutputJSFileName( return outputFileName } + +/** + * @internal + */ +/* istanbul ignore next (we leave this for e2e) */ +export function getCompileResultFromReferencedProject( + fileName: string, + configs: ConfigSet, + files: TSFiles, + referencedProject: _ts.ResolvedProjectReference, +): SourceOutput { + const [relativeProjectConfigPath, relativeFilePath] = [ + configs.resolvePath(referencedProject.sourceFile.fileName), + configs.resolvePath(fileName), + ] + if (referencedProject.commandLine.options.outFile !== undefined) { + throw new Error( + `The referenced project at ${relativeProjectConfigPath} is using ` + + `the outFile' option, which is not supported with ts-jest.`, + ) + } + + const jsFileName = getAndCacheOutputJSFileName(fileName, referencedProject, files) + const relativeJSFileName = configs.resolvePath(jsFileName) + if (!configs.compilerModule.sys.fileExists(jsFileName)) { + throw new Error( + // tslint:disable-next-line:prefer-template + `Could not find output JavaScript file for input ` + + `${relativeFilePath} (looked at ${relativeJSFileName}).\n` + + `The input file is part of a project reference located at ` + + `${relativeProjectConfigPath}, so ts-jest is looking for the ` + + 'project’s pre-built output on disk. Try running `tsc --build` ' + + 'to build project references.', + ) + } + + const mapFileName = `${jsFileName}.map` + const outputText = configs.compilerModule.sys.readFile(jsFileName) + const sourceMapText = configs.compilerModule.sys.readFile(mapFileName) + + return [outputText!, sourceMapText!] +} diff --git a/src/compiler/instance.ts b/src/compiler/instance.ts index 7150cf15cb..c14476ec11 100644 --- a/src/compiler/instance.ts +++ b/src/compiler/instance.ts @@ -35,7 +35,7 @@ import mkdirp = require('mkdirp') import { basename, extname, join, normalize } from 'path' import { ConfigSet } from '../config/config-set' -import { CompileFn, CompilerInstance, MemoryCache, TsCompiler } from '../types' +import { CompileFn, CompilerInstance, MemoryCache, TSFile, TsCompiler } from '../types' import { sha1 } from '../util/sha1' import { getResolvedModulesCache } from './compiler-utils' @@ -168,6 +168,7 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { versions: Object.create(null), outputs: Object.create(null), resolvedModules: Object.create(null), + files: new Map(), } // Enable `allowJs` when flag is set. if (compilerOptions.allowJs) { @@ -175,7 +176,14 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { extensions.push('.jsx') } // Initialize files from TypeScript into project. - for (const path of fileNames) memoryCache.versions[normalize(path)] = 1 + for (const path of fileNames) { + const normalizedFilePath = normalize(path) + memoryCache.versions[normalizedFilePath] = 1 + memoryCache.files.set(normalizedFilePath, { + text: readFileSync(normalizedFilePath, 'utf-8'), + version: 0, + }) + } /** * Get the extension for a transpiled file. */ @@ -187,10 +195,10 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { if (!tsJest.isolatedModules) { // Use language services by default compilerInstance = !tsJest.compilerHost - ? initializeLanguageServiceInstance(configs, logger, memoryCache) - : initializeProgramInstance(configs, logger, memoryCache) + ? initializeLanguageServiceInstance(configs, memoryCache, logger) + : initializeProgramInstance(configs, memoryCache, logger) } else { - compilerInstance = initializeTranspilerInstance(configs, logger) + compilerInstance = initializeTranspilerInstance(configs, memoryCache, logger) } const compile = compileAndCacheResult(cachedir, memoryCache, compilerInstance.compileFn, getExtension, logger) diff --git a/src/compiler/language-service.spec.ts b/src/compiler/language-service.spec.ts index 2607105a4b..c735f04416 100644 --- a/src/compiler/language-service.spec.ts +++ b/src/compiler/language-service.spec.ts @@ -40,7 +40,7 @@ describe('Language service', () => { ", "[level:20] visitSourceFileNode(): hoisting ", - "[level:20] diagnoseFn(): computing diagnostics for test-cache.ts using language service + "[level:20] compileFn(): computing diagnostics for test-cache.ts using language service ", "[level:20] readThrough(): writing caches ", @@ -63,6 +63,34 @@ describe('Language service', () => { removeSync(fileName) }) + it('should get compile result from referenced project when there is a built reference project', () => { + const tmp = tempDir('compiler') + const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp }, + tsJestConfig: { tsConfig: false }, + }) + const source = 'console.log("hello")' + const fileName = 'test-reference-project.ts' + const getAndCacheProjectReferenceSpy = jest + .spyOn(compilerUtils, 'getAndCacheProjectReference') + .mockReturnValueOnce({} as any) + jest + .spyOn(compilerUtils, 'getCompileResultFromReferencedProject') + .mockImplementationOnce(() => [ + source, + '{"version":3,"file":"test-reference-project.js","sourceRoot":"","sources":["test-reference-project.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA","sourcesContent":["console.log(\\"hello\\")"]}', + ]) + writeFileSync(fileName, source, 'utf8') + + compiler.compile(source, fileName) + + expect(getAndCacheProjectReferenceSpy).toHaveBeenCalled() + expect(compilerUtils.getCompileResultFromReferencedProject).toHaveBeenCalled() + + getAndCacheProjectReferenceSpy.mockRestore() + removeSync(fileName) + }) + it('should cache resolved modules for test file with testMatchPatterns from jest config when match', () => { // tslint:disable-next-line:no-empty const spy = jest.spyOn(compilerUtils, 'cacheResolvedModules').mockImplementationOnce(() => {}) diff --git a/src/compiler/language-service.ts b/src/compiler/language-service.ts index 0add135448..21a22b2a96 100644 --- a/src/compiler/language-service.ts +++ b/src/compiler/language-service.ts @@ -8,7 +8,13 @@ import { LINE_FEED } from '../constants' import { CompilerInstance, MemoryCache, SourceOutput } from '../types' import { Errors, interpolate } from '../util/messages' -import { cacheResolvedModules, hasOwn, isTestFile } from './compiler-utils' +import { + cacheResolvedModules, + getAndCacheProjectReference, + getCompileResultFromReferencedProject, + hasOwn, + isTestFile, +} from './compiler-utils' function doTypeChecking(configs: ConfigSet, fileName: string, service: _ts.LanguageService, logger: Logger) { if (configs.shouldReportDiagnostic(fileName)) { @@ -24,15 +30,15 @@ function doTypeChecking(configs: ConfigSet, fileName: string, service: _ts.Langu */ export const initializeLanguageServiceInstance = ( configs: ConfigSet, - logger: Logger, memoryCache: MemoryCache, + logger: Logger, ): CompilerInstance => { - logger.debug('compileUsingLanguageService(): create typescript compiler') + logger.debug('initializeLanguageServiceInstance(): create typescript compiler') const ts = configs.compilerModule const cwd = configs.cwd const cacheDir = configs.tsCacheDir - const { options } = configs.typescript + const { options, projectReferences } = configs.typescript const serviceHostTraceCtx = { namespace: 'ts:serviceHost', call: null, @@ -43,6 +49,11 @@ export const initializeLanguageServiceInstance = ( const updateMemoryCache = (contents: string, fileName: string) => { logger.debug({ fileName }, `updateMemoryCache(): update memory cache for language service`) + const file = memoryCache.files.get(fileName) + if (file && file.text !== contents) { + file.version++ + file.text = contents + } let shouldIncrementProjectVersion = false const fileVersion = memoryCache.versions[fileName] ?? 0 const isFileInCache = fileVersion !== 0 @@ -63,6 +74,7 @@ export const initializeLanguageServiceInstance = ( } const serviceHost: _ts.LanguageServiceHost = { getProjectVersion: () => String(projectVersion), + getProjectReferences: () => projectReferences, getScriptFileNames: () => Object.keys(memoryCache.versions), getScriptVersion: (fileName: string) => { const normalizedFileName = normalize(fileName) @@ -103,7 +115,7 @@ export const initializeLanguageServiceInstance = ( } logger.debug('compileUsingLanguageService(): creating language service') - const service: _ts.LanguageService = ts.createLanguageService(serviceHost) + const service: _ts.LanguageService = ts.createLanguageService(serviceHost, ts.createDocumentRegistry()) return { compileFn: (code: string, fileName: string): SourceOutput => { @@ -112,56 +124,68 @@ export const initializeLanguageServiceInstance = ( logger.debug({ normalizedFileName }, 'compileFn(): compiling using language service') // Must set memory cache before attempting to read file. updateMemoryCache(code, normalizedFileName) - const output: _ts.EmitOutput = service.getEmitOutput(normalizedFileName) - // Do type checking by getting TypeScript diagnostics - logger.debug(`diagnoseFn(): computing diagnostics for ${normalizedFileName} using language service`) - - doTypeChecking(configs, normalizedFileName, service, logger) - /** - * We don't need the following logic with no cache run because no cache always gives correct typing - */ - if (cacheDir) { - if (isTestFile(configs.testMatchPatterns, normalizedFileName)) { - cacheResolvedModules(normalizedFileName, code, memoryCache, service.getProgram()!, cacheDir, logger) - } else { - /* istanbul ignore next (covered by e2e) */ - Object.entries(memoryCache.resolvedModules) - .filter(entry => { - /** - * When imported modules change, we only need to check whether the test file is compiled previously or not - * base on memory cache. By checking memory cache, we can avoid repeatedly doing type checking against - * test file for 1st time run after clearing cache because - */ - return ( - entry[1].modulePaths.find(modulePath => modulePath === normalizedFileName) && - !hasOwn.call(memoryCache.outputs, entry[0]) - ) - }) - .forEach(entry => { - logger.debug( - `diagnoseFn(): computing diagnostics for test file that imports ${normalizedFileName} using language service`, - ) - - const testFileName = entry[0] - updateMemoryCache(entry[1].testFileContent, testFileName) - doTypeChecking(configs, testFileName, service, logger) - }) + const referencedProject = getAndCacheProjectReference( + normalizedFileName, + service.getProgram()!, + memoryCache.files, + projectReferences, + ) + if (referencedProject !== undefined) { + logger.debug({ normalizedFileName }, 'compileFn(): get compile result from referenced project') + + return getCompileResultFromReferencedProject(normalizedFileName, configs, memoryCache.files, referencedProject) + } else { + const output: _ts.EmitOutput = service.getEmitOutput(normalizedFileName) + // Do type checking by getting TypeScript diagnostics + logger.debug(`compileFn(): computing diagnostics for ${normalizedFileName} using language service`) + + doTypeChecking(configs, normalizedFileName, service, logger) + /** + * We don't need the following logic with no cache run because no cache always gives correct typing + */ + if (cacheDir) { + if (isTestFile(configs.testMatchPatterns, normalizedFileName)) { + cacheResolvedModules(normalizedFileName, code, memoryCache, service.getProgram()!, cacheDir, logger) + } else { + /* istanbul ignore next (covered by e2e) */ + Object.entries(memoryCache.resolvedModules) + .filter(entry => { + /** + * When imported modules change, we only need to check whether the test file is compiled previously or not + * base on memory cache. By checking memory cache, we can avoid repeatedly doing type checking against + * test file for 1st time run after clearing cache because + */ + return ( + entry[1].modulePaths.find(modulePath => modulePath === normalizedFileName) && + !hasOwn.call(memoryCache.outputs, entry[0]) + ) + }) + .forEach(entry => { + logger.debug( + `compileFn(): computing diagnostics for test file that imports ${normalizedFileName} using language service`, + ) + + const testFileName = entry[0] + updateMemoryCache(entry[1].testFileContent, testFileName) + doTypeChecking(configs, testFileName, service, logger) + }) + } + } + /* istanbul ignore next (this should never happen but is kept for security) */ + if (output.emitSkipped) { + throw new TypeError(`${relative(cwd, normalizedFileName)}: Emit skipped for language service`) + } + // Throw an error when requiring `.d.ts` files. + if (!output.outputFiles.length) { + throw new TypeError( + interpolate(Errors.UnableToRequireDefinitionFile, { + file: basename(normalizedFileName), + }), + ) } - } - /* istanbul ignore next (this should never happen but is kept for security) */ - if (output.emitSkipped) { - throw new TypeError(`${relative(cwd, normalizedFileName)}: Emit skipped for language service`) - } - // Throw an error when requiring `.d.ts` files. - if (!output.outputFiles.length) { - throw new TypeError( - interpolate(Errors.UnableToRequireDefinitionFile, { - file: basename(normalizedFileName), - }), - ) - } - return [output.outputFiles[1].text, output.outputFiles[0].text] + return [output.outputFiles[1].text, output.outputFiles[0].text] + } }, program: service.getProgram(), } diff --git a/src/compiler/program.spec.ts b/src/compiler/program.spec.ts index c29c981bc0..4b6a097c5c 100644 --- a/src/compiler/program.spec.ts +++ b/src/compiler/program.spec.ts @@ -39,7 +39,7 @@ describe('cache', () => { ", "[level:20] visitSourceFileNode(): hoisting ", - "[level:20] diagnoseFn(): computing diagnostics for test-cache-incremental-program.ts using incremental program + "[level:20] compileFn(): computing diagnostics for test-cache-incremental-program.ts using incremental program ", "[level:20] readThrough(): writing caches ", diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 5b6de5b66f..46e6259cad 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -24,10 +24,10 @@ function doTypeChecking(configs: ConfigSet, fileName: string, program: _ts.Progr */ export const initializeProgramInstance = ( configs: ConfigSet, - logger: Logger, memoryCache: MemoryCache, + logger: Logger, ): CompilerInstance => { - logger.debug('compileUsingProgram(): create typescript compiler') + logger.debug('initializeProgramInstance(): create typescript compiler') const ts = configs.compilerModule const cwd = configs.cwd @@ -117,7 +117,7 @@ export const initializeProgramInstance = ( customTransformers, ) // Do type checking by getting TypeScript diagnostics - logger.debug(`diagnoseFn(): computing diagnostics for ${normalizedFileName} using incremental program`) + logger.debug(`compileFn(): computing diagnostics for ${normalizedFileName} using incremental program`) doTypeChecking(configs, normalizedFileName, program, logger) /** @@ -142,7 +142,7 @@ export const initializeProgramInstance = ( }) .forEach(entry => { logger.debug( - `diagnoseFn(): computing diagnostics for test file that imports ${normalizedFileName} using incremental program`, + `compileFn(): computing diagnostics for test file that imports ${normalizedFileName} using incremental program`, ) doTypeChecking(configs, entry[0], program, logger) diff --git a/src/compiler/transpiler.spec.ts b/src/compiler/transpiler.spec.ts index aaa5a92375..c30b33b311 100644 --- a/src/compiler/transpiler.spec.ts +++ b/src/compiler/transpiler.spec.ts @@ -1,11 +1,14 @@ import { LogLevels } from 'bs-logger' import { removeSync, writeFileSync } from 'fs-extra' +import * as _ts from 'typescript' import { makeCompiler } from '../__helpers__/fakers' import { logTargetMock } from '../__helpers__/mocks' import ProcessedSource from '../__helpers__/processed-source' import { TS_JEST_OUT_DIR } from '../config/config-set' +import * as compilerUtils from './compiler-utils' + const logTarget = logTargetMock() describe('Transpiler', () => { @@ -19,7 +22,7 @@ describe('Transpiler', () => { it('should compile using transpileModule and not use cache', () => { const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false } }) - const spy = jest.spyOn(require('typescript'), 'transpileModule') + const spy = jest.spyOn(_ts, 'transpileModule') logTarget.clear() const compiled = compiler.compile('export default 42', __filename) @@ -30,7 +33,7 @@ describe('Transpiler', () => { Array [ "[level:20] readThrough(): no cache ", - "[level:20] getOutput(): compiling as isolated module + "[level:20] compileFn(): compiling as isolated module ", "[level:20] visitSourceFileNode(): hoisting ", @@ -40,38 +43,69 @@ describe('Transpiler', () => { spy.mockRestore() }) - it('should call createProgram() with projectReferences when there are projectReferences from tsconfig', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - tsConfig: 'src/__mocks__/tsconfig-project-references.json', - }, - }) - const programSpy = jest.spyOn(require('typescript'), 'createProgram') - logTarget.clear() - compiler.compile('export default 42', __filename) + it( + 'should call createProgram() with projectReferences, call getAndCacheProjectReference()' + + ' and getCompileResultFromReferenceProject() when there are projectReferences from tsconfig', + () => { + const programSpy = jest.spyOn(_ts, 'createProgram') + const source = 'console.log("hello")' + const fileName = 'isolated-test-reference-project.ts' + const getAndCacheProjectReferenceSpy = jest + .spyOn(compilerUtils, 'getAndCacheProjectReference') + .mockReturnValueOnce({} as any) + jest + .spyOn(compilerUtils, 'getCompileResultFromReferencedProject') + .mockImplementationOnce(() => [ + source, + '{"version":3,"file":"isolated-test-reference-project.js","sourceRoot":"","sources":["isolated-test-reference-project.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA","sourcesContent":["console.log(\\"hello\\")"]}', + ]) + writeFileSync(fileName, source) + const compiler = makeCompiler({ + tsJestConfig: { + ...baseTsJestConfig, + tsConfig: 'src/__mocks__/tsconfig-project-references.json', + }, + }) + compiler.compile(source, fileName) - expect(programSpy).toHaveBeenCalled() - expect((programSpy.mock.calls[0][1] as any).configFilePath).toContain('tsconfig-project-references.json') + expect(programSpy).toHaveBeenCalled() + expect((programSpy.mock.calls[0][0] as any).options.configFilePath).toContain('tsconfig-project-references.json') + expect(getAndCacheProjectReferenceSpy).toHaveBeenCalled() + expect(compilerUtils.getCompileResultFromReferencedProject).toHaveBeenCalled() - programSpy.mockRestore() - }) + programSpy.mockRestore() + getAndCacheProjectReferenceSpy.mockRestore() + jest.restoreAllMocks() + removeSync(fileName) + }, + ) it('should call createProgram() without projectReferences when there are no projectReferences from tsconfig', () => { + const programSpy = jest.spyOn(_ts, 'createProgram') + const source = 'console.log("hello")' + const fileName = 'isolated-test-reference-project-1.ts' + const getAndCacheProjectReferenceSpy = jest + .spyOn(compilerUtils, 'getAndCacheProjectReference') + .mockReturnValueOnce(undefined) + jest.spyOn(compilerUtils, 'getCompileResultFromReferencedProject') + writeFileSync(fileName, source, 'utf8') const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false, }, }) - const programSpy = jest.spyOn(require('typescript'), 'createProgram') - logTarget.clear() - compiler.compile('export default 42', __filename) + compiler.compile(source, fileName) expect(programSpy).toHaveBeenCalled() expect((programSpy.mock.calls[0][1] as any).configFilePath).toBeUndefined() + expect(getAndCacheProjectReferenceSpy).toHaveBeenCalled() + expect(compilerUtils.getCompileResultFromReferencedProject).not.toHaveBeenCalled() programSpy.mockRestore() + getAndCacheProjectReferenceSpy.mockRestore() + jest.restoreAllMocks() + removeSync(fileName) }) it('should compile js file for allowJs true', () => { diff --git a/src/compiler/transpiler.ts b/src/compiler/transpiler.ts index 9c49f184d4..a93fcfb23d 100644 --- a/src/compiler/transpiler.ts +++ b/src/compiler/transpiler.ts @@ -1,29 +1,24 @@ import { Logger } from 'bs-logger' -import { readFileSync } from 'fs' import { normalize } from 'path' import * as _ts from 'typescript' import { ConfigSet } from '../config/config-set' -import { CompilerInstance, SourceOutput, TSFile, TSFiles } from '../types' +import { CompilerInstance, MemoryCache, SourceOutput } from '../types' -import { getAndCacheOutputJSFileName, getAndCacheProjectReference } from './compiler-utils' +import { getAndCacheProjectReference, getCompileResultFromReferencedProject } from './compiler-utils' /** * @internal */ -export const initializeTranspilerInstance = (configs: ConfigSet, logger: Logger): CompilerInstance => { - logger.debug('compileUsingTranspileModule(): create typescript compiler') +export const initializeTranspilerInstance = ( + configs: ConfigSet, + memoryCache: MemoryCache, + logger: Logger, +): CompilerInstance => { + logger.debug('initializeTranspilerInstance(): create typescript compiler') const { options, projectReferences, fileNames } = configs.typescript - const files: TSFiles = new Map() const ts = configs.compilerModule - fileNames.forEach(filePath => { - const normalizedFilePath = normalize(filePath) - files.set(normalizedFilePath, { - text: readFileSync(normalizedFilePath, 'utf-8'), - version: 0, - }) - }) const program = projectReferences ? ts.createProgram({ rootNames: fileNames, @@ -32,7 +27,7 @@ export const initializeTranspilerInstance = (configs: ConfigSet, logger: Logger) }) : ts.createProgram([], options) const updateFileInCache = (contents: string, filePath: string) => { - const file = files.get(filePath) + const file = memoryCache.files.get(filePath) if (file && file.text !== contents) { file.version++ file.text = contents @@ -43,43 +38,21 @@ export const initializeTranspilerInstance = (configs: ConfigSet, logger: Logger) compileFn: (code: string, fileName: string): SourceOutput => { const normalizedFileName = normalize(fileName) - logger.debug({ normalizedFileName }, 'getOutput(): compiling as isolated module') - updateFileInCache(code, normalizedFileName) - const referencedProject = getAndCacheProjectReference(normalizedFileName, program, files, projectReferences) + const referencedProject = getAndCacheProjectReference( + normalizedFileName, + program, + memoryCache.files, + projectReferences, + ) /* istanbul ignore next (referencedProject object is too complex to mock so we leave this for e2e) */ if (referencedProject !== undefined) { - const [relativeProjectConfigPath, relativeFilePath] = [ - configs.resolvePath(referencedProject.sourceFile.fileName), - configs.resolvePath(normalizedFileName), - ] - if (referencedProject.commandLine.options.outFile !== undefined) { - throw new Error( - `The referenced project at ${relativeProjectConfigPath} is using ` + - `the outFile' option, which is not supported with ts-jest.`, - ) - } + logger.debug({ normalizedFileName }, 'compileFn(): get compile result from referenced project') - const jsFileName = getAndCacheOutputJSFileName(normalizedFileName, referencedProject, files) - const relativeJSFileName = configs.resolvePath(jsFileName) - if (!ts.sys.fileExists(jsFileName)) { - throw new Error( - // tslint:disable-next-line:prefer-template - `Could not find output JavaScript file for input ` + - `${relativeFilePath} (looked at ${relativeJSFileName}).\n` + - `The input file is part of a project reference located at ` + - `${relativeProjectConfigPath}, so ts-jest is looking for the ` + - 'project’s pre-built output on disk. Try running `tsc --build` ' + - 'to build project references.', - ) - } - - const mapFileName = `${jsFileName}.map` - const outputText = ts.sys.readFile(jsFileName) - const sourceMapText = ts.sys.readFile(mapFileName) - - return [outputText!, sourceMapText!] + return getCompileResultFromReferencedProject(normalizedFileName, configs, memoryCache.files, referencedProject) } else { + logger.debug({ normalizedFileName }, 'compileFn(): compiling as isolated module') + const result: _ts.TranspileOutput = ts.transpileModule(code, { fileName: normalizedFileName, transformers: configs.tsCustomTransformers, diff --git a/src/types.ts b/src/types.ts index cb0df60049..4e31d00a4a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -200,6 +200,7 @@ export interface MemoryCache { modulePaths: string[] } } + files: TSFiles } /** * @internal