Skip to content

Commit 92e3d03

Browse files
committed
chore: migrate @jest/transform to TypeScript
1 parent 6af2f67 commit 92e3d03

File tree

12 files changed

+123
-95
lines changed

12 files changed

+123
-95
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
- `[@jest/transform]`: New package extracted from `jest-runtime` ([#7915](https://github.com/facebook/jest/pull/7915))
4444
- `[babel-plugin-jest-hoist]`: Migrate to TypeScript ([#7898](https://github.com/facebook/jest/pull/7898))
4545
- `[@jest/core]` Create new package, which is `jest-cli` minus `yargs` and `prompts` ([#7696](https://github.com/facebook/jest/pull/7696))
46+
- `[@jest/transform]`: Migrate to TypeScript ([#7918](https://github.com/facebook/jest/pull/7918))
4647

4748
### Performance
4849

packages/babel-jest/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const createTransformer = (
2727
): Transform.Transformer => {
2828
options = {
2929
...options,
30-
// @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/32955
30+
// @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33118
3131
caller: {
3232
name: 'babel-jest',
3333
supportsStaticESM: false,

packages/jest-transform/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"main": "build/index.js",
1111
"dependencies": {
1212
"@babel/core": "^7.1.0",
13+
"@jest/types": "^24.1.0",
1314
"babel-plugin-istanbul": "^5.1.0",
1415
"chalk": "^2.0.1",
1516
"convert-source-map": "^1.4.0",
@@ -26,6 +27,7 @@
2627
"devDependencies": {
2728
"@types/babel__core": "^7.0.4",
2829
"@types/convert-source-map": "^1.5.1",
30+
"@types/fast-json-stable-stringify": "^2.0.0",
2931
"@types/graceful-fs": "^4.1.2",
3032
"@types/micromatch": "^3.1.0",
3133
"@types/write-file-atomic": "^2.1.1"

packages/jest-transform/src/ScriptTransformer.js renamed to packages/jest-transform/src/ScriptTransformer.ts

+73-58
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,54 @@
33
*
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
6-
*
7-
* @flow
86
*/
97

10-
import type {Path, ProjectConfig} from 'types/Config';
11-
import type {
12-
Transformer,
13-
TransformedSource,
14-
TransformResult,
15-
} from 'types/Transform';
16-
import type {ErrorWithCode} from 'types/Errors';
17-
import type {Options} from './types';
18-
198
import crypto from 'crypto';
209
import path from 'path';
2110
import vm from 'vm';
11+
import {Config, Transform} from '@jest/types';
2212
import {createDirectory} from 'jest-util';
2313
import fs from 'graceful-fs';
2414
import {transformSync as babelTransform} from '@babel/core';
15+
// @ts-ignore: should just be `require.resolve`, but the tests mess that up
2516
import babelPluginIstanbul from 'babel-plugin-istanbul';
2617
import convertSourceMap from 'convert-source-map';
2718
import HasteMap from 'jest-haste-map';
2819
import stableStringify from 'fast-json-stable-stringify';
2920
import slash from 'slash';
30-
import {version as VERSION} from '../package.json';
31-
import shouldInstrument from './shouldInstrument';
3221
import writeFileAtomic from 'write-file-atomic';
3322
import {sync as realpath} from 'realpath-native';
23+
import {Options} from './types';
24+
import shouldInstrument from './shouldInstrument';
3425
import enhanceUnexpectedTokenMessage from './enhanceUnexpectedTokenMessage';
3526

36-
type ProjectCache = {|
37-
configString: string,
38-
ignorePatternsRegExp: ?RegExp,
39-
transformedFiles: Map<string, TransformResult>,
40-
|};
27+
type ProjectCache = {
28+
configString: string;
29+
ignorePatternsRegExp: RegExp | null;
30+
transformedFiles: Map<string, Transform.TransformResult | string>;
31+
};
32+
33+
// Use `require` to avoid TS rootDir
34+
const {version: VERSION} = require('../package.json');
4135

4236
// This data structure is used to avoid recalculating some data every time that
4337
// we need to transform a file. Since ScriptTransformer is instantiated for each
4438
// file we need to keep this object in the local scope of this module.
45-
const projectCaches: WeakMap<ProjectConfig, ProjectCache> = new WeakMap();
39+
const projectCaches: WeakMap<
40+
Config.ProjectConfig,
41+
ProjectCache
42+
> = new WeakMap();
4643

4744
// To reset the cache for specific changesets (rather than package version).
4845
const CACHE_VERSION = '1';
4946

5047
export default class ScriptTransformer {
5148
static EVAL_RESULT_VARIABLE: string;
52-
_cache: ProjectCache;
53-
_config: ProjectConfig;
54-
_transformCache: Map<Path, ?Transformer>;
49+
private _cache: ProjectCache;
50+
private _config: Config.ProjectConfig;
51+
private _transformCache: Map<Config.Path, Transform.Transformer>;
5552

56-
constructor(config: ProjectConfig) {
53+
constructor(config: Config.ProjectConfig) {
5754
this._config = config;
5855
this._transformCache = new Map();
5956

@@ -72,7 +69,11 @@ export default class ScriptTransformer {
7269
this._cache = projectCache;
7370
}
7471

75-
_getCacheKey(fileData: string, filename: Path, instrument: boolean): string {
72+
private _getCacheKey(
73+
fileData: string,
74+
filename: Config.Path,
75+
instrument: boolean,
76+
): string {
7677
const configString = this._cache.configString;
7778
const transformer = this._getTransformer(filename);
7879

@@ -99,11 +100,12 @@ export default class ScriptTransformer {
99100
}
100101
}
101102

102-
_getFileCachePath(
103-
filename: Path,
103+
private _getFileCachePath(
104+
filename: Config.Path,
104105
content: string,
105106
instrument: boolean,
106-
): Path {
107+
): Config.Path {
108+
// @ts-ignore: not properly exported (needs ESM)
107109
const baseCacheDir = HasteMap.getCacheFilePath(
108110
this._config.cacheDirectory,
109111
'jest-transform-cache-' + this._config.name,
@@ -124,7 +126,7 @@ export default class ScriptTransformer {
124126
return cachePath;
125127
}
126128

127-
_getTransformPath(filename: Path) {
129+
private _getTransformPath(filename: Config.Path) {
128130
for (let i = 0; i < this._config.transform.length; i++) {
129131
if (new RegExp(this._config.transform[i][0]).test(filename)) {
130132
return this._config.transform[i][1];
@@ -133,8 +135,8 @@ export default class ScriptTransformer {
133135
return null;
134136
}
135137

136-
_getTransformer(filename: Path) {
137-
let transform: ?Transformer;
138+
private _getTransformer(filename: Config.Path) {
139+
let transform: Transform.Transformer | null = null;
138140
if (!this._config.transform || !this._config.transform.length) {
139141
return null;
140142
}
@@ -146,8 +148,7 @@ export default class ScriptTransformer {
146148
return transformer;
147149
}
148150

149-
// $FlowFixMe
150-
transform = (require(transformPath): Transformer);
151+
transform = require(transformPath) as Transform.Transformer;
151152
if (typeof transform.createTransformer === 'function') {
152153
transform = transform.createTransformer();
153154
}
@@ -161,10 +162,11 @@ export default class ScriptTransformer {
161162
return transform;
162163
}
163164

164-
_instrumentFile(filename: Path, content: string): string {
165+
private _instrumentFile(filename: Config.Path, content: string): string {
165166
const result = babelTransform(content, {
166167
auxiliaryCommentBefore: ' istanbul ignore next ',
167168
babelrc: false,
169+
// @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33118
168170
caller: {
169171
name: '@jest/transform',
170172
supportsStaticESM: false,
@@ -185,10 +187,18 @@ export default class ScriptTransformer {
185187
],
186188
});
187189

188-
return result ? result.code : content;
190+
if (result) {
191+
const {code} = result;
192+
193+
if (code) {
194+
return code;
195+
}
196+
}
197+
198+
return content;
189199
}
190200

191-
_getRealPath(filepath: Path): Path {
201+
private _getRealPath(filepath: Config.Path): Config.Path {
192202
try {
193203
return realpath(filepath) || filepath;
194204
} catch (err) {
@@ -198,15 +208,15 @@ export default class ScriptTransformer {
198208

199209
// We don't want to expose transformers to the outside - this function is just
200210
// to warm up `this._transformCache`
201-
preloadTransformer(filepath: Path): void {
211+
preloadTransformer(filepath: Config.Path): void {
202212
this._getTransformer(filepath);
203213
}
204214

205-
transformSource(filepath: Path, content: string, instrument: boolean) {
215+
transformSource(filepath: Config.Path, content: string, instrument: boolean) {
206216
const filename = this._getRealPath(filepath);
207217
const transform = this._getTransformer(filename);
208218
const cacheFilePath = this._getFileCachePath(filename, content, instrument);
209-
let sourceMapPath = cacheFilePath + '.map';
219+
let sourceMapPath: Config.Path | null = cacheFilePath + '.map';
210220
// Ignore cache if `config.cache` is set (--no-cache)
211221
let code = this._config.cache ? readCodeCacheFile(cacheFilePath) : null;
212222

@@ -233,7 +243,7 @@ export default class ScriptTransformer {
233243
};
234244
}
235245

236-
let transformed: TransformedSource = {
246+
let transformed: Transform.TransformedSource = {
237247
code: content,
238248
map: null,
239249
};
@@ -290,20 +300,20 @@ export default class ScriptTransformer {
290300
};
291301
}
292302

293-
_transformAndBuildScript(
294-
filename: Path,
295-
options: ?Options,
303+
private _transformAndBuildScript(
304+
filename: Config.Path,
305+
options: Options | null,
296306
instrument: boolean,
297307
fileSource?: string,
298-
): TransformResult {
308+
): Transform.TransformResult {
299309
const isInternalModule = !!(options && options.isInternalModule);
300310
const isCoreModule = !!(options && options.isCoreModule);
301311
const content = stripShebang(
302312
fileSource || fs.readFileSync(filename, 'utf8'),
303313
);
304314

305315
let wrappedCode: string;
306-
let sourceMapPath: ?string = null;
316+
let sourceMapPath: string | null = null;
307317
let mapCoverage = false;
308318

309319
const willTransform =
@@ -354,13 +364,13 @@ export default class ScriptTransformer {
354364
}
355365

356366
transform(
357-
filename: Path,
367+
filename: Config.Path,
358368
options: Options,
359369
fileSource?: string,
360-
): TransformResult {
370+
): Transform.TransformResult | string {
361371
let scriptCacheKey = null;
362372
let instrument = false;
363-
let result = '';
373+
let result: Transform.TransformResult | string | undefined = '';
364374

365375
if (!options.isCoreModule) {
366376
instrument = shouldInstrument(filename, options, this._config);
@@ -386,7 +396,7 @@ export default class ScriptTransformer {
386396
return result;
387397
}
388398

389-
_shouldTransform(filename: Path): boolean {
399+
private _shouldTransform(filename: Config.Path): boolean {
390400
const ignoreRegexp = this._cache.ignorePatternsRegExp;
391401
const isIgnored = ignoreRegexp ? ignoreRegexp.test(filename) : false;
392402

@@ -396,13 +406,13 @@ export default class ScriptTransformer {
396406
}
397407
}
398408

399-
const removeFile = (path: Path) => {
409+
const removeFile = (path: Config.Path) => {
400410
try {
401411
fs.unlinkSync(path);
402412
} catch (e) {}
403413
};
404414

405-
const stripShebang = content => {
415+
const stripShebang = (content: string) => {
406416
// If the file data starts with a shebang remove it. Leaves the empty line
407417
// to keep stack trace line numbers correct.
408418
if (content.startsWith('#!')) {
@@ -419,7 +429,7 @@ const stripShebang = content => {
419429
* it right away. This is not a great system, because source map cache file
420430
* could get corrupted, out-of-sync, etc.
421431
*/
422-
function writeCodeCacheFile(cachePath: Path, code: string) {
432+
function writeCodeCacheFile(cachePath: Config.Path, code: string) {
423433
const checksum = crypto
424434
.createHash('md5')
425435
.update(code)
@@ -433,7 +443,7 @@ function writeCodeCacheFile(cachePath: Path, code: string) {
433443
* could happen if an older version of `jest-runtime` writes non-atomically to
434444
* the same cache, for example.
435445
*/
436-
function readCodeCacheFile(cachePath: Path): ?string {
446+
function readCodeCacheFile(cachePath: Config.Path): string | null {
437447
const content = readCacheFile(cachePath);
438448
if (content == null) {
439449
return null;
@@ -455,7 +465,7 @@ function readCodeCacheFile(cachePath: Path): ?string {
455465
* two processes to write to the same file at the same time. It also reduces
456466
* the risk of reading a file that's being overwritten at the same time.
457467
*/
458-
const writeCacheFile = (cachePath: Path, fileData: string) => {
468+
const writeCacheFile = (cachePath: Config.Path, fileData: string) => {
459469
try {
460470
writeFileAtomic.sync(cachePath, fileData, {encoding: 'utf8'});
461471
} catch (e) {
@@ -479,12 +489,15 @@ const writeCacheFile = (cachePath: Path, fileData: string) => {
479489
* If the target file exists we can be reasonably sure another process has
480490
* legitimately won a cache write race and ignore the error.
481491
*/
482-
const cacheWriteErrorSafeToIgnore = (e: ErrorWithCode, cachePath: Path) =>
492+
const cacheWriteErrorSafeToIgnore = (
493+
e: Error & {code: string},
494+
cachePath: Config.Path,
495+
) =>
483496
process.platform === 'win32' &&
484497
e.code === 'EPERM' &&
485498
fs.existsSync(cachePath);
486499

487-
const readCacheFile = (cachePath: Path): ?string => {
500+
const readCacheFile = (cachePath: Config.Path): string | null => {
488501
if (!fs.existsSync(cachePath)) {
489502
return null;
490503
}
@@ -510,12 +523,14 @@ const readCacheFile = (cachePath: Path): ?string => {
510523
return fileData;
511524
};
512525

513-
const getScriptCacheKey = (filename, instrument: boolean) => {
526+
const getScriptCacheKey = (filename: Config.Path, instrument: boolean) => {
514527
const mtime = fs.statSync(filename).mtime;
515528
return filename + '_' + mtime.getTime() + (instrument ? '_instrumented' : '');
516529
};
517530

518-
const calcIgnorePatternRegexp = (config: ProjectConfig): ?RegExp => {
531+
const calcIgnorePatternRegexp = (
532+
config: Config.ProjectConfig,
533+
): RegExp | null => {
519534
if (
520535
!config.transformIgnorePatterns ||
521536
config.transformIgnorePatterns.length === 0
@@ -526,7 +541,7 @@ const calcIgnorePatternRegexp = (config: ProjectConfig): ?RegExp => {
526541
return new RegExp(config.transformIgnorePatterns.join('|'));
527542
};
528543

529-
const wrap = (content, ...extras) => {
544+
const wrap = (content: string, ...extras: Array<string>) => {
530545
const globals = new Set([
531546
'module',
532547
'exports',

packages/jest-transform/src/enhanceUnexpectedTokenMessage.js renamed to packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
22

3-
// @flow
4-
53
import chalk from 'chalk';
64

75
const DOT = ' \u2022 ';

packages/jest-transform/src/index.js renamed to packages/jest-transform/src/index.ts

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
*
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
6-
*
7-
* @flow
86
*/
97

108
export {default as ScriptTransformer} from './ScriptTransformer';

0 commit comments

Comments
 (0)