From ea9e546859ba35de67144766628f026f5c5a32c1 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 02:42:30 +0100 Subject: [PATCH 01/16] chore: migrate jest-haste-map to TypeScript --- CHANGELOG.md | 1 + packages/jest-cli/src/TestSequencer.js | 1 - packages/jest-haste-map/package.json | 3 + .../src/{HasteFS.js => HasteFS.ts} | 42 ++-- .../src/{ModuleMap.js => ModuleMap.ts} | 61 +++-- .../src/__tests__/index.test.js | 6 +- .../src/{blacklist.js => blacklist.ts} | 2 - .../src/{constants.js => constants.ts} | 9 +- .../src/crawlers/{node.js => node.ts} | 26 +- .../src/crawlers/{watchman.js => watchman.ts} | 29 +-- .../src/{getMockName.js => getMockName.ts} | 2 - .../jest-haste-map/src/{index.js => index.ts} | 234 +++++++++--------- .../jest-haste-map/src/lib/WatchmanWatcher.js | 4 +- .../lib/__tests__/dependencyExtractor.test.js | 2 - .../src/lib/__tests__/fast_path.test.js | 2 - .../__tests__/getPlatformExtension.test.js | 2 - .../lib/__tests__/isRegExpSupported.test.js | 2 - ...ncyExtractor.js => dependencyExtractor.ts} | 13 +- .../src/lib/{fast_path.js => fast_path.ts} | 2 - ...rmExtension.js => getPlatformExtension.ts} | 13 +- ...egExpSupported.js => isRegExpSupported.ts} | 2 - ...ormalizePathSep.js => normalizePathSep.ts} | 6 +- packages/jest-haste-map/src/types.js | 44 ---- packages/jest-haste-map/src/types.ts | 104 ++++++++ .../src/{worker.js => worker.ts} | 15 +- packages/jest-haste-map/tsconfig.json | 13 + tsconfig.json | 3 +- 27 files changed, 345 insertions(+), 298 deletions(-) rename packages/jest-haste-map/src/{HasteFS.js => HasteFS.ts} (67%) rename packages/jest-haste-map/src/{ModuleMap.js => ModuleMap.ts} (84%) rename packages/jest-haste-map/src/{blacklist.js => blacklist.ts} (99%) rename packages/jest-haste-map/src/{constants.js => constants.ts} (90%) rename packages/jest-haste-map/src/crawlers/{node.js => node.ts} (88%) rename packages/jest-haste-map/src/crawlers/{watchman.js => watchman.ts} (91%) rename packages/jest-haste-map/src/{getMockName.js => getMockName.ts} (97%) rename packages/jest-haste-map/src/{index.js => index.ts} (88%) rename packages/jest-haste-map/src/lib/{dependencyExtractor.js => dependencyExtractor.ts} (86%) rename packages/jest-haste-map/src/lib/{fast_path.js => fast_path.ts} (98%) rename packages/jest-haste-map/src/lib/{getPlatformExtension.js => getPlatformExtension.ts} (79%) rename packages/jest-haste-map/src/lib/{isRegExpSupported.js => isRegExpSupported.ts} (97%) rename packages/jest-haste-map/src/lib/{normalizePathSep.js => normalizePathSep.ts} (84%) delete mode 100644 packages/jest-haste-map/src/types.js create mode 100644 packages/jest-haste-map/src/types.ts rename packages/jest-haste-map/src/{worker.js => worker.ts} (91%) create mode 100644 packages/jest-haste-map/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index c910de37cdc7..7e8004209de7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - `[jest-watcher]`: Migrate to TypeScript ([#7843](https://github.com/facebook/jest/pull/7843)) - `[jest-mock]`: Migrate to TypeScript ([#7847](https://github.com/facebook/jest/pull/7847), [#7850](https://github.com/facebook/jest/pull/7850)) - `[jest-worker]`: Migrate to TypeScript ([#7853](https://github.com/facebook/jest/pull/7853)) +- `[jest-haste-map]`: Migrate to TypeScript ([#7854](https://github.com/facebook/jest/pull/7854)) ### Performance diff --git a/packages/jest-cli/src/TestSequencer.js b/packages/jest-cli/src/TestSequencer.js index b13c2e261d9e..0fab2560639c 100644 --- a/packages/jest-cli/src/TestSequencer.js +++ b/packages/jest-cli/src/TestSequencer.js @@ -12,7 +12,6 @@ import type {Context} from 'types/Context'; import type {Test} from 'types/TestRunner'; import fs from 'fs'; -// $FlowFixMe: Missing ESM export import {getCacheFilePath} from 'jest-haste-map'; const FAIL = 0; diff --git a/packages/jest-haste-map/package.json b/packages/jest-haste-map/package.json index 1daf9e83bee0..9bb467e58de3 100644 --- a/packages/jest-haste-map/package.json +++ b/packages/jest-haste-map/package.json @@ -8,7 +8,9 @@ }, "license": "MIT", "main": "build/index.js", + "types": "build/index.d.ts", "dependencies": { + "@jest/types": "^24.1.0", "fb-watchman": "^2.0.0", "graceful-fs": "^4.1.15", "invariant": "^2.2.4", @@ -23,6 +25,7 @@ "@types/graceful-fs": "^4.1.2", "@types/invariant": "^2.2.29", "@types/micromatch": "^3.1.0", + "@types/node": "^10.12.24", "@types/sane": "^2.0.0" }, "engines": { diff --git a/packages/jest-haste-map/src/HasteFS.js b/packages/jest-haste-map/src/HasteFS.ts similarity index 67% rename from packages/jest-haste-map/src/HasteFS.js rename to packages/jest-haste-map/src/HasteFS.ts index c703376accde..de3628871f27 100644 --- a/packages/jest-haste-map/src/HasteFS.js +++ b/packages/jest-haste-map/src/HasteFS.ts @@ -3,66 +3,63 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {Glob, Path} from 'types/Config'; -import type {FileData} from 'types/HasteMap'; - +import micromatch from 'micromatch'; import {replacePathSepForGlob} from 'jest-util'; +import {Config} from '@jest/types'; +import {FileData} from './types'; import * as fastPath from './lib/fast_path'; -import micromatch from 'micromatch'; import H from './constants'; export default class HasteFS { - _rootDir: Path; - _files: FileData; + private readonly _rootDir: Config.Path; + private readonly _files: FileData; - constructor({rootDir, files}: {rootDir: Path, files: FileData}) { + constructor({rootDir, files}: {rootDir: Config.Path; files: FileData}) { this._rootDir = rootDir; this._files = files; } - getModuleName(file: Path): ?string { + getModuleName(file: Config.Path): string | null { const fileMetadata = this._getFileData(file); return (fileMetadata && fileMetadata[H.ID]) || null; } - getSize(file: Path): ?number { + getSize(file: Config.Path): number | null { const fileMetadata = this._getFileData(file); return (fileMetadata && fileMetadata[H.SIZE]) || null; } - getDependencies(file: Path): ?Array { + getDependencies(file: Config.Path): Array | null { const fileMetadata = this._getFileData(file); return (fileMetadata && fileMetadata[H.DEPENDENCIES]) || null; } - getSha1(file: Path): ?string { + getSha1(file: Config.Path): string | null { const fileMetadata = this._getFileData(file); return (fileMetadata && fileMetadata[H.SHA1]) || null; } - exists(file: Path): boolean { + exists(file: Config.Path): boolean { return this._getFileData(file) != null; } - getAllFiles(): Array { + getAllFiles(): Array { return Array.from(this.getAbsoluteFileIterator()); } - getFileIterator(): Iterator { + getFileIterator(): Iterable { return this._files.keys(); } - *getAbsoluteFileIterator(): Iterator { - for (const file of this._files.keys()) { + *getAbsoluteFileIterator(): Iterable { + for (const file of this.getFileIterator()) { yield fastPath.resolve(this._rootDir, file); } } - matchFiles(pattern: RegExp | string): Array { + matchFiles(pattern: RegExp | string): Array { if (!(pattern instanceof RegExp)) { pattern = new RegExp(pattern); } @@ -75,7 +72,10 @@ export default class HasteFS { return files; } - matchFilesWithGlob(globs: Array, root: ?Path): Set { + matchFilesWithGlob( + globs: Array, + root: Config.Path | null, + ): Set { const files = new Set(); for (const file of this.getAbsoluteFileIterator()) { const filePath = root ? fastPath.relative(root, file) : file; @@ -86,7 +86,7 @@ export default class HasteFS { return files; } - _getFileData(file: Path) { + private _getFileData(file: Config.Path) { const relativePath = fastPath.relative(this._rootDir, file); return this._files.get(relativePath); } diff --git a/packages/jest-haste-map/src/ModuleMap.js b/packages/jest-haste-map/src/ModuleMap.ts similarity index 84% rename from packages/jest-haste-map/src/ModuleMap.js rename to packages/jest-haste-map/src/ModuleMap.ts index 7f2390020fff..cde59fe06d2a 100644 --- a/packages/jest-haste-map/src/ModuleMap.js +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -3,12 +3,10 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {Path} from 'types/Config'; -import type { +import {Config} from '@jest/types'; +import { DuplicatesSet, HTypeValue, ModuleMetaData, @@ -16,28 +14,27 @@ import type { ModuleMapData, DuplicatesIndex, MockData, -} from 'types/HasteMap'; +} from './types'; import * as fastPath from './lib/fast_path'; import H from './constants'; -const EMPTY_OBJ = {}; +const EMPTY_OBJ = {} as {[key: string]: any}; const EMPTY_MAP = new Map(); -export opaque type SerializableModuleMap = { +type ValueType = T extends Map ? V : T; + +export type SerializableModuleMap = { // There is no easier way to extract the type of the entries of a Map - duplicates: $Call< - typeof Array.from, - $Call<$PropertyType>, - >, - map: $Call>>, - mocks: $Call>>, - rootDir: string, + duplicates: [string, ValueType]; + map: [string, ValueType]; + mocks: [string, ValueType]; + rootDir: Config.Path; }; export default class ModuleMap { - _raw: RawModuleMap; - static DuplicateHasteCandidatesError: Class; + private readonly _raw: RawModuleMap; + static DuplicateHasteCandidatesError: DuplicateHasteCandidatesError; constructor(raw: RawModuleMap) { this._raw = raw; @@ -45,10 +42,10 @@ export default class ModuleMap { getModule( name: string, - platform: ?string, - supportsNativePlatform: ?boolean, - type: ?HTypeValue, - ): ?Path { + platform: string | null, + supportsNativePlatform: boolean | null, + type: HTypeValue | null, + ): string | null { if (!type) { type = H.MODULE; } @@ -66,13 +63,13 @@ export default class ModuleMap { getPackage( name: string, - platform: ?string, - supportsNativePlatform: ?boolean, - ): ?Path { + platform: string | null, + _: boolean | null, + ): string | null { return this.getModule(name, platform, null, H.PACKAGE); } - getMockModule(name: string): ?Path { + getMockModule(name: string): string | undefined { const mockPath = this._raw.mocks.get(name) || this._raw.mocks.get(name + '/index'); return mockPath && fastPath.resolve(this._raw.rootDir, mockPath); @@ -113,11 +110,11 @@ export default class ModuleMap { * extra sure. If metadata exists both in the `duplicates` object and the * `map`, this would be a bug. */ - _getModuleMetadata( + private _getModuleMetadata( name: string, - platform: ?string, + platform: string | null, supportsNativePlatform: boolean, - ): ?ModuleMetaData { + ): ModuleMetaData | null { const map = this._raw.map.get(name) || EMPTY_OBJ; const dupMap = this._raw.duplicates.get(name) || EMPTY_MAP; if (platform != null) { @@ -154,11 +151,11 @@ export default class ModuleMap { return null; } - _assertNoDuplicates( + private _assertNoDuplicates( name: string, platform: string, supportsNativePlatform: boolean, - relativePathSet: ?DuplicatesSet, + relativePathSet: DuplicatesSet | null, ) { if (relativePathSet == null) { return; @@ -180,7 +177,7 @@ export default class ModuleMap { ); } - static create(rootDir: Path) { + static create(rootDir: string) { return new ModuleMap({ duplicates: new Map(), map: new Map(), @@ -190,9 +187,9 @@ export default class ModuleMap { } } -class DuplicateHasteCandidatesError extends Error { +export class DuplicateHasteCandidatesError extends Error { hasteName: string; - platform: ?string; + platform: string | null; supportsNativePlatform: boolean; duplicatesSet: DuplicatesSet; diff --git a/packages/jest-haste-map/src/__tests__/index.test.js b/packages/jest-haste-map/src/__tests__/index.test.js index 7e23749f3d93..c11a752bd8b9 100644 --- a/packages/jest-haste-map/src/__tests__/index.test.js +++ b/packages/jest-haste-map/src/__tests__/index.test.js @@ -6,10 +6,8 @@ * */ -'use strict'; - +import crypto from 'crypto'; import {skipSuiteOnWindows} from '../../../../scripts/ConditionalTest'; -const crypto = require('crypto'); function mockHashContents(contents) { return crypto @@ -75,7 +73,7 @@ jest.mock('sane', () => ({ WatchmanWatcher: mockWatcherConstructor, })); -jest.mock('../lib/WatchmanWatcher.js', () => mockWatcherConstructor); +jest.mock('../lib/WatchmanWatcher', () => mockWatcherConstructor); let mockChangedFiles; let mockFs; diff --git a/packages/jest-haste-map/src/blacklist.js b/packages/jest-haste-map/src/blacklist.ts similarity index 99% rename from packages/jest-haste-map/src/blacklist.js rename to packages/jest-haste-map/src/blacklist.ts index 61e1b550a858..caead002eaeb 100644 --- a/packages/jest-haste-map/src/blacklist.js +++ b/packages/jest-haste-map/src/blacklist.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ // This list is compiled after the MDN list of the most common MIME types (see diff --git a/packages/jest-haste-map/src/constants.js b/packages/jest-haste-map/src/constants.ts similarity index 90% rename from packages/jest-haste-map/src/constants.js rename to packages/jest-haste-map/src/constants.ts index 6bbe7c4fb52e..1717934e47ef 100644 --- a/packages/jest-haste-map/src/constants.js +++ b/packages/jest-haste-map/src/constants.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ /* eslint-disable sort-keys */ @@ -16,7 +14,10 @@ * This constant key map allows to keep the map smaller without having to build * a custom serialization library. */ -export default { + +import {HType} from './types'; + +const constants: HType = { /* file map attributes */ ID: 0, MTIME: 1, @@ -37,3 +38,5 @@ export default { GENERIC_PLATFORM: 'g', NATIVE_PLATFORM: 'native', }; + +export default constants; diff --git a/packages/jest-haste-map/src/crawlers/node.js b/packages/jest-haste-map/src/crawlers/node.ts similarity index 88% rename from packages/jest-haste-map/src/crawlers/node.js rename to packages/jest-haste-map/src/crawlers/node.ts index ffb155ba6321..ec4aaa927e4f 100644 --- a/packages/jest-haste-map/src/crawlers/node.js +++ b/packages/jest-haste-map/src/crawlers/node.ts @@ -3,22 +3,18 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {InternalHasteMap} from 'types/HasteMap'; -import type {IgnoreMatcher, CrawlerOptions} from '../types'; - import fs from 'fs'; import path from 'path'; import {spawn} from 'child_process'; import H from '../constants'; import * as fastPath from '../lib/fast_path'; +import {IgnoreMatcher, InternalHasteMap, CrawlerOptions} from '../types'; + +type Result = Array<[/* id */ string, /* mtime */ number, /* size */ number]>; -type Callback = ( - result: Array<[/* id */ string, /* mtime */ number, /* size */ number]>, -) => void; +type Callback = (result: Result) => void; function find( roots: Array, @@ -26,7 +22,7 @@ function find( ignore: IgnoreMatcher, callback: Callback, ): void { - const result = []; + const result: Result = []; let activeCalls = 0; function search(directory: string): void { @@ -82,7 +78,7 @@ function findNative( ignore: IgnoreMatcher, callback: Callback, ): void { - const args = [].concat(roots); + const args = roots.slice(); args.push('-type', 'f'); if (extensions.length) { args.push('('); @@ -108,7 +104,7 @@ function findNative( .trim() .split('\n') .filter(x => !ignore(x)); - const result = []; + const result: Result = []; let count = lines.length; if (!count) { callback([]); @@ -127,7 +123,7 @@ function findNative( }); } -module.exports = function nodeCrawl( +export = function nodeCrawl( options: CrawlerOptions, ): Promise { if (options.mapper) { @@ -144,13 +140,11 @@ module.exports = function nodeCrawl( } = options; return new Promise(resolve => { - const callback = list => { + const callback = (list: Result) => { const files = new Map(); list.forEach(fileData => { - const filePath = fileData[0]; + const [filePath, mtime, size] = fileData; const relativeFilePath = fastPath.relative(rootDir, filePath); - const mtime = fileData[1]; - const size = fileData[2]; const existingFile = data.files.get(relativeFilePath); if (existingFile && existingFile[H.MTIME] === mtime) { files.set(relativeFilePath, existingFile); diff --git a/packages/jest-haste-map/src/crawlers/watchman.js b/packages/jest-haste-map/src/crawlers/watchman.ts similarity index 91% rename from packages/jest-haste-map/src/crawlers/watchman.js rename to packages/jest-haste-map/src/crawlers/watchman.ts index b07b9e635172..873e917a992e 100644 --- a/packages/jest-haste-map/src/crawlers/watchman.js +++ b/packages/jest-haste-map/src/crawlers/watchman.ts @@ -3,18 +3,17 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {InternalHasteMap} from 'types/HasteMap'; -import type {CrawlerOptions} from '../types'; - -import * as fastPath from '../lib/fast_path'; -import normalizePathSep from '../lib/normalizePathSep'; import path from 'path'; import watchman from 'fb-watchman'; +import {Config} from '@jest/types'; +import * as fastPath from '../lib/fast_path'; +import normalizePathSep from '../lib/normalizePathSep'; import H from '../constants'; +import {InternalHasteMap, CrawlerOptions, FileMetaData} from '../types'; + +type WatchmanRoots = Map>; const watchmanURL = 'https://facebook.github.io/watchman/docs/troubleshooting.html'; @@ -26,7 +25,7 @@ function WatchmanError(error: Error): Error { return error; } -module.exports = async function watchmanCrawl( +export = async function watchmanCrawl( options: CrawlerOptions, ): Promise { const fields = ['name', 'exists', 'mtime_ms', 'size']; @@ -34,7 +33,7 @@ module.exports = async function watchmanCrawl( const defaultWatchExpression = [ 'allof', ['type', 'f'], - ['anyof'].concat(extensions.map(extension => ['suffix', extension])), + ['anyof', ...extensions.map(extension => ['suffix', extension])], ]; const clocks = data.clocks; const client = new watchman.Client(); @@ -42,7 +41,7 @@ module.exports = async function watchmanCrawl( let clientError; client.on('error', error => (clientError = WatchmanError(error))); - const cmd = (...args) => + const cmd = (...args: Array): Promise => new Promise((resolve, reject) => client.command(args, (error, result) => error ? reject(WatchmanError(error)) : resolve(result), @@ -57,7 +56,9 @@ module.exports = async function watchmanCrawl( } } - async function getWatchmanRoots(roots) { + async function getWatchmanRoots( + roots: Array, + ): Promise { const watchmanRoots = new Map(); await Promise.all( roots.map(async root => { @@ -85,7 +86,7 @@ module.exports = async function watchmanCrawl( return watchmanRoots; } - async function queryWatchmanForDirs(rootProjectDirMappings) { + async function queryWatchmanForDirs(rootProjectDirMappings: WatchmanRoots) { const files = new Map(); let isFresh = false; await Promise.all( @@ -181,7 +182,7 @@ module.exports = async function watchmanCrawl( } const existingFileData = data.files.get(relativeFilePath); - let nextData; + let nextData: FileMetaData; if (existingFileData && existingFileData[H.MTIME] === mtime) { nextData = existingFileData; @@ -193,7 +194,7 @@ module.exports = async function watchmanCrawl( nextData = [...existingFileData]; nextData[1] = mtime; } else { - // See ../constants.js + // See ../constants.ts nextData = ['', mtime, size, 0, [], sha1hex]; } diff --git a/packages/jest-haste-map/src/getMockName.js b/packages/jest-haste-map/src/getMockName.ts similarity index 97% rename from packages/jest-haste-map/src/getMockName.js rename to packages/jest-haste-map/src/getMockName.ts index af35f390c7a9..3040e20a5ee3 100644 --- a/packages/jest-haste-map/src/getMockName.js +++ b/packages/jest-haste-map/src/getMockName.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import path from 'path'; diff --git a/packages/jest-haste-map/src/index.js b/packages/jest-haste-map/src/index.ts similarity index 88% rename from packages/jest-haste-map/src/index.js rename to packages/jest-haste-map/src/index.ts index 7831169d2ff0..0fdf524f59b4 100644 --- a/packages/jest-haste-map/src/index.js +++ b/packages/jest-haste-map/src/index.ts @@ -3,103 +3,100 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import {execSync} from 'child_process'; -import {version as VERSION} from '../package.json'; -import {getSha1, worker} from './worker'; import crypto from 'crypto'; import EventEmitter from 'events'; import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import sane from 'sane'; +import invariant from 'invariant'; +import {Config} from '@jest/types'; +import serializer from 'jest-serializer'; +import Worker from 'jest-worker'; +import {getSha1, worker} from './worker'; import getMockName from './getMockName'; import getPlatformExtension from './lib/getPlatformExtension'; import H from './constants'; import HasteFS from './HasteFS'; -import HasteModuleMap from './ModuleMap'; -import invariant from 'invariant'; -// eslint-disable-next-line import/default +import HasteModuleMap, { + SerializableModuleMap as HasteSerializableModuleMap, +} from './ModuleMap'; import nodeCrawl from './crawlers/node'; import normalizePathSep from './lib/normalizePathSep'; -import os from 'os'; -import path from 'path'; -import sane from 'sane'; -import serializer from 'jest-serializer'; -// eslint-disable-next-line import/default import watchmanCrawl from './crawlers/watchman'; +// @ts-ignore: not converted to TypeScript - it's a fork: https://github.com/facebook/jest/pull/5387 import WatchmanWatcher from './lib/WatchmanWatcher'; import * as fastPath from './lib/fast_path'; -import Worker from 'jest-worker'; - -import type {Console} from 'console'; -import type {Mapper} from './types'; -import type {Path} from 'types/Config'; -import type { +import { + FileMetaData, HasteMap as HasteMapObject, - InternalHasteMap, - ModuleMetaData, - ModuleMapData, HasteRegExp, + InternalHasteMap, + Mapper, MockData, -} from 'types/HasteMap'; -import type {SerializableModuleMap as HasteSerializableModuleMap} from './ModuleMap'; + ModuleMapData, + ModuleMetaData, + WorkerMetadata, +} from './types'; type HType = typeof H; type Options = { - cacheDirectory?: string, - computeDependencies?: boolean, - computeSha1?: boolean, - console?: Console, - dependencyExtractor?: string, - extensions: Array, - forceNodeFilesystemAPI?: boolean, - hasteImplModulePath?: string, - ignorePattern?: ?HasteRegExp, - mapper?: ?Mapper, - maxWorkers: number, - mocksPattern?: string, - name: string, - platforms: Array, - providesModuleNodeModules?: Array, - resetCache?: boolean, - retainAllFiles: boolean, - rootDir: string, - roots: Array, - throwOnModuleCollision?: boolean, - useWatchman?: boolean, - watch?: boolean, + cacheDirectory?: string; + computeDependencies?: boolean; + computeSha1?: boolean; + console?: Console; + dependencyExtractor?: string; + extensions: Array; + forceNodeFilesystemAPI?: boolean; + hasteImplModulePath?: string; + ignorePattern?: HasteRegExp; + mapper?: Mapper; + maxWorkers: number; + mocksPattern?: string; + name: string; + platforms: Array; + providesModuleNodeModules?: Array; + resetCache?: boolean; + retainAllFiles: boolean; + rootDir: string; + roots: Array; + throwOnModuleCollision?: boolean; + useWatchman?: boolean; + watch?: boolean; }; type InternalOptions = { - cacheDirectory: string, - computeDependencies: boolean, - computeSha1: boolean, - dependencyExtractor?: string, - extensions: Array, - forceNodeFilesystemAPI: boolean, - hasteImplModulePath?: string, - ignorePattern: ?HasteRegExp, - mapper?: ?Mapper, - maxWorkers: number, - mocksPattern: ?RegExp, - name: string, - platforms: Array, - resetCache: ?boolean, - retainAllFiles: boolean, - rootDir: string, - roots: Array, - throwOnModuleCollision: boolean, - useWatchman: boolean, - watch: boolean, + cacheDirectory: string; + computeDependencies: boolean; + computeSha1: boolean; + dependencyExtractor?: string; + extensions: Array; + forceNodeFilesystemAPI: boolean; + hasteImplModulePath?: string; + ignorePattern?: HasteRegExp; + mapper?: Mapper; + maxWorkers: number; + mocksPattern: RegExp | null; + name: string; + platforms: Array; + resetCache?: boolean; + retainAllFiles: boolean; + rootDir: string; + roots: Array; + throwOnModuleCollision: boolean; + useWatchman: boolean; + watch: boolean; }; type Watcher = { - close(callback: () => void): void, + close(callback: () => void): void; }; -type WorkerInterface = {worker: typeof worker, getSha1: typeof getSha1}; +type WorkerInterface = {worker: typeof worker; getSha1: typeof getSha1}; export type ModuleMap = HasteModuleMap; export type SerializableModuleMap = HasteSerializableModuleMap; @@ -109,6 +106,11 @@ const CHANGE_INTERVAL = 30; const MAX_WAIT_TIME = 240000; const NODE_MODULES = path.sep + 'node_modules' + path.sep; +// TypeScript doesn't like us importing from outside `rootDir` +const {version: VERSION} = JSON.parse( + fs.readFileSync(require.resolve('../package.json'), 'utf8'), +); + const canUseWatchman = ((): boolean => { try { execSync('watchman --version', {stdio: ['ignore']}); @@ -117,10 +119,10 @@ const canUseWatchman = ((): boolean => { return false; })(); -const escapePathSeparator = string => +const escapePathSeparator = (string: string) => path.sep === '\\' ? string.replace(/(\/|\\)/g, '\\\\') : string; -const getWhiteList = (list: ?Array): ?RegExp => { +const getWhiteList = (list: Array | undefined): RegExp | null => { if (list && list.length) { const newList = list.map(item => escapePathSeparator(item.replace(/(\/)/g, path.sep)), @@ -218,14 +220,14 @@ const getWhiteList = (list: ?Array): ?RegExp => { * */ class HasteMap extends EventEmitter { - _buildPromise: ?Promise; - _cachePath: Path; - _changeInterval: IntervalID; + _buildPromise: Promise | null; + _cachePath: Config.Path; + _changeInterval?: NodeJS.Timeout; _console: Console; _options: InternalOptions; _watchers: Array; - _whitelist: ?RegExp; - _worker: ?WorkerInterface; + _whitelist: RegExp | null; + _worker: WorkerInterface | null; constructor(options: Options) { super(); @@ -309,7 +311,7 @@ class HasteMap extends EventEmitter { } static getCacheFilePath( - tmpdir: Path, + tmpdir: Config.Path, name: string, ...extra: Array ): string { @@ -344,7 +346,7 @@ class HasteMap extends EventEmitter { }); const __hasteMapForTest = (process.env.NODE_ENV === 'test' && hasteMap) || null; - return this._watch(hasteMap, hasteFS, moduleMap).then(() => ({ + return this._watch(hasteMap).then(() => ({ __hasteMapForTest, hasteFS, moduleMap, @@ -383,8 +385,8 @@ class HasteMap extends EventEmitter { * 2. crawl the file system. */ _buildFileMap(): Promise<{ - deprecatedFiles: Array<{moduleName: string, path: string}>, - hasteMap: InternalHasteMap, + deprecatedFiles: Array<{moduleName: string; path: string}>; + hasteMap: InternalHasteMap; }> { const read = this._options.resetCache ? this._createEmptyMap : this.read; @@ -392,7 +394,7 @@ class HasteMap extends EventEmitter { .then(() => read.call(this)) .catch(() => this._createEmptyMap()) .then(cachedHasteMap => { - const cachedFiles = []; + const cachedFiles: Array<{moduleName: string; path: string}> = []; for (const [relativeFilePath, fileMetadata] of cachedHasteMap.files) { const moduleName = fileMetadata[H.ID]; cachedFiles.push({moduleName, path: relativeFilePath}); @@ -413,15 +415,15 @@ class HasteMap extends EventEmitter { hasteMap: InternalHasteMap, map: ModuleMapData, mocks: MockData, - filePath: Path, - workerOptions: ?{forceInBand: boolean}, - ): ?Promise { + filePath: Config.Path, + workerOptions?: {forceInBand: boolean} | null, + ): Promise | null { const rootDir = this._options.rootDir; const setModule = (id: string, module: ModuleMetaData) => { let moduleMap = map.get(id); if (!moduleMap) { - moduleMap = Object.create(null); + moduleMap = Object.create(null) as {}; map.set(id, moduleMap); } const platform = @@ -489,7 +491,7 @@ class HasteMap extends EventEmitter { const computeSha1 = this._options.computeSha1 && !fileMetadata[H.SHA1]; // Callback called when the response from the worker is successful. - const workerReply = metadata => { + const workerReply = (metadata: WorkerMetadata) => { // `1` for truthy values instead of `true` to save cache space. fileMetadata[H.VISITED] = 1; @@ -509,13 +511,13 @@ class HasteMap extends EventEmitter { }; // Callback called when the response from the worker is an error. - const workerError = error => { + const workerError = (error: Error | unknown) => { if (typeof error !== 'object' || !error.message || !error.stack) { error = new Error(error); error.stack = ''; // Remove stack for stack-less errors. } - // $FlowFixMe: checking error code is OK if error comes from "fs". + // @ts-ignore: checking error code is OK if error comes from "fs". if (!['ENOENT', 'EACCES'].includes(error.code)) { throw error; } @@ -584,7 +586,7 @@ class HasteMap extends EventEmitter { const moduleId = fileMetadata[H.ID]; let modulesByPlatform = map.get(moduleId); if (!modulesByPlatform) { - modulesByPlatform = Object.create(null); + modulesByPlatform = Object.create(null) as {}; map.set(moduleId, modulesByPlatform); } modulesByPlatform[platform] = module; @@ -606,8 +608,8 @@ class HasteMap extends EventEmitter { } _buildHasteMap(data: { - deprecatedFiles: Array<{moduleName: string, path: string}>, - hasteMap: InternalHasteMap, + deprecatedFiles: Array<{moduleName: string; path: string}>; + hasteMap: InternalHasteMap; }): Promise { const {deprecatedFiles, hasteMap} = data; const map = new Map(); @@ -647,8 +649,9 @@ class HasteMap extends EventEmitter { _cleanup() { const worker = this._worker; - // $FlowFixMe + // @ts-ignore if (worker && typeof worker.end === 'function') { + // @ts-ignore worker.end(); } @@ -665,16 +668,17 @@ class HasteMap extends EventEmitter { /** * Creates workers or parses files and extracts metadata in-process. */ - _getWorker(options: ?{forceInBand: boolean}): WorkerInterface { + _getWorker(options?: {forceInBand: boolean} | null): WorkerInterface { if (!this._worker) { if ((options && options.forceInBand) || this._options.maxWorkers <= 1) { this._worker = {getSha1, worker}; } else { - this._worker = (new Worker(require.resolve('./worker'), { + // @ts-ignore: assignment of a worker with custom properties. + this._worker = new Worker(require.resolve('./worker'), { exposedMethods: ['getSha1', 'worker'], maxRetries: 3, numWorkers: this._options.maxWorkers, - }): WorkerInterface); + }) as WorkerInterface; } } @@ -687,7 +691,7 @@ class HasteMap extends EventEmitter { const crawl = canUseWatchman && this._options.useWatchman ? watchmanCrawl : nodeCrawl; - const retry = error => { + const retry = (error: Error) => { if (crawl === watchmanCrawl) { this._console.warn( `jest-haste-map: Watchman crawl failed. Retrying once with node ` + @@ -737,11 +741,7 @@ class HasteMap extends EventEmitter { /** * Watch mode */ - _watch( - hasteMap: InternalHasteMap, - hasteFS: HasteFS, - moduleMap: ModuleMap, - ): Promise { + _watch(hasteMap: InternalHasteMap): Promise { if (!this._options.watch) { return Promise.resolve(); } @@ -751,7 +751,7 @@ class HasteMap extends EventEmitter { this._options.throwOnModuleCollision = false; this._options.retainAllFiles = true; - const Watcher = + const Watcher: sane.Watcher = canUseWatchman && this._options.useWatchman ? WatchmanWatcher : os.platform() === 'darwin' @@ -762,11 +762,15 @@ class HasteMap extends EventEmitter { const rootDir = this._options.rootDir; let changeQueue = Promise.resolve(); - let eventsQueue = []; + let eventsQueue: Array<{ + filePath: Config.Path; + stat: fs.Stats | undefined; + type: string; + }> = []; // We only need to copy the entire haste map once on every "frame". let mustCopy = true; - const createWatcher = root => { + const createWatcher = (root: Config.Path): Promise => { const watcher = new Watcher(root, { dot: false, glob: extensions.map(extension => '**/*.' + extension), @@ -809,9 +813,9 @@ class HasteMap extends EventEmitter { const onChange = ( type: string, - filePath: Path, - root: Path, - stat: ?fs.Stats, + filePath: Config.Path, + root: Config.Path, + stat?: fs.Stats, ) => { filePath = path.join(root, normalizePathSep(filePath)); if ( @@ -831,8 +835,8 @@ class HasteMap extends EventEmitter { event.type === type && event.filePath === filePath && ((!event.stat && !stat) || - (event.stat && - stat && + (!!event.stat && + !!stat && event.stat.mtime.getTime() === stat.mtime.getTime())), ) ) { @@ -894,7 +898,7 @@ class HasteMap extends EventEmitter { stat, 'since the file exists or changed, it should have stats', ); - const fileMetadata = [ + const fileMetadata: FileMetaData = [ '', stat.mtime.getTime(), stat.size, @@ -924,7 +928,7 @@ class HasteMap extends EventEmitter { } return null; }) - .catch(error => { + .catch((error: Error) => { this._console.error( `jest-haste-map: watch error:\n ${error.stack}\n`, ); @@ -985,7 +989,7 @@ class HasteMap extends EventEmitter { let dedupMap = hasteMap.map.get(moduleName); if (dedupMap == null) { - dedupMap = Object.create(null); + dedupMap = Object.create(null) as {}; hasteMap.map.set(moduleName, dedupMap); } dedupMap[platform] = uniqueModule; @@ -1013,7 +1017,7 @@ class HasteMap extends EventEmitter { /** * Helpers */ - _ignore(filePath: Path): boolean { + _ignore(filePath: Config.Path): boolean { const ignorePattern = this._options.ignorePattern; const ignoreMatched = ignorePattern instanceof RegExp @@ -1026,7 +1030,7 @@ class HasteMap extends EventEmitter { ); } - _isNodeModulesDir(filePath: Path): boolean { + _isNodeModulesDir(filePath: Config.Path): boolean { if (!filePath.includes(NODE_MODULES)) { return false; } @@ -1059,10 +1063,12 @@ class HasteMap extends EventEmitter { } static H: HType; - static ModuleMap: Class; + static ModuleMap: typeof HasteModuleMap; } -const copy = object => Object.assign(Object.create(null), object); +function copy(object: T): T { + return Object.assign(Object.create(null), object); +} function copyMap(input: Map): Map { return new Map(input); diff --git a/packages/jest-haste-map/src/lib/WatchmanWatcher.js b/packages/jest-haste-map/src/lib/WatchmanWatcher.js index f7436aaa9f0f..af0f49c45abd 100644 --- a/packages/jest-haste-map/src/lib/WatchmanWatcher.js +++ b/packages/jest-haste-map/src/lib/WatchmanWatcher.js @@ -8,9 +8,9 @@ import fs from 'fs'; import path from 'path'; import assert from 'assert'; -import common from 'sane/src/common'; -import watchman from 'fb-watchman'; import {EventEmitter} from 'events'; +import watchman from 'fb-watchman'; +import common from 'sane/src/common'; import RecrawlWarning from 'sane/src/utils/recrawl-warning-dedupe'; const CHANGE_EVENT = common.CHANGE_EVENT; diff --git a/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js b/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js index 9809a38140b8..e13ed50c735f 100644 --- a/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js +++ b/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import {extract} from '../dependencyExtractor'; diff --git a/packages/jest-haste-map/src/lib/__tests__/fast_path.test.js b/packages/jest-haste-map/src/lib/__tests__/fast_path.test.js index 170a7861a55a..fd76610eca4a 100644 --- a/packages/jest-haste-map/src/lib/__tests__/fast_path.test.js +++ b/packages/jest-haste-map/src/lib/__tests__/fast_path.test.js @@ -7,8 +7,6 @@ * */ -'use strict'; - import path from 'path'; import {relative, resolve} from '../fast_path'; diff --git a/packages/jest-haste-map/src/lib/__tests__/getPlatformExtension.test.js b/packages/jest-haste-map/src/lib/__tests__/getPlatformExtension.test.js index 16a2b0b3cee6..6541ac0e16a2 100644 --- a/packages/jest-haste-map/src/lib/__tests__/getPlatformExtension.test.js +++ b/packages/jest-haste-map/src/lib/__tests__/getPlatformExtension.test.js @@ -7,8 +7,6 @@ * */ -'use strict'; - import getPlatformExtension from '../getPlatformExtension'; describe('getPlatformExtension', () => { diff --git a/packages/jest-haste-map/src/lib/__tests__/isRegExpSupported.test.js b/packages/jest-haste-map/src/lib/__tests__/isRegExpSupported.test.js index 740f3dd5eb3d..b27295eaa320 100644 --- a/packages/jest-haste-map/src/lib/__tests__/isRegExpSupported.test.js +++ b/packages/jest-haste-map/src/lib/__tests__/isRegExpSupported.test.js @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import isRegExpSupported from '../isRegExpSupported'; diff --git a/packages/jest-haste-map/src/lib/dependencyExtractor.js b/packages/jest-haste-map/src/lib/dependencyExtractor.ts similarity index 86% rename from packages/jest-haste-map/src/lib/dependencyExtractor.js rename to packages/jest-haste-map/src/lib/dependencyExtractor.ts index b55cff653f1d..1e10b59db7c2 100644 --- a/packages/jest-haste-map/src/lib/dependencyExtractor.js +++ b/packages/jest-haste-map/src/lib/dependencyExtractor.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import isRegExpSupported from './isRegExpSupported'; @@ -13,22 +11,23 @@ import isRegExpSupported from './isRegExpSupported'; const NOT_A_DOT = isRegExpSupported('(? `([\`'"])([^'"\`]*?)(?:\\${pos})`; +const CAPTURE_STRING_LITERAL = (pos: number) => + `([\`'"])([^'"\`]*?)(?:\\${pos})`; const WORD_SEPARATOR = '\\b'; const LEFT_PARENTHESIS = '\\('; const RIGHT_PARENTHESIS = '\\)'; const WHITESPACE = '\\s*'; const OPTIONAL_COMMA = '(:?,\\s*)?'; -function createRegExp(parts, flags) { +function createRegExp(parts: Array, flags: string) { return new RegExp(parts.join(''), flags); } -function alternatives(...parts) { +function alternatives(...parts: Array) { return `(?:${parts.join('|')})`; } -function functionCallStart(...names) { +function functionCallStart(...names: Array) { return [ NOT_A_DOT, WORD_SEPARATOR, @@ -78,7 +77,7 @@ const JEST_EXTENSIONS_RE = createRegExp( export function extract(code: string): Set { const dependencies = new Set(); - const addDependency = (match: string, q: string, dep: string) => { + const addDependency = (match: string, _: string, dep: string) => { dependencies.add(dep); return match; }; diff --git a/packages/jest-haste-map/src/lib/fast_path.js b/packages/jest-haste-map/src/lib/fast_path.ts similarity index 98% rename from packages/jest-haste-map/src/lib/fast_path.js rename to packages/jest-haste-map/src/lib/fast_path.ts index 4312eee07d93..f293c8a0f2bb 100644 --- a/packages/jest-haste-map/src/lib/fast_path.js +++ b/packages/jest-haste-map/src/lib/fast_path.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import path from 'path'; diff --git a/packages/jest-haste-map/src/lib/getPlatformExtension.js b/packages/jest-haste-map/src/lib/getPlatformExtension.ts similarity index 79% rename from packages/jest-haste-map/src/lib/getPlatformExtension.js rename to packages/jest-haste-map/src/lib/getPlatformExtension.ts index f5fe9e1d7422..f9dac1dace0d 100644 --- a/packages/jest-haste-map/src/lib/getPlatformExtension.js +++ b/packages/jest-haste-map/src/lib/getPlatformExtension.ts @@ -3,22 +3,15 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -const SUPPORTED_PLATFORM_EXTS = { - android: true, - ios: true, - native: true, - web: true, -}; +const SUPPORTED_PLATFORM_EXTS = new Set(['android', 'ios', 'native', 'web']); // Extract platform extension: index.ios.js -> ios export default function getPlatformExtension( file: string, platforms?: Array, -): ?string { +): string | null { const last = file.lastIndexOf('.'); const secondToLast = file.lastIndexOf('.', last - 1); if (secondToLast === -1) { @@ -30,5 +23,5 @@ export default function getPlatformExtension( if (platforms && platforms.indexOf(platform) !== -1) { return platform; } - return SUPPORTED_PLATFORM_EXTS[platform] ? platform : null; + return SUPPORTED_PLATFORM_EXTS.has(platform) ? platform : null; } diff --git a/packages/jest-haste-map/src/lib/isRegExpSupported.js b/packages/jest-haste-map/src/lib/isRegExpSupported.ts similarity index 97% rename from packages/jest-haste-map/src/lib/isRegExpSupported.js rename to packages/jest-haste-map/src/lib/isRegExpSupported.ts index ffcdc63193cc..9f35631ae46d 100644 --- a/packages/jest-haste-map/src/lib/isRegExpSupported.js +++ b/packages/jest-haste-map/src/lib/isRegExpSupported.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ export default function isRegExpSupported(value: string): boolean { diff --git a/packages/jest-haste-map/src/lib/normalizePathSep.js b/packages/jest-haste-map/src/lib/normalizePathSep.ts similarity index 84% rename from packages/jest-haste-map/src/lib/normalizePathSep.js rename to packages/jest-haste-map/src/lib/normalizePathSep.ts index b10f0c4f5de4..7c84e8377c55 100644 --- a/packages/jest-haste-map/src/lib/normalizePathSep.js +++ b/packages/jest-haste-map/src/lib/normalizePathSep.ts @@ -3,13 +3,11 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -const path = require('path'); +import path from 'path'; -let normalizePathSep; +let normalizePathSep: (string: string) => string; if (path.sep === '/') { normalizePathSep = (filePath: string) => filePath; } else { diff --git a/packages/jest-haste-map/src/types.js b/packages/jest-haste-map/src/types.js deleted file mode 100644 index 2577c5329296..000000000000 --- a/packages/jest-haste-map/src/types.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {InternalHasteMap, ModuleMetaData} from 'types/HasteMap'; - -export type IgnoreMatcher = (item: string) => boolean; -export type Mapper = (item: string) => ?Array; - -export type WorkerMessage = { - computeDependencies: boolean, - computeSha1: boolean, - dependencyExtractor?: string, - rootDir: string, - filePath: string, - hasteImplModulePath?: string, -}; - -export type WorkerMetadata = {| - dependencies: ?Array, - id: ?string, - module: ?ModuleMetaData, - sha1: ?string, -|}; - -export type CrawlerOptions = {| - computeSha1: boolean, - data: InternalHasteMap, - extensions: Array, - forceNodeFilesystemAPI: boolean, - ignore: IgnoreMatcher, - mapper?: ?Mapper, - rootDir: string, - roots: Array, -|}; - -export type HasteImpl = { - getHasteName(filePath: string): string | void, -}; diff --git a/packages/jest-haste-map/src/types.ts b/packages/jest-haste-map/src/types.ts new file mode 100644 index 000000000000..b44c004656b0 --- /dev/null +++ b/packages/jest-haste-map/src/types.ts @@ -0,0 +1,104 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {Config} from '@jest/types'; +import ModuleMap from './ModuleMap'; +import HasteFS from './HasteFS'; + +export type IgnoreMatcher = (item: string) => boolean; +export type Mapper = (item: string) => Array | null; + +export type WorkerMessage = { + computeDependencies: boolean; + computeSha1: boolean; + dependencyExtractor?: string; + rootDir: string; + filePath: string; + hasteImplModulePath?: string; +}; + +export type WorkerMetadata = { + dependencies: Array | undefined | null; + id: string | undefined | null; + module: ModuleMetaData | undefined | null; + sha1: string | undefined | null; +}; + +export type CrawlerOptions = { + computeSha1: boolean; + data: InternalHasteMap; + extensions: Array; + forceNodeFilesystemAPI: boolean; + ignore: IgnoreMatcher; + mapper?: Mapper | null; + rootDir: string; + roots: Array; +}; + +export type HasteImpl = { + getHasteName(filePath: Config.Path): string | void; +}; + +export type FileData = Map; + +export type FileMetaData = [ + /* id */ string, + /* mtime */ number, + /* size */ number, + /* visited */ 0 | 1, + /* dependencies */ Array, + /* sha1 */ string | null | undefined +]; + +export type MockData = Map; +export type ModuleMapData = Map; +export type WatchmanClocks = Map; +export type HasteRegExp = RegExp | ((str: string) => boolean); + +export type DuplicatesSet = Map; +export type DuplicatesIndex = Map>; + +export type InternalHasteMap = { + clocks: WatchmanClocks; + duplicates: DuplicatesIndex; + files: FileData; + map: ModuleMapData; + mocks: MockData; +}; + +export type HasteMap = { + hasteFS: HasteFS; + moduleMap: ModuleMap; + __hasteMapForTest?: InternalHasteMap | null; +}; + +export type RawModuleMap = { + rootDir: Config.Path; + duplicates: DuplicatesIndex; + map: ModuleMapData; + mocks: MockData; +}; + +type ModuleMapItem = {[platform: string]: ModuleMetaData}; +export type ModuleMetaData = [Config.Path, /* type */ number]; + +export type HType = { + ID: 0; + MTIME: 1; + SIZE: 2; + VISITED: 3; + DEPENDENCIES: 4; + SHA1: 5; + PATH: 0; + TYPE: 1; + MODULE: 0; + PACKAGE: 1; + GENERIC_PLATFORM: 'g'; + NATIVE_PLATFORM: 'native'; +}; + +export type HTypeValue = HType[keyof HType]; diff --git a/packages/jest-haste-map/src/worker.js b/packages/jest-haste-map/src/worker.ts similarity index 91% rename from packages/jest-haste-map/src/worker.js rename to packages/jest-haste-map/src/worker.ts index 1b0165f19425..bb7c60122dad 100644 --- a/packages/jest-haste-map/src/worker.js +++ b/packages/jest-haste-map/src/worker.ts @@ -3,23 +3,20 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {HasteImpl, WorkerMessage, WorkerMetadata} from './types'; - import crypto from 'crypto'; import path from 'path'; import fs from 'graceful-fs'; +import {HasteImpl, WorkerMessage, WorkerMetadata} from './types'; import blacklist from './blacklist'; import H from './constants'; import * as dependencyExtractor from './lib/dependencyExtractor'; const PACKAGE_JSON = path.sep + 'package.json'; -let hasteImpl: ?HasteImpl = null; -let hasteImplModulePath: ?string = null; +let hasteImpl: HasteImpl | null = null; +let hasteImplModulePath: string | null = null; function sha1hex(content: string | Buffer): string { return crypto @@ -38,11 +35,11 @@ export async function worker(data: WorkerMessage): Promise { } hasteImplModulePath = data.hasteImplModulePath; // $FlowFixMe: dynamic require - hasteImpl = (require(hasteImplModulePath): HasteImpl); + hasteImpl = require(hasteImplModulePath); } - let content; - let dependencies; + let content: string | undefined; + let dependencies: Array | undefined; let id; let module; let sha1; diff --git a/packages/jest-haste-map/tsconfig.json b/packages/jest-haste-map/tsconfig.json new file mode 100644 index 000000000000..8290de687869 --- /dev/null +++ b/packages/jest-haste-map/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build" + }, + "references": [ + {"path": "../jest-worker"}, + {"path": "../jest-serializer"}, + {"path": "../jest-util"}, + {"path": "../jest-types"} + ] +} diff --git a/tsconfig.json b/tsconfig.json index 6b1f7373d1ab..9c25fc411393 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,7 +20,8 @@ /* Module Resolution Options */ "moduleResolution": "node", - "esModuleInterop": true + "esModuleInterop": true, + "resolveJsonModule": true }, "exclude": ["**/__tests__/**/*", "**/build/**/*", "**/build-es5/**/*"] } From 3717a2e928e61f1dc098fff306069a2cfa71ed55 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 10:34:40 +0100 Subject: [PATCH 02/16] PR feedback --- packages/jest-haste-map/src/ModuleMap.ts | 4 ++-- packages/jest-haste-map/src/crawlers/node.ts | 2 +- packages/jest-haste-map/src/index.ts | 20 +++++++++----------- packages/jest-haste-map/src/worker.ts | 4 +--- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index cde59fe06d2a..8f811da6915f 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -46,7 +46,7 @@ export default class ModuleMap { supportsNativePlatform: boolean | null, type: HTypeValue | null, ): string | null { - if (!type) { + if (type == null) { type = H.MODULE; } const module = this._getModuleMetadata( @@ -64,7 +64,7 @@ export default class ModuleMap { getPackage( name: string, platform: string | null, - _: boolean | null, + _supportsNativePlatform: boolean | null, ): string | null { return this.getModule(name, platform, null, H.PACKAGE); } diff --git a/packages/jest-haste-map/src/crawlers/node.ts b/packages/jest-haste-map/src/crawlers/node.ts index ec4aaa927e4f..6813e79ac519 100644 --- a/packages/jest-haste-map/src/crawlers/node.ts +++ b/packages/jest-haste-map/src/crawlers/node.ts @@ -78,7 +78,7 @@ function findNative( ignore: IgnoreMatcher, callback: Callback, ): void { - const args = roots.slice(); + const args = Array.from(roots); args.push('-type', 'f'); if (extensions.length) { args.push('('); diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index 0fdf524f59b4..4e328f6dd27b 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -273,7 +273,6 @@ class HasteMap extends EventEmitter { let dependencyExtractorHash = ''; if (options.hasteImplModulePath) { - // $FlowFixMe: dynamic require const hasteImpl = require(options.hasteImplModulePath); if (hasteImpl.getCacheKey) { hasteImplHash = String(hasteImpl.getCacheKey()); @@ -281,7 +280,6 @@ class HasteMap extends EventEmitter { } if (options.dependencyExtractor) { - // $FlowFixMe: dynamic require const dependencyExtractor = require(options.dependencyExtractor); if (dependencyExtractor.getCacheKey) { dependencyExtractorHash = String(dependencyExtractor.getCacheKey()); @@ -416,7 +414,7 @@ class HasteMap extends EventEmitter { map: ModuleMapData, mocks: MockData, filePath: Config.Path, - workerOptions?: {forceInBand: boolean} | null, + workerOptions?: {forceInBand: boolean}, ): Promise | null { const rootDir = this._options.rootDir; @@ -661,14 +659,14 @@ class HasteMap extends EventEmitter { /** * 4. serialize the new `HasteMap` in a cache file. */ - _persist(hasteMap: InternalHasteMap) { + private _persist(hasteMap: InternalHasteMap) { serializer.writeFileSync(this._cachePath, hasteMap); } /** * Creates workers or parses files and extracts metadata in-process. */ - _getWorker(options?: {forceInBand: boolean} | null): WorkerInterface { + private _getWorker(options?: {forceInBand: boolean}): WorkerInterface { if (!this._worker) { if ((options && options.forceInBand) || this._options.maxWorkers <= 1) { this._worker = {getSha1, worker}; @@ -685,7 +683,7 @@ class HasteMap extends EventEmitter { return this._worker; } - _crawl(hasteMap: InternalHasteMap): Promise { + private _crawl(hasteMap: InternalHasteMap): Promise { const options = this._options; const ignore = this._ignore.bind(this); const crawl = @@ -741,7 +739,7 @@ class HasteMap extends EventEmitter { /** * Watch mode */ - _watch(hasteMap: InternalHasteMap): Promise { + private _watch(hasteMap: InternalHasteMap): Promise { if (!this._options.watch) { return Promise.resolve(); } @@ -951,7 +949,7 @@ class HasteMap extends EventEmitter { * 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( + private _recoverDuplicates( hasteMap: InternalHasteMap, relativeFilePath: string, moduleName: string, @@ -1017,7 +1015,7 @@ class HasteMap extends EventEmitter { /** * Helpers */ - _ignore(filePath: Config.Path): boolean { + private _ignore(filePath: Config.Path): boolean { const ignorePattern = this._options.ignorePattern; const ignoreMatched = ignorePattern instanceof RegExp @@ -1030,7 +1028,7 @@ class HasteMap extends EventEmitter { ); } - _isNodeModulesDir(filePath: Config.Path): boolean { + private _isNodeModulesDir(filePath: Config.Path): boolean { if (!filePath.includes(NODE_MODULES)) { return false; } @@ -1052,7 +1050,7 @@ class HasteMap extends EventEmitter { return true; } - _createEmptyMap(): InternalHasteMap { + private _createEmptyMap(): InternalHasteMap { return { clocks: new Map(), duplicates: new Map(), diff --git a/packages/jest-haste-map/src/worker.ts b/packages/jest-haste-map/src/worker.ts index bb7c60122dad..a9ee0d715f02 100644 --- a/packages/jest-haste-map/src/worker.ts +++ b/packages/jest-haste-map/src/worker.ts @@ -34,7 +34,6 @@ export async function worker(data: WorkerMessage): Promise { throw new Error('jest-haste-map: hasteImplModulePath changed'); } hasteImplModulePath = data.hasteImplModulePath; - // $FlowFixMe: dynamic require hasteImpl = require(hasteImplModulePath); } @@ -77,8 +76,7 @@ export async function worker(data: WorkerMessage): Promise { const content = getContent(); dependencies = Array.from( data.dependencyExtractor - ? // $FlowFixMe - require(data.dependencyExtractor).extract( + ? require(data.dependencyExtractor).extract( content, filePath, dependencyExtractor.extract, From e405c065538f67f4286aa5531c58100cc460cf29 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 10:39:46 +0100 Subject: [PATCH 03/16] fix a type error --- packages/jest-haste-map/src/types.ts | 2 +- packages/jest-haste-map/src/worker.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/jest-haste-map/src/types.ts b/packages/jest-haste-map/src/types.ts index b44c004656b0..c5e85fc8d9b9 100644 --- a/packages/jest-haste-map/src/types.ts +++ b/packages/jest-haste-map/src/types.ts @@ -40,7 +40,7 @@ export type CrawlerOptions = { }; export type HasteImpl = { - getHasteName(filePath: Config.Path): string | void; + getHasteName(filePath: Config.Path): string | undefined; }; export type FileData = Map; diff --git a/packages/jest-haste-map/src/worker.ts b/packages/jest-haste-map/src/worker.ts index a9ee0d715f02..4f3772d1db03 100644 --- a/packages/jest-haste-map/src/worker.ts +++ b/packages/jest-haste-map/src/worker.ts @@ -38,10 +38,10 @@ export async function worker(data: WorkerMessage): Promise { } let content: string | undefined; - let dependencies: Array | undefined; - let id; - let module; - let sha1; + let dependencies: WorkerMetadata['dependencies']; + let id: WorkerMetadata['id']; + let module: WorkerMetadata['module']; + let sha1: WorkerMetadata['sha1']; const {computeDependencies, computeSha1, rootDir, filePath} = data; From 542f33686ff57ba97aa188f28910d2592a493a84 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 10:52:34 +0100 Subject: [PATCH 04/16] update lockfile --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index e28de1a42440..4d6dea0f8c63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1688,7 +1688,7 @@ dependencies: "@types/node" "*" -"@types/node@*": +"@types/node@*", "@types/node@^10.12.24": version "10.12.24" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.24.tgz#b13564af612a22a20b5d95ca40f1bffb3af315cf" integrity sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ== From 5e2774ff87487ae806660b150d372ed4831020dc Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 22:32:42 +0100 Subject: [PATCH 05/16] some more types slayed --- packages/jest-haste-map/src/ModuleMap.ts | 4 ++-- packages/jest-haste-map/src/crawlers/watchman.ts | 7 +++++-- packages/jest-haste-map/src/index.ts | 15 ++++++++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index 8f811da6915f..7db3f3dae933 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -34,7 +34,7 @@ export type SerializableModuleMap = { export default class ModuleMap { private readonly _raw: RawModuleMap; - static DuplicateHasteCandidatesError: DuplicateHasteCandidatesError; + static DuplicateHasteCandidatesError: typeof DuplicateHasteCandidatesError; constructor(raw: RawModuleMap) { this._raw = raw; @@ -187,7 +187,7 @@ export default class ModuleMap { } } -export class DuplicateHasteCandidatesError extends Error { +class DuplicateHasteCandidatesError extends Error { hasteName: string; platform: string | null; supportsNativePlatform: boolean; diff --git a/packages/jest-haste-map/src/crawlers/watchman.ts b/packages/jest-haste-map/src/crawlers/watchman.ts index 873e917a992e..94906a2a38cb 100644 --- a/packages/jest-haste-map/src/crawlers/watchman.ts +++ b/packages/jest-haste-map/src/crawlers/watchman.ts @@ -41,6 +41,7 @@ export = async function watchmanCrawl( let clientError; client.on('error', error => (clientError = WatchmanError(error))); + // TODO: type better than `any` const cmd = (...args: Array): Promise => new Promise((resolve, reject) => client.command(args, (error, result) => @@ -138,7 +139,7 @@ export = async function watchmanCrawl( } let files = data.files; - let watchmanFiles; + let watchmanFiles: Map; try { const watchmanRoots = await getWatchmanRoots(roots); const watchmanFileResults = await queryWatchmanForDirs(watchmanRoots); @@ -158,7 +159,8 @@ export = async function watchmanCrawl( throw clientError; } - for (const [watchRoot, response] of watchmanFiles) { + // TODO: remove non-null + for (const [watchRoot, response] of watchmanFiles!) { const fsRoot = normalizePathSep(watchRoot); const relativeFsRoot = fastPath.relative(rootDir, fsRoot); clocks.set(relativeFsRoot, response.clock); @@ -191,6 +193,7 @@ export = async function watchmanCrawl( sha1hex && existingFileData[H.SHA1] === sha1hex ) { + // @ts-ignore: TODO why is this wrong? nextData = [...existingFileData]; nextData[1] = mtime; } else { diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index 4e328f6dd27b..641e1285386f 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -509,7 +509,7 @@ class HasteMap extends EventEmitter { }; // Callback called when the response from the worker is an error. - const workerError = (error: Error | unknown) => { + const workerError = (error: Error | any) => { if (typeof error !== 'object' || !error.message || !error.stack) { error = new Error(error); error.stack = ''; // Remove stack for stack-less errors. @@ -759,7 +759,7 @@ class HasteMap extends EventEmitter { const ignorePattern = this._options.ignorePattern; const rootDir = this._options.rootDir; - let changeQueue = Promise.resolve(); + let changeQueue: Promise = Promise.resolve(); let eventsQueue: Array<{ filePath: Config.Path; stat: fs.Stats | undefined; @@ -769,6 +769,7 @@ class HasteMap extends EventEmitter { let mustCopy = true; const createWatcher = (root: Config.Path): Promise => { + // @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), @@ -852,7 +853,10 @@ class HasteMap extends EventEmitter { }; } - const add = () => eventsQueue.push({filePath, stat, type}); + const add = () => { + eventsQueue.push({filePath, stat, type}); + return null; + }; const relativeFilePath = fastPath.relative(rootDir, filePath); const fileMetadata = hasteMap.files.get(relativeFilePath); @@ -898,8 +902,8 @@ class HasteMap extends EventEmitter { ); const fileMetadata: FileMetaData = [ '', - stat.mtime.getTime(), - stat.size, + stat ? stat.mtime.getTime() : -1, + stat ? stat.size : 0, 0, [], null, @@ -998,6 +1002,7 @@ class HasteMap extends EventEmitter { } end(): Promise { + // @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(); From ef6dfdcd823e2b348020a6c0b9d47f8f45c4cd03 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Mon, 11 Feb 2019 22:28:03 +0000 Subject: [PATCH 06/16] Fix broken type definitions --- packages/jest-haste-map/src/ModuleMap.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index 7db3f3dae933..7441fed6b0c7 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -22,13 +22,13 @@ import H from './constants'; const EMPTY_OBJ = {} as {[key: string]: any}; const EMPTY_MAP = new Map(); -type ValueType = T extends Map ? V : T; +type ValueType = T extends Map ? V : T; export type SerializableModuleMap = { // There is no easier way to extract the type of the entries of a Map - duplicates: [string, ValueType]; - map: [string, ValueType]; - mocks: [string, ValueType]; + duplicates: ReadonlyArray<[string, ValueType]>; + map: ReadonlyArray<[string, ValueType]>; + mocks: ReadonlyArray<[string, ValueType]>; rootDir: Config.Path; }; From e7476abf2b246722476825cf07793cb5f7801cd9 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 23:37:33 +0100 Subject: [PATCH 07/16] never!! --- packages/jest-haste-map/src/ModuleMap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index 7441fed6b0c7..5961c1253670 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -22,7 +22,7 @@ import H from './constants'; const EMPTY_OBJ = {} as {[key: string]: any}; const EMPTY_MAP = new Map(); -type ValueType = T extends Map ? V : T; +type ValueType = T extends Map ? V : never; export type SerializableModuleMap = { // There is no easier way to extract the type of the entries of a Map From e4bb9fea67bd09f3754c2decba3df5c3a6a36e81 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 23:41:16 +0100 Subject: [PATCH 08/16] remove old comment --- packages/jest-haste-map/src/ModuleMap.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index 5961c1253670..d4f9c377e59e 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -25,7 +25,6 @@ const EMPTY_MAP = new Map(); type ValueType = T extends Map ? V : never; export type SerializableModuleMap = { - // There is no easier way to extract the type of the entries of a Map duplicates: ReadonlyArray<[string, ValueType]>; map: ReadonlyArray<[string, ValueType]>; mocks: ReadonlyArray<[string, ValueType]>; From 1d5836471f5a3cc9778cc32a391fb2d405a23ac3 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 23:51:01 +0100 Subject: [PATCH 09/16] use path type --- packages/jest-haste-map/src/ModuleMap.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index d4f9c377e59e..be8e845ca53e 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -44,7 +44,7 @@ export default class ModuleMap { platform: string | null, supportsNativePlatform: boolean | null, type: HTypeValue | null, - ): string | null { + ): Config.Path | null { if (type == null) { type = H.MODULE; } @@ -64,11 +64,11 @@ export default class ModuleMap { name: string, platform: string | null, _supportsNativePlatform: boolean | null, - ): string | null { + ): Config.Path | null { return this.getModule(name, platform, null, H.PACKAGE); } - getMockModule(name: string): string | undefined { + getMockModule(name: string): Config.Path | undefined { const mockPath = this._raw.mocks.get(name) || this._raw.mocks.get(name + '/index'); return mockPath && fastPath.resolve(this._raw.rootDir, mockPath); From 8ee92dc11c32f11cde5417199e73db8d56c86c10 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 23:55:53 +0100 Subject: [PATCH 10/16] use path type, again --- packages/jest-haste-map/src/ModuleMap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index be8e845ca53e..07246b1babcb 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -176,7 +176,7 @@ export default class ModuleMap { ); } - static create(rootDir: string) { + static create(rootDir: Config.Path) { return new ModuleMap({ duplicates: new Map(), map: new Map(), From c0db70f8c751e41d451c5214f09a2d1a89e735f9 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 11 Feb 2019 23:56:14 +0100 Subject: [PATCH 11/16] --wip-- [skip ci] --- packages/jest-haste-map/build/HasteFS.js | 231 +++ packages/jest-haste-map/build/ModuleMap.js | 302 ++++ packages/jest-haste-map/build/blacklist.js | 58 + packages/jest-haste-map/build/constants.js | 47 + .../jest-haste-map/build/crawlers/node.js | 258 ++++ .../jest-haste-map/build/crawlers/watchman.js | 559 ++++++++ packages/jest-haste-map/build/getMockName.js | 38 + packages/jest-haste-map/build/index.js | 1272 +++++++++++++++++ .../build/lib/WatchmanWatcher.js | 400 ++++++ .../build/lib/dependencyExtractor.js | 100 ++ .../jest-haste-map/build/lib/fast_path.js | 43 + .../build/lib/getPlatformExtension.js | 31 + .../build/lib/isRegExpSupported.js | 22 + .../build/lib/normalizePathSep.js | 37 + packages/jest-haste-map/build/types.js | 1 + packages/jest-haste-map/build/worker.js | 230 +++ 16 files changed, 3629 insertions(+) create mode 100644 packages/jest-haste-map/build/HasteFS.js create mode 100644 packages/jest-haste-map/build/ModuleMap.js create mode 100644 packages/jest-haste-map/build/blacklist.js create mode 100644 packages/jest-haste-map/build/constants.js create mode 100644 packages/jest-haste-map/build/crawlers/node.js create mode 100644 packages/jest-haste-map/build/crawlers/watchman.js create mode 100644 packages/jest-haste-map/build/getMockName.js create mode 100644 packages/jest-haste-map/build/index.js create mode 100644 packages/jest-haste-map/build/lib/WatchmanWatcher.js create mode 100644 packages/jest-haste-map/build/lib/dependencyExtractor.js create mode 100644 packages/jest-haste-map/build/lib/fast_path.js create mode 100644 packages/jest-haste-map/build/lib/getPlatformExtension.js create mode 100644 packages/jest-haste-map/build/lib/isRegExpSupported.js create mode 100644 packages/jest-haste-map/build/lib/normalizePathSep.js create mode 100644 packages/jest-haste-map/build/types.js create mode 100644 packages/jest-haste-map/build/worker.js diff --git a/packages/jest-haste-map/build/HasteFS.js b/packages/jest-haste-map/build/HasteFS.js new file mode 100644 index 000000000000..7489b7662a1e --- /dev/null +++ b/packages/jest-haste-map/build/HasteFS.js @@ -0,0 +1,231 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = void 0; + +function _micromatch() { + const data = _interopRequireDefault(require('micromatch')); + + _micromatch = function _micromatch() { + return data; + }; + + return data; +} + +function _jestUtil() { + const data = require('jest-util'); + + _jestUtil = function _jestUtil() { + return data; + }; + + return data; +} + +var fastPath = _interopRequireWildcard(require('./lib/fast_path')); + +var _constants = _interopRequireDefault(require('./constants')); + +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}; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +class HasteFS { + constructor({rootDir, files}) { + this._rootDir = rootDir; + this._files = files; + } + + getModuleName(file) { + const fileMetadata = this._getFileData(file); + + return (fileMetadata && fileMetadata[_constants.default.ID]) || null; + } + + getSize(file) { + const fileMetadata = this._getFileData(file); + + return (fileMetadata && fileMetadata[_constants.default.SIZE]) || null; + } + + getDependencies(file) { + const fileMetadata = this._getFileData(file); + + return ( + (fileMetadata && fileMetadata[_constants.default.DEPENDENCIES]) || null + ); + } + + getSha1(file) { + const fileMetadata = this._getFileData(file); + + return (fileMetadata && fileMetadata[_constants.default.SHA1]) || null; + } + + exists(file) { + return this._getFileData(file) != null; + } + + getAllFiles() { + return Array.from(this.getAbsoluteFileIterator()); + } + + getFileIterator() { + return this._files.keys(); + } + + *getAbsoluteFileIterator() { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for ( + var _iterator = this.getFileIterator()[Symbol.iterator](), _step; + !(_iteratorNormalCompletion = (_step = _iterator.next()).done); + _iteratorNormalCompletion = true + ) { + const file = _step.value; + yield fastPath.resolve(this._rootDir, file); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + + matchFiles(pattern) { + if (!(pattern instanceof RegExp)) { + pattern = new RegExp(pattern); + } + + const files = []; + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for ( + var _iterator2 = this.getAbsoluteFileIterator()[Symbol.iterator](), + _step2; + !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); + _iteratorNormalCompletion2 = true + ) { + const file = _step2.value; + + if (pattern.test(file)) { + files.push(file); + } + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return != null) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + return files; + } + + matchFilesWithGlob(globs, root) { + const files = new Set(); + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for ( + var _iterator3 = this.getAbsoluteFileIterator()[Symbol.iterator](), + _step3; + !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); + _iteratorNormalCompletion3 = true + ) { + const file = _step3.value; + const filePath = root ? fastPath.relative(root, file) : file; + + if ( + _micromatch().default.some( + (0, _jestUtil().replacePathSepForGlob)(filePath), + globs + ) + ) { + files.add(file); + } + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return != null) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + + return files; + } + + _getFileData(file) { + const relativePath = fastPath.relative(this._rootDir, file); + return this._files.get(relativePath); + } +} + +exports.default = HasteFS; diff --git a/packages/jest-haste-map/build/ModuleMap.js b/packages/jest-haste-map/build/ModuleMap.js new file mode 100644 index 000000000000..791d833f0290 --- /dev/null +++ b/packages/jest-haste-map/build/ModuleMap.js @@ -0,0 +1,302 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = void 0; + +var fastPath = _interopRequireWildcard(require('./lib/fast_path')); + +var _constants = _interopRequireDefault(require('./constants')); + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +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 _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; +} + +const EMPTY_OBJ = {}; +const EMPTY_MAP = new Map(); + +class ModuleMap { + constructor(raw) { + this._raw = raw; + } + + getModule(name, platform, supportsNativePlatform, type) { + if (type == null) { + type = _constants.default.MODULE; + } + + const module = this._getModuleMetadata( + name, + platform, + !!supportsNativePlatform + ); + + if (module && module[_constants.default.TYPE] === type) { + const modulePath = module[_constants.default.PATH]; + return modulePath && fastPath.resolve(this._raw.rootDir, modulePath); + } + + return null; + } + + getPackage(name, platform, _supportsNativePlatform) { + return this.getModule(name, platform, null, _constants.default.PACKAGE); + } + + getMockModule(name) { + const mockPath = + this._raw.mocks.get(name) || this._raw.mocks.get(name + '/index'); + + return mockPath && fastPath.resolve(this._raw.rootDir, mockPath); + } + + getRawModuleMap() { + return { + duplicates: this._raw.duplicates, + map: this._raw.map, + mocks: this._raw.mocks, + rootDir: this._raw.rootDir + }; + } + + toJSON() { + return { + duplicates: Array.from(this._raw.duplicates), + map: Array.from(this._raw.map), + mocks: Array.from(this._raw.mocks), + rootDir: this._raw.rootDir + }; + } + + static fromJSON(serializableModuleMap) { + return new ModuleMap({ + duplicates: new Map(serializableModuleMap.duplicates), + map: new Map(serializableModuleMap.map), + mocks: new Map(serializableModuleMap.mocks), + rootDir: serializableModuleMap.rootDir + }); + } + /** + * When looking up a module's data, we walk through each eligible platform for + * the query. For each platform, we want to check if there are known + * duplicates for that name+platform pair. The duplication logic normally + * removes elements from the `map` object, but we want to check upfront to be + * extra sure. If metadata exists both in the `duplicates` object and the + * `map`, this would be a bug. + */ + + _getModuleMetadata(name, platform, supportsNativePlatform) { + const map = this._raw.map.get(name) || EMPTY_OBJ; + const dupMap = this._raw.duplicates.get(name) || EMPTY_MAP; + + if (platform != null) { + this._assertNoDuplicates( + name, + platform, + supportsNativePlatform, + dupMap.get(platform) + ); + + if (map[platform] != null) { + return map[platform]; + } + } + + if (supportsNativePlatform) { + this._assertNoDuplicates( + name, + _constants.default.NATIVE_PLATFORM, + supportsNativePlatform, + dupMap.get(_constants.default.NATIVE_PLATFORM) + ); + + if (map[_constants.default.NATIVE_PLATFORM]) { + return map[_constants.default.NATIVE_PLATFORM]; + } + } + + this._assertNoDuplicates( + name, + _constants.default.GENERIC_PLATFORM, + supportsNativePlatform, + dupMap.get(_constants.default.GENERIC_PLATFORM) + ); + + if (map[_constants.default.GENERIC_PLATFORM]) { + return map[_constants.default.GENERIC_PLATFORM]; + } + + return null; + } + + _assertNoDuplicates(name, platform, supportsNativePlatform, relativePathSet) { + if (relativePathSet == null) { + return; + } // Force flow refinement + + const previousSet = relativePathSet; + const duplicates = new Map(); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for ( + var _iterator = previousSet[Symbol.iterator](), _step; + !(_iteratorNormalCompletion = (_step = _iterator.next()).done); + _iteratorNormalCompletion = true + ) { + const _step$value = _slicedToArray(_step.value, 2), + relativePath = _step$value[0], + type = _step$value[1]; + + const duplicatePath = fastPath.resolve(this._raw.rootDir, relativePath); + duplicates.set(duplicatePath, type); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + throw new DuplicateHasteCandidatesError( + name, + platform, + supportsNativePlatform, + duplicates + ); + } + + static create(rootDir) { + return new ModuleMap({ + duplicates: new Map(), + map: new Map(), + mocks: new Map(), + rootDir + }); + } +} + +exports.default = ModuleMap; + +class DuplicateHasteCandidatesError extends Error { + constructor(name, platform, supportsNativePlatform, duplicatesSet) { + const platformMessage = getPlatformMessage(platform); + super( + `The name \`${name}\` was looked up in the Haste module map. It ` + + `cannot be resolved, because there exists several different ` + + `files, or packages, that provide a module for ` + + `that particular name and platform. ${platformMessage} You must ` + + `delete or blacklist files until there remains only one of these:\n\n` + + Array.from(duplicatesSet) + .map( + ([dupFilePath, dupFileType]) => + ` * \`${dupFilePath}\` (${getTypeMessage(dupFileType)})\n` + ) + .sort() + .join('') + ); + this.hasteName = name; + this.platform = platform; + this.supportsNativePlatform = supportsNativePlatform; + this.duplicatesSet = duplicatesSet; + } +} + +function getPlatformMessage(platform) { + if (platform === _constants.default.GENERIC_PLATFORM) { + return 'The platform is generic (no extension).'; + } + + return `The platform extension is \`${platform}\`.`; +} + +function getTypeMessage(type) { + switch (type) { + case _constants.default.MODULE: + return 'module'; + + case _constants.default.PACKAGE: + return 'package'; + } + + return 'unknown'; +} + +ModuleMap.DuplicateHasteCandidatesError = DuplicateHasteCandidatesError; diff --git a/packages/jest-haste-map/build/blacklist.js b/packages/jest-haste-map/build/blacklist.js new file mode 100644 index 000000000000..32a1dba34577 --- /dev/null +++ b/packages/jest-haste-map/build/blacklist.js @@ -0,0 +1,58 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = void 0; + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +// This list is compiled after the MDN list of the most common MIME types (see +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/ +// Complete_list_of_MIME_types). +// +// Only MIME types starting with "image/", "video/", "audio/" and "font/" are +// reflected in the list. Adding "application/" is too risky since some text +// file formats (like ".js" and ".json") have an "application/" MIME type. +// +const extensions = new Set([ + // JSONs are never haste modules, except for "package.json", which is handled. + '.json', // Image extensions. + '.bmp', + '.gif', + '.ico', + '.jpeg', + '.jpg', + '.png', + '.svg', + '.tiff', + '.tif', + '.webp', // Video extensions. + '.avi', + '.mp4', + '.mpeg', + '.mpg', + '.ogv', + '.webm', + '.3gp', + '.3g2', // Audio extensions. + '.aac', + '.midi', + '.mid', + '.mp3', + '.oga', + '.wav', + '.3gp', + '.3g2', // Font extensions. + '.eot', + '.otf', + '.ttf', + '.woff', + '.woff2' +]); +var _default = extensions; +exports.default = _default; diff --git a/packages/jest-haste-map/build/constants.js b/packages/jest-haste-map/build/constants.js new file mode 100644 index 000000000000..bcbcf38ab1ef --- /dev/null +++ b/packages/jest-haste-map/build/constants.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = void 0; + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* eslint-disable sort-keys */ + +/* + * This file exports a set of constants that are used for Jest's haste map + * serialization. On very large repositories, the haste map cache becomes very + * large to the point where it is the largest overhead in starting up Jest. + * + * This constant key map allows to keep the map smaller without having to build + * a custom serialization library. + */ +const constants = { + /* file map attributes */ + ID: 0, + MTIME: 1, + SIZE: 2, + VISITED: 3, + DEPENDENCIES: 4, + SHA1: 5, + + /* module map attributes */ + PATH: 0, + TYPE: 1, + + /* module types */ + MODULE: 0, + PACKAGE: 1, + + /* platforms */ + GENERIC_PLATFORM: 'g', + NATIVE_PLATFORM: 'native' +}; +var _default = constants; +exports.default = _default; diff --git a/packages/jest-haste-map/build/crawlers/node.js b/packages/jest-haste-map/build/crawlers/node.js new file mode 100644 index 000000000000..29a941958d98 --- /dev/null +++ b/packages/jest-haste-map/build/crawlers/node.js @@ -0,0 +1,258 @@ +'use strict'; + +function _fs() { + const data = _interopRequireDefault(require('fs')); + + _fs = function _fs() { + return data; + }; + + return data; +} + +function _path() { + const data = _interopRequireDefault(require('path')); + + _path = function _path() { + return data; + }; + + return data; +} + +function _child_process() { + const data = require('child_process'); + + _child_process = function _child_process() { + return data; + }; + + return data; +} + +var _constants = _interopRequireDefault(require('../constants')); + +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 find(roots, extensions, ignore, callback) { + const result = []; + let activeCalls = 0; + + function search(directory) { + activeCalls++; + + _fs().default.readdir(directory, (err, names) => { + activeCalls--; + + if (err) { + callback(result); + return; + } + + names.forEach(file => { + file = _path().default.join(directory, file); + + if (ignore(file)) { + return; + } + + activeCalls++; + + _fs().default.lstat(file, (err, stat) => { + activeCalls--; + + if (!err && stat && !stat.isSymbolicLink()) { + if (stat.isDirectory()) { + search(file); + } else { + const ext = _path() + .default.extname(file) + .substr(1); + + if (extensions.indexOf(ext) !== -1) { + result.push([file, stat.mtime.getTime(), stat.size]); + } + } + } + + if (activeCalls === 0) { + callback(result); + } + }); + }); + + if (activeCalls === 0) { + callback(result); + } + }); + } + + if (roots.length > 0) { + roots.forEach(search); + } else { + callback(result); + } +} + +function findNative(roots, extensions, ignore, callback) { + const args = Array.from(roots); + args.push('-type', 'f'); + + if (extensions.length) { + args.push('('); + } + + extensions.forEach((ext, index) => { + if (index) { + args.push('-o'); + } + + args.push('-iname'); + args.push('*.' + ext); + }); + + if (extensions.length) { + args.push(')'); + } + + const child = (0, _child_process().spawn)('find', args); + let stdout = ''; + child.stdout.setEncoding('utf-8'); + child.stdout.on('data', data => (stdout += data)); + child.stdout.on('close', () => { + const lines = stdout + .trim() + .split('\n') + .filter(x => !ignore(x)); + const result = []; + let count = lines.length; + + if (!count) { + callback([]); + } else { + lines.forEach(path => { + _fs().default.stat(path, (err, stat) => { + if (!err && stat) { + result.push([path, stat.mtime.getTime(), stat.size]); + } + + if (--count === 0) { + callback(result); + } + }); + }); + } + }); +} + +module.exports = function nodeCrawl(options) { + if (options.mapper) { + throw new Error(`Option 'mapper' isn't supported by the Node crawler`); + } + + const data = options.data, + extensions = options.extensions, + forceNodeFilesystemAPI = options.forceNodeFilesystemAPI, + ignore = options.ignore, + rootDir = options.rootDir, + roots = options.roots; + return new Promise(resolve => { + const callback = list => { + const files = new Map(); + list.forEach(fileData => { + const _fileData = _slicedToArray(fileData, 3), + filePath = _fileData[0], + mtime = _fileData[1], + size = _fileData[2]; + + const relativeFilePath = fastPath.relative(rootDir, filePath); + const existingFile = data.files.get(relativeFilePath); + + if (existingFile && existingFile[_constants.default.MTIME] === mtime) { + files.set(relativeFilePath, existingFile); + } else { + // See ../constants.js; SHA-1 will always be null and fulfilled later. + files.set(relativeFilePath, ['', mtime, size, 0, [], null]); + } + }); + data.files = files; + resolve(data); + }; + + if (forceNodeFilesystemAPI || process.platform === 'win32') { + find(roots, extensions, ignore, callback); + } else { + findNative(roots, extensions, ignore, callback); + } + }); +}; diff --git a/packages/jest-haste-map/build/crawlers/watchman.js b/packages/jest-haste-map/build/crawlers/watchman.js new file mode 100644 index 000000000000..5eea023ec95a --- /dev/null +++ b/packages/jest-haste-map/build/crawlers/watchman.js @@ -0,0 +1,559 @@ +'use strict'; + +function _path() { + const data = _interopRequireDefault(require('path')); + + _path = function _path() { + return data; + }; + + return data; +} + +function _fbWatchman() { + const data = _interopRequireDefault(require('fb-watchman')); + + _fbWatchman = function _fbWatchman() { + return data; + }; + + return data; +} + +var fastPath = _interopRequireWildcard(require('../lib/fast_path')); + +var _normalizePathSep = _interopRequireDefault( + require('../lib/normalizePathSep') +); + +var _constants = _interopRequireDefault(require('../constants')); + +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); + }); + }; +} + +const watchmanURL = + 'https://facebook.github.io/watchman/docs/troubleshooting.html'; + +function WatchmanError(error) { + error.message = + `Watchman error: ${error.message.trim()}. Make sure watchman ` + + `is running for this project. See ${watchmanURL}.`; + return error; +} + +module.exports = + /*#__PURE__*/ + (function() { + var _watchmanCrawl = _asyncToGenerator(function*(options) { + const fields = ['name', 'exists', 'mtime_ms', 'size']; + const data = options.data, + extensions = options.extensions, + ignore = options.ignore, + rootDir = options.rootDir, + roots = options.roots; + const defaultWatchExpression = [ + 'allof', + ['type', 'f'], + ['anyof', ...extensions.map(extension => ['suffix', extension])] + ]; + const clocks = data.clocks; + const client = new (_fbWatchman()).default.Client(); + let clientError; + client.on('error', error => (clientError = WatchmanError(error))); // TODO: type better than `any` + + const cmd = (...args) => + new Promise((resolve, reject) => + client.command(args, (error, result) => + error ? reject(WatchmanError(error)) : resolve(result) + ) + ); + + if (options.computeSha1) { + const _ref = yield cmd('list-capabilities'), + capabilities = _ref.capabilities; + + if (capabilities.indexOf('field-content.sha1hex') !== -1) { + fields.push('content.sha1hex'); + } + } + + function getWatchmanRoots(_x2) { + return _getWatchmanRoots.apply(this, arguments); + } + + function _getWatchmanRoots() { + _getWatchmanRoots = _asyncToGenerator(function*(roots) { + const watchmanRoots = new Map(); + yield Promise.all( + roots.map( + /*#__PURE__*/ + (function() { + var _ref2 = _asyncToGenerator(function*(root) { + const response = yield cmd('watch-project', root); + const existing = watchmanRoots.get(response.watch); // A root can only be filtered if it was never seen with a + // relative_path before. + + const canBeFiltered = !existing || existing.length > 0; + + if (canBeFiltered) { + if (response.relative_path) { + watchmanRoots.set( + response.watch, + (existing || []).concat(response.relative_path) + ); + } else { + // Make the filter directories an empty array to signal that this + // root was already seen and needs to be watched for all files or + // directories. + watchmanRoots.set(response.watch, []); + } + } + }); + + return function(_x4) { + return _ref2.apply(this, arguments); + }; + })() + ) + ); + return watchmanRoots; + }); + return _getWatchmanRoots.apply(this, arguments); + } + + function queryWatchmanForDirs(_x3) { + return _queryWatchmanForDirs.apply(this, arguments); + } + + function _queryWatchmanForDirs() { + _queryWatchmanForDirs = _asyncToGenerator(function*( + rootProjectDirMappings + ) { + const files = new Map(); + let isFresh = false; + yield Promise.all( + Array.from(rootProjectDirMappings).map( + /*#__PURE__*/ + (function() { + var _ref3 = _asyncToGenerator(function*([ + root, + directoryFilters + ]) { + const expression = Array.from(defaultWatchExpression); + const glob = []; + + if (directoryFilters.length > 0) { + expression.push([ + 'anyof', + ...directoryFilters.map(dir => ['dirname', dir]) + ]); + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for ( + var _iterator2 = directoryFilters[Symbol.iterator](), + _step2; + !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()) + .done); + _iteratorNormalCompletion2 = true + ) { + const directory = _step2.value; + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for ( + var _iterator3 = extensions[Symbol.iterator](), + _step3; + !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()) + .done); + _iteratorNormalCompletion3 = true + ) { + const extension = _step3.value; + glob.push(`${directory}/**/*.${extension}`); + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if ( + !_iteratorNormalCompletion3 && + _iterator3.return != null + ) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if ( + !_iteratorNormalCompletion2 && + _iterator2.return != null + ) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + } else { + var _iteratorNormalCompletion4 = true; + var _didIteratorError4 = false; + var _iteratorError4 = undefined; + + try { + for ( + var _iterator4 = extensions[Symbol.iterator](), _step4; + !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()) + .done); + _iteratorNormalCompletion4 = true + ) { + const extension = _step4.value; + glob.push(`**/*.${extension}`); + } + } catch (err) { + _didIteratorError4 = true; + _iteratorError4 = err; + } finally { + try { + if ( + !_iteratorNormalCompletion4 && + _iterator4.return != null + ) { + _iterator4.return(); + } + } finally { + if (_didIteratorError4) { + throw _iteratorError4; + } + } + } + } + + const relativeRoot = fastPath.relative(rootDir, root); + const query = clocks.has(relativeRoot) // Use the `since` generator if we have a clock available + ? { + expression, + fields, + since: clocks.get(relativeRoot) + } // Otherwise use the `glob` filter + : { + expression, + fields, + glob + }; + const response = yield cmd('query', root, query); + + if ('warning' in response) { + console.warn('watchman warning: ', response.warning); + } + + isFresh = isFresh || response.is_fresh_instance; + files.set(root, response); + }); + + return function(_x5) { + return _ref3.apply(this, arguments); + }; + })() + ) + ); + return { + files, + isFresh + }; + }); + return _queryWatchmanForDirs.apply(this, arguments); + } + + let files = data.files; + let watchmanFiles; + + try { + const watchmanRoots = yield getWatchmanRoots(roots); + const watchmanFileResults = yield queryWatchmanForDirs(watchmanRoots); // Reset the file map if watchman was restarted and sends us a list of + // files. + + if (watchmanFileResults.isFresh) { + files = new Map(); + } + + watchmanFiles = watchmanFileResults.files; + } finally { + client.end(); + } + + if (clientError) { + throw clientError; + } // TODO: remove non-null + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for ( + var _iterator = watchmanFiles[Symbol.iterator](), _step; + !(_iteratorNormalCompletion = (_step = _iterator.next()).done); + _iteratorNormalCompletion = true + ) { + const _step$value = _slicedToArray(_step.value, 2), + watchRoot = _step$value[0], + response = _step$value[1]; + + const fsRoot = (0, _normalizePathSep.default)(watchRoot); + const relativeFsRoot = fastPath.relative(rootDir, fsRoot); + clocks.set(relativeFsRoot, response.clock); + var _iteratorNormalCompletion5 = true; + var _didIteratorError5 = false; + var _iteratorError5 = undefined; + + try { + for ( + var _iterator5 = response.files[Symbol.iterator](), _step5; + !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); + _iteratorNormalCompletion5 = true + ) { + const fileData = _step5.value; + const filePath = + fsRoot + + _path().default.sep + + (0, _normalizePathSep.default)(fileData.name); + const relativeFilePath = fastPath.relative(rootDir, filePath); + + if (!fileData.exists) { + files.delete(relativeFilePath); + } else if (!ignore(filePath)) { + const mtime = + typeof fileData.mtime_ms === 'number' + ? fileData.mtime_ms + : fileData.mtime_ms.toNumber(); + const size = fileData.size; + let sha1hex = fileData['content.sha1hex']; + + if (typeof sha1hex !== 'string' || sha1hex.length !== 40) { + sha1hex = null; + } + + const existingFileData = data.files.get(relativeFilePath); + let nextData; + + if ( + existingFileData && + existingFileData[_constants.default.MTIME] === mtime + ) { + nextData = existingFileData; + } else if ( + existingFileData && + sha1hex && + existingFileData[_constants.default.SHA1] === sha1hex + ) { + // @ts-ignore: TODO why is this wrong? + nextData = [...existingFileData]; + nextData[1] = mtime; + } else { + // See ../constants.ts + nextData = ['', mtime, size, 0, [], sha1hex]; + } + + const mappings = options.mapper + ? options.mapper(filePath) + : null; + + if (mappings) { + var _iteratorNormalCompletion6 = true; + var _didIteratorError6 = false; + var _iteratorError6 = undefined; + + try { + for ( + var _iterator6 = mappings[Symbol.iterator](), _step6; + !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()) + .done); + _iteratorNormalCompletion6 = true + ) { + const absoluteVirtualFilePath = _step6.value; + + if (!ignore(absoluteVirtualFilePath)) { + const relativeVirtualFilePath = fastPath.relative( + rootDir, + absoluteVirtualFilePath + ); + files.set(relativeVirtualFilePath, nextData); + } + } + } catch (err) { + _didIteratorError6 = true; + _iteratorError6 = err; + } finally { + try { + if ( + !_iteratorNormalCompletion6 && + _iterator6.return != null + ) { + _iterator6.return(); + } + } finally { + if (_didIteratorError6) { + throw _iteratorError6; + } + } + } + } else { + files.set(relativeFilePath, nextData); + } + } + } + } catch (err) { + _didIteratorError5 = true; + _iteratorError5 = err; + } finally { + try { + if (!_iteratorNormalCompletion5 && _iterator5.return != null) { + _iterator5.return(); + } + } finally { + if (_didIteratorError5) { + throw _iteratorError5; + } + } + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + data.files = files; + return data; + }); + + function watchmanCrawl(_x) { + return _watchmanCrawl.apply(this, arguments); + } + + return watchmanCrawl; + })(); diff --git a/packages/jest-haste-map/build/getMockName.js b/packages/jest-haste-map/build/getMockName.js new file mode 100644 index 000000000000..29e0f9980ca3 --- /dev/null +++ b/packages/jest-haste-map/build/getMockName.js @@ -0,0 +1,38 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = void 0; + +function _path() { + const data = _interopRequireDefault(require('path')); + + _path = function _path() { + return data; + }; + + return data; +} + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +const MOCKS_PATTERN = _path().default.sep + '__mocks__' + _path().default.sep; + +const getMockName = filePath => { + const mockPath = filePath.split(MOCKS_PATTERN)[1]; + return mockPath + .substring(0, mockPath.lastIndexOf(_path().default.extname(mockPath))) + .replace(/\\/g, '/'); +}; + +var _default = getMockName; +exports.default = _default; diff --git a/packages/jest-haste-map/build/index.js b/packages/jest-haste-map/build/index.js new file mode 100644 index 000000000000..541331ff0bfc --- /dev/null +++ b/packages/jest-haste-map/build/index.js @@ -0,0 +1,1272 @@ +'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 _fs() { + const data = _interopRequireDefault(require('fs')); + + _fs = function _fs() { + 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 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; +} + +const CHANGE_INTERVAL = 30; +const MAX_WAIT_TIME = 240000; + +const NODE_MODULES = _path().default.sep + 'node_modules' + _path().default.sep; // TypeScript doesn't like us importing from outside `rootDir` + +const _JSON$parse = JSON.parse( + _fs().default.readFileSync(require.resolve('../package.json'), 'utf8') + ), + VERSION = _JSON$parse.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, // 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().default { + constructor(options) { + super(); + 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, + 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)), + 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() { + if (!this._buildPromise) { + this._buildPromise = this._buildFileMap() + .then(data => this._buildHasteMap(data)) + .then(hasteMap => { + this._persist(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; + + return this._watch(hasteMap).then(() => ({ + __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() { + const read = this._options.resetCache ? this._createEmptyMap : this.read; + return Promise.resolve() + .then(() => read.call(this)) + .catch(() => this._createEmptyMap()) + .then(cachedHasteMap => { + const cachedFiles = []; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for ( + var _iterator = cachedHasteMap.files[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]; + + const moduleName = fileMetadata[_constants.default.ID]; + cachedFiles.push({ + moduleName, + path: relativeFilePath + }); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return this._crawl(cachedHasteMap).then(hasteMap => { + const deprecatedFiles = cachedFiles.filter( + file => !hasteMap.files.has(file.path) + ); + return { + deprecatedFiles, + 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 message = + `jest-haste-map: Haste module naming collision:\n` + + ` Duplicate module name: ${id}\n` + + ` Paths: ${fastPath.resolve( + rootDir, + module[_constants.default.PATH] + )} collides with ` + + `${fastPath.resolve( + rootDir, + existingModule[_constants.default.PATH] + )}\n\nThis ` + + `${this._options.throwOnModuleCollision ? 'error' : 'warning'} ` + + `is caused by \`hasteImpl\` returning the same name for different` + + ` files.`; + + if (this._options.throwOnModuleCollision) { + throw new Error(message); + } + + this._console.warn(message); // 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 || []; + + 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) { + this._console.warn( + `jest-haste-map: duplicate manual mock found:\n` + + ` Module name: ${mockPath}\n` + + ` Duplicate Mock path: ${filePath}\nThis warning ` + + `is caused by two manual mock files with the same file name.\n` + + `Jest will use the mock file found in: \n` + + `${filePath}\n` + + ` Please delete one of the following two files: \n ` + + `${_path().default.join( + rootDir, + existingMockPath + )}\n${filePath}\n\n` + ); + } + + 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 deprecatedFiles = data.deprecatedFiles, + hasteMap = data.hasteMap; + const map = new Map(); + const mocks = new Map(); + const promises = []; + + for (let i = 0; i < deprecatedFiles.length; ++i) { + const file = deprecatedFiles[i]; + + this._recoverDuplicates(hasteMap, file.path, file.moduleName); + } + + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for ( + var _iterator2 = hasteMap.files.keys()[Symbol.iterator](), _step2; + !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); + _iteratorNormalCompletion2 = true + ) { + const relativeFilePath = _step2.value; + // 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; + }) + .catch(error => { + this._cleanup(); + + return Promise.reject(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 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)({ + computeSha1: options.computeSha1, + data: hasteMap, + extensions: options.extensions, + forceNodeFilesystemAPI: options.forceNodeFilesystemAPI, + ignore, + mapper: options.mapper, + rootDir: options.rootDir, + roots: options.roots + }).catch(e => { + throw new Error( + `Crawler retry failed:\n` + + ` Original error: ${error.message}\n` + + ` Retry error: ${e.message}\n` + ); + }); + } + + throw error; + }; + + try { + return crawl({ + computeSha1: options.computeSha1, + data: hasteMap, + extensions: options.extensions, + forceNodeFilesystemAPI: options.forceNodeFilesystemAPI, + ignore, + rootDir: options.rootDir, + roots: options.roots + }).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; + const Watcher = + canUseWatchman && this._options.useWatchman + ? _WatchmanWatcher.default + : _os().default.platform() === 'darwin' + ? _sane().default.FSEventsWatcher + : _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; + this.emit('change', { + eventsQueue, + hasteFS: new _HasteFS.default({ + files: hasteMap.files, + rootDir + }), + moduleMap: new _ModuleMap.default({ + duplicates: hasteMap.duplicates, + map: hasteMap.map, + mocks: hasteMap.mocks, + rootDir + }) + }); + 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() + }; + } +} + +function copy(object) { + return Object.assign(Object.create(null), object); +} + +function copyMap(input) { + return new Map(input); +} + +HasteMap.H = _constants.default; +HasteMap.ModuleMap = _ModuleMap.default; +module.exports = HasteMap; diff --git a/packages/jest-haste-map/build/lib/WatchmanWatcher.js b/packages/jest-haste-map/build/lib/WatchmanWatcher.js new file mode 100644 index 000000000000..f6d5eed37a2b --- /dev/null +++ b/packages/jest-haste-map/build/lib/WatchmanWatcher.js @@ -0,0 +1,400 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = WatchmanWatcher; + +function _fs() { + const data = _interopRequireDefault(require('fs')); + + _fs = function _fs() { + return data; + }; + + return data; +} + +function _path() { + const data = _interopRequireDefault(require('path')); + + _path = function _path() { + return data; + }; + + return data; +} + +function _assert() { + const data = _interopRequireDefault(require('assert')); + + _assert = function _assert() { + return data; + }; + + return data; +} + +function _events() { + const data = require('events'); + + _events = function _events() { + return data; + }; + + return data; +} + +function _fbWatchman() { + const data = _interopRequireDefault(require('fb-watchman')); + + _fbWatchman = function _fbWatchman() { + return data; + }; + + return data; +} + +function _common() { + const data = _interopRequireDefault(require('sane/src/common')); + + _common = function _common() { + return data; + }; + + return data; +} + +function _recrawlWarningDedupe() { + const data = _interopRequireDefault( + require('sane/src/utils/recrawl-warning-dedupe') + ); + + _recrawlWarningDedupe = function _recrawlWarningDedupe() { + return data; + }; + + return data; +} + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +const CHANGE_EVENT = _common().default.CHANGE_EVENT; + +const DELETE_EVENT = _common().default.DELETE_EVENT; + +const ADD_EVENT = _common().default.ADD_EVENT; + +const ALL_EVENT = _common().default.ALL_EVENT; + +const SUB_NAME = 'sane-sub'; +/** + * Watches `dir`. + * + * @class PollWatcher + * @param String dir + * @param {Object} opts + * @public + */ + +function WatchmanWatcher(dir, opts) { + _common().default.assignOptions(this, opts); + + this.root = _path().default.resolve(dir); + this.init(); +} // eslint-disable-next-line no-proto + +WatchmanWatcher.prototype.__proto__ = _events().EventEmitter.prototype; +/** + * Run the watchman `watch` command on the root and subscribe to changes. + * + * @private + */ + +WatchmanWatcher.prototype.init = function() { + if (this.client) { + this.client.removeAllListeners(); + } + + const self = this; + this.client = new (_fbWatchman()).default.Client(); + this.client.on('error', error => { + self.emit('error', error); + }); + this.client.on('subscription', this.handleChangeEvent.bind(this)); + this.client.on('end', () => { + console.warn('[sane] Warning: Lost connection to watchman, reconnecting..'); + self.init(); + }); + this.watchProjectInfo = null; + + function getWatchRoot() { + return self.watchProjectInfo ? self.watchProjectInfo.root : self.root; + } + + function onCapability(error, resp) { + if (handleError(self, error)) { + // The Watchman watcher is unusable on this system, we cannot continue + return; + } + + handleWarning(resp); + self.capabilities = resp.capabilities; + + if (self.capabilities.relative_root) { + self.client.command(['watch-project', getWatchRoot()], onWatchProject); + } else { + self.client.command(['watch', getWatchRoot()], onWatch); + } + } + + function onWatchProject(error, resp) { + if (handleError(self, error)) { + return; + } + + handleWarning(resp); + self.watchProjectInfo = { + relativePath: resp.relative_path ? resp.relative_path : '', + root: resp.watch + }; + self.client.command(['clock', getWatchRoot()], onClock); + } + + function onWatch(error, resp) { + if (handleError(self, error)) { + return; + } + + handleWarning(resp); + self.client.command(['clock', getWatchRoot()], onClock); + } + + function onClock(error, resp) { + if (handleError(self, error)) { + return; + } + + handleWarning(resp); + const options = { + fields: ['name', 'exists', 'new'], + since: resp.clock + }; // If the server has the wildmatch capability available it supports + // the recursive **/*.foo style match and we can offload our globs + // to the watchman server. This saves both on data size to be + // communicated back to us and compute for evaluating the globs + // in our node process. + + if (self.capabilities.wildmatch) { + if (self.globs.length === 0) { + if (!self.dot) { + // Make sure we honor the dot option if even we're not using globs. + options.expression = [ + 'match', + '**', + 'wholename', + { + includedotfiles: false + } + ]; + } + } else { + options.expression = ['anyof']; + + for (const i in self.globs) { + options.expression.push([ + 'match', + self.globs[i], + 'wholename', + { + includedotfiles: self.dot + } + ]); + } + } + } + + if (self.capabilities.relative_root) { + options.relative_root = self.watchProjectInfo.relativePath; + } + + self.client.command( + ['subscribe', getWatchRoot(), SUB_NAME, options], + onSubscribe + ); + } + + function onSubscribe(error, resp) { + if (handleError(self, error)) { + return; + } + + handleWarning(resp); + self.emit('ready'); + } + + self.client.capabilityCheck( + { + optional: ['wildmatch', 'relative_root'] + }, + onCapability + ); +}; +/** + * Handles a change event coming from the subscription. + * + * @param {Object} resp + * @private + */ + +WatchmanWatcher.prototype.handleChangeEvent = function(resp) { + _assert().default.equal( + resp.subscription, + SUB_NAME, + 'Invalid subscription event.' + ); + + if (resp.is_fresh_instance) { + this.emit('fresh_instance'); + } + + if (resp.is_fresh_instance) { + this.emit('fresh_instance'); + } + + if (Array.isArray(resp.files)) { + resp.files.forEach(this.handleFileChange, this); + } +}; +/** + * Handles a single change event record. + * + * @param {Object} changeDescriptor + * @private + */ + +WatchmanWatcher.prototype.handleFileChange = function(changeDescriptor) { + const self = this; + let absPath; + let relativePath; + + if (this.capabilities.relative_root) { + relativePath = changeDescriptor.name; + absPath = _path().default.join( + this.watchProjectInfo.root, + this.watchProjectInfo.relativePath, + relativePath + ); + } else { + absPath = _path().default.join(this.root, changeDescriptor.name); + relativePath = changeDescriptor.name; + } + + if ( + !(self.capabilities.wildmatch && !this.hasIgnore) && + !_common().default.isFileIncluded( + this.globs, + this.dot, + this.doIgnore, + relativePath + ) + ) { + return; + } + + if (!changeDescriptor.exists) { + self.emitEvent(DELETE_EVENT, relativePath, self.root); + } else { + _fs().default.lstat(absPath, (error, stat) => { + // Files can be deleted between the event and the lstat call + // the most reliable thing to do here is to ignore the event. + if (error && error.code === 'ENOENT') { + return; + } + + if (handleError(self, error)) { + return; + } + + const eventType = changeDescriptor.new ? ADD_EVENT : CHANGE_EVENT; // Change event on dirs are mostly useless. + + if (!(eventType === CHANGE_EVENT && stat.isDirectory())) { + self.emitEvent(eventType, relativePath, self.root, stat); + } + }); + } +}; +/** + * Dispatches the event. + * + * @param {string} eventType + * @param {string} filepath + * @param {string} root + * @param {fs.Stat} stat + * @private + */ + +WatchmanWatcher.prototype.emitEvent = function( + eventType, + filepath, + root, + stat +) { + this.emit(eventType, filepath, root, stat); + this.emit(ALL_EVENT, eventType, filepath, root, stat); +}; +/** + * Closes the watcher. + * + * @param {function} callback + * @private + */ + +WatchmanWatcher.prototype.close = function(callback) { + this.client.removeAllListeners(); + this.client.end(); + callback && callback(null, true); +}; +/** + * Handles an error and returns true if exists. + * + * @param {WatchmanWatcher} self + * @param {Error} error + * @private + */ + +function handleError(self, error) { + if (error != null) { + self.emit('error', error); + return true; + } else { + return false; + } +} +/** + * Handles a warning in the watchman resp object. + * + * @param {object} resp + * @private + */ + +function handleWarning(resp) { + if ('warning' in resp) { + if (_recrawlWarningDedupe().default.isRecrawlWarningDupe(resp.warning)) { + return true; + } + + console.warn(resp.warning); + return true; + } else { + return false; + } +} diff --git a/packages/jest-haste-map/build/lib/dependencyExtractor.js b/packages/jest-haste-map/build/lib/dependencyExtractor.js new file mode 100644 index 000000000000..be0c9aa07b2a --- /dev/null +++ b/packages/jest-haste-map/build/lib/dependencyExtractor.js @@ -0,0 +1,100 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.extract = extract; + +var _isRegExpSupported = _interopRequireDefault(require('./isRegExpSupported')); + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +// Negative look behind is only supported in Node 9+ +const NOT_A_DOT = (0, _isRegExpSupported.default)('(? `([\`'"])([^'"\`]*?)(?:\\${pos})`; + +const WORD_SEPARATOR = '\\b'; +const LEFT_PARENTHESIS = '\\('; +const RIGHT_PARENTHESIS = '\\)'; +const WHITESPACE = '\\s*'; +const OPTIONAL_COMMA = '(:?,\\s*)?'; + +function createRegExp(parts, flags) { + return new RegExp(parts.join(''), flags); +} + +function alternatives(...parts) { + return `(?:${parts.join('|')})`; +} + +function functionCallStart(...names) { + return [ + NOT_A_DOT, + WORD_SEPARATOR, + alternatives(...names), + WHITESPACE, + LEFT_PARENTHESIS, + WHITESPACE + ]; +} + +const BLOCK_COMMENT_RE = /\/\*[^]*?\*\//g; +const LINE_COMMENT_RE = /\/\/.*/g; +const REQUIRE_OR_DYNAMIC_IMPORT_RE = createRegExp( + [ + ...functionCallStart('require', 'import'), + CAPTURE_STRING_LITERAL(1), + WHITESPACE, + OPTIONAL_COMMA, + RIGHT_PARENTHESIS + ], + 'g' +); +const IMPORT_OR_EXPORT_RE = createRegExp( + [ + '\\b(?:import|export)\\s+(?!type(?:of)?\\s+)[^\'"]+\\s+from\\s+', + CAPTURE_STRING_LITERAL(1) + ], + 'g' +); +const JEST_EXTENSIONS_RE = createRegExp( + [ + ...functionCallStart( + 'require\\s*\\.\\s*(?:requireActual|requireMock)', + 'jest\\s*\\.\\s*(?:requireActual|requireMock|genMockFromModule)' + ), + CAPTURE_STRING_LITERAL(1), + WHITESPACE, + OPTIONAL_COMMA, + RIGHT_PARENTHESIS + ], + 'g' +); + +function extract(code) { + const dependencies = new Set(); + + const addDependency = (match, _, dep) => { + dependencies.add(dep); + return match; + }; + + code + .replace(BLOCK_COMMENT_RE, '') + .replace(LINE_COMMENT_RE, '') + .replace(IMPORT_OR_EXPORT_RE, addDependency) + .replace(REQUIRE_OR_DYNAMIC_IMPORT_RE, addDependency) + .replace(JEST_EXTENSIONS_RE, addDependency); + return dependencies; +} diff --git a/packages/jest-haste-map/build/lib/fast_path.js b/packages/jest-haste-map/build/lib/fast_path.js new file mode 100644 index 000000000000..31b5bbb7d367 --- /dev/null +++ b/packages/jest-haste-map/build/lib/fast_path.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.relative = relative; +exports.resolve = resolve; + +function _path() { + const data = _interopRequireDefault(require('path')); + + _path = function _path() { + return data; + }; + + return data; +} + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +// rootDir and filename must be absolute paths (resolved) +function relative(rootDir, filename) { + return filename.indexOf(rootDir + _path().default.sep) === 0 + ? filename.substr(rootDir.length + 1) + : _path().default.relative(rootDir, filename); +} + +const INDIRECTION_FRAGMENT = '..' + _path().default.sep; // rootDir must be an absolute path and relativeFilename must be simple +// (e.g.: foo/bar or ../foo/bar, but never ./foo or foo/../bar) + +function resolve(rootDir, relativeFilename) { + return relativeFilename.indexOf(INDIRECTION_FRAGMENT) === 0 + ? _path().default.resolve(rootDir, relativeFilename) + : rootDir + _path().default.sep + relativeFilename; +} diff --git a/packages/jest-haste-map/build/lib/getPlatformExtension.js b/packages/jest-haste-map/build/lib/getPlatformExtension.js new file mode 100644 index 000000000000..6b9e564f9b84 --- /dev/null +++ b/packages/jest-haste-map/build/lib/getPlatformExtension.js @@ -0,0 +1,31 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = getPlatformExtension; + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +const SUPPORTED_PLATFORM_EXTS = new Set(['android', 'ios', 'native', 'web']); // Extract platform extension: index.ios.js -> ios + +function getPlatformExtension(file, platforms) { + const last = file.lastIndexOf('.'); + const secondToLast = file.lastIndexOf('.', last - 1); + + if (secondToLast === -1) { + return null; + } + + const platform = file.substring(secondToLast + 1, last); // If an overriding platform array is passed, check that first + + if (platforms && platforms.indexOf(platform) !== -1) { + return platform; + } + + return SUPPORTED_PLATFORM_EXTS.has(platform) ? platform : null; +} diff --git a/packages/jest-haste-map/build/lib/isRegExpSupported.js b/packages/jest-haste-map/build/lib/isRegExpSupported.js new file mode 100644 index 000000000000..44de4e119061 --- /dev/null +++ b/packages/jest-haste-map/build/lib/isRegExpSupported.js @@ -0,0 +1,22 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = isRegExpSupported; + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +function isRegExpSupported(value) { + try { + // eslint-disable-next-line no-new + new RegExp(value); + return true; + } catch (e) { + return false; + } +} diff --git a/packages/jest-haste-map/build/lib/normalizePathSep.js b/packages/jest-haste-map/build/lib/normalizePathSep.js new file mode 100644 index 000000000000..23c7782bd90b --- /dev/null +++ b/packages/jest-haste-map/build/lib/normalizePathSep.js @@ -0,0 +1,37 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.default = void 0; + +function _path() { + const data = _interopRequireDefault(require('path')); + + _path = function _path() { + return data; + }; + + return data; +} + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +let normalizePathSep; + +if (_path().default.sep === '/') { + normalizePathSep = filePath => filePath; +} else { + normalizePathSep = filePath => filePath.replace(/\//g, _path().default.sep); +} + +var _default = normalizePathSep; +exports.default = _default; diff --git a/packages/jest-haste-map/build/types.js b/packages/jest-haste-map/build/types.js new file mode 100644 index 000000000000..ad9a93a7c160 --- /dev/null +++ b/packages/jest-haste-map/build/types.js @@ -0,0 +1 @@ +'use strict'; diff --git a/packages/jest-haste-map/build/worker.js b/packages/jest-haste-map/build/worker.js new file mode 100644 index 000000000000..1996d4a8e270 --- /dev/null +++ b/packages/jest-haste-map/build/worker.js @@ -0,0 +1,230 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.worker = worker; +exports.getSha1 = getSha1; + +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 _gracefulFs() { + const data = _interopRequireDefault(require('graceful-fs')); + + _gracefulFs = function _gracefulFs() { + return data; + }; + + return data; +} + +var _blacklist = _interopRequireDefault(require('./blacklist')); + +var _constants = _interopRequireDefault(require('./constants')); + +var dependencyExtractor = _interopRequireWildcard( + require('./lib/dependencyExtractor') +); + +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 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); + }); + }; +} + +const PACKAGE_JSON = _path().default.sep + 'package.json'; +let hasteImpl = null; +let hasteImplModulePath = null; + +function sha1hex(content) { + return _crypto() + .default.createHash('sha1') + .update(content) + .digest('hex'); +} + +function worker(_x) { + return _worker.apply(this, arguments); +} + +function _worker() { + _worker = _asyncToGenerator(function*(data) { + if ( + data.hasteImplModulePath && + data.hasteImplModulePath !== hasteImplModulePath + ) { + if (hasteImpl) { + throw new Error('jest-haste-map: hasteImplModulePath changed'); + } + + hasteImplModulePath = data.hasteImplModulePath; + hasteImpl = require(hasteImplModulePath); + } + + let content; + let dependencies; + let id; + let module; + let sha1; + const computeDependencies = data.computeDependencies, + computeSha1 = data.computeSha1, + rootDir = data.rootDir, + filePath = data.filePath; + + const getContent = () => { + if (content === undefined) { + content = _gracefulFs().default.readFileSync(filePath, 'utf8'); + } + + return content; + }; + + if (filePath.endsWith(PACKAGE_JSON)) { + // Process a package.json that is returned as a PACKAGE type with its name. + try { + const fileData = JSON.parse(getContent()); + + if (fileData.name) { + const relativeFilePath = _path().default.relative(rootDir, filePath); + + id = fileData.name; + module = [relativeFilePath, _constants.default.PACKAGE]; + } + } catch (err) { + throw new Error(`Cannot parse ${filePath} as JSON: ${err.message}`); + } + } else if ( + !_blacklist.default.has(filePath.substr(filePath.lastIndexOf('.'))) + ) { + // Process a random file that is returned as a MODULE. + if (hasteImpl) { + id = hasteImpl.getHasteName(filePath); + } + + if (computeDependencies) { + const content = getContent(); + dependencies = Array.from( + data.dependencyExtractor + ? require(data.dependencyExtractor).extract( + content, + filePath, + dependencyExtractor.extract + ) + : dependencyExtractor.extract(content) + ); + } + + if (id) { + const relativeFilePath = _path().default.relative(rootDir, filePath); + + module = [relativeFilePath, _constants.default.MODULE]; + } + } // If a SHA-1 is requested on update, compute it. + + if (computeSha1) { + sha1 = sha1hex( + getContent() || _gracefulFs().default.readFileSync(filePath) + ); + } + + return { + dependencies, + id, + module, + sha1 + }; + }); + return _worker.apply(this, arguments); +} + +function getSha1(_x2) { + return _getSha.apply(this, arguments); +} + +function _getSha() { + _getSha = _asyncToGenerator(function*(data) { + const sha1 = data.computeSha1 + ? sha1hex(_gracefulFs().default.readFileSync(data.filePath)) + : null; + return { + dependencies: undefined, + id: undefined, + module: undefined, + sha1 + }; + }); + return _getSha.apply(this, arguments); +} From a19130356afd59dff1f64c7928ced1aa555a801d Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 12 Feb 2019 00:22:43 +0100 Subject: [PATCH 12/16] fix test --- packages/jest-haste-map/src/__tests__/index.test.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/jest-haste-map/src/__tests__/index.test.js b/packages/jest-haste-map/src/__tests__/index.test.js index c11a752bd8b9..e77723b5aa24 100644 --- a/packages/jest-haste-map/src/__tests__/index.test.js +++ b/packages/jest-haste-map/src/__tests__/index.test.js @@ -146,6 +146,9 @@ describe('HasteMap', () => { mockEmitters = Object.create(null); mockFs = object({ + [require.resolve('../../package.json')]: JSON.stringify({ + version: '1.0.0', + }), '/project/fruits/Banana.js': ` const Strawberry = require("Strawberry"); `, @@ -517,7 +520,7 @@ describe('HasteMap', () => { expect(data.map.get('fbjs')).not.toBeDefined(); // cache file + 5 modules - the node_module - expect(fs.readFileSync.mock.calls.length).toBe(6); + expect(fs.readFileSync.mock.calls.length).toBe(7); }); }); @@ -637,7 +640,7 @@ describe('HasteMap', () => { .then(({__hasteMapForTest: initialData}) => { // The first run should access the file system once for the (empty) // cache file and five times for the files in the system. - expect(fs.readFileSync.mock.calls.length).toBe(6); + expect(fs.readFileSync.mock.calls.length).toBe(7); fs.readFileSync.mockClear(); From faeae4c3b25be8dad3e0b776930ef2e9fb4a25ad Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 12 Feb 2019 00:34:57 +0100 Subject: [PATCH 13/16] update comments in test --- packages/jest-haste-map/src/__tests__/index.test.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/jest-haste-map/src/__tests__/index.test.js b/packages/jest-haste-map/src/__tests__/index.test.js index e77723b5aa24..bda4878ec8c9 100644 --- a/packages/jest-haste-map/src/__tests__/index.test.js +++ b/packages/jest-haste-map/src/__tests__/index.test.js @@ -519,7 +519,7 @@ describe('HasteMap', () => { expect(data.map.get('fbjs')).not.toBeDefined(); - // cache file + 5 modules - the node_module + // package.json + cache file + 5 modules - the node_module expect(fs.readFileSync.mock.calls.length).toBe(7); }); }); @@ -638,8 +638,9 @@ describe('HasteMap', () => { new HasteMap(defaultConfig) .build() .then(({__hasteMapForTest: initialData}) => { - // The first run should access the file system once for the (empty) - // cache file and five times for the files in the system. + // The first run should access the file system once for package.json, + // once for the (empty) cache file and five times for the files in the + // system. expect(fs.readFileSync.mock.calls.length).toBe(7); fs.readFileSync.mockClear(); From 66eb178e0863c5e47913e57218393e6af4e42a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Tue, 12 Feb 2019 00:42:35 +0100 Subject: [PATCH 14/16] one less ts-ignore --- packages/jest-haste-map/build/crawlers/watchman.js | 11 ++++++++--- packages/jest-haste-map/src/crawlers/watchman.ts | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/jest-haste-map/build/crawlers/watchman.js b/packages/jest-haste-map/build/crawlers/watchman.js index 5eea023ec95a..4407357cd958 100644 --- a/packages/jest-haste-map/build/crawlers/watchman.js +++ b/packages/jest-haste-map/build/crawlers/watchman.js @@ -461,9 +461,14 @@ module.exports = sha1hex && existingFileData[_constants.default.SHA1] === sha1hex ) { - // @ts-ignore: TODO why is this wrong? - nextData = [...existingFileData]; - nextData[1] = mtime; + nextData = [ + existingFileData[0], + mtime, + existingFileData[2], + existingFileData[3], + existingFileData[4], + existingFileData[5] + ]; } else { // See ../constants.ts nextData = ['', mtime, size, 0, [], sha1hex]; diff --git a/packages/jest-haste-map/src/crawlers/watchman.ts b/packages/jest-haste-map/src/crawlers/watchman.ts index 94906a2a38cb..b7f5fc453f0b 100644 --- a/packages/jest-haste-map/src/crawlers/watchman.ts +++ b/packages/jest-haste-map/src/crawlers/watchman.ts @@ -193,9 +193,14 @@ export = async function watchmanCrawl( sha1hex && existingFileData[H.SHA1] === sha1hex ) { - // @ts-ignore: TODO why is this wrong? - nextData = [...existingFileData]; - nextData[1] = mtime; + nextData = [ + existingFileData[0], + mtime, + existingFileData[2], + existingFileData[3], + existingFileData[4], + existingFileData[5], + ]; } else { // See ../constants.ts nextData = ['', mtime, size, 0, [], sha1hex]; From 05e4b8ac73a188fe27669a20287d068a7cf609c9 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 12 Feb 2019 00:46:08 +0100 Subject: [PATCH 15/16] Revert "--wip-- [skip ci]" This reverts commit c0db70f8c751e41d451c5214f09a2d1a89e735f9. --- packages/jest-haste-map/build/HasteFS.js | 231 --- packages/jest-haste-map/build/ModuleMap.js | 302 ---- packages/jest-haste-map/build/blacklist.js | 58 - packages/jest-haste-map/build/constants.js | 47 - .../jest-haste-map/build/crawlers/node.js | 258 ---- .../jest-haste-map/build/crawlers/watchman.js | 564 -------- packages/jest-haste-map/build/getMockName.js | 38 - packages/jest-haste-map/build/index.js | 1272 ----------------- .../build/lib/WatchmanWatcher.js | 400 ------ .../build/lib/dependencyExtractor.js | 100 -- .../jest-haste-map/build/lib/fast_path.js | 43 - .../build/lib/getPlatformExtension.js | 31 - .../build/lib/isRegExpSupported.js | 22 - .../build/lib/normalizePathSep.js | 37 - packages/jest-haste-map/build/types.js | 1 - packages/jest-haste-map/build/worker.js | 230 --- 16 files changed, 3634 deletions(-) delete mode 100644 packages/jest-haste-map/build/HasteFS.js delete mode 100644 packages/jest-haste-map/build/ModuleMap.js delete mode 100644 packages/jest-haste-map/build/blacklist.js delete mode 100644 packages/jest-haste-map/build/constants.js delete mode 100644 packages/jest-haste-map/build/crawlers/node.js delete mode 100644 packages/jest-haste-map/build/crawlers/watchman.js delete mode 100644 packages/jest-haste-map/build/getMockName.js delete mode 100644 packages/jest-haste-map/build/index.js delete mode 100644 packages/jest-haste-map/build/lib/WatchmanWatcher.js delete mode 100644 packages/jest-haste-map/build/lib/dependencyExtractor.js delete mode 100644 packages/jest-haste-map/build/lib/fast_path.js delete mode 100644 packages/jest-haste-map/build/lib/getPlatformExtension.js delete mode 100644 packages/jest-haste-map/build/lib/isRegExpSupported.js delete mode 100644 packages/jest-haste-map/build/lib/normalizePathSep.js delete mode 100644 packages/jest-haste-map/build/types.js delete mode 100644 packages/jest-haste-map/build/worker.js diff --git a/packages/jest-haste-map/build/HasteFS.js b/packages/jest-haste-map/build/HasteFS.js deleted file mode 100644 index 7489b7662a1e..000000000000 --- a/packages/jest-haste-map/build/HasteFS.js +++ /dev/null @@ -1,231 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = void 0; - -function _micromatch() { - const data = _interopRequireDefault(require('micromatch')); - - _micromatch = function _micromatch() { - return data; - }; - - return data; -} - -function _jestUtil() { - const data = require('jest-util'); - - _jestUtil = function _jestUtil() { - return data; - }; - - return data; -} - -var fastPath = _interopRequireWildcard(require('./lib/fast_path')); - -var _constants = _interopRequireDefault(require('./constants')); - -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}; -} - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -class HasteFS { - constructor({rootDir, files}) { - this._rootDir = rootDir; - this._files = files; - } - - getModuleName(file) { - const fileMetadata = this._getFileData(file); - - return (fileMetadata && fileMetadata[_constants.default.ID]) || null; - } - - getSize(file) { - const fileMetadata = this._getFileData(file); - - return (fileMetadata && fileMetadata[_constants.default.SIZE]) || null; - } - - getDependencies(file) { - const fileMetadata = this._getFileData(file); - - return ( - (fileMetadata && fileMetadata[_constants.default.DEPENDENCIES]) || null - ); - } - - getSha1(file) { - const fileMetadata = this._getFileData(file); - - return (fileMetadata && fileMetadata[_constants.default.SHA1]) || null; - } - - exists(file) { - return this._getFileData(file) != null; - } - - getAllFiles() { - return Array.from(this.getAbsoluteFileIterator()); - } - - getFileIterator() { - return this._files.keys(); - } - - *getAbsoluteFileIterator() { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for ( - var _iterator = this.getFileIterator()[Symbol.iterator](), _step; - !(_iteratorNormalCompletion = (_step = _iterator.next()).done); - _iteratorNormalCompletion = true - ) { - const file = _step.value; - yield fastPath.resolve(this._rootDir, file); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - } - - matchFiles(pattern) { - if (!(pattern instanceof RegExp)) { - pattern = new RegExp(pattern); - } - - const files = []; - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for ( - var _iterator2 = this.getAbsoluteFileIterator()[Symbol.iterator](), - _step2; - !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); - _iteratorNormalCompletion2 = true - ) { - const file = _step2.value; - - if (pattern.test(file)) { - files.push(file); - } - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return != null) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - return files; - } - - matchFilesWithGlob(globs, root) { - const files = new Set(); - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for ( - var _iterator3 = this.getAbsoluteFileIterator()[Symbol.iterator](), - _step3; - !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); - _iteratorNormalCompletion3 = true - ) { - const file = _step3.value; - const filePath = root ? fastPath.relative(root, file) : file; - - if ( - _micromatch().default.some( - (0, _jestUtil().replacePathSepForGlob)(filePath), - globs - ) - ) { - files.add(file); - } - } - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return != null) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - - return files; - } - - _getFileData(file) { - const relativePath = fastPath.relative(this._rootDir, file); - return this._files.get(relativePath); - } -} - -exports.default = HasteFS; diff --git a/packages/jest-haste-map/build/ModuleMap.js b/packages/jest-haste-map/build/ModuleMap.js deleted file mode 100644 index 791d833f0290..000000000000 --- a/packages/jest-haste-map/build/ModuleMap.js +++ /dev/null @@ -1,302 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = void 0; - -var fastPath = _interopRequireWildcard(require('./lib/fast_path')); - -var _constants = _interopRequireDefault(require('./constants')); - -function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : {default: obj}; -} - -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 _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; -} - -const EMPTY_OBJ = {}; -const EMPTY_MAP = new Map(); - -class ModuleMap { - constructor(raw) { - this._raw = raw; - } - - getModule(name, platform, supportsNativePlatform, type) { - if (type == null) { - type = _constants.default.MODULE; - } - - const module = this._getModuleMetadata( - name, - platform, - !!supportsNativePlatform - ); - - if (module && module[_constants.default.TYPE] === type) { - const modulePath = module[_constants.default.PATH]; - return modulePath && fastPath.resolve(this._raw.rootDir, modulePath); - } - - return null; - } - - getPackage(name, platform, _supportsNativePlatform) { - return this.getModule(name, platform, null, _constants.default.PACKAGE); - } - - getMockModule(name) { - const mockPath = - this._raw.mocks.get(name) || this._raw.mocks.get(name + '/index'); - - return mockPath && fastPath.resolve(this._raw.rootDir, mockPath); - } - - getRawModuleMap() { - return { - duplicates: this._raw.duplicates, - map: this._raw.map, - mocks: this._raw.mocks, - rootDir: this._raw.rootDir - }; - } - - toJSON() { - return { - duplicates: Array.from(this._raw.duplicates), - map: Array.from(this._raw.map), - mocks: Array.from(this._raw.mocks), - rootDir: this._raw.rootDir - }; - } - - static fromJSON(serializableModuleMap) { - return new ModuleMap({ - duplicates: new Map(serializableModuleMap.duplicates), - map: new Map(serializableModuleMap.map), - mocks: new Map(serializableModuleMap.mocks), - rootDir: serializableModuleMap.rootDir - }); - } - /** - * When looking up a module's data, we walk through each eligible platform for - * the query. For each platform, we want to check if there are known - * duplicates for that name+platform pair. The duplication logic normally - * removes elements from the `map` object, but we want to check upfront to be - * extra sure. If metadata exists both in the `duplicates` object and the - * `map`, this would be a bug. - */ - - _getModuleMetadata(name, platform, supportsNativePlatform) { - const map = this._raw.map.get(name) || EMPTY_OBJ; - const dupMap = this._raw.duplicates.get(name) || EMPTY_MAP; - - if (platform != null) { - this._assertNoDuplicates( - name, - platform, - supportsNativePlatform, - dupMap.get(platform) - ); - - if (map[platform] != null) { - return map[platform]; - } - } - - if (supportsNativePlatform) { - this._assertNoDuplicates( - name, - _constants.default.NATIVE_PLATFORM, - supportsNativePlatform, - dupMap.get(_constants.default.NATIVE_PLATFORM) - ); - - if (map[_constants.default.NATIVE_PLATFORM]) { - return map[_constants.default.NATIVE_PLATFORM]; - } - } - - this._assertNoDuplicates( - name, - _constants.default.GENERIC_PLATFORM, - supportsNativePlatform, - dupMap.get(_constants.default.GENERIC_PLATFORM) - ); - - if (map[_constants.default.GENERIC_PLATFORM]) { - return map[_constants.default.GENERIC_PLATFORM]; - } - - return null; - } - - _assertNoDuplicates(name, platform, supportsNativePlatform, relativePathSet) { - if (relativePathSet == null) { - return; - } // Force flow refinement - - const previousSet = relativePathSet; - const duplicates = new Map(); - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for ( - var _iterator = previousSet[Symbol.iterator](), _step; - !(_iteratorNormalCompletion = (_step = _iterator.next()).done); - _iteratorNormalCompletion = true - ) { - const _step$value = _slicedToArray(_step.value, 2), - relativePath = _step$value[0], - type = _step$value[1]; - - const duplicatePath = fastPath.resolve(this._raw.rootDir, relativePath); - duplicates.set(duplicatePath, type); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - throw new DuplicateHasteCandidatesError( - name, - platform, - supportsNativePlatform, - duplicates - ); - } - - static create(rootDir) { - return new ModuleMap({ - duplicates: new Map(), - map: new Map(), - mocks: new Map(), - rootDir - }); - } -} - -exports.default = ModuleMap; - -class DuplicateHasteCandidatesError extends Error { - constructor(name, platform, supportsNativePlatform, duplicatesSet) { - const platformMessage = getPlatformMessage(platform); - super( - `The name \`${name}\` was looked up in the Haste module map. It ` + - `cannot be resolved, because there exists several different ` + - `files, or packages, that provide a module for ` + - `that particular name and platform. ${platformMessage} You must ` + - `delete or blacklist files until there remains only one of these:\n\n` + - Array.from(duplicatesSet) - .map( - ([dupFilePath, dupFileType]) => - ` * \`${dupFilePath}\` (${getTypeMessage(dupFileType)})\n` - ) - .sort() - .join('') - ); - this.hasteName = name; - this.platform = platform; - this.supportsNativePlatform = supportsNativePlatform; - this.duplicatesSet = duplicatesSet; - } -} - -function getPlatformMessage(platform) { - if (platform === _constants.default.GENERIC_PLATFORM) { - return 'The platform is generic (no extension).'; - } - - return `The platform extension is \`${platform}\`.`; -} - -function getTypeMessage(type) { - switch (type) { - case _constants.default.MODULE: - return 'module'; - - case _constants.default.PACKAGE: - return 'package'; - } - - return 'unknown'; -} - -ModuleMap.DuplicateHasteCandidatesError = DuplicateHasteCandidatesError; diff --git a/packages/jest-haste-map/build/blacklist.js b/packages/jest-haste-map/build/blacklist.js deleted file mode 100644 index 32a1dba34577..000000000000 --- a/packages/jest-haste-map/build/blacklist.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = void 0; - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -// This list is compiled after the MDN list of the most common MIME types (see -// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/ -// Complete_list_of_MIME_types). -// -// Only MIME types starting with "image/", "video/", "audio/" and "font/" are -// reflected in the list. Adding "application/" is too risky since some text -// file formats (like ".js" and ".json") have an "application/" MIME type. -// -const extensions = new Set([ - // JSONs are never haste modules, except for "package.json", which is handled. - '.json', // Image extensions. - '.bmp', - '.gif', - '.ico', - '.jpeg', - '.jpg', - '.png', - '.svg', - '.tiff', - '.tif', - '.webp', // Video extensions. - '.avi', - '.mp4', - '.mpeg', - '.mpg', - '.ogv', - '.webm', - '.3gp', - '.3g2', // Audio extensions. - '.aac', - '.midi', - '.mid', - '.mp3', - '.oga', - '.wav', - '.3gp', - '.3g2', // Font extensions. - '.eot', - '.otf', - '.ttf', - '.woff', - '.woff2' -]); -var _default = extensions; -exports.default = _default; diff --git a/packages/jest-haste-map/build/constants.js b/packages/jest-haste-map/build/constants.js deleted file mode 100644 index bcbcf38ab1ef..000000000000 --- a/packages/jest-haste-map/build/constants.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = void 0; - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* eslint-disable sort-keys */ - -/* - * This file exports a set of constants that are used for Jest's haste map - * serialization. On very large repositories, the haste map cache becomes very - * large to the point where it is the largest overhead in starting up Jest. - * - * This constant key map allows to keep the map smaller without having to build - * a custom serialization library. - */ -const constants = { - /* file map attributes */ - ID: 0, - MTIME: 1, - SIZE: 2, - VISITED: 3, - DEPENDENCIES: 4, - SHA1: 5, - - /* module map attributes */ - PATH: 0, - TYPE: 1, - - /* module types */ - MODULE: 0, - PACKAGE: 1, - - /* platforms */ - GENERIC_PLATFORM: 'g', - NATIVE_PLATFORM: 'native' -}; -var _default = constants; -exports.default = _default; diff --git a/packages/jest-haste-map/build/crawlers/node.js b/packages/jest-haste-map/build/crawlers/node.js deleted file mode 100644 index 29a941958d98..000000000000 --- a/packages/jest-haste-map/build/crawlers/node.js +++ /dev/null @@ -1,258 +0,0 @@ -'use strict'; - -function _fs() { - const data = _interopRequireDefault(require('fs')); - - _fs = function _fs() { - return data; - }; - - return data; -} - -function _path() { - const data = _interopRequireDefault(require('path')); - - _path = function _path() { - return data; - }; - - return data; -} - -function _child_process() { - const data = require('child_process'); - - _child_process = function _child_process() { - return data; - }; - - return data; -} - -var _constants = _interopRequireDefault(require('../constants')); - -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 find(roots, extensions, ignore, callback) { - const result = []; - let activeCalls = 0; - - function search(directory) { - activeCalls++; - - _fs().default.readdir(directory, (err, names) => { - activeCalls--; - - if (err) { - callback(result); - return; - } - - names.forEach(file => { - file = _path().default.join(directory, file); - - if (ignore(file)) { - return; - } - - activeCalls++; - - _fs().default.lstat(file, (err, stat) => { - activeCalls--; - - if (!err && stat && !stat.isSymbolicLink()) { - if (stat.isDirectory()) { - search(file); - } else { - const ext = _path() - .default.extname(file) - .substr(1); - - if (extensions.indexOf(ext) !== -1) { - result.push([file, stat.mtime.getTime(), stat.size]); - } - } - } - - if (activeCalls === 0) { - callback(result); - } - }); - }); - - if (activeCalls === 0) { - callback(result); - } - }); - } - - if (roots.length > 0) { - roots.forEach(search); - } else { - callback(result); - } -} - -function findNative(roots, extensions, ignore, callback) { - const args = Array.from(roots); - args.push('-type', 'f'); - - if (extensions.length) { - args.push('('); - } - - extensions.forEach((ext, index) => { - if (index) { - args.push('-o'); - } - - args.push('-iname'); - args.push('*.' + ext); - }); - - if (extensions.length) { - args.push(')'); - } - - const child = (0, _child_process().spawn)('find', args); - let stdout = ''; - child.stdout.setEncoding('utf-8'); - child.stdout.on('data', data => (stdout += data)); - child.stdout.on('close', () => { - const lines = stdout - .trim() - .split('\n') - .filter(x => !ignore(x)); - const result = []; - let count = lines.length; - - if (!count) { - callback([]); - } else { - lines.forEach(path => { - _fs().default.stat(path, (err, stat) => { - if (!err && stat) { - result.push([path, stat.mtime.getTime(), stat.size]); - } - - if (--count === 0) { - callback(result); - } - }); - }); - } - }); -} - -module.exports = function nodeCrawl(options) { - if (options.mapper) { - throw new Error(`Option 'mapper' isn't supported by the Node crawler`); - } - - const data = options.data, - extensions = options.extensions, - forceNodeFilesystemAPI = options.forceNodeFilesystemAPI, - ignore = options.ignore, - rootDir = options.rootDir, - roots = options.roots; - return new Promise(resolve => { - const callback = list => { - const files = new Map(); - list.forEach(fileData => { - const _fileData = _slicedToArray(fileData, 3), - filePath = _fileData[0], - mtime = _fileData[1], - size = _fileData[2]; - - const relativeFilePath = fastPath.relative(rootDir, filePath); - const existingFile = data.files.get(relativeFilePath); - - if (existingFile && existingFile[_constants.default.MTIME] === mtime) { - files.set(relativeFilePath, existingFile); - } else { - // See ../constants.js; SHA-1 will always be null and fulfilled later. - files.set(relativeFilePath, ['', mtime, size, 0, [], null]); - } - }); - data.files = files; - resolve(data); - }; - - if (forceNodeFilesystemAPI || process.platform === 'win32') { - find(roots, extensions, ignore, callback); - } else { - findNative(roots, extensions, ignore, callback); - } - }); -}; diff --git a/packages/jest-haste-map/build/crawlers/watchman.js b/packages/jest-haste-map/build/crawlers/watchman.js deleted file mode 100644 index 4407357cd958..000000000000 --- a/packages/jest-haste-map/build/crawlers/watchman.js +++ /dev/null @@ -1,564 +0,0 @@ -'use strict'; - -function _path() { - const data = _interopRequireDefault(require('path')); - - _path = function _path() { - return data; - }; - - return data; -} - -function _fbWatchman() { - const data = _interopRequireDefault(require('fb-watchman')); - - _fbWatchman = function _fbWatchman() { - return data; - }; - - return data; -} - -var fastPath = _interopRequireWildcard(require('../lib/fast_path')); - -var _normalizePathSep = _interopRequireDefault( - require('../lib/normalizePathSep') -); - -var _constants = _interopRequireDefault(require('../constants')); - -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); - }); - }; -} - -const watchmanURL = - 'https://facebook.github.io/watchman/docs/troubleshooting.html'; - -function WatchmanError(error) { - error.message = - `Watchman error: ${error.message.trim()}. Make sure watchman ` + - `is running for this project. See ${watchmanURL}.`; - return error; -} - -module.exports = - /*#__PURE__*/ - (function() { - var _watchmanCrawl = _asyncToGenerator(function*(options) { - const fields = ['name', 'exists', 'mtime_ms', 'size']; - const data = options.data, - extensions = options.extensions, - ignore = options.ignore, - rootDir = options.rootDir, - roots = options.roots; - const defaultWatchExpression = [ - 'allof', - ['type', 'f'], - ['anyof', ...extensions.map(extension => ['suffix', extension])] - ]; - const clocks = data.clocks; - const client = new (_fbWatchman()).default.Client(); - let clientError; - client.on('error', error => (clientError = WatchmanError(error))); // TODO: type better than `any` - - const cmd = (...args) => - new Promise((resolve, reject) => - client.command(args, (error, result) => - error ? reject(WatchmanError(error)) : resolve(result) - ) - ); - - if (options.computeSha1) { - const _ref = yield cmd('list-capabilities'), - capabilities = _ref.capabilities; - - if (capabilities.indexOf('field-content.sha1hex') !== -1) { - fields.push('content.sha1hex'); - } - } - - function getWatchmanRoots(_x2) { - return _getWatchmanRoots.apply(this, arguments); - } - - function _getWatchmanRoots() { - _getWatchmanRoots = _asyncToGenerator(function*(roots) { - const watchmanRoots = new Map(); - yield Promise.all( - roots.map( - /*#__PURE__*/ - (function() { - var _ref2 = _asyncToGenerator(function*(root) { - const response = yield cmd('watch-project', root); - const existing = watchmanRoots.get(response.watch); // A root can only be filtered if it was never seen with a - // relative_path before. - - const canBeFiltered = !existing || existing.length > 0; - - if (canBeFiltered) { - if (response.relative_path) { - watchmanRoots.set( - response.watch, - (existing || []).concat(response.relative_path) - ); - } else { - // Make the filter directories an empty array to signal that this - // root was already seen and needs to be watched for all files or - // directories. - watchmanRoots.set(response.watch, []); - } - } - }); - - return function(_x4) { - return _ref2.apply(this, arguments); - }; - })() - ) - ); - return watchmanRoots; - }); - return _getWatchmanRoots.apply(this, arguments); - } - - function queryWatchmanForDirs(_x3) { - return _queryWatchmanForDirs.apply(this, arguments); - } - - function _queryWatchmanForDirs() { - _queryWatchmanForDirs = _asyncToGenerator(function*( - rootProjectDirMappings - ) { - const files = new Map(); - let isFresh = false; - yield Promise.all( - Array.from(rootProjectDirMappings).map( - /*#__PURE__*/ - (function() { - var _ref3 = _asyncToGenerator(function*([ - root, - directoryFilters - ]) { - const expression = Array.from(defaultWatchExpression); - const glob = []; - - if (directoryFilters.length > 0) { - expression.push([ - 'anyof', - ...directoryFilters.map(dir => ['dirname', dir]) - ]); - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for ( - var _iterator2 = directoryFilters[Symbol.iterator](), - _step2; - !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()) - .done); - _iteratorNormalCompletion2 = true - ) { - const directory = _step2.value; - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for ( - var _iterator3 = extensions[Symbol.iterator](), - _step3; - !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()) - .done); - _iteratorNormalCompletion3 = true - ) { - const extension = _step3.value; - glob.push(`${directory}/**/*.${extension}`); - } - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if ( - !_iteratorNormalCompletion3 && - _iterator3.return != null - ) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if ( - !_iteratorNormalCompletion2 && - _iterator2.return != null - ) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - } else { - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for ( - var _iterator4 = extensions[Symbol.iterator](), _step4; - !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()) - .done); - _iteratorNormalCompletion4 = true - ) { - const extension = _step4.value; - glob.push(`**/*.${extension}`); - } - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if ( - !_iteratorNormalCompletion4 && - _iterator4.return != null - ) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - } - - const relativeRoot = fastPath.relative(rootDir, root); - const query = clocks.has(relativeRoot) // Use the `since` generator if we have a clock available - ? { - expression, - fields, - since: clocks.get(relativeRoot) - } // Otherwise use the `glob` filter - : { - expression, - fields, - glob - }; - const response = yield cmd('query', root, query); - - if ('warning' in response) { - console.warn('watchman warning: ', response.warning); - } - - isFresh = isFresh || response.is_fresh_instance; - files.set(root, response); - }); - - return function(_x5) { - return _ref3.apply(this, arguments); - }; - })() - ) - ); - return { - files, - isFresh - }; - }); - return _queryWatchmanForDirs.apply(this, arguments); - } - - let files = data.files; - let watchmanFiles; - - try { - const watchmanRoots = yield getWatchmanRoots(roots); - const watchmanFileResults = yield queryWatchmanForDirs(watchmanRoots); // Reset the file map if watchman was restarted and sends us a list of - // files. - - if (watchmanFileResults.isFresh) { - files = new Map(); - } - - watchmanFiles = watchmanFileResults.files; - } finally { - client.end(); - } - - if (clientError) { - throw clientError; - } // TODO: remove non-null - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for ( - var _iterator = watchmanFiles[Symbol.iterator](), _step; - !(_iteratorNormalCompletion = (_step = _iterator.next()).done); - _iteratorNormalCompletion = true - ) { - const _step$value = _slicedToArray(_step.value, 2), - watchRoot = _step$value[0], - response = _step$value[1]; - - const fsRoot = (0, _normalizePathSep.default)(watchRoot); - const relativeFsRoot = fastPath.relative(rootDir, fsRoot); - clocks.set(relativeFsRoot, response.clock); - var _iteratorNormalCompletion5 = true; - var _didIteratorError5 = false; - var _iteratorError5 = undefined; - - try { - for ( - var _iterator5 = response.files[Symbol.iterator](), _step5; - !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); - _iteratorNormalCompletion5 = true - ) { - const fileData = _step5.value; - const filePath = - fsRoot + - _path().default.sep + - (0, _normalizePathSep.default)(fileData.name); - const relativeFilePath = fastPath.relative(rootDir, filePath); - - if (!fileData.exists) { - files.delete(relativeFilePath); - } else if (!ignore(filePath)) { - const mtime = - typeof fileData.mtime_ms === 'number' - ? fileData.mtime_ms - : fileData.mtime_ms.toNumber(); - const size = fileData.size; - let sha1hex = fileData['content.sha1hex']; - - if (typeof sha1hex !== 'string' || sha1hex.length !== 40) { - sha1hex = null; - } - - const existingFileData = data.files.get(relativeFilePath); - let nextData; - - if ( - existingFileData && - existingFileData[_constants.default.MTIME] === mtime - ) { - nextData = existingFileData; - } else if ( - existingFileData && - sha1hex && - existingFileData[_constants.default.SHA1] === sha1hex - ) { - nextData = [ - existingFileData[0], - mtime, - existingFileData[2], - existingFileData[3], - existingFileData[4], - existingFileData[5] - ]; - } else { - // See ../constants.ts - nextData = ['', mtime, size, 0, [], sha1hex]; - } - - const mappings = options.mapper - ? options.mapper(filePath) - : null; - - if (mappings) { - var _iteratorNormalCompletion6 = true; - var _didIteratorError6 = false; - var _iteratorError6 = undefined; - - try { - for ( - var _iterator6 = mappings[Symbol.iterator](), _step6; - !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()) - .done); - _iteratorNormalCompletion6 = true - ) { - const absoluteVirtualFilePath = _step6.value; - - if (!ignore(absoluteVirtualFilePath)) { - const relativeVirtualFilePath = fastPath.relative( - rootDir, - absoluteVirtualFilePath - ); - files.set(relativeVirtualFilePath, nextData); - } - } - } catch (err) { - _didIteratorError6 = true; - _iteratorError6 = err; - } finally { - try { - if ( - !_iteratorNormalCompletion6 && - _iterator6.return != null - ) { - _iterator6.return(); - } - } finally { - if (_didIteratorError6) { - throw _iteratorError6; - } - } - } - } else { - files.set(relativeFilePath, nextData); - } - } - } - } catch (err) { - _didIteratorError5 = true; - _iteratorError5 = err; - } finally { - try { - if (!_iteratorNormalCompletion5 && _iterator5.return != null) { - _iterator5.return(); - } - } finally { - if (_didIteratorError5) { - throw _iteratorError5; - } - } - } - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - data.files = files; - return data; - }); - - function watchmanCrawl(_x) { - return _watchmanCrawl.apply(this, arguments); - } - - return watchmanCrawl; - })(); diff --git a/packages/jest-haste-map/build/getMockName.js b/packages/jest-haste-map/build/getMockName.js deleted file mode 100644 index 29e0f9980ca3..000000000000 --- a/packages/jest-haste-map/build/getMockName.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = void 0; - -function _path() { - const data = _interopRequireDefault(require('path')); - - _path = function _path() { - return data; - }; - - return data; -} - -function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : {default: obj}; -} - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -const MOCKS_PATTERN = _path().default.sep + '__mocks__' + _path().default.sep; - -const getMockName = filePath => { - const mockPath = filePath.split(MOCKS_PATTERN)[1]; - return mockPath - .substring(0, mockPath.lastIndexOf(_path().default.extname(mockPath))) - .replace(/\\/g, '/'); -}; - -var _default = getMockName; -exports.default = _default; diff --git a/packages/jest-haste-map/build/index.js b/packages/jest-haste-map/build/index.js deleted file mode 100644 index 541331ff0bfc..000000000000 --- a/packages/jest-haste-map/build/index.js +++ /dev/null @@ -1,1272 +0,0 @@ -'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 _fs() { - const data = _interopRequireDefault(require('fs')); - - _fs = function _fs() { - 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 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; -} - -const CHANGE_INTERVAL = 30; -const MAX_WAIT_TIME = 240000; - -const NODE_MODULES = _path().default.sep + 'node_modules' + _path().default.sep; // TypeScript doesn't like us importing from outside `rootDir` - -const _JSON$parse = JSON.parse( - _fs().default.readFileSync(require.resolve('../package.json'), 'utf8') - ), - VERSION = _JSON$parse.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, // 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().default { - constructor(options) { - super(); - 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, - 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)), - 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() { - if (!this._buildPromise) { - this._buildPromise = this._buildFileMap() - .then(data => this._buildHasteMap(data)) - .then(hasteMap => { - this._persist(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; - - return this._watch(hasteMap).then(() => ({ - __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() { - const read = this._options.resetCache ? this._createEmptyMap : this.read; - return Promise.resolve() - .then(() => read.call(this)) - .catch(() => this._createEmptyMap()) - .then(cachedHasteMap => { - const cachedFiles = []; - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for ( - var _iterator = cachedHasteMap.files[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]; - - const moduleName = fileMetadata[_constants.default.ID]; - cachedFiles.push({ - moduleName, - path: relativeFilePath - }); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - return this._crawl(cachedHasteMap).then(hasteMap => { - const deprecatedFiles = cachedFiles.filter( - file => !hasteMap.files.has(file.path) - ); - return { - deprecatedFiles, - 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 message = - `jest-haste-map: Haste module naming collision:\n` + - ` Duplicate module name: ${id}\n` + - ` Paths: ${fastPath.resolve( - rootDir, - module[_constants.default.PATH] - )} collides with ` + - `${fastPath.resolve( - rootDir, - existingModule[_constants.default.PATH] - )}\n\nThis ` + - `${this._options.throwOnModuleCollision ? 'error' : 'warning'} ` + - `is caused by \`hasteImpl\` returning the same name for different` + - ` files.`; - - if (this._options.throwOnModuleCollision) { - throw new Error(message); - } - - this._console.warn(message); // 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 || []; - - 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) { - this._console.warn( - `jest-haste-map: duplicate manual mock found:\n` + - ` Module name: ${mockPath}\n` + - ` Duplicate Mock path: ${filePath}\nThis warning ` + - `is caused by two manual mock files with the same file name.\n` + - `Jest will use the mock file found in: \n` + - `${filePath}\n` + - ` Please delete one of the following two files: \n ` + - `${_path().default.join( - rootDir, - existingMockPath - )}\n${filePath}\n\n` - ); - } - - 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 deprecatedFiles = data.deprecatedFiles, - hasteMap = data.hasteMap; - const map = new Map(); - const mocks = new Map(); - const promises = []; - - for (let i = 0; i < deprecatedFiles.length; ++i) { - const file = deprecatedFiles[i]; - - this._recoverDuplicates(hasteMap, file.path, file.moduleName); - } - - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for ( - var _iterator2 = hasteMap.files.keys()[Symbol.iterator](), _step2; - !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); - _iteratorNormalCompletion2 = true - ) { - const relativeFilePath = _step2.value; - // 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; - }) - .catch(error => { - this._cleanup(); - - return Promise.reject(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 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)({ - computeSha1: options.computeSha1, - data: hasteMap, - extensions: options.extensions, - forceNodeFilesystemAPI: options.forceNodeFilesystemAPI, - ignore, - mapper: options.mapper, - rootDir: options.rootDir, - roots: options.roots - }).catch(e => { - throw new Error( - `Crawler retry failed:\n` + - ` Original error: ${error.message}\n` + - ` Retry error: ${e.message}\n` - ); - }); - } - - throw error; - }; - - try { - return crawl({ - computeSha1: options.computeSha1, - data: hasteMap, - extensions: options.extensions, - forceNodeFilesystemAPI: options.forceNodeFilesystemAPI, - ignore, - rootDir: options.rootDir, - roots: options.roots - }).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; - const Watcher = - canUseWatchman && this._options.useWatchman - ? _WatchmanWatcher.default - : _os().default.platform() === 'darwin' - ? _sane().default.FSEventsWatcher - : _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; - this.emit('change', { - eventsQueue, - hasteFS: new _HasteFS.default({ - files: hasteMap.files, - rootDir - }), - moduleMap: new _ModuleMap.default({ - duplicates: hasteMap.duplicates, - map: hasteMap.map, - mocks: hasteMap.mocks, - rootDir - }) - }); - 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() - }; - } -} - -function copy(object) { - return Object.assign(Object.create(null), object); -} - -function copyMap(input) { - return new Map(input); -} - -HasteMap.H = _constants.default; -HasteMap.ModuleMap = _ModuleMap.default; -module.exports = HasteMap; diff --git a/packages/jest-haste-map/build/lib/WatchmanWatcher.js b/packages/jest-haste-map/build/lib/WatchmanWatcher.js deleted file mode 100644 index f6d5eed37a2b..000000000000 --- a/packages/jest-haste-map/build/lib/WatchmanWatcher.js +++ /dev/null @@ -1,400 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = WatchmanWatcher; - -function _fs() { - const data = _interopRequireDefault(require('fs')); - - _fs = function _fs() { - return data; - }; - - return data; -} - -function _path() { - const data = _interopRequireDefault(require('path')); - - _path = function _path() { - return data; - }; - - return data; -} - -function _assert() { - const data = _interopRequireDefault(require('assert')); - - _assert = function _assert() { - return data; - }; - - return data; -} - -function _events() { - const data = require('events'); - - _events = function _events() { - return data; - }; - - return data; -} - -function _fbWatchman() { - const data = _interopRequireDefault(require('fb-watchman')); - - _fbWatchman = function _fbWatchman() { - return data; - }; - - return data; -} - -function _common() { - const data = _interopRequireDefault(require('sane/src/common')); - - _common = function _common() { - return data; - }; - - return data; -} - -function _recrawlWarningDedupe() { - const data = _interopRequireDefault( - require('sane/src/utils/recrawl-warning-dedupe') - ); - - _recrawlWarningDedupe = function _recrawlWarningDedupe() { - return data; - }; - - return data; -} - -function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : {default: obj}; -} - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -const CHANGE_EVENT = _common().default.CHANGE_EVENT; - -const DELETE_EVENT = _common().default.DELETE_EVENT; - -const ADD_EVENT = _common().default.ADD_EVENT; - -const ALL_EVENT = _common().default.ALL_EVENT; - -const SUB_NAME = 'sane-sub'; -/** - * Watches `dir`. - * - * @class PollWatcher - * @param String dir - * @param {Object} opts - * @public - */ - -function WatchmanWatcher(dir, opts) { - _common().default.assignOptions(this, opts); - - this.root = _path().default.resolve(dir); - this.init(); -} // eslint-disable-next-line no-proto - -WatchmanWatcher.prototype.__proto__ = _events().EventEmitter.prototype; -/** - * Run the watchman `watch` command on the root and subscribe to changes. - * - * @private - */ - -WatchmanWatcher.prototype.init = function() { - if (this.client) { - this.client.removeAllListeners(); - } - - const self = this; - this.client = new (_fbWatchman()).default.Client(); - this.client.on('error', error => { - self.emit('error', error); - }); - this.client.on('subscription', this.handleChangeEvent.bind(this)); - this.client.on('end', () => { - console.warn('[sane] Warning: Lost connection to watchman, reconnecting..'); - self.init(); - }); - this.watchProjectInfo = null; - - function getWatchRoot() { - return self.watchProjectInfo ? self.watchProjectInfo.root : self.root; - } - - function onCapability(error, resp) { - if (handleError(self, error)) { - // The Watchman watcher is unusable on this system, we cannot continue - return; - } - - handleWarning(resp); - self.capabilities = resp.capabilities; - - if (self.capabilities.relative_root) { - self.client.command(['watch-project', getWatchRoot()], onWatchProject); - } else { - self.client.command(['watch', getWatchRoot()], onWatch); - } - } - - function onWatchProject(error, resp) { - if (handleError(self, error)) { - return; - } - - handleWarning(resp); - self.watchProjectInfo = { - relativePath: resp.relative_path ? resp.relative_path : '', - root: resp.watch - }; - self.client.command(['clock', getWatchRoot()], onClock); - } - - function onWatch(error, resp) { - if (handleError(self, error)) { - return; - } - - handleWarning(resp); - self.client.command(['clock', getWatchRoot()], onClock); - } - - function onClock(error, resp) { - if (handleError(self, error)) { - return; - } - - handleWarning(resp); - const options = { - fields: ['name', 'exists', 'new'], - since: resp.clock - }; // If the server has the wildmatch capability available it supports - // the recursive **/*.foo style match and we can offload our globs - // to the watchman server. This saves both on data size to be - // communicated back to us and compute for evaluating the globs - // in our node process. - - if (self.capabilities.wildmatch) { - if (self.globs.length === 0) { - if (!self.dot) { - // Make sure we honor the dot option if even we're not using globs. - options.expression = [ - 'match', - '**', - 'wholename', - { - includedotfiles: false - } - ]; - } - } else { - options.expression = ['anyof']; - - for (const i in self.globs) { - options.expression.push([ - 'match', - self.globs[i], - 'wholename', - { - includedotfiles: self.dot - } - ]); - } - } - } - - if (self.capabilities.relative_root) { - options.relative_root = self.watchProjectInfo.relativePath; - } - - self.client.command( - ['subscribe', getWatchRoot(), SUB_NAME, options], - onSubscribe - ); - } - - function onSubscribe(error, resp) { - if (handleError(self, error)) { - return; - } - - handleWarning(resp); - self.emit('ready'); - } - - self.client.capabilityCheck( - { - optional: ['wildmatch', 'relative_root'] - }, - onCapability - ); -}; -/** - * Handles a change event coming from the subscription. - * - * @param {Object} resp - * @private - */ - -WatchmanWatcher.prototype.handleChangeEvent = function(resp) { - _assert().default.equal( - resp.subscription, - SUB_NAME, - 'Invalid subscription event.' - ); - - if (resp.is_fresh_instance) { - this.emit('fresh_instance'); - } - - if (resp.is_fresh_instance) { - this.emit('fresh_instance'); - } - - if (Array.isArray(resp.files)) { - resp.files.forEach(this.handleFileChange, this); - } -}; -/** - * Handles a single change event record. - * - * @param {Object} changeDescriptor - * @private - */ - -WatchmanWatcher.prototype.handleFileChange = function(changeDescriptor) { - const self = this; - let absPath; - let relativePath; - - if (this.capabilities.relative_root) { - relativePath = changeDescriptor.name; - absPath = _path().default.join( - this.watchProjectInfo.root, - this.watchProjectInfo.relativePath, - relativePath - ); - } else { - absPath = _path().default.join(this.root, changeDescriptor.name); - relativePath = changeDescriptor.name; - } - - if ( - !(self.capabilities.wildmatch && !this.hasIgnore) && - !_common().default.isFileIncluded( - this.globs, - this.dot, - this.doIgnore, - relativePath - ) - ) { - return; - } - - if (!changeDescriptor.exists) { - self.emitEvent(DELETE_EVENT, relativePath, self.root); - } else { - _fs().default.lstat(absPath, (error, stat) => { - // Files can be deleted between the event and the lstat call - // the most reliable thing to do here is to ignore the event. - if (error && error.code === 'ENOENT') { - return; - } - - if (handleError(self, error)) { - return; - } - - const eventType = changeDescriptor.new ? ADD_EVENT : CHANGE_EVENT; // Change event on dirs are mostly useless. - - if (!(eventType === CHANGE_EVENT && stat.isDirectory())) { - self.emitEvent(eventType, relativePath, self.root, stat); - } - }); - } -}; -/** - * Dispatches the event. - * - * @param {string} eventType - * @param {string} filepath - * @param {string} root - * @param {fs.Stat} stat - * @private - */ - -WatchmanWatcher.prototype.emitEvent = function( - eventType, - filepath, - root, - stat -) { - this.emit(eventType, filepath, root, stat); - this.emit(ALL_EVENT, eventType, filepath, root, stat); -}; -/** - * Closes the watcher. - * - * @param {function} callback - * @private - */ - -WatchmanWatcher.prototype.close = function(callback) { - this.client.removeAllListeners(); - this.client.end(); - callback && callback(null, true); -}; -/** - * Handles an error and returns true if exists. - * - * @param {WatchmanWatcher} self - * @param {Error} error - * @private - */ - -function handleError(self, error) { - if (error != null) { - self.emit('error', error); - return true; - } else { - return false; - } -} -/** - * Handles a warning in the watchman resp object. - * - * @param {object} resp - * @private - */ - -function handleWarning(resp) { - if ('warning' in resp) { - if (_recrawlWarningDedupe().default.isRecrawlWarningDupe(resp.warning)) { - return true; - } - - console.warn(resp.warning); - return true; - } else { - return false; - } -} diff --git a/packages/jest-haste-map/build/lib/dependencyExtractor.js b/packages/jest-haste-map/build/lib/dependencyExtractor.js deleted file mode 100644 index be0c9aa07b2a..000000000000 --- a/packages/jest-haste-map/build/lib/dependencyExtractor.js +++ /dev/null @@ -1,100 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.extract = extract; - -var _isRegExpSupported = _interopRequireDefault(require('./isRegExpSupported')); - -function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : {default: obj}; -} - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -// Negative look behind is only supported in Node 9+ -const NOT_A_DOT = (0, _isRegExpSupported.default)('(? `([\`'"])([^'"\`]*?)(?:\\${pos})`; - -const WORD_SEPARATOR = '\\b'; -const LEFT_PARENTHESIS = '\\('; -const RIGHT_PARENTHESIS = '\\)'; -const WHITESPACE = '\\s*'; -const OPTIONAL_COMMA = '(:?,\\s*)?'; - -function createRegExp(parts, flags) { - return new RegExp(parts.join(''), flags); -} - -function alternatives(...parts) { - return `(?:${parts.join('|')})`; -} - -function functionCallStart(...names) { - return [ - NOT_A_DOT, - WORD_SEPARATOR, - alternatives(...names), - WHITESPACE, - LEFT_PARENTHESIS, - WHITESPACE - ]; -} - -const BLOCK_COMMENT_RE = /\/\*[^]*?\*\//g; -const LINE_COMMENT_RE = /\/\/.*/g; -const REQUIRE_OR_DYNAMIC_IMPORT_RE = createRegExp( - [ - ...functionCallStart('require', 'import'), - CAPTURE_STRING_LITERAL(1), - WHITESPACE, - OPTIONAL_COMMA, - RIGHT_PARENTHESIS - ], - 'g' -); -const IMPORT_OR_EXPORT_RE = createRegExp( - [ - '\\b(?:import|export)\\s+(?!type(?:of)?\\s+)[^\'"]+\\s+from\\s+', - CAPTURE_STRING_LITERAL(1) - ], - 'g' -); -const JEST_EXTENSIONS_RE = createRegExp( - [ - ...functionCallStart( - 'require\\s*\\.\\s*(?:requireActual|requireMock)', - 'jest\\s*\\.\\s*(?:requireActual|requireMock|genMockFromModule)' - ), - CAPTURE_STRING_LITERAL(1), - WHITESPACE, - OPTIONAL_COMMA, - RIGHT_PARENTHESIS - ], - 'g' -); - -function extract(code) { - const dependencies = new Set(); - - const addDependency = (match, _, dep) => { - dependencies.add(dep); - return match; - }; - - code - .replace(BLOCK_COMMENT_RE, '') - .replace(LINE_COMMENT_RE, '') - .replace(IMPORT_OR_EXPORT_RE, addDependency) - .replace(REQUIRE_OR_DYNAMIC_IMPORT_RE, addDependency) - .replace(JEST_EXTENSIONS_RE, addDependency); - return dependencies; -} diff --git a/packages/jest-haste-map/build/lib/fast_path.js b/packages/jest-haste-map/build/lib/fast_path.js deleted file mode 100644 index 31b5bbb7d367..000000000000 --- a/packages/jest-haste-map/build/lib/fast_path.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.relative = relative; -exports.resolve = resolve; - -function _path() { - const data = _interopRequireDefault(require('path')); - - _path = function _path() { - return data; - }; - - return data; -} - -function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : {default: obj}; -} - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -// rootDir and filename must be absolute paths (resolved) -function relative(rootDir, filename) { - return filename.indexOf(rootDir + _path().default.sep) === 0 - ? filename.substr(rootDir.length + 1) - : _path().default.relative(rootDir, filename); -} - -const INDIRECTION_FRAGMENT = '..' + _path().default.sep; // rootDir must be an absolute path and relativeFilename must be simple -// (e.g.: foo/bar or ../foo/bar, but never ./foo or foo/../bar) - -function resolve(rootDir, relativeFilename) { - return relativeFilename.indexOf(INDIRECTION_FRAGMENT) === 0 - ? _path().default.resolve(rootDir, relativeFilename) - : rootDir + _path().default.sep + relativeFilename; -} diff --git a/packages/jest-haste-map/build/lib/getPlatformExtension.js b/packages/jest-haste-map/build/lib/getPlatformExtension.js deleted file mode 100644 index 6b9e564f9b84..000000000000 --- a/packages/jest-haste-map/build/lib/getPlatformExtension.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = getPlatformExtension; - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -const SUPPORTED_PLATFORM_EXTS = new Set(['android', 'ios', 'native', 'web']); // Extract platform extension: index.ios.js -> ios - -function getPlatformExtension(file, platforms) { - const last = file.lastIndexOf('.'); - const secondToLast = file.lastIndexOf('.', last - 1); - - if (secondToLast === -1) { - return null; - } - - const platform = file.substring(secondToLast + 1, last); // If an overriding platform array is passed, check that first - - if (platforms && platforms.indexOf(platform) !== -1) { - return platform; - } - - return SUPPORTED_PLATFORM_EXTS.has(platform) ? platform : null; -} diff --git a/packages/jest-haste-map/build/lib/isRegExpSupported.js b/packages/jest-haste-map/build/lib/isRegExpSupported.js deleted file mode 100644 index 44de4e119061..000000000000 --- a/packages/jest-haste-map/build/lib/isRegExpSupported.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = isRegExpSupported; - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -function isRegExpSupported(value) { - try { - // eslint-disable-next-line no-new - new RegExp(value); - return true; - } catch (e) { - return false; - } -} diff --git a/packages/jest-haste-map/build/lib/normalizePathSep.js b/packages/jest-haste-map/build/lib/normalizePathSep.js deleted file mode 100644 index 23c7782bd90b..000000000000 --- a/packages/jest-haste-map/build/lib/normalizePathSep.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.default = void 0; - -function _path() { - const data = _interopRequireDefault(require('path')); - - _path = function _path() { - return data; - }; - - return data; -} - -function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : {default: obj}; -} - -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -let normalizePathSep; - -if (_path().default.sep === '/') { - normalizePathSep = filePath => filePath; -} else { - normalizePathSep = filePath => filePath.replace(/\//g, _path().default.sep); -} - -var _default = normalizePathSep; -exports.default = _default; diff --git a/packages/jest-haste-map/build/types.js b/packages/jest-haste-map/build/types.js deleted file mode 100644 index ad9a93a7c160..000000000000 --- a/packages/jest-haste-map/build/types.js +++ /dev/null @@ -1 +0,0 @@ -'use strict'; diff --git a/packages/jest-haste-map/build/worker.js b/packages/jest-haste-map/build/worker.js deleted file mode 100644 index 1996d4a8e270..000000000000 --- a/packages/jest-haste-map/build/worker.js +++ /dev/null @@ -1,230 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.worker = worker; -exports.getSha1 = getSha1; - -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 _gracefulFs() { - const data = _interopRequireDefault(require('graceful-fs')); - - _gracefulFs = function _gracefulFs() { - return data; - }; - - return data; -} - -var _blacklist = _interopRequireDefault(require('./blacklist')); - -var _constants = _interopRequireDefault(require('./constants')); - -var dependencyExtractor = _interopRequireWildcard( - require('./lib/dependencyExtractor') -); - -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 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); - }); - }; -} - -const PACKAGE_JSON = _path().default.sep + 'package.json'; -let hasteImpl = null; -let hasteImplModulePath = null; - -function sha1hex(content) { - return _crypto() - .default.createHash('sha1') - .update(content) - .digest('hex'); -} - -function worker(_x) { - return _worker.apply(this, arguments); -} - -function _worker() { - _worker = _asyncToGenerator(function*(data) { - if ( - data.hasteImplModulePath && - data.hasteImplModulePath !== hasteImplModulePath - ) { - if (hasteImpl) { - throw new Error('jest-haste-map: hasteImplModulePath changed'); - } - - hasteImplModulePath = data.hasteImplModulePath; - hasteImpl = require(hasteImplModulePath); - } - - let content; - let dependencies; - let id; - let module; - let sha1; - const computeDependencies = data.computeDependencies, - computeSha1 = data.computeSha1, - rootDir = data.rootDir, - filePath = data.filePath; - - const getContent = () => { - if (content === undefined) { - content = _gracefulFs().default.readFileSync(filePath, 'utf8'); - } - - return content; - }; - - if (filePath.endsWith(PACKAGE_JSON)) { - // Process a package.json that is returned as a PACKAGE type with its name. - try { - const fileData = JSON.parse(getContent()); - - if (fileData.name) { - const relativeFilePath = _path().default.relative(rootDir, filePath); - - id = fileData.name; - module = [relativeFilePath, _constants.default.PACKAGE]; - } - } catch (err) { - throw new Error(`Cannot parse ${filePath} as JSON: ${err.message}`); - } - } else if ( - !_blacklist.default.has(filePath.substr(filePath.lastIndexOf('.'))) - ) { - // Process a random file that is returned as a MODULE. - if (hasteImpl) { - id = hasteImpl.getHasteName(filePath); - } - - if (computeDependencies) { - const content = getContent(); - dependencies = Array.from( - data.dependencyExtractor - ? require(data.dependencyExtractor).extract( - content, - filePath, - dependencyExtractor.extract - ) - : dependencyExtractor.extract(content) - ); - } - - if (id) { - const relativeFilePath = _path().default.relative(rootDir, filePath); - - module = [relativeFilePath, _constants.default.MODULE]; - } - } // If a SHA-1 is requested on update, compute it. - - if (computeSha1) { - sha1 = sha1hex( - getContent() || _gracefulFs().default.readFileSync(filePath) - ); - } - - return { - dependencies, - id, - module, - sha1 - }; - }); - return _worker.apply(this, arguments); -} - -function getSha1(_x2) { - return _getSha.apply(this, arguments); -} - -function _getSha() { - _getSha = _asyncToGenerator(function*(data) { - const sha1 = data.computeSha1 - ? sha1hex(_gracefulFs().default.readFileSync(data.filePath)) - : null; - return { - dependencies: undefined, - id: undefined, - module: undefined, - sha1 - }; - }); - return _getSha.apply(this, arguments); -} From c19c4b4f84c2c51fd21f61e37c0de6b0e0b4aa63 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 12 Feb 2019 00:51:59 +0100 Subject: [PATCH 16/16] require skips nasty fs read --- .../jest-haste-map/src/__tests__/index.test.js | 14 +++++--------- packages/jest-haste-map/src/index.ts | 7 +++---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/packages/jest-haste-map/src/__tests__/index.test.js b/packages/jest-haste-map/src/__tests__/index.test.js index bda4878ec8c9..c11a752bd8b9 100644 --- a/packages/jest-haste-map/src/__tests__/index.test.js +++ b/packages/jest-haste-map/src/__tests__/index.test.js @@ -146,9 +146,6 @@ describe('HasteMap', () => { mockEmitters = Object.create(null); mockFs = object({ - [require.resolve('../../package.json')]: JSON.stringify({ - version: '1.0.0', - }), '/project/fruits/Banana.js': ` const Strawberry = require("Strawberry"); `, @@ -519,8 +516,8 @@ describe('HasteMap', () => { expect(data.map.get('fbjs')).not.toBeDefined(); - // package.json + cache file + 5 modules - the node_module - expect(fs.readFileSync.mock.calls.length).toBe(7); + // cache file + 5 modules - the node_module + expect(fs.readFileSync.mock.calls.length).toBe(6); }); }); @@ -638,10 +635,9 @@ describe('HasteMap', () => { new HasteMap(defaultConfig) .build() .then(({__hasteMapForTest: initialData}) => { - // The first run should access the file system once for package.json, - // once for the (empty) cache file and five times for the files in the - // system. - expect(fs.readFileSync.mock.calls.length).toBe(7); + // The first run should access the file system once for the (empty) + // cache file and five times for the files in the system. + expect(fs.readFileSync.mock.calls.length).toBe(6); fs.readFileSync.mockClear(); diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index 641e1285386f..f6bd3bad058b 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -106,10 +106,9 @@ const CHANGE_INTERVAL = 30; const MAX_WAIT_TIME = 240000; const NODE_MODULES = path.sep + 'node_modules' + path.sep; -// TypeScript doesn't like us importing from outside `rootDir` -const {version: VERSION} = JSON.parse( - fs.readFileSync(require.resolve('../package.json'), 'utf8'), -); +// TypeScript doesn't like us importing from outside `rootDir`, but it doesn't +// understand `require`. +const {version: VERSION} = require('../package.json'); const canUseWatchman = ((): boolean => { try {