747 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			747 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| Object.defineProperty(exports, '__esModule', {
 | |
|   value: true
 | |
| });
 | |
| exports.default = void 0;
 | |
| 
 | |
| function _crypto() {
 | |
|   const data = _interopRequireDefault(require('crypto'));
 | |
| 
 | |
|   _crypto = function _crypto() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _path() {
 | |
|   const data = _interopRequireDefault(require('path'));
 | |
| 
 | |
|   _path = function _path() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _vm() {
 | |
|   const data = _interopRequireDefault(require('vm'));
 | |
| 
 | |
|   _vm = function _vm() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _jestUtil() {
 | |
|   const data = require('jest-util');
 | |
| 
 | |
|   _jestUtil = function _jestUtil() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _gracefulFs() {
 | |
|   const data = _interopRequireDefault(require('graceful-fs'));
 | |
| 
 | |
|   _gracefulFs = function _gracefulFs() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _core() {
 | |
|   const data = require('@babel/core');
 | |
| 
 | |
|   _core = function _core() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _babelPluginIstanbul() {
 | |
|   const data = _interopRequireDefault(require('babel-plugin-istanbul'));
 | |
| 
 | |
|   _babelPluginIstanbul = function _babelPluginIstanbul() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _convertSourceMap() {
 | |
|   const data = _interopRequireDefault(require('convert-source-map'));
 | |
| 
 | |
|   _convertSourceMap = function _convertSourceMap() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _jestHasteMap() {
 | |
|   const data = _interopRequireDefault(require('jest-haste-map'));
 | |
| 
 | |
|   _jestHasteMap = function _jestHasteMap() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _fastJsonStableStringify() {
 | |
|   const data = _interopRequireDefault(require('fast-json-stable-stringify'));
 | |
| 
 | |
|   _fastJsonStableStringify = function _fastJsonStableStringify() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _slash() {
 | |
|   const data = _interopRequireDefault(require('slash'));
 | |
| 
 | |
|   _slash = function _slash() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _writeFileAtomic() {
 | |
|   const data = _interopRequireDefault(require('write-file-atomic'));
 | |
| 
 | |
|   _writeFileAtomic = function _writeFileAtomic() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _realpathNative() {
 | |
|   const data = require('realpath-native');
 | |
| 
 | |
|   _realpathNative = function _realpathNative() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| var _shouldInstrument = _interopRequireDefault(require('./shouldInstrument'));
 | |
| 
 | |
| var _enhanceUnexpectedTokenMessage = _interopRequireDefault(
 | |
|   require('./enhanceUnexpectedTokenMessage')
 | |
| );
 | |
| 
 | |
| function _interopRequireDefault(obj) {
 | |
|   return obj && obj.__esModule ? obj : {default: obj};
 | |
| }
 | |
| 
 | |
| function _defineProperty(obj, key, value) {
 | |
|   if (key in obj) {
 | |
|     Object.defineProperty(obj, key, {
 | |
|       value: value,
 | |
|       enumerable: true,
 | |
|       configurable: true,
 | |
|       writable: true
 | |
|     });
 | |
|   } else {
 | |
|     obj[key] = value;
 | |
|   }
 | |
|   return obj;
 | |
| }
 | |
| 
 | |
| // Use `require` to avoid TS rootDir
 | |
| const _require = require('../package.json'),
 | |
|   VERSION = _require.version; // 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 = new WeakMap(); // To reset the cache for specific changesets (rather than package version).
 | |
| 
 | |
| const CACHE_VERSION = '1';
 | |
| 
 | |
| class ScriptTransformer {
 | |
|   constructor(config) {
 | |
|     _defineProperty(this, '_cache', void 0);
 | |
| 
 | |
|     _defineProperty(this, '_config', void 0);
 | |
| 
 | |
|     _defineProperty(this, '_transformCache', void 0);
 | |
| 
 | |
|     this._config = config;
 | |
|     this._transformCache = new Map();
 | |
|     let projectCache = projectCaches.get(config);
 | |
| 
 | |
|     if (!projectCache) {
 | |
|       projectCache = {
 | |
|         configString: (0, _fastJsonStableStringify().default)(this._config),
 | |
|         ignorePatternsRegExp: calcIgnorePatternRegExp(this._config),
 | |
|         transformRegExp: calcTransformRegExp(this._config),
 | |
|         transformedFiles: new Map()
 | |
|       };
 | |
|       projectCaches.set(config, projectCache);
 | |
|     }
 | |
| 
 | |
|     this._cache = projectCache;
 | |
|   }
 | |
| 
 | |
|   _getCacheKey(fileData, filename, instrument) {
 | |
|     const configString = this._cache.configString;
 | |
| 
 | |
|     const transformer = this._getTransformer(filename);
 | |
| 
 | |
|     if (transformer && typeof transformer.getCacheKey === 'function') {
 | |
|       return _crypto()
 | |
|         .default.createHash('md5')
 | |
|         .update(
 | |
|           transformer.getCacheKey(fileData, filename, configString, {
 | |
|             config: this._config,
 | |
|             instrument,
 | |
|             rootDir: this._config.rootDir
 | |
|           })
 | |
|         )
 | |
|         .update(CACHE_VERSION)
 | |
|         .digest('hex');
 | |
|     } else {
 | |
|       return _crypto()
 | |
|         .default.createHash('md5')
 | |
|         .update(fileData)
 | |
|         .update(configString)
 | |
|         .update(instrument ? 'instrument' : '')
 | |
|         .update(filename)
 | |
|         .update(CACHE_VERSION)
 | |
|         .digest('hex');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   _getFileCachePath(filename, content, instrument) {
 | |
|     const baseCacheDir = _jestHasteMap().default.getCacheFilePath(
 | |
|       this._config.cacheDirectory,
 | |
|       'jest-transform-cache-' + this._config.name,
 | |
|       VERSION
 | |
|     );
 | |
| 
 | |
|     const cacheKey = this._getCacheKey(content, filename, instrument); // Create sub folders based on the cacheKey to avoid creating one
 | |
|     // directory with many files.
 | |
| 
 | |
|     const cacheDir = _path().default.join(
 | |
|       baseCacheDir,
 | |
|       cacheKey[0] + cacheKey[1]
 | |
|     );
 | |
| 
 | |
|     const cacheFilenamePrefix = _path()
 | |
|       .default.basename(filename, _path().default.extname(filename))
 | |
|       .replace(/\W/g, '');
 | |
| 
 | |
|     const cachePath = (0, _slash().default)(
 | |
|       _path().default.join(cacheDir, cacheFilenamePrefix + '_' + cacheKey)
 | |
|     );
 | |
|     (0, _jestUtil().createDirectory)(cacheDir);
 | |
|     return cachePath;
 | |
|   }
 | |
| 
 | |
|   _getTransformPath(filename) {
 | |
|     const transformRegExp = this._cache.transformRegExp;
 | |
| 
 | |
|     if (!transformRegExp) {
 | |
|       return undefined;
 | |
|     }
 | |
| 
 | |
|     for (let i = 0; i < transformRegExp.length; i++) {
 | |
|       if (transformRegExp[i][0].test(filename)) {
 | |
|         return transformRegExp[i][1];
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return undefined;
 | |
|   }
 | |
| 
 | |
|   _getTransformer(filename) {
 | |
|     let transform = null;
 | |
| 
 | |
|     if (!this._config.transform || !this._config.transform.length) {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     const transformPath = this._getTransformPath(filename);
 | |
| 
 | |
|     if (transformPath) {
 | |
|       const transformer = this._transformCache.get(transformPath);
 | |
| 
 | |
|       if (transformer != null) {
 | |
|         return transformer;
 | |
|       }
 | |
| 
 | |
|       transform = require(transformPath);
 | |
| 
 | |
|       if (typeof transform.createTransformer === 'function') {
 | |
|         transform = transform.createTransformer();
 | |
|       }
 | |
| 
 | |
|       if (typeof transform.process !== 'function') {
 | |
|         throw new TypeError(
 | |
|           'Jest: a transform must export a `process` function.'
 | |
|         );
 | |
|       }
 | |
| 
 | |
|       this._transformCache.set(transformPath, transform);
 | |
|     }
 | |
| 
 | |
|     return transform;
 | |
|   }
 | |
| 
 | |
|   _instrumentFile(filename, content) {
 | |
|     const result = (0, _core().transformSync)(content, {
 | |
|       auxiliaryCommentBefore: ' istanbul ignore next ',
 | |
|       babelrc: false,
 | |
|       caller: {
 | |
|         name: '@jest/transform',
 | |
|         supportsStaticESM: false
 | |
|       },
 | |
|       configFile: false,
 | |
|       filename,
 | |
|       plugins: [
 | |
|         [
 | |
|           _babelPluginIstanbul().default,
 | |
|           {
 | |
|             compact: false,
 | |
|             // files outside `cwd` will not be instrumented
 | |
|             cwd: this._config.rootDir,
 | |
|             exclude: [],
 | |
|             useInlineSourceMaps: false
 | |
|           }
 | |
|         ]
 | |
|       ]
 | |
|     });
 | |
| 
 | |
|     if (result) {
 | |
|       const code = result.code;
 | |
| 
 | |
|       if (code) {
 | |
|         return code;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return content;
 | |
|   }
 | |
| 
 | |
|   _getRealPath(filepath) {
 | |
|     try {
 | |
|       return (0, _realpathNative().sync)(filepath) || filepath;
 | |
|     } catch (err) {
 | |
|       return filepath;
 | |
|     }
 | |
|   } // We don't want to expose transformers to the outside - this function is just
 | |
|   // to warm up `this._transformCache`
 | |
| 
 | |
|   preloadTransformer(filepath) {
 | |
|     this._getTransformer(filepath);
 | |
|   }
 | |
| 
 | |
|   transformSource(filepath, content, instrument) {
 | |
|     const filename = this._getRealPath(filepath);
 | |
| 
 | |
|     const transform = this._getTransformer(filename);
 | |
| 
 | |
|     const cacheFilePath = this._getFileCachePath(filename, content, instrument);
 | |
| 
 | |
|     let sourceMapPath = cacheFilePath + '.map'; // Ignore cache if `config.cache` is set (--no-cache)
 | |
| 
 | |
|     let code = this._config.cache ? readCodeCacheFile(cacheFilePath) : null;
 | |
|     const shouldCallTransform = transform && this.shouldTransform(filename); // That means that the transform has a custom instrumentation
 | |
|     // logic and will handle it based on `config.collectCoverage` option
 | |
| 
 | |
|     const transformWillInstrument =
 | |
|       shouldCallTransform && transform && transform.canInstrument; // If we handle the coverage instrumentation, we should try to map code
 | |
|     // coverage against original source with any provided source map
 | |
| 
 | |
|     const mapCoverage = instrument && !transformWillInstrument;
 | |
| 
 | |
|     if (code) {
 | |
|       // This is broken: we return the code, and a path for the source map
 | |
|       // directly from the cache. But, nothing ensures the source map actually
 | |
|       // matches that source code. They could have gotten out-of-sync in case
 | |
|       // two separate processes write concurrently to the same cache files.
 | |
|       return {
 | |
|         code,
 | |
|         mapCoverage,
 | |
|         sourceMapPath
 | |
|       };
 | |
|     }
 | |
| 
 | |
|     let transformed = {
 | |
|       code: content,
 | |
|       map: null
 | |
|     };
 | |
| 
 | |
|     if (transform && shouldCallTransform) {
 | |
|       const processed = transform.process(content, filename, this._config, {
 | |
|         instrument
 | |
|       });
 | |
| 
 | |
|       if (typeof processed === 'string') {
 | |
|         transformed.code = processed;
 | |
|       } else if (processed != null && typeof processed.code === 'string') {
 | |
|         transformed = processed;
 | |
|       } else {
 | |
|         throw new TypeError(
 | |
|           "Jest: a transform's `process` function must return a string, " +
 | |
|             'or an object with `code` key containing this string.'
 | |
|         );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (!transformed.map) {
 | |
|       //Could be a potential freeze here.
 | |
|       //See: https://github.com/facebook/jest/pull/5177#discussion_r158883570
 | |
|       const inlineSourceMap = _convertSourceMap().default.fromSource(
 | |
|         transformed.code
 | |
|       );
 | |
| 
 | |
|       if (inlineSourceMap) {
 | |
|         transformed.map = inlineSourceMap.toJSON();
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (!transformWillInstrument && instrument) {
 | |
|       code = this._instrumentFile(filename, transformed.code);
 | |
|     } else {
 | |
|       code = transformed.code;
 | |
|     }
 | |
| 
 | |
|     if (transformed.map) {
 | |
|       const sourceMapContent =
 | |
|         typeof transformed.map === 'string'
 | |
|           ? transformed.map
 | |
|           : JSON.stringify(transformed.map);
 | |
|       writeCacheFile(sourceMapPath, sourceMapContent);
 | |
|     } else {
 | |
|       sourceMapPath = null;
 | |
|     }
 | |
| 
 | |
|     writeCodeCacheFile(cacheFilePath, code);
 | |
|     return {
 | |
|       code,
 | |
|       mapCoverage,
 | |
|       sourceMapPath
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   _transformAndBuildScript(filename, options, instrument, fileSource) {
 | |
|     const isInternalModule = !!(options && options.isInternalModule);
 | |
|     const isCoreModule = !!(options && options.isCoreModule);
 | |
|     const content = stripShebang(
 | |
|       fileSource || _gracefulFs().default.readFileSync(filename, 'utf8')
 | |
|     );
 | |
|     let wrappedCode;
 | |
|     let sourceMapPath = null;
 | |
|     let mapCoverage = false;
 | |
|     const willTransform =
 | |
|       !isInternalModule &&
 | |
|       !isCoreModule &&
 | |
|       (this.shouldTransform(filename) || instrument);
 | |
| 
 | |
|     try {
 | |
|       const extraGlobals = (options && options.extraGlobals) || [];
 | |
| 
 | |
|       if (willTransform) {
 | |
|         const transformedSource = this.transformSource(
 | |
|           filename,
 | |
|           content,
 | |
|           instrument
 | |
|         );
 | |
|         wrappedCode = wrap(transformedSource.code, ...extraGlobals);
 | |
|         sourceMapPath = transformedSource.sourceMapPath;
 | |
|         mapCoverage = transformedSource.mapCoverage;
 | |
|       } else {
 | |
|         wrappedCode = wrap(content, ...extraGlobals);
 | |
|       }
 | |
| 
 | |
|       return {
 | |
|         mapCoverage,
 | |
|         script: new (_vm()).default.Script(wrappedCode, {
 | |
|           displayErrors: true,
 | |
|           filename: isCoreModule ? 'jest-nodejs-core-' + filename : filename
 | |
|         }),
 | |
|         sourceMapPath
 | |
|       };
 | |
|     } catch (e) {
 | |
|       if (e.codeFrame) {
 | |
|         e.stack = e.message + '\n' + e.codeFrame;
 | |
|       }
 | |
| 
 | |
|       if (
 | |
|         e instanceof SyntaxError &&
 | |
|         e.message.includes('Unexpected token') &&
 | |
|         !e.message.includes(' expected')
 | |
|       ) {
 | |
|         throw (0, _enhanceUnexpectedTokenMessage.default)(e);
 | |
|       }
 | |
| 
 | |
|       throw e;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   transform(filename, options, fileSource) {
 | |
|     let scriptCacheKey = undefined;
 | |
|     let instrument = false;
 | |
| 
 | |
|     if (!options.isCoreModule) {
 | |
|       instrument = (0, _shouldInstrument.default)(
 | |
|         filename,
 | |
|         options,
 | |
|         this._config
 | |
|       );
 | |
|       scriptCacheKey = getScriptCacheKey(filename, instrument);
 | |
| 
 | |
|       const result = this._cache.transformedFiles.get(scriptCacheKey);
 | |
| 
 | |
|       if (result) {
 | |
|         return result;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     const result = this._transformAndBuildScript(
 | |
|       filename,
 | |
|       options,
 | |
|       instrument,
 | |
|       fileSource
 | |
|     );
 | |
| 
 | |
|     if (scriptCacheKey) {
 | |
|       this._cache.transformedFiles.set(scriptCacheKey, result);
 | |
|     }
 | |
| 
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   transformJson(filename, options, fileSource) {
 | |
|     const isInternalModule = options.isInternalModule;
 | |
|     const isCoreModule = options.isCoreModule;
 | |
|     const willTransform =
 | |
|       !isInternalModule && !isCoreModule && this.shouldTransform(filename);
 | |
| 
 | |
|     if (willTransform) {
 | |
|       const _this$transformSource = this.transformSource(
 | |
|           filename,
 | |
|           fileSource,
 | |
|           false
 | |
|         ),
 | |
|         transformedJsonSource = _this$transformSource.code;
 | |
| 
 | |
|       return transformedJsonSource;
 | |
|     }
 | |
| 
 | |
|     return fileSource;
 | |
|   }
 | |
|   /**
 | |
|    * @deprecated use `this.shouldTransform` instead
 | |
|    */
 | |
|   // @ts-ignore: Unused and private - remove in Jest 25
 | |
| 
 | |
|   _shouldTransform(filename) {
 | |
|     return this.shouldTransform(filename);
 | |
|   }
 | |
| 
 | |
|   shouldTransform(filename) {
 | |
|     const ignoreRegexp = this._cache.ignorePatternsRegExp;
 | |
|     const isIgnored = ignoreRegexp ? ignoreRegexp.test(filename) : false;
 | |
|     return (
 | |
|       !!this._config.transform && !!this._config.transform.length && !isIgnored
 | |
|     );
 | |
|   }
 | |
| }
 | |
| 
 | |
| exports.default = ScriptTransformer;
 | |
| 
 | |
| _defineProperty(ScriptTransformer, 'EVAL_RESULT_VARIABLE', void 0);
 | |
| 
 | |
| const removeFile = path => {
 | |
|   try {
 | |
|     _gracefulFs().default.unlinkSync(path);
 | |
|   } catch (e) {}
 | |
| };
 | |
| 
 | |
| const stripShebang = content => {
 | |
|   // If the file data starts with a shebang remove it. Leaves the empty line
 | |
|   // to keep stack trace line numbers correct.
 | |
|   if (content.startsWith('#!')) {
 | |
|     return content.replace(/^#!.*/, '');
 | |
|   } else {
 | |
|     return content;
 | |
|   }
 | |
| };
 | |
| /**
 | |
|  * This is like `writeCacheFile` but with an additional sanity checksum. We
 | |
|  * cannot use the same technique for source maps because we expose source map
 | |
|  * cache file paths directly to callsites, with the expectation they can read
 | |
|  * it right away. This is not a great system, because source map cache file
 | |
|  * could get corrupted, out-of-sync, etc.
 | |
|  */
 | |
| 
 | |
| function writeCodeCacheFile(cachePath, code) {
 | |
|   const checksum = _crypto()
 | |
|     .default.createHash('md5')
 | |
|     .update(code)
 | |
|     .digest('hex');
 | |
| 
 | |
|   writeCacheFile(cachePath, checksum + '\n' + code);
 | |
| }
 | |
| /**
 | |
|  * Read counterpart of `writeCodeCacheFile`. We verify that the content of the
 | |
|  * file matches the checksum, in case some kind of corruption happened. This
 | |
|  * could happen if an older version of `jest-runtime` writes non-atomically to
 | |
|  * the same cache, for example.
 | |
|  */
 | |
| 
 | |
| function readCodeCacheFile(cachePath) {
 | |
|   const content = readCacheFile(cachePath);
 | |
| 
 | |
|   if (content == null) {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   const code = content.substr(33);
 | |
| 
 | |
|   const checksum = _crypto()
 | |
|     .default.createHash('md5')
 | |
|     .update(code)
 | |
|     .digest('hex');
 | |
| 
 | |
|   if (checksum === content.substr(0, 32)) {
 | |
|     return code;
 | |
|   }
 | |
| 
 | |
|   return null;
 | |
| }
 | |
| /**
 | |
|  * Writing to the cache atomically relies on 'rename' being atomic on most
 | |
|  * file systems. Doing atomic write reduces the risk of corruption by avoiding
 | |
|  * 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, fileData) => {
 | |
|   try {
 | |
|     _writeFileAtomic().default.sync(cachePath, fileData, {
 | |
|       encoding: 'utf8'
 | |
|     });
 | |
|   } catch (e) {
 | |
|     if (cacheWriteErrorSafeToIgnore(e, cachePath)) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     e.message =
 | |
|       'jest: failed to cache transform results in: ' +
 | |
|       cachePath +
 | |
|       '\nFailure message: ' +
 | |
|       e.message;
 | |
|     removeFile(cachePath);
 | |
|     throw e;
 | |
|   }
 | |
| };
 | |
| /**
 | |
|  * On Windows, renames are not atomic, leading to EPERM exceptions when two
 | |
|  * processes attempt to rename to the same target file at the same time.
 | |
|  * 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, cachePath) =>
 | |
|   process.platform === 'win32' &&
 | |
|   e.code === 'EPERM' &&
 | |
|   _gracefulFs().default.existsSync(cachePath);
 | |
| 
 | |
| const readCacheFile = cachePath => {
 | |
|   if (!_gracefulFs().default.existsSync(cachePath)) {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   let fileData;
 | |
| 
 | |
|   try {
 | |
|     fileData = _gracefulFs().default.readFileSync(cachePath, 'utf8');
 | |
|   } catch (e) {
 | |
|     e.message =
 | |
|       'jest: failed to read cache file: ' +
 | |
|       cachePath +
 | |
|       '\nFailure message: ' +
 | |
|       e.message;
 | |
|     removeFile(cachePath);
 | |
|     throw e;
 | |
|   }
 | |
| 
 | |
|   if (fileData == null) {
 | |
|     // We must have somehow created the file but failed to write to it,
 | |
|     // let's delete it and retry.
 | |
|     removeFile(cachePath);
 | |
|   }
 | |
| 
 | |
|   return fileData;
 | |
| };
 | |
| 
 | |
| const getScriptCacheKey = (filename, instrument) => {
 | |
|   const mtime = _gracefulFs().default.statSync(filename).mtime;
 | |
| 
 | |
|   return filename + '_' + mtime.getTime() + (instrument ? '_instrumented' : '');
 | |
| };
 | |
| 
 | |
| const calcIgnorePatternRegExp = config => {
 | |
|   if (
 | |
|     !config.transformIgnorePatterns ||
 | |
|     config.transformIgnorePatterns.length === 0
 | |
|   ) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   return new RegExp(config.transformIgnorePatterns.join('|'));
 | |
| };
 | |
| 
 | |
| const calcTransformRegExp = config => {
 | |
|   if (!config.transform.length) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   const transformRegexp = [];
 | |
| 
 | |
|   for (let i = 0; i < config.transform.length; i++) {
 | |
|     transformRegexp.push([
 | |
|       new RegExp(config.transform[i][0]),
 | |
|       config.transform[i][1]
 | |
|     ]);
 | |
|   }
 | |
| 
 | |
|   return transformRegexp;
 | |
| };
 | |
| 
 | |
| const wrap = (content, ...extras) => {
 | |
|   const globals = new Set([
 | |
|     'module',
 | |
|     'exports',
 | |
|     'require',
 | |
|     '__dirname',
 | |
|     '__filename',
 | |
|     'global',
 | |
|     'jest',
 | |
|     ...extras
 | |
|   ]);
 | |
|   return (
 | |
|     '({"' +
 | |
|     ScriptTransformer.EVAL_RESULT_VARIABLE +
 | |
|     `":function(${Array.from(globals).join(',')}){` +
 | |
|     content +
 | |
|     '\n}});'
 | |
|   );
 | |
| }; // TODO: Can this be added to the static property?
 | |
| 
 | |
| ScriptTransformer.EVAL_RESULT_VARIABLE = 'Object.<anonymous>';
 |