From 0feb5560a588f87d1d989bf521859fba0fda20fe Mon Sep 17 00:00:00 2001 From: Ahn Date: Fri, 28 May 2021 22:14:23 +0200 Subject: [PATCH] fix(compiler): add empty string file content to compiler cache (#2633) Closes #2625 --- e2e/__external-repos__/custom-typings/foo.ts | 0 .../simple/with-dependency/empty.ts | 0 .../simple/with-dependency/package.json | 3 +- .../simple/with-dependency/tsconfig.json | 8 ++-- package-lock.json | 38 +++++++------------ package.json | 1 + scripts/lib/paths.js | 15 ++++---- src/__mocks__/empty.ts | 0 src/compiler/ts-compiler.spec.ts | 15 +++++++- src/compiler/ts-compiler.ts | 4 +- 10 files changed, 41 insertions(+), 43 deletions(-) create mode 100644 e2e/__external-repos__/custom-typings/foo.ts create mode 100644 e2e/__external-repos__/simple/with-dependency/empty.ts create mode 100644 src/__mocks__/empty.ts diff --git a/e2e/__external-repos__/custom-typings/foo.ts b/e2e/__external-repos__/custom-typings/foo.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/e2e/__external-repos__/simple/with-dependency/empty.ts b/e2e/__external-repos__/simple/with-dependency/empty.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/e2e/__external-repos__/simple/with-dependency/package.json b/e2e/__external-repos__/simple/with-dependency/package.json index 7f761bf8f8..15496a8459 100644 --- a/e2e/__external-repos__/simple/with-dependency/package.json +++ b/e2e/__external-repos__/simple/with-dependency/package.json @@ -1,6 +1,7 @@ { "name": "with-dependency", - "version": "0.0.1", + "version": "0.0.0", + "license": "MIT", "scripts": { "test": "jest --no-cache" }, diff --git a/e2e/__external-repos__/simple/with-dependency/tsconfig.json b/e2e/__external-repos__/simple/with-dependency/tsconfig.json index e2a32abfa8..6e4fc1746e 100644 --- a/e2e/__external-repos__/simple/with-dependency/tsconfig.json +++ b/e2e/__external-repos__/simple/with-dependency/tsconfig.json @@ -13,9 +13,7 @@ "downlevelIteration": true, "strict": true, "moduleResolution": "node", - "esModuleInterop": true - }, - "include": [ - "./src" - ] + "esModuleInterop": true, + "noEmitOnError": true + } } diff --git a/package-lock.json b/package-lock.json index 79947ea658..6f6c7242f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3512,9 +3512,9 @@ } }, "es-abstract": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.2.tgz", - "integrity": "sha512-byRiNIQXE6HWNySaU6JohoNXzYgbBjztwFnBLUTiJmWXjaU9bSq3urQLUlNLQ292tc+gc07zYZXNZjaOoAX3sw==", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -4298,15 +4298,6 @@ "bser": "2.1.1" } }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4743,9 +4734,9 @@ } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7372,15 +7363,13 @@ } }, "listr2": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.8.4.tgz", - "integrity": "sha512-DX+iKRcxaGbBjoLJBQlGceZoqdhV6Z54wpsvIVoVKNJ/lEXK8KhGhLaZnIGKRQmDmtJOtyNSnnKFUS1qn+jqsw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.9.0.tgz", + "integrity": "sha512-+JxQt7Vi4WEWgJsxmOEX9lDbCumrb3mrEYIeE1VI7I4lf2rXE4v9pq3RMVNp+a9s6mCgc/IsF0ppHsLrx2BEAw==", "dev": true, "requires": { "cli-truncate": "^2.1.0", "colorette": "^1.2.2", - "figures": "^3.2.0", - "indent-string": "^4.0.0", "log-update": "^4.0.0", "p-map": "^4.0.0", "rxjs": "^6.6.7", @@ -8091,15 +8080,14 @@ } }, "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", "dev": true, "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" + "es-abstract": "^1.18.2" } }, "once": { diff --git a/package.json b/package.json index 89db3d222c..22f09ec304 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "eslint-plugin-prettier": "latest", "execa": "latest", "fs-extra": "10.x", + "glob": "^7.1.7", "glob-gitignore": "latest", "husky": "4.x", "jest": "^27.0.0", diff --git a/scripts/lib/paths.js b/scripts/lib/paths.js index d53e2e54b9..fb125f52c0 100644 --- a/scripts/lib/paths.js +++ b/scripts/lib/paths.js @@ -1,5 +1,7 @@ const os = require('os') const path = require('path') +const glob = require('glob') +const fs = require('fs') const rootDir = path.resolve(__dirname, '..', '..') const cacheDir = path.join(rootDir, '.cache') @@ -16,14 +18,11 @@ const e2eWorkDir = process.env.TS_JEST_E2E_WORKDIR : path.join(os.tmpdir(), '--ts-jest-temp-e2e--') const e2eWorkTemplatesDir = path.join(e2eWorkDir, '__templates__') const e2eWorkDirLink = path.join(e2eRootDir, '__workdir_synlink__') -const projectsToRun = [ - `${e2eExternalRepoDir}/custom-typings`, - `${e2eExternalRepoDir}/memory-usage`, - `${e2eExternalRepoDir}/path-mapping`, - `${e2eExternalRepoDir}/simple/with-dependency`, - `${e2eExternalRepoDir}/simple-project-references`, - `${e2eExternalRepoDir}/yarn-workspace-composite`, -] +const projectsToRun = glob + .sync(`${e2eExternalRepoDir}/*`) + .filter((e2ePath) => fs.lstatSync(e2ePath).isDirectory() && fs.existsSync(path.join(e2ePath, 'package.json'))) + .sort() +projectsToRun.push(`${e2eExternalRepoDir}/simple/with-dependency`) const rawCompilerOptionsFileName = path.join('src', 'raw-compiler-options.ts') const generatedPath = path.join(process.cwd(), rawCompilerOptionsFileName) diff --git a/src/__mocks__/empty.ts b/src/__mocks__/empty.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/compiler/ts-compiler.spec.ts b/src/compiler/ts-compiler.spec.ts index 540750aec6..80f4885c48 100644 --- a/src/compiler/ts-compiler.spec.ts +++ b/src/compiler/ts-compiler.spec.ts @@ -3,12 +3,13 @@ import { basename, join, normalize } from 'path' import { DiagnosticCategory, EmitOutput, ModuleKind, ScriptTarget, TranspileOutput } from 'typescript' -import { makeCompiler } from '../__helpers__/fakers' +import { createConfigSet, makeCompiler } from '../__helpers__/fakers' import { mockFolder } from '../__helpers__/path' import type { DepGraphInfo } from '../types' import { Errors, interpolate } from '../utils/messages' import { updateOutput } from './compiler-utils' +import { TsCompiler } from './ts-compiler' const baseTsJestConfig = { tsconfig: join(process.cwd(), 'tsconfig.spec.json') } @@ -163,9 +164,12 @@ describe('TsCompiler', () => { const sourceMap = '{}' test.each([true, false])('should compile codes with useESM %p', (useESM) => { - const compiler = makeCompiler({ + const configSet = createConfigSet({ tsJestConfig: { ...baseTsJestConfig, useESM }, }) + const emptyFile = join(mockFolder, 'empty.ts') + configSet.parsedTsConfig.fileNames.push(emptyFile) + const compiler = new TsCompiler(configSet, new Map()) // @ts-expect-error testing purpose compiler._languageService.getEmitOutput = jest.fn().mockReturnValueOnce({ outputFiles: [{ text: sourceMap }, { text: jsOutput }], @@ -193,6 +197,13 @@ describe('TsCompiler', () => { expect(esModuleInterop).toEqual(useESM ? true : esModuleInterop) expect(allowSyntheticDefaultImports).toEqual(useESM ? true : allowSyntheticDefaultImports) expect(output).toEqual(updateOutput(jsOutput, fileName, sourceMap)) + + // @ts-expect-error testing purpose + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + compiler._languageService!.getSemanticDiagnostics(fileName) + + // @ts-expect-error testing purpose + expect(compiler._fileContentCache.has(emptyFile)).toBe(true) }) test('should show a warning message and return original file content for non ts/tsx files if emitSkipped is true', () => { diff --git a/src/compiler/ts-compiler.ts b/src/compiler/ts-compiler.ts index 7eafdb1b86..5c5831bc07 100644 --- a/src/compiler/ts-compiler.ts +++ b/src/compiler/ts-compiler.ts @@ -266,7 +266,7 @@ export class TsCompiler implements TsCompilerInstance { this._logger.trace({ normalizedFileName, cacheHit: hit }, 'getScriptSnapshot():', 'cache', hit ? 'hit' : 'miss') - // Read contents from TypeScript memory cache. + // Read file content from either memory cache or Jest runtime cache or fallback to file system read if (!hit) { const fileContent = // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -274,7 +274,7 @@ export class TsCompiler implements TsCompilerInstance { this._runtimeCacheFS.get(normalizedFileName) ?? this._cachedReadFile?.(normalizedFileName) ?? undefined - if (fileContent) { + if (fileContent !== undefined) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this._fileContentCache!.set(normalizedFileName, fileContent) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion