3
3
*
4
4
* This source code is licensed under the MIT license found in the
5
5
* LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
6
*/
9
7
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
-
19
8
import crypto from 'crypto' ;
20
9
import path from 'path' ;
21
10
import vm from 'vm' ;
11
+ import { Config , Transform } from '@jest/types' ;
22
12
import { createDirectory } from 'jest-util' ;
23
13
import fs from 'graceful-fs' ;
24
14
import { transformSync as babelTransform } from '@babel/core' ;
15
+ // @ts -ignore: should just be `require.resolve`, but the tests mess that up
25
16
import babelPluginIstanbul from 'babel-plugin-istanbul' ;
26
17
import convertSourceMap from 'convert-source-map' ;
27
18
import HasteMap from 'jest-haste-map' ;
28
19
import stableStringify from 'fast-json-stable-stringify' ;
29
20
import slash from 'slash' ;
30
- import { version as VERSION } from '../package.json' ;
31
- import shouldInstrument from './shouldInstrument' ;
32
21
import writeFileAtomic from 'write-file-atomic' ;
33
22
import { sync as realpath } from 'realpath-native' ;
23
+ import { Options } from './types' ;
24
+ import shouldInstrument from './shouldInstrument' ;
34
25
import enhanceUnexpectedTokenMessage from './enhanceUnexpectedTokenMessage' ;
35
26
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' ) ;
41
35
42
36
// This data structure is used to avoid recalculating some data every time that
43
37
// we need to transform a file. Since ScriptTransformer is instantiated for each
44
38
// 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 ( ) ;
46
43
47
44
// To reset the cache for specific changesets (rather than package version).
48
45
const CACHE_VERSION = '1' ;
49
46
50
47
export default class ScriptTransformer {
51
48
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 > ;
55
52
56
- constructor ( config : ProjectConfig ) {
53
+ constructor ( config : Config . ProjectConfig ) {
57
54
this . _config = config ;
58
55
this . _transformCache = new Map ( ) ;
59
56
@@ -72,7 +69,11 @@ export default class ScriptTransformer {
72
69
this . _cache = projectCache ;
73
70
}
74
71
75
- _getCacheKey ( fileData : string , filename : Path , instrument : boolean ) : string {
72
+ private _getCacheKey (
73
+ fileData : string ,
74
+ filename : Config . Path ,
75
+ instrument : boolean ,
76
+ ) : string {
76
77
const configString = this . _cache . configString ;
77
78
const transformer = this . _getTransformer ( filename ) ;
78
79
@@ -99,11 +100,12 @@ export default class ScriptTransformer {
99
100
}
100
101
}
101
102
102
- _getFileCachePath (
103
- filename : Path ,
103
+ private _getFileCachePath (
104
+ filename : Config . Path ,
104
105
content : string ,
105
106
instrument : boolean ,
106
- ) : Path {
107
+ ) : Config . Path {
108
+ // @ts -ignore: not properly exported (needs ESM)
107
109
const baseCacheDir = HasteMap . getCacheFilePath (
108
110
this . _config . cacheDirectory ,
109
111
'jest-transform-cache-' + this . _config . name ,
@@ -124,7 +126,7 @@ export default class ScriptTransformer {
124
126
return cachePath ;
125
127
}
126
128
127
- _getTransformPath ( filename : Path ) {
129
+ private _getTransformPath ( filename : Config . Path ) {
128
130
for ( let i = 0 ; i < this . _config . transform . length ; i ++ ) {
129
131
if ( new RegExp ( this . _config . transform [ i ] [ 0 ] ) . test ( filename ) ) {
130
132
return this . _config . transform [ i ] [ 1 ] ;
@@ -133,8 +135,8 @@ export default class ScriptTransformer {
133
135
return null ;
134
136
}
135
137
136
- _getTransformer ( filename : Path ) {
137
- let transform : ? Transformer ;
138
+ private _getTransformer ( filename : Config . Path ) {
139
+ let transform : Transform . Transformer | null = null ;
138
140
if ( ! this . _config . transform || ! this . _config . transform . length ) {
139
141
return null ;
140
142
}
@@ -146,8 +148,7 @@ export default class ScriptTransformer {
146
148
return transformer ;
147
149
}
148
150
149
- // $FlowFixMe
150
- transform = ( require ( transformPath ) : Transformer ) ;
151
+ transform = require ( transformPath ) as Transform . Transformer ;
151
152
if ( typeof transform . createTransformer === 'function' ) {
152
153
transform = transform . createTransformer ( ) ;
153
154
}
@@ -161,10 +162,11 @@ export default class ScriptTransformer {
161
162
return transform ;
162
163
}
163
164
164
- _instrumentFile ( filename : Path , content : string ) : string {
165
+ private _instrumentFile ( filename : Config . Path , content : string ) : string {
165
166
const result = babelTransform ( content , {
166
167
auxiliaryCommentBefore : ' istanbul ignore next ' ,
167
168
babelrc : false ,
169
+ // @ts -ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33118
168
170
caller : {
169
171
name : '@jest/transform' ,
170
172
supportsStaticESM : false ,
@@ -185,10 +187,18 @@ export default class ScriptTransformer {
185
187
] ,
186
188
} ) ;
187
189
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 ;
189
199
}
190
200
191
- _getRealPath ( filepath : Path ) : Path {
201
+ private _getRealPath ( filepath : Config . Path ) : Config . Path {
192
202
try {
193
203
return realpath ( filepath ) || filepath ;
194
204
} catch ( err ) {
@@ -198,15 +208,15 @@ export default class ScriptTransformer {
198
208
199
209
// We don't want to expose transformers to the outside - this function is just
200
210
// to warm up `this._transformCache`
201
- preloadTransformer ( filepath : Path ) : void {
211
+ preloadTransformer ( filepath : Config . Path ) : void {
202
212
this . _getTransformer ( filepath ) ;
203
213
}
204
214
205
- transformSource ( filepath : Path , content : string , instrument : boolean ) {
215
+ transformSource ( filepath : Config . Path , content : string , instrument : boolean ) {
206
216
const filename = this . _getRealPath ( filepath ) ;
207
217
const transform = this . _getTransformer ( filename ) ;
208
218
const cacheFilePath = this . _getFileCachePath ( filename , content , instrument ) ;
209
- let sourceMapPath = cacheFilePath + '.map' ;
219
+ let sourceMapPath : Config . Path | null = cacheFilePath + '.map' ;
210
220
// Ignore cache if `config.cache` is set (--no-cache)
211
221
let code = this . _config . cache ? readCodeCacheFile ( cacheFilePath ) : null ;
212
222
@@ -233,7 +243,7 @@ export default class ScriptTransformer {
233
243
} ;
234
244
}
235
245
236
- let transformed : TransformedSource = {
246
+ let transformed : Transform . TransformedSource = {
237
247
code : content ,
238
248
map : null ,
239
249
} ;
@@ -290,20 +300,20 @@ export default class ScriptTransformer {
290
300
} ;
291
301
}
292
302
293
- _transformAndBuildScript (
294
- filename : Path ,
295
- options : ? Options ,
303
+ private _transformAndBuildScript (
304
+ filename : Config . Path ,
305
+ options : Options | null ,
296
306
instrument : boolean ,
297
307
fileSource ?: string ,
298
- ) : TransformResult {
308
+ ) : Transform . TransformResult {
299
309
const isInternalModule = ! ! ( options && options . isInternalModule ) ;
300
310
const isCoreModule = ! ! ( options && options . isCoreModule ) ;
301
311
const content = stripShebang (
302
312
fileSource || fs . readFileSync ( filename , 'utf8' ) ,
303
313
) ;
304
314
305
315
let wrappedCode : string ;
306
- let sourceMapPath : ? string = null ;
316
+ let sourceMapPath : string | null = null ;
307
317
let mapCoverage = false ;
308
318
309
319
const willTransform =
@@ -354,13 +364,13 @@ export default class ScriptTransformer {
354
364
}
355
365
356
366
transform (
357
- filename : Path ,
367
+ filename : Config . Path ,
358
368
options : Options ,
359
369
fileSource ?: string ,
360
- ) : TransformResult {
370
+ ) : Transform . TransformResult | string {
361
371
let scriptCacheKey = null ;
362
372
let instrument = false ;
363
- let result = '' ;
373
+ let result : Transform . TransformResult | string | undefined = '' ;
364
374
365
375
if ( ! options . isCoreModule ) {
366
376
instrument = shouldInstrument ( filename , options , this . _config ) ;
@@ -386,7 +396,7 @@ export default class ScriptTransformer {
386
396
return result ;
387
397
}
388
398
389
- _shouldTransform ( filename : Path ) : boolean {
399
+ private _shouldTransform ( filename : Config . Path ) : boolean {
390
400
const ignoreRegexp = this . _cache . ignorePatternsRegExp ;
391
401
const isIgnored = ignoreRegexp ? ignoreRegexp . test ( filename ) : false ;
392
402
@@ -396,13 +406,13 @@ export default class ScriptTransformer {
396
406
}
397
407
}
398
408
399
- const removeFile = ( path : Path ) => {
409
+ const removeFile = ( path : Config . Path ) => {
400
410
try {
401
411
fs . unlinkSync ( path ) ;
402
412
} catch ( e ) { }
403
413
} ;
404
414
405
- const stripShebang = content => {
415
+ const stripShebang = ( content : string ) => {
406
416
// If the file data starts with a shebang remove it. Leaves the empty line
407
417
// to keep stack trace line numbers correct.
408
418
if ( content . startsWith ( '#!' ) ) {
@@ -419,7 +429,7 @@ const stripShebang = content => {
419
429
* it right away. This is not a great system, because source map cache file
420
430
* could get corrupted, out-of-sync, etc.
421
431
*/
422
- function writeCodeCacheFile ( cachePath : Path , code : string ) {
432
+ function writeCodeCacheFile ( cachePath : Config . Path , code : string ) {
423
433
const checksum = crypto
424
434
. createHash ( 'md5' )
425
435
. update ( code )
@@ -433,7 +443,7 @@ function writeCodeCacheFile(cachePath: Path, code: string) {
433
443
* could happen if an older version of `jest-runtime` writes non-atomically to
434
444
* the same cache, for example.
435
445
*/
436
- function readCodeCacheFile ( cachePath : Path ) : ? string {
446
+ function readCodeCacheFile ( cachePath : Config . Path ) : string | null {
437
447
const content = readCacheFile ( cachePath ) ;
438
448
if ( content == null ) {
439
449
return null ;
@@ -455,7 +465,7 @@ function readCodeCacheFile(cachePath: Path): ?string {
455
465
* two processes to write to the same file at the same time. It also reduces
456
466
* the risk of reading a file that's being overwritten at the same time.
457
467
*/
458
- const writeCacheFile = ( cachePath : Path , fileData : string ) => {
468
+ const writeCacheFile = ( cachePath : Config . Path , fileData : string ) => {
459
469
try {
460
470
writeFileAtomic . sync ( cachePath , fileData , { encoding : 'utf8' } ) ;
461
471
} catch ( e ) {
@@ -479,12 +489,15 @@ const writeCacheFile = (cachePath: Path, fileData: string) => {
479
489
* If the target file exists we can be reasonably sure another process has
480
490
* legitimately won a cache write race and ignore the error.
481
491
*/
482
- const cacheWriteErrorSafeToIgnore = ( e : ErrorWithCode , cachePath : Path ) =>
492
+ const cacheWriteErrorSafeToIgnore = (
493
+ e : Error & { code : string } ,
494
+ cachePath : Config . Path ,
495
+ ) =>
483
496
process . platform === 'win32' &&
484
497
e . code === 'EPERM' &&
485
498
fs . existsSync ( cachePath ) ;
486
499
487
- const readCacheFile = ( cachePath : Path ) : ? string => {
500
+ const readCacheFile = ( cachePath : Config . Path ) : string | null => {
488
501
if ( ! fs . existsSync ( cachePath ) ) {
489
502
return null ;
490
503
}
@@ -510,12 +523,14 @@ const readCacheFile = (cachePath: Path): ?string => {
510
523
return fileData ;
511
524
} ;
512
525
513
- const getScriptCacheKey = ( filename , instrument : boolean ) => {
526
+ const getScriptCacheKey = ( filename : Config . Path , instrument : boolean ) => {
514
527
const mtime = fs . statSync ( filename ) . mtime ;
515
528
return filename + '_' + mtime . getTime ( ) + ( instrument ? '_instrumented' : '' ) ;
516
529
} ;
517
530
518
- const calcIgnorePatternRegexp = ( config : ProjectConfig ) : ?RegExp => {
531
+ const calcIgnorePatternRegexp = (
532
+ config : Config . ProjectConfig ,
533
+ ) : RegExp | null => {
519
534
if (
520
535
! config . transformIgnorePatterns ||
521
536
config . transformIgnorePatterns . length === 0
@@ -526,7 +541,7 @@ const calcIgnorePatternRegexp = (config: ProjectConfig): ?RegExp => {
526
541
return new RegExp ( config . transformIgnorePatterns . join ( '|' ) ) ;
527
542
} ;
528
543
529
- const wrap = ( content , ...extras ) => {
544
+ const wrap = ( content : string , ...extras : Array < string > ) => {
530
545
const globals = new Set ( [
531
546
'module' ,
532
547
'exports' ,
0 commit comments