| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390 | 'use strict';function _child_process() {  const data = require('child_process');  _child_process = function _child_process() {    return data;  };  return data;}function _crypto() {  const data = _interopRequireDefault(require('crypto'));  _crypto = function _crypto() {    return data;  };  return data;}function _events() {  const data = _interopRequireDefault(require('events'));  _events = function _events() {    return data;  };  return data;}function _os() {  const data = _interopRequireDefault(require('os'));  _os = function _os() {    return data;  };  return data;}function _path() {  const data = _interopRequireDefault(require('path'));  _path = function _path() {    return data;  };  return data;}function _sane() {  const data = _interopRequireDefault(require('sane'));  _sane = function _sane() {    return data;  };  return data;}function _invariant() {  const data = _interopRequireDefault(require('invariant'));  _invariant = function _invariant() {    return data;  };  return data;}function _jestSerializer() {  const data = _interopRequireDefault(require('jest-serializer'));  _jestSerializer = function _jestSerializer() {    return data;  };  return data;}function _jestWorker() {  const data = _interopRequireDefault(require('jest-worker'));  _jestWorker = function _jestWorker() {    return data;  };  return data;}var _worker = require('./worker');var _getMockName = _interopRequireDefault(require('./getMockName'));var _getPlatformExtension = _interopRequireDefault(  require('./lib/getPlatformExtension'));var _constants = _interopRequireDefault(require('./constants'));var _HasteFS = _interopRequireDefault(require('./HasteFS'));var _ModuleMap = _interopRequireDefault(require('./ModuleMap'));var _node = _interopRequireDefault(require('./crawlers/node'));var _normalizePathSep = _interopRequireDefault(  require('./lib/normalizePathSep'));var _watchman = _interopRequireDefault(require('./crawlers/watchman'));var _WatchmanWatcher = _interopRequireDefault(require('./lib/WatchmanWatcher'));var _FSEventsWatcher = _interopRequireDefault(require('./lib/FSEventsWatcher'));var fastPath = _interopRequireWildcard(require('./lib/fast_path'));function _interopRequireWildcard(obj) {  if (obj && obj.__esModule) {    return obj;  } else {    var newObj = {};    if (obj != null) {      for (var key in obj) {        if (Object.prototype.hasOwnProperty.call(obj, key)) {          var desc =            Object.defineProperty && Object.getOwnPropertyDescriptor              ? Object.getOwnPropertyDescriptor(obj, key)              : {};          if (desc.get || desc.set) {            Object.defineProperty(newObj, key, desc);          } else {            newObj[key] = obj[key];          }        }      }    }    newObj.default = obj;    return newObj;  }}function _interopRequireDefault(obj) {  return obj && obj.__esModule ? obj : {default: obj};}function _slicedToArray(arr, i) {  return (    _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest()  );}function _nonIterableRest() {  throw new TypeError('Invalid attempt to destructure non-iterable instance');}function _iterableToArrayLimit(arr, i) {  var _arr = [];  var _n = true;  var _d = false;  var _e = undefined;  try {    for (      var _i = arr[Symbol.iterator](), _s;      !(_n = (_s = _i.next()).done);      _n = true    ) {      _arr.push(_s.value);      if (i && _arr.length === i) break;    }  } catch (err) {    _d = true;    _e = err;  } finally {    try {      if (!_n && _i['return'] != null) _i['return']();    } finally {      if (_d) throw _e;    }  }  return _arr;}function _arrayWithHoles(arr) {  if (Array.isArray(arr)) return arr;}function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {  try {    var info = gen[key](arg);    var value = info.value;  } catch (error) {    reject(error);    return;  }  if (info.done) {    resolve(value);  } else {    Promise.resolve(value).then(_next, _throw);  }}function _asyncToGenerator(fn) {  return function() {    var self = this,      args = arguments;    return new Promise(function(resolve, reject) {      var gen = fn.apply(self, args);      function _next(value) {        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);      }      function _throw(err) {        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);      }      _next(undefined);    });  };}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;}const CHANGE_INTERVAL = 30;const MAX_WAIT_TIME = 240000;const NODE_MODULES = _path().default.sep + 'node_modules' + _path().default.sep;const PACKAGE_JSON = _path().default.sep + 'package.json'; // TypeScript doesn't like us importing from outside `rootDir`, but it doesn't// understand `require`.const _require = require('../package.json'),  VERSION = _require.version;const canUseWatchman = (() => {  try {    (0, _child_process().execSync)('watchman --version', {      stdio: ['ignore']    });    return true;  } catch (e) {}  return false;})();const escapePathSeparator = string =>  _path().default.sep === '\\' ? string.replace(/(\/|\\)/g, '\\\\') : string;const getWhiteList = list => {  if (list && list.length) {    const newList = list.map(item =>      escapePathSeparator(item.replace(/(\/)/g, _path().default.sep))    );    return new RegExp(      '(' +        escapePathSeparator(NODE_MODULES) +        '(?:' +        newList.join('|') +        ')(?=$|' +        escapePathSeparator(_path().default.sep) +        '))',      'g'    );  }  return null;};/** * HasteMap is a JavaScript implementation of Facebook's haste module system. * * This implementation is inspired by https://github.com/facebook/node-haste * and was built with for high-performance in large code repositories with * hundreds of thousands of files. This implementation is scalable and provides * predictable performance. * * Because the haste map creation and synchronization is critical to startup * performance and most tasks are blocked by I/O this class makes heavy use of * synchronous operations. It uses worker processes for parallelizing file * access and metadata extraction. * * The data structures created by `jest-haste-map` can be used directly from the * cache without further processing. The metadata objects in the `files` and * `map` objects contain cross-references: a metadata object from one can look * up the corresponding metadata object in the other map. Note that in most * projects, the number of files will be greater than the number of haste * modules one module can refer to many files based on platform extensions. * * type HasteMap = { *   clocks: WatchmanClocks, *   files: {[filepath: string]: FileMetaData}, *   map: {[id: string]: ModuleMapItem}, *   mocks: {[id: string]: string}, * } * * // Watchman clocks are used for query synchronization and file system deltas. * type WatchmanClocks = {[filepath: string]: string}; * * type FileMetaData = { *   id: ?string, // used to look up module metadata objects in `map`. *   mtime: number, // check for outdated files. *   size: number, // size of the file in bytes. *   visited: boolean, // whether the file has been parsed or not. *   dependencies: Array<string>, // all relative dependencies of this file. *   sha1: ?string, // SHA-1 of the file, if requested via options. * }; * * // Modules can be targeted to a specific platform based on the file name. * // Example: platform.ios.js and Platform.android.js will both map to the same * // `Platform` module. The platform should be specified during resolution. * type ModuleMapItem = {[platform: string]: ModuleMetaData}; * * // * type ModuleMetaData = { *   path: string, // the path to look up the file object in `files`. *   type: string, // the module type (either `package` or `module`). * }; * * Note that the data structures described above are conceptual only. The actual * implementation uses arrays and constant keys for metadata storage. Instead of * `{id: 'flatMap', mtime: 3421, size: 42, visited: true, dependencies: []}` the real * representation is similar to `['flatMap', 3421, 42, 1, []]` to save storage space * and reduce parse and write time of a big JSON blob. * * The HasteMap is created as follows: *  1. read data from the cache or create an empty structure. * *  2. crawl the file system. *     * empty cache: crawl the entire file system. *     * cache available: *       * if watchman is available: get file system delta changes. *       * if watchman is unavailable: crawl the entire file system. *     * build metadata objects for every file. This builds the `files` part of *       the `HasteMap`. * *  3. parse and extract metadata from changed files. *     * this is done in parallel over worker processes to improve performance. *     * the worst case is to parse all files. *     * the best case is no file system access and retrieving all data from *       the cache. *     * the average case is a small number of changed files. * *  4. serialize the new `HasteMap` in a cache file. *     Worker processes can directly access the cache through `HasteMap.read()`. * *//* eslint-disable-next-line no-redeclare */class HasteMap extends _events().default {  constructor(options) {    super();    _defineProperty(this, '_buildPromise', void 0);    _defineProperty(this, '_cachePath', void 0);    _defineProperty(this, '_changeInterval', void 0);    _defineProperty(this, '_console', void 0);    _defineProperty(this, '_options', void 0);    _defineProperty(this, '_watchers', void 0);    _defineProperty(this, '_whitelist', void 0);    _defineProperty(this, '_worker', void 0);    this._options = {      cacheDirectory: options.cacheDirectory || _os().default.tmpdir(),      computeDependencies:        options.computeDependencies === undefined          ? true          : options.computeDependencies,      computeSha1: options.computeSha1 || false,      dependencyExtractor: options.dependencyExtractor,      extensions: options.extensions,      forceNodeFilesystemAPI: !!options.forceNodeFilesystemAPI,      hasteImplModulePath: options.hasteImplModulePath,      ignorePattern: options.ignorePattern,      mapper: options.mapper,      maxWorkers: options.maxWorkers,      mocksPattern: options.mocksPattern        ? new RegExp(options.mocksPattern)        : null,      name: options.name,      platforms: options.platforms,      resetCache: options.resetCache,      retainAllFiles: options.retainAllFiles,      rootDir: options.rootDir,      roots: Array.from(new Set(options.roots)),      skipPackageJson: !!options.skipPackageJson,      throwOnModuleCollision: !!options.throwOnModuleCollision,      useWatchman: options.useWatchman == null ? true : options.useWatchman,      watch: !!options.watch    };    this._console = options.console || global.console;    if (options.ignorePattern && !(options.ignorePattern instanceof RegExp)) {      this._console.warn(        'jest-haste-map: the `ignorePattern` options as a function is being ' +          'deprecated. Provide a RegExp instead. See https://github.com/facebook/jest/pull/4063.'      );    }    const rootDirHash = _crypto()      .default.createHash('md5')      .update(options.rootDir)      .digest('hex');    let hasteImplHash = '';    let dependencyExtractorHash = '';    if (options.hasteImplModulePath) {      const hasteImpl = require(options.hasteImplModulePath);      if (hasteImpl.getCacheKey) {        hasteImplHash = String(hasteImpl.getCacheKey());      }    }    if (options.dependencyExtractor) {      const dependencyExtractor = require(options.dependencyExtractor);      if (dependencyExtractor.getCacheKey) {        dependencyExtractorHash = String(dependencyExtractor.getCacheKey());      }    }    this._cachePath = HasteMap.getCacheFilePath(      this._options.cacheDirectory,      `haste-map-${this._options.name}-${rootDirHash}`,      VERSION,      this._options.name,      this._options.roots        .map(root => fastPath.relative(options.rootDir, root))        .join(':'),      this._options.extensions.join(':'),      this._options.platforms.join(':'),      this._options.computeSha1.toString(),      options.mocksPattern || '',      (options.ignorePattern || '').toString(),      hasteImplHash,      dependencyExtractorHash    );    this._whitelist = getWhiteList(options.providesModuleNodeModules);    this._buildPromise = null;    this._watchers = [];    this._worker = null;  }  static getCacheFilePath(tmpdir, name, ...extra) {    const hash = _crypto()      .default.createHash('md5')      .update(extra.join(''));    return _path().default.join(      tmpdir,      name.replace(/\W/g, '-') + '-' + hash.digest('hex')    );  }  getCacheFilePath() {    return this._cachePath;  }  build() {    var _this = this;    if (!this._buildPromise) {      this._buildPromise = _asyncToGenerator(function*() {        const data = yield _this._buildFileMap(); // Persist when we don't know if files changed (changedFiles undefined)        // or when we know a file was changed or deleted.        let hasteMap;        if (          data.changedFiles === undefined ||          data.changedFiles.size > 0 ||          data.removedFiles.size > 0        ) {          hasteMap = yield _this._buildHasteMap(data);          _this._persist(hasteMap);        } else {          hasteMap = data.hasteMap;        }        const rootDir = _this._options.rootDir;        const hasteFS = new _HasteFS.default({          files: hasteMap.files,          rootDir        });        const moduleMap = new _ModuleMap.default({          duplicates: hasteMap.duplicates,          map: hasteMap.map,          mocks: hasteMap.mocks,          rootDir        });        const __hasteMapForTest =          (process.env.NODE_ENV === 'test' && hasteMap) || null;        yield _this._watch(hasteMap);        return {          __hasteMapForTest,          hasteFS,          moduleMap        };      })();    }    return this._buildPromise;  }  /**   * 1. read data from the cache or create an empty structure.   */  read() {    let hasteMap;    try {      hasteMap = _jestSerializer().default.readFileSync(this._cachePath);    } catch (err) {      hasteMap = this._createEmptyMap();    }    return hasteMap;  }  readModuleMap() {    const data = this.read();    return new _ModuleMap.default({      duplicates: data.duplicates,      map: data.map,      mocks: data.mocks,      rootDir: this._options.rootDir    });  }  /**   * 2. crawl the file system.   */  _buildFileMap() {    var _this2 = this;    return _asyncToGenerator(function*() {      let hasteMap;      try {        const read = _this2._options.resetCache          ? _this2._createEmptyMap          : _this2.read;        hasteMap = yield read.call(_this2);      } catch (_unused) {        hasteMap = _this2._createEmptyMap();      }      return _this2._crawl(hasteMap);    })();  }  /**   * 3. parse and extract metadata from changed files.   */  _processFile(hasteMap, map, mocks, filePath, workerOptions) {    const rootDir = this._options.rootDir;    const setModule = (id, module) => {      let moduleMap = map.get(id);      if (!moduleMap) {        moduleMap = Object.create(null);        map.set(id, moduleMap);      }      const platform =        (0, _getPlatformExtension.default)(          module[_constants.default.PATH],          this._options.platforms        ) || _constants.default.GENERIC_PLATFORM;      const existingModule = moduleMap[platform];      if (        existingModule &&        existingModule[_constants.default.PATH] !==          module[_constants.default.PATH]      ) {        const method = this._options.throwOnModuleCollision ? 'error' : 'warn';        this._console[method](          [            'jest-haste-map: Haste module naming collision: ' + id,            '  The following files share their name; please adjust your hasteImpl:',            '    * <rootDir>' +              _path().default.sep +              existingModule[_constants.default.PATH],            '    * <rootDir>' +              _path().default.sep +              module[_constants.default.PATH],            ''          ].join('\n')        );        if (this._options.throwOnModuleCollision) {          throw new DuplicateError(            existingModule[_constants.default.PATH],            module[_constants.default.PATH]          );        } // We do NOT want consumers to use a module that is ambiguous.        delete moduleMap[platform];        if (Object.keys(moduleMap).length === 1) {          map.delete(id);        }        let dupsByPlatform = hasteMap.duplicates.get(id);        if (dupsByPlatform == null) {          dupsByPlatform = new Map();          hasteMap.duplicates.set(id, dupsByPlatform);        }        const dups = new Map([          [module[_constants.default.PATH], module[_constants.default.TYPE]],          [            existingModule[_constants.default.PATH],            existingModule[_constants.default.TYPE]          ]        ]);        dupsByPlatform.set(platform, dups);        return;      }      const dupsByPlatform = hasteMap.duplicates.get(id);      if (dupsByPlatform != null) {        const dups = dupsByPlatform.get(platform);        if (dups != null) {          dups.set(            module[_constants.default.PATH],            module[_constants.default.TYPE]          );        }        return;      }      moduleMap[platform] = module;    };    const relativeFilePath = fastPath.relative(rootDir, filePath);    const fileMetadata = hasteMap.files.get(relativeFilePath);    if (!fileMetadata) {      throw new Error(        'jest-haste-map: File to process was not found in the haste map.'      );    }    const moduleMetadata = hasteMap.map.get(      fileMetadata[_constants.default.ID]    );    const computeSha1 =      this._options.computeSha1 && !fileMetadata[_constants.default.SHA1]; // Callback called when the response from the worker is successful.    const workerReply = metadata => {      // `1` for truthy values instead of `true` to save cache space.      fileMetadata[_constants.default.VISITED] = 1;      const metadataId = metadata.id;      const metadataModule = metadata.module;      if (metadataId && metadataModule) {        fileMetadata[_constants.default.ID] = metadataId;        setModule(metadataId, metadataModule);      }      fileMetadata[_constants.default.DEPENDENCIES] = metadata.dependencies        ? metadata.dependencies.join(_constants.default.DEPENDENCY_DELIM)        : '';      if (computeSha1) {        fileMetadata[_constants.default.SHA1] = metadata.sha1;      }    }; // Callback called when the response from the worker is an error.    const workerError = error => {      if (typeof error !== 'object' || !error.message || !error.stack) {        error = new Error(error);        error.stack = ''; // Remove stack for stack-less errors.      } // @ts-ignore: checking error code is OK if error comes from "fs".      if (!['ENOENT', 'EACCES'].includes(error.code)) {        throw error;      } // If a file cannot be read we remove it from the file list and      // ignore the failure silently.      hasteMap.files.delete(relativeFilePath);    }; // If we retain all files in the virtual HasteFS representation, we avoid    // reading them if they aren't important (node_modules).    if (this._options.retainAllFiles && this._isNodeModulesDir(filePath)) {      if (computeSha1) {        return this._getWorker(workerOptions)          .getSha1({            computeDependencies: this._options.computeDependencies,            computeSha1,            dependencyExtractor: this._options.dependencyExtractor,            filePath,            hasteImplModulePath: this._options.hasteImplModulePath,            rootDir          })          .then(workerReply, workerError);      }      return null;    }    if (      this._options.mocksPattern &&      this._options.mocksPattern.test(filePath)    ) {      const mockPath = (0, _getMockName.default)(filePath);      const existingMockPath = mocks.get(mockPath);      if (existingMockPath) {        const secondMockPath = fastPath.relative(rootDir, filePath);        if (existingMockPath !== secondMockPath) {          const method = this._options.throwOnModuleCollision            ? 'error'            : 'warn';          this._console[method](            [              'jest-haste-map: duplicate manual mock found: ' + mockPath,              '  The following files share their name; please delete one of them:',              '    * <rootDir>' + _path().default.sep + existingMockPath,              '    * <rootDir>' + _path().default.sep + secondMockPath,              ''            ].join('\n')          );          if (this._options.throwOnModuleCollision) {            throw new DuplicateError(existingMockPath, secondMockPath);          }        }      }      mocks.set(mockPath, relativeFilePath);    }    if (fileMetadata[_constants.default.VISITED]) {      if (!fileMetadata[_constants.default.ID]) {        return null;      }      if (moduleMetadata != null) {        const platform =          (0, _getPlatformExtension.default)(            filePath,            this._options.platforms          ) || _constants.default.GENERIC_PLATFORM;        const module = moduleMetadata[platform];        if (module == null) {          return null;        }        const moduleId = fileMetadata[_constants.default.ID];        let modulesByPlatform = map.get(moduleId);        if (!modulesByPlatform) {          modulesByPlatform = Object.create(null);          map.set(moduleId, modulesByPlatform);        }        modulesByPlatform[platform] = module;        return null;      }    }    return this._getWorker(workerOptions)      .worker({        computeDependencies: this._options.computeDependencies,        computeSha1,        dependencyExtractor: this._options.dependencyExtractor,        filePath,        hasteImplModulePath: this._options.hasteImplModulePath,        rootDir      })      .then(workerReply, workerError);  }  _buildHasteMap(data) {    const removedFiles = data.removedFiles,      changedFiles = data.changedFiles,      hasteMap = data.hasteMap; // If any files were removed or we did not track what files changed, process    // every file looking for changes. Otherwise, process only changed files.    let map;    let mocks;    let filesToProcess;    if (changedFiles === undefined || removedFiles.size) {      map = new Map();      mocks = new Map();      filesToProcess = hasteMap.files;    } else {      map = hasteMap.map;      mocks = hasteMap.mocks;      filesToProcess = changedFiles;    }    var _iteratorNormalCompletion = true;    var _didIteratorError = false;    var _iteratorError = undefined;    try {      for (        var _iterator = removedFiles[Symbol.iterator](), _step;        !(_iteratorNormalCompletion = (_step = _iterator.next()).done);        _iteratorNormalCompletion = true      ) {        const _step$value = _slicedToArray(_step.value, 2),          relativeFilePath = _step$value[0],          fileMetadata = _step$value[1];        this._recoverDuplicates(          hasteMap,          relativeFilePath,          fileMetadata[_constants.default.ID]        );      }    } catch (err) {      _didIteratorError = true;      _iteratorError = err;    } finally {      try {        if (!_iteratorNormalCompletion && _iterator.return != null) {          _iterator.return();        }      } finally {        if (_didIteratorError) {          throw _iteratorError;        }      }    }    const promises = [];    var _iteratorNormalCompletion2 = true;    var _didIteratorError2 = false;    var _iteratorError2 = undefined;    try {      for (        var _iterator2 = filesToProcess.keys()[Symbol.iterator](), _step2;        !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done);        _iteratorNormalCompletion2 = true      ) {        const relativeFilePath = _step2.value;        if (          this._options.skipPackageJson &&          relativeFilePath.endsWith(PACKAGE_JSON)        ) {          continue;        } // SHA-1, if requested, should already be present thanks to the crawler.        const filePath = fastPath.resolve(          this._options.rootDir,          relativeFilePath        );        const promise = this._processFile(hasteMap, map, mocks, filePath);        if (promise) {          promises.push(promise);        }      }    } catch (err) {      _didIteratorError2 = true;      _iteratorError2 = err;    } finally {      try {        if (!_iteratorNormalCompletion2 && _iterator2.return != null) {          _iterator2.return();        }      } finally {        if (_didIteratorError2) {          throw _iteratorError2;        }      }    }    return Promise.all(promises).then(      () => {        this._cleanup();        hasteMap.map = map;        hasteMap.mocks = mocks;        return hasteMap;      },      error => {        this._cleanup();        throw error;      }    );  }  _cleanup() {    const worker = this._worker; // @ts-ignore    if (worker && typeof worker.end === 'function') {      // @ts-ignore      worker.end();    }    this._worker = null;  }  /**   * 4. serialize the new `HasteMap` in a cache file.   */  _persist(hasteMap) {    _jestSerializer().default.writeFileSync(this._cachePath, hasteMap);  }  /**   * Creates workers or parses files and extracts metadata in-process.   */  _getWorker(options) {    if (!this._worker) {      if ((options && options.forceInBand) || this._options.maxWorkers <= 1) {        this._worker = {          getSha1: _worker.getSha1,          worker: _worker.worker        };      } else {        // @ts-ignore: assignment of a worker with custom properties.        this._worker = new (_jestWorker()).default(          require.resolve('./worker'),          {            exposedMethods: ['getSha1', 'worker'],            maxRetries: 3,            numWorkers: this._options.maxWorkers          }        );      }    }    return this._worker;  }  _crawl(hasteMap) {    const options = this._options;    const ignore = this._ignore.bind(this);    const crawl =      canUseWatchman && this._options.useWatchman        ? _watchman.default        : _node.default;    const crawlerOptions = {      computeSha1: options.computeSha1,      data: hasteMap,      extensions: options.extensions,      forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,      ignore,      mapper: options.mapper,      rootDir: options.rootDir,      roots: options.roots    };    const retry = error => {      if (crawl === _watchman.default) {        this._console.warn(          `jest-haste-map: Watchman crawl failed. Retrying once with node ` +            `crawler.\n` +            `  Usually this happens when watchman isn't running. Create an ` +            `empty \`.watchmanconfig\` file in your project's root folder or ` +            `initialize a git or hg repository in your project.\n` +            `  ` +            error        );        return (0, _node.default)(crawlerOptions).catch(e => {          throw new Error(            `Crawler retry failed:\n` +              `  Original error: ${error.message}\n` +              `  Retry error: ${e.message}\n`          );        });      }      throw error;    };    try {      return crawl(crawlerOptions).catch(retry);    } catch (error) {      return retry(error);    }  }  /**   * Watch mode   */  _watch(hasteMap) {    if (!this._options.watch) {      return Promise.resolve();    } // In watch mode, we'll only warn about module collisions and we'll retain    // all files, even changes to node_modules.    this._options.throwOnModuleCollision = false;    this._options.retainAllFiles = true; // WatchmanWatcher > FSEventsWatcher > sane.NodeWatcher    const Watcher =      canUseWatchman && this._options.useWatchman        ? _WatchmanWatcher.default        : _FSEventsWatcher.default.isSupported()        ? _FSEventsWatcher.default        : _sane().default.NodeWatcher;    const extensions = this._options.extensions;    const ignorePattern = this._options.ignorePattern;    const rootDir = this._options.rootDir;    let changeQueue = Promise.resolve();    let eventsQueue = []; // We only need to copy the entire haste map once on every "frame".    let mustCopy = true;    const createWatcher = root => {      // @ts-ignore: TODO how? "Cannot use 'new' with an expression whose type lacks a call or construct signature."      const watcher = new Watcher(root, {        dot: false,        glob: extensions.map(extension => '**/*.' + extension),        ignored: ignorePattern      });      return new Promise((resolve, reject) => {        const rejectTimeout = setTimeout(          () => reject(new Error('Failed to start watch mode.')),          MAX_WAIT_TIME        );        watcher.once('ready', () => {          clearTimeout(rejectTimeout);          watcher.on('all', onChange);          resolve(watcher);        });      });    };    const emitChange = () => {      if (eventsQueue.length) {        mustCopy = true;        const changeEvent = {          eventsQueue,          hasteFS: new _HasteFS.default({            files: hasteMap.files,            rootDir          }),          moduleMap: new _ModuleMap.default({            duplicates: hasteMap.duplicates,            map: hasteMap.map,            mocks: hasteMap.mocks,            rootDir          })        };        this.emit('change', changeEvent);        eventsQueue = [];      }    };    const onChange = (type, filePath, root, stat) => {      filePath = _path().default.join(        root,        (0, _normalizePathSep.default)(filePath)      );      if (        (stat && stat.isDirectory()) ||        this._ignore(filePath) ||        !extensions.some(extension => filePath.endsWith(extension))      ) {        return;      }      changeQueue = changeQueue        .then(() => {          // If we get duplicate events for the same file, ignore them.          if (            eventsQueue.find(              event =>                event.type === type &&                event.filePath === filePath &&                ((!event.stat && !stat) ||                  (!!event.stat &&                    !!stat &&                    event.stat.mtime.getTime() === stat.mtime.getTime()))            )          ) {            return null;          }          if (mustCopy) {            mustCopy = false;            hasteMap = {              clocks: new Map(hasteMap.clocks),              duplicates: new Map(hasteMap.duplicates),              files: new Map(hasteMap.files),              map: new Map(hasteMap.map),              mocks: new Map(hasteMap.mocks)            };          }          const add = () => {            eventsQueue.push({              filePath,              stat,              type            });            return null;          };          const relativeFilePath = fastPath.relative(rootDir, filePath);          const fileMetadata = hasteMap.files.get(relativeFilePath); // If it's not an addition, delete the file and all its metadata          if (fileMetadata != null) {            const moduleName = fileMetadata[_constants.default.ID];            const platform =              (0, _getPlatformExtension.default)(                filePath,                this._options.platforms              ) || _constants.default.GENERIC_PLATFORM;            hasteMap.files.delete(relativeFilePath);            let moduleMap = hasteMap.map.get(moduleName);            if (moduleMap != null) {              // We are forced to copy the object because jest-haste-map exposes              // the map as an immutable entity.              moduleMap = copy(moduleMap);              delete moduleMap[platform];              if (Object.keys(moduleMap).length === 0) {                hasteMap.map.delete(moduleName);              } else {                hasteMap.map.set(moduleName, moduleMap);              }            }            if (              this._options.mocksPattern &&              this._options.mocksPattern.test(filePath)            ) {              const mockName = (0, _getMockName.default)(filePath);              hasteMap.mocks.delete(mockName);            }            this._recoverDuplicates(hasteMap, relativeFilePath, moduleName);          } // If the file was added or changed,          // parse it and update the haste map.          if (type === 'add' || type === 'change') {            (0, _invariant().default)(              stat,              'since the file exists or changed, it should have stats'            );            const fileMetadata = [              '',              stat ? stat.mtime.getTime() : -1,              stat ? stat.size : 0,              0,              '',              null            ];            hasteMap.files.set(relativeFilePath, fileMetadata);            const promise = this._processFile(              hasteMap,              hasteMap.map,              hasteMap.mocks,              filePath,              {                forceInBand: true              }            ); // Cleanup            this._cleanup();            if (promise) {              return promise.then(add);            } else {              // If a file in node_modules has changed,              // emit an event regardless.              add();            }          } else {            add();          }          return null;        })        .catch(error => {          this._console.error(            `jest-haste-map: watch error:\n  ${error.stack}\n`          );        });    };    this._changeInterval = setInterval(emitChange, CHANGE_INTERVAL);    return Promise.all(this._options.roots.map(createWatcher)).then(      watchers => {        this._watchers = watchers;      }    );  }  /**   * This function should be called when the file under `filePath` is removed   * or changed. When that happens, we want to figure out if that file was   * part of a group of files that had the same ID. If it was, we want to   * remove it from the group. Furthermore, if there is only one file   * remaining in the group, then we want to restore that single file as the   * correct resolution for its ID, and cleanup the duplicates index.   */  _recoverDuplicates(hasteMap, relativeFilePath, moduleName) {    let dupsByPlatform = hasteMap.duplicates.get(moduleName);    if (dupsByPlatform == null) {      return;    }    const platform =      (0, _getPlatformExtension.default)(        relativeFilePath,        this._options.platforms      ) || _constants.default.GENERIC_PLATFORM;    let dups = dupsByPlatform.get(platform);    if (dups == null) {      return;    }    dupsByPlatform = copyMap(dupsByPlatform);    hasteMap.duplicates.set(moduleName, dupsByPlatform);    dups = copyMap(dups);    dupsByPlatform.set(platform, dups);    dups.delete(relativeFilePath);    if (dups.size !== 1) {      return;    }    const uniqueModule = dups.entries().next().value;    if (!uniqueModule) {      return;    }    let dedupMap = hasteMap.map.get(moduleName);    if (dedupMap == null) {      dedupMap = Object.create(null);      hasteMap.map.set(moduleName, dedupMap);    }    dedupMap[platform] = uniqueModule;    dupsByPlatform.delete(platform);    if (dupsByPlatform.size === 0) {      hasteMap.duplicates.delete(moduleName);    }  }  end() {    // @ts-ignore: TODO TS cannot decide if `setInterval` and `clearInterval` comes from NodeJS or the DOM    clearInterval(this._changeInterval);    if (!this._watchers.length) {      return Promise.resolve();    }    return Promise.all(      this._watchers.map(        watcher => new Promise(resolve => watcher.close(resolve))      )    ).then(() => {      this._watchers = [];    });  }  /**   * Helpers   */  _ignore(filePath) {    const ignorePattern = this._options.ignorePattern;    const ignoreMatched =      ignorePattern instanceof RegExp        ? ignorePattern.test(filePath)        : ignorePattern && ignorePattern(filePath);    return (      ignoreMatched ||      (!this._options.retainAllFiles && this._isNodeModulesDir(filePath))    );  }  _isNodeModulesDir(filePath) {    if (!filePath.includes(NODE_MODULES)) {      return false;    }    if (this._whitelist) {      const whitelist = this._whitelist;      const match = whitelist.exec(filePath);      const matchEndIndex = whitelist.lastIndex;      whitelist.lastIndex = 0;      if (!match) {        return true;      }      const filePathInPackage = filePath.substr(matchEndIndex);      return filePathInPackage.startsWith(NODE_MODULES);    }    return true;  }  _createEmptyMap() {    return {      clocks: new Map(),      duplicates: new Map(),      files: new Map(),      map: new Map(),      mocks: new Map()    };  }}_defineProperty(HasteMap, 'H', void 0);_defineProperty(HasteMap, 'DuplicateError', void 0);_defineProperty(HasteMap, 'ModuleMap', void 0);class DuplicateError extends Error {  constructor(mockPath1, mockPath2) {    super('Duplicated files or mocks. Please check the console for more info');    _defineProperty(this, 'mockPath1', void 0);    _defineProperty(this, 'mockPath2', void 0);    this.mockPath1 = mockPath1;    this.mockPath2 = mockPath2;  }}function copy(object) {  return Object.assign(Object.create(null), object);}function copyMap(input) {  return new Map(input);}HasteMap.H = _constants.default;HasteMap.DuplicateError = DuplicateError;HasteMap.ModuleMap = _ModuleMap.default;module.exports = HasteMap;
 |