From 12709693796026ab2ed3c9f8137cf720a81e0f4f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 17 Feb 2019 00:21:16 +0100 Subject: [PATCH 1/4] chore: migrate @jest/transform to TypeScript --- CHANGELOG.md | 1 + packages/babel-jest/src/index.ts | 2 +- packages/jest-transform/package.json | 2 + ...iptTransformer.js => ScriptTransformer.ts} | 131 ++++++++++-------- ...ge.js => enhanceUnexpectedTokenMessage.ts} | 2 - .../jest-transform/src/{index.js => index.ts} | 2 - ...houldInstrument.js => shouldInstrument.ts} | 15 +- packages/jest-transform/src/types.js | 21 --- packages/jest-transform/src/types.ts | 20 +++ packages/jest-transform/tsconfig.json | 13 ++ packages/jest-types/src/Transform.ts | 4 +- yarn.lock | 5 + 12 files changed, 123 insertions(+), 95 deletions(-) rename packages/jest-transform/src/{ScriptTransformer.js => ScriptTransformer.ts} (82%) rename packages/jest-transform/src/{enhanceUnexpectedTokenMessage.js => enhanceUnexpectedTokenMessage.ts} (99%) rename packages/jest-transform/src/{index.js => index.ts} (96%) rename packages/jest-transform/src/{shouldInstrument.js => shouldInstrument.ts} (88%) delete mode 100644 packages/jest-transform/src/types.js create mode 100644 packages/jest-transform/src/types.ts create mode 100644 packages/jest-transform/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index d23db1531297..5d980e89930b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ - `[@jest/transform]`: New package extracted from `jest-runtime` ([#7915](https://github.com/facebook/jest/pull/7915)) - `[babel-plugin-jest-hoist]`: Migrate to TypeScript ([#7898](https://github.com/facebook/jest/pull/7898)) - `[@jest/core]` Create new package, which is `jest-cli` minus `yargs` and `prompts` ([#7696](https://github.com/facebook/jest/pull/7696)) +- `[@jest/transform]`: Migrate to TypeScript ([#7918](https://github.com/facebook/jest/pull/7918)) ### Performance diff --git a/packages/babel-jest/src/index.ts b/packages/babel-jest/src/index.ts index ea8a5bde75cd..346a948fa280 100644 --- a/packages/babel-jest/src/index.ts +++ b/packages/babel-jest/src/index.ts @@ -27,7 +27,7 @@ const createTransformer = ( ): Transform.Transformer => { options = { ...options, - // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/32955 + // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33118 caller: { name: 'babel-jest', supportsStaticESM: false, diff --git a/packages/jest-transform/package.json b/packages/jest-transform/package.json index 345321986283..2fb3d06fa0cd 100644 --- a/packages/jest-transform/package.json +++ b/packages/jest-transform/package.json @@ -10,6 +10,7 @@ "main": "build/index.js", "dependencies": { "@babel/core": "^7.1.0", + "@jest/types": "^24.1.0", "babel-plugin-istanbul": "^5.1.0", "chalk": "^2.0.1", "convert-source-map": "^1.4.0", @@ -26,6 +27,7 @@ "devDependencies": { "@types/babel__core": "^7.0.4", "@types/convert-source-map": "^1.5.1", + "@types/fast-json-stable-stringify": "^2.0.0", "@types/graceful-fs": "^4.1.2", "@types/micromatch": "^3.1.0", "@types/write-file-atomic": "^2.1.1" diff --git a/packages/jest-transform/src/ScriptTransformer.js b/packages/jest-transform/src/ScriptTransformer.ts similarity index 82% rename from packages/jest-transform/src/ScriptTransformer.js rename to packages/jest-transform/src/ScriptTransformer.ts index 44b5959fb39e..b91f1955db77 100644 --- a/packages/jest-transform/src/ScriptTransformer.js +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -3,57 +3,54 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {Path, ProjectConfig} from 'types/Config'; -import type { - Transformer, - TransformedSource, - TransformResult, -} from 'types/Transform'; -import type {ErrorWithCode} from 'types/Errors'; -import type {Options} from './types'; - import crypto from 'crypto'; import path from 'path'; import vm from 'vm'; +import {Config, Transform} from '@jest/types'; import {createDirectory} from 'jest-util'; import fs from 'graceful-fs'; import {transformSync as babelTransform} from '@babel/core'; +// @ts-ignore: should just be `require.resolve`, but the tests mess that up import babelPluginIstanbul from 'babel-plugin-istanbul'; import convertSourceMap from 'convert-source-map'; import HasteMap from 'jest-haste-map'; import stableStringify from 'fast-json-stable-stringify'; import slash from 'slash'; -import {version as VERSION} from '../package.json'; -import shouldInstrument from './shouldInstrument'; import writeFileAtomic from 'write-file-atomic'; import {sync as realpath} from 'realpath-native'; +import {Options} from './types'; +import shouldInstrument from './shouldInstrument'; import enhanceUnexpectedTokenMessage from './enhanceUnexpectedTokenMessage'; -type ProjectCache = {| - configString: string, - ignorePatternsRegExp: ?RegExp, - transformedFiles: Map, -|}; +type ProjectCache = { + configString: string; + ignorePatternsRegExp: RegExp | null; + transformedFiles: Map; +}; + +// Use `require` to avoid TS rootDir +const {version: VERSION} = require('../package.json'); // This data structure is used to avoid recalculating some data every time that // we need to transform a file. Since ScriptTransformer is instantiated for each // file we need to keep this object in the local scope of this module. -const projectCaches: WeakMap = new WeakMap(); +const projectCaches: WeakMap< + Config.ProjectConfig, + ProjectCache +> = new WeakMap(); // To reset the cache for specific changesets (rather than package version). const CACHE_VERSION = '1'; export default class ScriptTransformer { static EVAL_RESULT_VARIABLE: string; - _cache: ProjectCache; - _config: ProjectConfig; - _transformCache: Map; + private _cache: ProjectCache; + private _config: Config.ProjectConfig; + private _transformCache: Map; - constructor(config: ProjectConfig) { + constructor(config: Config.ProjectConfig) { this._config = config; this._transformCache = new Map(); @@ -72,7 +69,11 @@ export default class ScriptTransformer { this._cache = projectCache; } - _getCacheKey(fileData: string, filename: Path, instrument: boolean): string { + private _getCacheKey( + fileData: string, + filename: Config.Path, + instrument: boolean, + ): string { const configString = this._cache.configString; const transformer = this._getTransformer(filename); @@ -99,11 +100,12 @@ export default class ScriptTransformer { } } - _getFileCachePath( - filename: Path, + private _getFileCachePath( + filename: Config.Path, content: string, instrument: boolean, - ): Path { + ): Config.Path { + // @ts-ignore: not properly exported (needs ESM) const baseCacheDir = HasteMap.getCacheFilePath( this._config.cacheDirectory, 'jest-transform-cache-' + this._config.name, @@ -124,7 +126,7 @@ export default class ScriptTransformer { return cachePath; } - _getTransformPath(filename: Path) { + private _getTransformPath(filename: Config.Path) { for (let i = 0; i < this._config.transform.length; i++) { if (new RegExp(this._config.transform[i][0]).test(filename)) { return this._config.transform[i][1]; @@ -133,8 +135,8 @@ export default class ScriptTransformer { return null; } - _getTransformer(filename: Path) { - let transform: ?Transformer; + private _getTransformer(filename: Config.Path) { + let transform: Transform.Transformer | null = null; if (!this._config.transform || !this._config.transform.length) { return null; } @@ -146,8 +148,7 @@ export default class ScriptTransformer { return transformer; } - // $FlowFixMe - transform = (require(transformPath): Transformer); + transform = require(transformPath) as Transform.Transformer; if (typeof transform.createTransformer === 'function') { transform = transform.createTransformer(); } @@ -161,10 +162,11 @@ export default class ScriptTransformer { return transform; } - _instrumentFile(filename: Path, content: string): string { + private _instrumentFile(filename: Config.Path, content: string): string { const result = babelTransform(content, { auxiliaryCommentBefore: ' istanbul ignore next ', babelrc: false, + // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33118 caller: { name: '@jest/transform', supportsStaticESM: false, @@ -185,10 +187,18 @@ export default class ScriptTransformer { ], }); - return result ? result.code : content; + if (result) { + const {code} = result; + + if (code) { + return code; + } + } + + return content; } - _getRealPath(filepath: Path): Path { + private _getRealPath(filepath: Config.Path): Config.Path { try { return realpath(filepath) || filepath; } catch (err) { @@ -198,15 +208,15 @@ export default class ScriptTransformer { // We don't want to expose transformers to the outside - this function is just // to warm up `this._transformCache` - preloadTransformer(filepath: Path): void { + preloadTransformer(filepath: Config.Path): void { this._getTransformer(filepath); } - transformSource(filepath: Path, content: string, instrument: boolean) { + transformSource(filepath: Config.Path, content: string, instrument: boolean) { const filename = this._getRealPath(filepath); const transform = this._getTransformer(filename); const cacheFilePath = this._getFileCachePath(filename, content, instrument); - let sourceMapPath = cacheFilePath + '.map'; + let sourceMapPath: Config.Path | null = cacheFilePath + '.map'; // Ignore cache if `config.cache` is set (--no-cache) let code = this._config.cache ? readCodeCacheFile(cacheFilePath) : null; @@ -233,7 +243,7 @@ export default class ScriptTransformer { }; } - let transformed: TransformedSource = { + let transformed: Transform.TransformedSource = { code: content, map: null, }; @@ -290,12 +300,12 @@ export default class ScriptTransformer { }; } - _transformAndBuildScript( - filename: Path, - options: ?Options, + private _transformAndBuildScript( + filename: Config.Path, + options: Options | null, instrument: boolean, fileSource?: string, - ): TransformResult { + ): Transform.TransformResult { const isInternalModule = !!(options && options.isInternalModule); const isCoreModule = !!(options && options.isCoreModule); const content = stripShebang( @@ -303,7 +313,7 @@ export default class ScriptTransformer { ); let wrappedCode: string; - let sourceMapPath: ?string = null; + let sourceMapPath: string | null = null; let mapCoverage = false; const willTransform = @@ -354,13 +364,13 @@ export default class ScriptTransformer { } transform( - filename: Path, + filename: Config.Path, options: Options, fileSource?: string, - ): TransformResult { + ): Transform.TransformResult | string { let scriptCacheKey = null; let instrument = false; - let result = ''; + let result: Transform.TransformResult | string | undefined = ''; if (!options.isCoreModule) { instrument = shouldInstrument(filename, options, this._config); @@ -386,7 +396,7 @@ export default class ScriptTransformer { return result; } - _shouldTransform(filename: Path): boolean { + private _shouldTransform(filename: Config.Path): boolean { const ignoreRegexp = this._cache.ignorePatternsRegExp; const isIgnored = ignoreRegexp ? ignoreRegexp.test(filename) : false; @@ -396,13 +406,13 @@ export default class ScriptTransformer { } } -const removeFile = (path: Path) => { +const removeFile = (path: Config.Path) => { try { fs.unlinkSync(path); } catch (e) {} }; -const stripShebang = content => { +const stripShebang = (content: string) => { // If the file data starts with a shebang remove it. Leaves the empty line // to keep stack trace line numbers correct. if (content.startsWith('#!')) { @@ -419,7 +429,7 @@ const stripShebang = content => { * it right away. This is not a great system, because source map cache file * could get corrupted, out-of-sync, etc. */ -function writeCodeCacheFile(cachePath: Path, code: string) { +function writeCodeCacheFile(cachePath: Config.Path, code: string) { const checksum = crypto .createHash('md5') .update(code) @@ -433,7 +443,7 @@ function writeCodeCacheFile(cachePath: Path, code: string) { * could happen if an older version of `jest-runtime` writes non-atomically to * the same cache, for example. */ -function readCodeCacheFile(cachePath: Path): ?string { +function readCodeCacheFile(cachePath: Config.Path): string | null { const content = readCacheFile(cachePath); if (content == null) { return null; @@ -455,7 +465,7 @@ function readCodeCacheFile(cachePath: Path): ?string { * two processes to write to the same file at the same time. It also reduces * the risk of reading a file that's being overwritten at the same time. */ -const writeCacheFile = (cachePath: Path, fileData: string) => { +const writeCacheFile = (cachePath: Config.Path, fileData: string) => { try { writeFileAtomic.sync(cachePath, fileData, {encoding: 'utf8'}); } catch (e) { @@ -479,12 +489,15 @@ const writeCacheFile = (cachePath: Path, fileData: string) => { * If the target file exists we can be reasonably sure another process has * legitimately won a cache write race and ignore the error. */ -const cacheWriteErrorSafeToIgnore = (e: ErrorWithCode, cachePath: Path) => +const cacheWriteErrorSafeToIgnore = ( + e: Error & {code: string}, + cachePath: Config.Path, +) => process.platform === 'win32' && e.code === 'EPERM' && fs.existsSync(cachePath); -const readCacheFile = (cachePath: Path): ?string => { +const readCacheFile = (cachePath: Config.Path): string | null => { if (!fs.existsSync(cachePath)) { return null; } @@ -510,12 +523,14 @@ const readCacheFile = (cachePath: Path): ?string => { return fileData; }; -const getScriptCacheKey = (filename, instrument: boolean) => { +const getScriptCacheKey = (filename: Config.Path, instrument: boolean) => { const mtime = fs.statSync(filename).mtime; return filename + '_' + mtime.getTime() + (instrument ? '_instrumented' : ''); }; -const calcIgnorePatternRegexp = (config: ProjectConfig): ?RegExp => { +const calcIgnorePatternRegexp = ( + config: Config.ProjectConfig, +): RegExp | null => { if ( !config.transformIgnorePatterns || config.transformIgnorePatterns.length === 0 @@ -526,7 +541,7 @@ const calcIgnorePatternRegexp = (config: ProjectConfig): ?RegExp => { return new RegExp(config.transformIgnorePatterns.join('|')); }; -const wrap = (content, ...extras) => { +const wrap = (content: string, ...extras: Array) => { const globals = new Set([ 'module', 'exports', diff --git a/packages/jest-transform/src/enhanceUnexpectedTokenMessage.js b/packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts similarity index 99% rename from packages/jest-transform/src/enhanceUnexpectedTokenMessage.js rename to packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts index af941fa7cf53..e16129fe7c95 100644 --- a/packages/jest-transform/src/enhanceUnexpectedTokenMessage.js +++ b/packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts @@ -1,7 +1,5 @@ // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. -// @flow - import chalk from 'chalk'; const DOT = ' \u2022 '; diff --git a/packages/jest-transform/src/index.js b/packages/jest-transform/src/index.ts similarity index 96% rename from packages/jest-transform/src/index.js rename to packages/jest-transform/src/index.ts index 37cbb258b92a..56881982c5b3 100644 --- a/packages/jest-transform/src/index.js +++ b/packages/jest-transform/src/index.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ export {default as ScriptTransformer} from './ScriptTransformer'; diff --git a/packages/jest-transform/src/shouldInstrument.js b/packages/jest-transform/src/shouldInstrument.ts similarity index 88% rename from packages/jest-transform/src/shouldInstrument.js rename to packages/jest-transform/src/shouldInstrument.ts index c0b869d4318b..d8585c37a8b2 100644 --- a/packages/jest-transform/src/shouldInstrument.js +++ b/packages/jest-transform/src/shouldInstrument.ts @@ -3,26 +3,23 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {Path, ProjectConfig} from 'types/Config'; -import type {Options} from './types'; - import path from 'path'; +import {Config} from '@jest/types'; import {escapePathForRegex} from 'jest-regex-util'; import {replacePathSepForGlob} from 'jest-util'; import micromatch from 'micromatch'; +import {Options} from './types'; const MOCKS_PATTERN = new RegExp( escapePathForRegex(path.sep + '__mocks__' + path.sep), ); export default function shouldInstrument( - filename: Path, + filename: Config.Path, options: Options, - config: ProjectConfig, + config: Config.ProjectConfig, ): boolean { if (!options.collectCoverage) { return false; @@ -38,7 +35,7 @@ export default function shouldInstrument( if ( !config.testPathIgnorePatterns || - !config.testPathIgnorePatterns.some(pattern => filename.match(pattern)) + !config.testPathIgnorePatterns.some(pattern => !!filename.match(pattern)) ) { if ( config.testRegex && @@ -79,7 +76,7 @@ export default function shouldInstrument( if ( config.coveragePathIgnorePatterns && - config.coveragePathIgnorePatterns.some(pattern => filename.match(pattern)) + config.coveragePathIgnorePatterns.some(pattern => !!filename.match(pattern)) ) { return false; } diff --git a/packages/jest-transform/src/types.js b/packages/jest-transform/src/types.js deleted file mode 100644 index 00f577bdad80..000000000000 --- a/packages/jest-transform/src/types.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {Glob, Path} from 'types/Config'; - -// TODO: Pick from `GlobalConfig` -export type Options = {| - changedFiles: ?Set, - collectCoverage: boolean, - collectCoverageFrom: Array, - collectCoverageOnlyFrom: ?{[key: string]: boolean, __proto__: null}, - extraGlobals?: Array, - isCoreModule?: boolean, - isInternalModule?: boolean, -|}; diff --git a/packages/jest-transform/src/types.ts b/packages/jest-transform/src/types.ts new file mode 100644 index 000000000000..0e66ae444fbf --- /dev/null +++ b/packages/jest-transform/src/types.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {Config} from '@jest/types'; + +export type Options = Pick< + Config.GlobalConfig, + | 'collectCoverage' + | 'collectCoverageFrom' + | 'collectCoverageOnlyFrom' + | 'extraGlobals' +> & { + changedFiles: Set | undefined; + isCoreModule?: boolean; + isInternalModule?: boolean; +}; diff --git a/packages/jest-transform/tsconfig.json b/packages/jest-transform/tsconfig.json new file mode 100644 index 000000000000..73d865a32cda --- /dev/null +++ b/packages/jest-transform/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build" + }, + "references": [ + {"path": "../jest-haste-map"}, + {"path": "../jest-regex-util"}, + {"path": "../jest-types"}, + {"path": "../jest-util"} + ] +} diff --git a/packages/jest-types/src/Transform.ts b/packages/jest-types/src/Transform.ts index 473434637f90..63bbb0bad081 100644 --- a/packages/jest-types/src/Transform.ts +++ b/packages/jest-types/src/Transform.ts @@ -26,7 +26,7 @@ export type TransformedSource = { export type TransformResult = { script: Script; mapCoverage: boolean; - sourceMapPath?: string; + sourceMapPath: string | null; }; export type TransformOptions = { @@ -41,7 +41,7 @@ export type CacheKeyOptions = { export type Transformer = { canInstrument?: boolean; - createTransformer?: (options: any) => Transformer; + createTransformer?: (options?: any) => Transformer; getCacheKey: ( fileData: string, diff --git a/yarn.lock b/yarn.lock index 2ca7de58e22a..59b677434489 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1575,6 +1575,11 @@ resolved "https://registry.yarnpkg.com/@types/exit/-/exit-0.1.30.tgz#7078b736a7d166c80b6394dc0d9de1577ca76daf" integrity sha1-cHi3NqfRZsgLY5TcDZ3hV3ynba8= +"@types/fast-json-stable-stringify@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#40363bb847cb86b2c2e1599f1398d11e8329c921" + integrity sha512-mky/O83TXmGY39P1H9YbUpjV6l6voRYlufqfFCvel8l1phuy8HRjdWc1rrPuN53ITBJlbyMSV6z3niOySO5pgQ== + "@types/fb-watchman@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/fb-watchman/-/fb-watchman-2.0.0.tgz#ca60ded406baa8c81c65ac1f86763a5d00aa7c55" From 3f1dcd8299a4621e1baa52659e718ad93046dcd7 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 17 Feb 2019 01:08:07 +0100 Subject: [PATCH 2/4] move transform types to transform package and fix babel-jest export types --- packages/babel-jest/package.json | 3 +- packages/babel-jest/src/__tests__/index.ts | 6 +- packages/babel-jest/src/index.ts | 50 +++++++--------- packages/babel-jest/tsconfig.json | 1 + packages/jest-transform/package.json | 1 + .../jest-transform/src/ScriptTransformer.ts | 25 ++++---- packages/jest-transform/src/index.ts | 1 + packages/jest-transform/src/types.ts | 51 ++++++++++++++++ packages/jest-types/package.json | 5 +- packages/jest-types/src/Transform.ts | 59 ------------------- packages/jest-types/src/index.ts | 12 +--- 11 files changed, 97 insertions(+), 117 deletions(-) delete mode 100644 packages/jest-types/src/Transform.ts diff --git a/packages/babel-jest/package.json b/packages/babel-jest/package.json index a827589d2319..226e23853ce9 100644 --- a/packages/babel-jest/package.json +++ b/packages/babel-jest/package.json @@ -11,7 +11,9 @@ "main": "build/index.js", "types": "build/index.d.ts", "dependencies": { + "@jest/transform": "^24.1.0", "@jest/types": "^24.1.0", + "@types/babel__core": "^7.0.4", "babel-plugin-istanbul": "^5.1.0", "babel-preset-jest": "^24.1.0", "chalk": "^2.4.2", @@ -19,7 +21,6 @@ }, "devDependencies": { "@babel/core": "^7.1.0", - "@types/babel__core": "^7.0.4", "@types/slash": "^2.0.0" }, "peerDependencies": { diff --git a/packages/babel-jest/src/__tests__/index.ts b/packages/babel-jest/src/__tests__/index.ts index 01fbd54b92c9..6b3d264a883f 100644 --- a/packages/babel-jest/src/__tests__/index.ts +++ b/packages/babel-jest/src/__tests__/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {Config, Transform} from '@jest/types'; +import {Config} from '@jest/types'; import babelJest from '../index'; //Mock data for all the tests @@ -30,14 +30,12 @@ test(`Returns source string with inline maps when no transformOptions is passed` sourceString, 'dummy_path.js', (mockConfig as unknown) as Config.ProjectConfig, - ) as Transform.TransformedSource; + ) as any; expect(typeof result).toBe('object'); expect(result.code).toBeDefined(); expect(result.map).toBeDefined(); expect(result.code).toMatch('//# sourceMappingURL'); expect(result.code).toMatch('customMultiply'); - // @ts-ignore: it's fine if we get wrong types, the tests will fail then expect(result.map.sources).toEqual(['dummy_path.js']); - // @ts-ignore: it's fine if we get wrong types, the tests will fail then expect(JSON.stringify(result.map.sourcesContent)).toMatch('customMultiply'); }); diff --git a/packages/babel-jest/src/index.ts b/packages/babel-jest/src/index.ts index 346a948fa280..2df36fe37d22 100644 --- a/packages/babel-jest/src/index.ts +++ b/packages/babel-jest/src/index.ts @@ -8,12 +8,13 @@ import crypto from 'crypto'; import fs from 'fs'; import path from 'path'; -import {Config, Transform} from '@jest/types'; +import {Transformer} from '@jest/transform'; +import {Config} from '@jest/types'; import { - transformSync as babelTransform, loadPartialConfig, - TransformOptions, PartialConfig, + TransformOptions, + transformSync as babelTransform, } from '@babel/core'; import chalk from 'chalk'; import slash from 'slash'; @@ -22,9 +23,15 @@ const THIS_FILE = fs.readFileSync(__filename); const jestPresetPath = require.resolve('babel-preset-jest'); const babelIstanbulPlugin = require.resolve('babel-plugin-istanbul'); +// Narrow down the types +interface BabelJestTransformer extends Transformer { + canInstrument: true; + createTransformer: (options?: TransformOptions) => BabelJestTransformer; +} + const createTransformer = ( options: TransformOptions = {}, -): Transform.Transformer => { +): BabelJestTransformer => { options = { ...options, // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33118 @@ -58,18 +65,15 @@ const createTransformer = ( return babelConfig; } - return { + const transformer: BabelJestTransformer = { canInstrument: true, + createTransformer, getCacheKey( - fileData: string, - filename: Config.Path, - configString: string, - { - config, - instrument, - rootDir, - }: {config: Config.ProjectConfig} & Transform.CacheKeyOptions, - ): string { + fileData, + filename, + configString, + {config, instrument, rootDir}, + ) { const babelOptions = loadBabelConfig(config.cwd, filename); const configPath = [ babelOptions.config || '', @@ -97,12 +101,7 @@ const createTransformer = ( .update(process.env.BABEL_ENV || '') .digest('hex'); }, - process( - src: string, - filename: Config.Path, - config: Config.ProjectConfig, - transformOptions?: Transform.TransformOptions, - ): string | Transform.TransformedSource { + process(src, filename, config, transformOptions) { const babelOptions = {...loadBabelConfig(config.cwd, filename).options}; if (transformOptions && transformOptions.instrument) { @@ -132,13 +131,8 @@ const createTransformer = ( return src; }, }; -}; -const transformer = createTransformer(); - -// FIXME: This is not part of the exported TS types. When fixed, remember to -// move @types/babel__core to `dependencies` instead of `devDependencies` -// (one fix is to use ESM, maybe for Jest 25?) -transformer.createTransformer = createTransformer; + return transformer; +}; -export = transformer; +export = createTransformer(); diff --git a/packages/babel-jest/tsconfig.json b/packages/babel-jest/tsconfig.json index 75c28b2f54a9..c11e5a122222 100644 --- a/packages/babel-jest/tsconfig.json +++ b/packages/babel-jest/tsconfig.json @@ -6,6 +6,7 @@ }, // TODO: include `babel-preset-jest` if it's ever in TS even though we don't care about its types "references": [ + {"path": "../jest-transform"}, {"path": "../jest-types"} ] } diff --git a/packages/jest-transform/package.json b/packages/jest-transform/package.json index 2fb3d06fa0cd..61152b5281f7 100644 --- a/packages/jest-transform/package.json +++ b/packages/jest-transform/package.json @@ -22,6 +22,7 @@ "micromatch": "^3.1.10", "realpath-native": "^1.1.0", "slash": "^2.0.0", + "source-map": "^0.6.1", "write-file-atomic": "2.4.1" }, "devDependencies": { diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts index b91f1955db77..dda65661d94a 100644 --- a/packages/jest-transform/src/ScriptTransformer.ts +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -8,7 +8,7 @@ import crypto from 'crypto'; import path from 'path'; import vm from 'vm'; -import {Config, Transform} from '@jest/types'; +import {Config} from '@jest/types'; import {createDirectory} from 'jest-util'; import fs from 'graceful-fs'; import {transformSync as babelTransform} from '@babel/core'; @@ -20,14 +20,19 @@ import stableStringify from 'fast-json-stable-stringify'; import slash from 'slash'; import writeFileAtomic from 'write-file-atomic'; import {sync as realpath} from 'realpath-native'; -import {Options} from './types'; +import { + Options, + Transformer, + TransformedSource, + TransformResult, +} from './types'; import shouldInstrument from './shouldInstrument'; import enhanceUnexpectedTokenMessage from './enhanceUnexpectedTokenMessage'; type ProjectCache = { configString: string; ignorePatternsRegExp: RegExp | null; - transformedFiles: Map; + transformedFiles: Map; }; // Use `require` to avoid TS rootDir @@ -48,7 +53,7 @@ export default class ScriptTransformer { static EVAL_RESULT_VARIABLE: string; private _cache: ProjectCache; private _config: Config.ProjectConfig; - private _transformCache: Map; + private _transformCache: Map; constructor(config: Config.ProjectConfig) { this._config = config; @@ -136,7 +141,7 @@ export default class ScriptTransformer { } private _getTransformer(filename: Config.Path) { - let transform: Transform.Transformer | null = null; + let transform: Transformer | null = null; if (!this._config.transform || !this._config.transform.length) { return null; } @@ -148,7 +153,7 @@ export default class ScriptTransformer { return transformer; } - transform = require(transformPath) as Transform.Transformer; + transform = require(transformPath) as Transformer; if (typeof transform.createTransformer === 'function') { transform = transform.createTransformer(); } @@ -243,7 +248,7 @@ export default class ScriptTransformer { }; } - let transformed: Transform.TransformedSource = { + let transformed: TransformedSource = { code: content, map: null, }; @@ -305,7 +310,7 @@ export default class ScriptTransformer { options: Options | null, instrument: boolean, fileSource?: string, - ): Transform.TransformResult { + ): TransformResult { const isInternalModule = !!(options && options.isInternalModule); const isCoreModule = !!(options && options.isCoreModule); const content = stripShebang( @@ -367,10 +372,10 @@ export default class ScriptTransformer { filename: Config.Path, options: Options, fileSource?: string, - ): Transform.TransformResult | string { + ): TransformResult | string { let scriptCacheKey = null; let instrument = false; - let result: Transform.TransformResult | string | undefined = ''; + let result: TransformResult | string | undefined = ''; if (!options.isCoreModule) { instrument = shouldInstrument(filename, options, this._config); diff --git a/packages/jest-transform/src/index.ts b/packages/jest-transform/src/index.ts index 56881982c5b3..6f10151c3051 100644 --- a/packages/jest-transform/src/index.ts +++ b/packages/jest-transform/src/index.ts @@ -7,3 +7,4 @@ export {default as ScriptTransformer} from './ScriptTransformer'; export {default as shouldInstrument} from './shouldInstrument'; +export {Transformer} from './types'; diff --git a/packages/jest-transform/src/types.ts b/packages/jest-transform/src/types.ts index 0e66ae444fbf..91df3f394de9 100644 --- a/packages/jest-transform/src/types.ts +++ b/packages/jest-transform/src/types.ts @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +import {Script} from 'vm'; +import {RawSourceMap} from 'source-map'; import {Config} from '@jest/types'; export type Options = Pick< @@ -18,3 +20,52 @@ export type Options = Pick< isCoreModule?: boolean; isInternalModule?: boolean; }; + +// https://stackoverflow.com/a/48216010/1850276 +type Omit = Pick>; + +// This is fixed in a newer version, but that depends on Node 8 which is a +// breaking change (engine warning when installing) +interface FixedRawSourceMap extends Omit { + version: number; +} + +export type TransformedSource = { + code: string; + map?: FixedRawSourceMap | string | null; +}; + +export type TransformResult = { + script: Script; + mapCoverage: boolean; + sourceMapPath: string | null; +}; + +export type TransformOptions = { + instrument: boolean; +}; + +export type CacheKeyOptions = { + config: Config.ProjectConfig; + instrument: boolean; + rootDir: string; +}; + +export interface Transformer { + canInstrument?: boolean; + createTransformer?: (options?: any) => Transformer; + + getCacheKey: ( + fileData: string, + filePath: Config.Path, + configStr: string, + options: CacheKeyOptions, + ) => string; + + process: ( + sourceText: string, + sourcePath: Config.Path, + config: Config.ProjectConfig, + options?: TransformOptions, + ) => string | TransformedSource; +} diff --git a/packages/jest-types/package.json b/packages/jest-types/package.json index 572e2b791882..86018bd9b822 100644 --- a/packages/jest-types/package.json +++ b/packages/jest-types/package.json @@ -11,8 +11,5 @@ }, "license": "MIT", "main": "build/index.js", - "types": "build/index.d.ts", - "dependencies": { - "source-map": "^0.6.1" - } + "types": "build/index.d.ts" } diff --git a/packages/jest-types/src/Transform.ts b/packages/jest-types/src/Transform.ts deleted file mode 100644 index 63bbb0bad081..000000000000 --- a/packages/jest-types/src/Transform.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import {Script} from 'vm'; -import {RawSourceMap} from 'source-map'; -import {Path, ProjectConfig} from './Config'; - -// https://stackoverflow.com/a/48216010/1850276 -type Omit = Pick>; - -// This is fixed in a newer version, but that depends on Node 8 which is a -// breaking change (engine warning when installing) -interface FixedRawSourceMap extends Omit { - version: number; -} - -export type TransformedSource = { - code: string; - map?: FixedRawSourceMap | string | null; -}; - -export type TransformResult = { - script: Script; - mapCoverage: boolean; - sourceMapPath: string | null; -}; - -export type TransformOptions = { - instrument: boolean; -}; - -export type CacheKeyOptions = { - config: ProjectConfig; - instrument: boolean; - rootDir: string; -}; - -export type Transformer = { - canInstrument?: boolean; - createTransformer?: (options?: any) => Transformer; - - getCacheKey: ( - fileData: string, - filePath: Path, - configStr: string, - options: CacheKeyOptions, - ) => string; - - process: ( - sourceText: string, - sourcePath: Path, - config: ProjectConfig, - options?: TransformOptions, - ) => string | TransformedSource; -}; diff --git a/packages/jest-types/src/index.ts b/packages/jest-types/src/index.ts index 5f72f2e75feb..70361152f936 100644 --- a/packages/jest-types/src/index.ts +++ b/packages/jest-types/src/index.ts @@ -10,17 +10,7 @@ import * as Console from './Console'; import * as SourceMaps from './SourceMaps'; import * as TestResult from './TestResult'; import * as Mocks from './Mocks'; -import * as Transform from './Transform'; import * as PrettyFormat from './PrettyFormat'; import * as Matchers from './Matchers'; -export { - Config, - Console, - SourceMaps, - TestResult, - Mocks, - Transform, - PrettyFormat, - Matchers, -}; +export {Config, Console, SourceMaps, TestResult, Mocks, PrettyFormat, Matchers}; From 1fab8223b541a42f3e3cd7ad5a58dff25e10eb0e Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 17 Feb 2019 11:04:18 +0100 Subject: [PATCH 3/4] chore: `transform` cannot return `string` --- packages/jest-transform/src/ScriptTransformer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts index dda65661d94a..350616c327ad 100644 --- a/packages/jest-transform/src/ScriptTransformer.ts +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -32,7 +32,7 @@ import enhanceUnexpectedTokenMessage from './enhanceUnexpectedTokenMessage'; type ProjectCache = { configString: string; ignorePatternsRegExp: RegExp | null; - transformedFiles: Map; + transformedFiles: Map; }; // Use `require` to avoid TS rootDir @@ -372,10 +372,10 @@ export default class ScriptTransformer { filename: Config.Path, options: Options, fileSource?: string, - ): TransformResult | string { + ): TransformResult { let scriptCacheKey = null; let instrument = false; - let result: TransformResult | string | undefined = ''; + let result: TransformResult | undefined; if (!options.isCoreModule) { instrument = shouldInstrument(filename, options, this._config); From d1dfdd5ed061a5d17a3017b2b9ac654f24787bb7 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 17 Feb 2019 11:18:25 +0100 Subject: [PATCH 4/4] sneak in some missing types in @jest/core --- packages/jest-core/package.json | 4 +++- yarn.lock | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/jest-core/package.json b/packages/jest-core/package.json index 4d835cd058dc..adc6256996b9 100644 --- a/packages/jest-core/package.json +++ b/packages/jest-core/package.json @@ -34,7 +34,9 @@ "@types/exit": "^0.1.30", "@types/graceful-fs": "^4.1.2", "@types/micromatch": "^3.1.0", - "@types/rimraf": "^2.0.2" + "@types/p-each-series": "^1.0.0", + "@types/rimraf": "^2.0.2", + "@types/strip-ansi": "^3.0.0" }, "engines": { "node": ">= 6" diff --git a/yarn.lock b/yarn.lock index 59b677434489..a11c96da8288 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1710,6 +1710,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.24.tgz#b13564af612a22a20b5d95ca40f1bffb3af315cf" integrity sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ== +"@types/p-each-series@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/p-each-series/-/p-each-series-1.0.0.tgz#04d8a62a63a2fb82a1673ec98edabaf58dd73072" + integrity sha512-bqQAn+tAs1QwGQYNIbv8a0XT8Pzl6Z+6SVpca+vJngcvwRwws7eJj9P2rTJDpjwOSyX1iRNSlIokUlusV0mP0A== + "@types/prettier@^1.16.1": version "1.16.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.16.1.tgz#328d1c9b54402e44119398bcb6a31b7bbd606d59"