| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266 | 'use strict';Object.defineProperty(exports, '__esModule', {  value: true});exports.DuplicateError = void 0;Object.defineProperty(exports, 'ModuleMap', {  enumerable: true,  get: function () {    return _ModuleMap.default;  }});exports.default = void 0;function _child_process() {  const data = require('child_process');  _child_process = function () {    return data;  };  return data;}function _crypto() {  const data = require('crypto');  _crypto = function () {    return data;  };  return data;}function _events() {  const data = require('events');  _events = function () {    return data;  };  return data;}function _os() {  const data = require('os');  _os = function () {    return data;  };  return data;}function path() {  const data = _interopRequireWildcard(require('path'));  path = function () {    return data;  };  return data;}function _jestRegexUtil() {  const data = require('jest-regex-util');  _jestRegexUtil = function () {    return data;  };  return data;}function _jestSerializer() {  const data = _interopRequireDefault(require('jest-serializer'));  _jestSerializer = function () {    return data;  };  return data;}function _jestWorker() {  const data = require('jest-worker');  _jestWorker = function () {    return data;  };  return data;}var _HasteFS = _interopRequireDefault(require('./HasteFS'));var _ModuleMap = _interopRequireDefault(require('./ModuleMap'));var _constants = _interopRequireDefault(require('./constants'));var _node = _interopRequireDefault(require('./crawlers/node'));var _watchman = _interopRequireDefault(require('./crawlers/watchman'));var _getMockName = _interopRequireDefault(require('./getMockName'));var fastPath = _interopRequireWildcard(require('./lib/fast_path'));var _getPlatformExtension = _interopRequireDefault(  require('./lib/getPlatformExtension'));var _normalizePathSep = _interopRequireDefault(  require('./lib/normalizePathSep'));var _FSEventsWatcher = _interopRequireDefault(  require('./watchers/FSEventsWatcher'));var _NodeWatcher = _interopRequireDefault(require('./watchers/NodeWatcher'));var _WatchmanWatcher = _interopRequireDefault(  require('./watchers/WatchmanWatcher'));var _worker = require('./worker');function _interopRequireDefault(obj) {  return obj && obj.__esModule ? obj : {default: obj};}function _getRequireWildcardCache(nodeInterop) {  if (typeof WeakMap !== 'function') return null;  var cacheBabelInterop = new WeakMap();  var cacheNodeInterop = new WeakMap();  return (_getRequireWildcardCache = function (nodeInterop) {    return nodeInterop ? cacheNodeInterop : cacheBabelInterop;  })(nodeInterop);}function _interopRequireWildcard(obj, nodeInterop) {  if (!nodeInterop && obj && obj.__esModule) {    return obj;  }  if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {    return {default: obj};  }  var cache = _getRequireWildcardCache(nodeInterop);  if (cache && cache.has(obj)) {    return cache.get(obj);  }  var newObj = {};  var hasPropertyDescriptor =    Object.defineProperty && Object.getOwnPropertyDescriptor;  for (var key in obj) {    if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {      var desc = hasPropertyDescriptor        ? Object.getOwnPropertyDescriptor(obj, key)        : null;      if (desc && (desc.get || desc.set)) {        Object.defineProperty(newObj, key, desc);      } else {        newObj[key] = obj[key];      }    }  }  newObj.default = obj;  if (cache) {    cache.set(obj, newObj);  }  return newObj;}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;}// TypeScript doesn't like us importing from outside `rootDir`, but it doesn't// understand `require`.const {version: VERSION} = require('../package.json');const CHANGE_INTERVAL = 30;const MAX_WAIT_TIME = 240000;const NODE_MODULES = path().sep + 'node_modules' + path().sep;const PACKAGE_JSON = path().sep + 'package.json';const VCS_DIRECTORIES = ['.git', '.hg']  .map(vcs =>    (0, _jestRegexUtil().escapePathForRegex)(path().sep + vcs + path().sep)  )  .join('|');const canUseWatchman = (() => {  try {    (0, _child_process().execSync)('watchman --version', {      stdio: ['ignore']    });    return true;  } catch {}  return false;})();function invariant(condition, message) {  if (!condition) {    throw new Error(message);  }}/** * 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()`. * */class HasteMap extends _events().EventEmitter {  static getStatic(config) {    if (config.haste.hasteMapModulePath) {      return require(config.haste.hasteMapModulePath);    }    return HasteMap;  }  static create(options) {    if (options.hasteMapModulePath) {      const CustomHasteMap = require(options.hasteMapModulePath);      return new CustomHasteMap(options);    }    return new HasteMap(options);  }  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, '_worker', void 0);    this._options = {      cacheDirectory: options.cacheDirectory || (0, _os().tmpdir)(),      computeDependencies:        options.computeDependencies === undefined          ? true          : options.computeDependencies,      computeSha1: options.computeSha1 || false,      dependencyExtractor: options.dependencyExtractor || null,      enableSymlinks: options.enableSymlinks || false,      extensions: options.extensions,      forceNodeFilesystemAPI: !!options.forceNodeFilesystemAPI,      hasteImplModulePath: options.hasteImplModulePath,      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) {      if (options.ignorePattern instanceof RegExp) {        this._options.ignorePattern = new RegExp(          options.ignorePattern.source.concat('|' + VCS_DIRECTORIES),          options.ignorePattern.flags        );      } else {        throw new Error(          'jest-haste-map: the `ignorePattern` option must be a RegExp'        );      }    } else {      this._options.ignorePattern = new RegExp(VCS_DIRECTORIES);    }    if (this._options.enableSymlinks && this._options.useWatchman) {      throw new Error(        'jest-haste-map: enableSymlinks config option was set, but ' +          'is incompatible with watchman.\n' +          'Set either `enableSymlinks` to false or `useWatchman` to false.'      );    }    const rootDirHash = (0, _crypto().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._options.computeDependencies.toString()    );    this._buildPromise = null;    this._watchers = [];    this._worker = null;  }  static getCacheFilePath(tmpdir, name, ...extra) {    const hash = (0, _crypto().createHash)('md5').update(extra.join(''));    return path().join(      tmpdir,      name.replace(/\W/g, '-') + '-' + hash.digest('hex')    );  }  static getModuleMapFromJSON(json) {    return _ModuleMap.default.fromJSON(json);  }  getCacheFilePath() {    return this._cachePath;  }  build() {    if (!this._buildPromise) {      this._buildPromise = (async () => {        const data = await 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 = await 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;        await 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 {      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.   */  async _buildFileMap() {    let hasteMap;    try {      const read = this._options.resetCache ? this._createEmptyMap : this.read;      hasteMap = await read.call(this);    } catch {      hasteMap = this._createEmptyMap();    }    return this._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().sep +              existingModule[_constants.default.PATH],            '    * <rootDir>' + path().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.      }      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 && filePath.includes(NODE_MODULES)) {      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().sep + existingMockPath,              '    * <rootDir>' + path().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, changedFiles, hasteMap} = data; // 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;    }    for (const [relativeFilePath, fileMetadata] of removedFiles) {      this._recoverDuplicates(        hasteMap,        relativeFilePath,        fileMetadata[_constants.default.ID]      );    }    const promises = [];    for (const relativeFilePath of filesToProcess.keys()) {      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);      }    }    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-expect-error    if (worker && typeof worker.end === 'function') {      // @ts-expect-error      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-expect-error: assignment of a worker with custom properties.        this._worker = new (_jestWorker().Worker)(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,      enableSymlinks: options.enableSymlinks,      extensions: options.extensions,      forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,      ignore,      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        : _NodeWatcher.default;    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 => {      const watcher = new Watcher(root, {        dot: true,        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().join(root, (0, _normalizePathSep.default)(filePath));      if (        (stat && stat.isDirectory()) ||        this._ignore(filePath) ||        !extensions.some(extension => filePath.endsWith(extension))      ) {        return;      }      const relativeFilePath = fastPath.relative(rootDir, filePath);      const fileMetadata = hasteMap.files.get(relativeFilePath); // The file has been accessed, not modified      if (        type === 'change' &&        fileMetadata &&        stat &&        fileMetadata[_constants.default.MTIME] === stat.mtime.getTime()      ) {        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 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') {            invariant(              stat,              'since the file exists or changed, it should have stats'            );            const fileMetadata = [              '',              stat.mtime.getTime(),              stat.size,              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);    }  }  async end() {    if (this._changeInterval) {      clearInterval(this._changeInterval);    }    if (!this._watchers.length) {      return;    }    await Promise.all(this._watchers.map(watcher => watcher.close()));    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 && filePath.includes(NODE_MODULES))    );  }  _createEmptyMap() {    return {      clocks: new Map(),      duplicates: new Map(),      files: new Map(),      map: new Map(),      mocks: new Map()    };  }}exports.default = HasteMap;_defineProperty(HasteMap, 'H', _constants.default);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;  }}exports.DuplicateError = DuplicateError;function copy(object) {  return Object.assign(Object.create(null), object);}function copyMap(input) {  return new Map(input);}
 |