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 83% rename from packages/jest-haste-map/src/ModuleMap.js rename to packages/jest-haste-map/src/ModuleMap.ts index 7f2390020fff..07246b1babcb 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,26 @@ 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 = { - // 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, +type ValueType = T extends Map ? V : never; + +export type SerializableModuleMap = { + duplicates: ReadonlyArray<[string, ValueType]>; + map: ReadonlyArray<[string, ValueType]>; + mocks: ReadonlyArray<[string, ValueType]>; + rootDir: Config.Path; }; export default class ModuleMap { - _raw: RawModuleMap; - static DuplicateHasteCandidatesError: Class; + private readonly _raw: RawModuleMap; + static DuplicateHasteCandidatesError: typeof DuplicateHasteCandidatesError; constructor(raw: RawModuleMap) { this._raw = raw; @@ -45,11 +41,11 @@ export default class ModuleMap { getModule( name: string, - platform: ?string, - supportsNativePlatform: ?boolean, - type: ?HTypeValue, - ): ?Path { - if (!type) { + platform: string | null, + supportsNativePlatform: boolean | null, + type: HTypeValue | null, + ): Config.Path | null { + if (type == null) { type = H.MODULE; } const module = this._getModuleMetadata( @@ -66,13 +62,13 @@ export default class ModuleMap { getPackage( name: string, - platform: ?string, - supportsNativePlatform: ?boolean, - ): ?Path { + platform: string | null, + _supportsNativePlatform: boolean | null, + ): Config.Path | null { return this.getModule(name, platform, null, H.PACKAGE); } - getMockModule(name: string): ?Path { + 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); @@ -113,11 +109,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 +150,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 +176,7 @@ export default class ModuleMap { ); } - static create(rootDir: Path) { + static create(rootDir: Config.Path) { return new ModuleMap({ duplicates: new Map(), map: new Map(), @@ -192,7 +188,7 @@ export default class ModuleMap { 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..6813e79ac519 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 = Array.from(roots); 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 86% rename from packages/jest-haste-map/src/crawlers/watchman.js rename to packages/jest-haste-map/src/crawlers/watchman.ts index b07b9e635172..b7f5fc453f0b 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,8 @@ module.exports = async function watchmanCrawl( let clientError; client.on('error', error => (clientError = WatchmanError(error))); - const cmd = (...args) => + // TODO: type better than `any` + const cmd = (...args: Array): Promise => new Promise((resolve, reject) => client.command(args, (error, result) => error ? reject(WatchmanError(error)) : resolve(result), @@ -57,7 +57,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 +87,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( @@ -137,7 +139,7 @@ module.exports = async function watchmanCrawl( } let files = data.files; - let watchmanFiles; + let watchmanFiles: Map; try { const watchmanRoots = await getWatchmanRoots(roots); const watchmanFileResults = await queryWatchmanForDirs(watchmanRoots); @@ -157,7 +159,8 @@ module.exports = 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); @@ -181,7 +184,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; @@ -190,10 +193,16 @@ module.exports = async function watchmanCrawl( sha1hex && existingFileData[H.SHA1] === sha1hex ) { - nextData = [...existingFileData]; - nextData[1] = mtime; + nextData = [ + existingFileData[0], + mtime, + existingFileData[2], + existingFileData[3], + existingFileData[4], + existingFileData[5], + ]; } 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 86% rename from packages/jest-haste-map/src/index.js rename to packages/jest-haste-map/src/index.ts index 7831169d2ff0..f6bd3bad058b 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,10 @@ 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`, but it doesn't +// understand `require`. +const {version: VERSION} = require('../package.json'); + const canUseWatchman = ((): boolean => { try { execSync('watchman --version', {stdio: ['ignore']}); @@ -117,10 +118,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 +219,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(); @@ -271,7 +272,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()); @@ -279,7 +279,6 @@ class HasteMap extends EventEmitter { } if (options.dependencyExtractor) { - // $FlowFixMe: dynamic require const dependencyExtractor = require(options.dependencyExtractor); if (dependencyExtractor.getCacheKey) { dependencyExtractorHash = String(dependencyExtractor.getCacheKey()); @@ -309,7 +308,7 @@ class HasteMap extends EventEmitter { } static getCacheFilePath( - tmpdir: Path, + tmpdir: Config.Path, name: string, ...extra: Array ): string { @@ -344,7 +343,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 +382,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 +391,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 +412,15 @@ class HasteMap extends EventEmitter { hasteMap: InternalHasteMap, map: ModuleMapData, mocks: MockData, - filePath: Path, - workerOptions: ?{forceInBand: boolean}, - ): ?Promise { + filePath: Config.Path, + workerOptions?: {forceInBand: boolean}, + ): 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 +488,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 +508,13 @@ class HasteMap extends EventEmitter { }; // Callback called when the response from the worker is an error. - const workerError = error => { + 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. } - // $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 +583,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 +605,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 +646,9 @@ class HasteMap extends EventEmitter { _cleanup() { const worker = this._worker; - // $FlowFixMe + // @ts-ignore if (worker && typeof worker.end === 'function') { + // @ts-ignore worker.end(); } @@ -658,36 +658,37 @@ 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}): WorkerInterface { + private _getWorker(options?: {forceInBand: boolean}): 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; } } return this._worker; } - _crawl(hasteMap: InternalHasteMap): Promise { + private _crawl(hasteMap: InternalHasteMap): Promise { const options = this._options; const ignore = this._ignore.bind(this); 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 +738,7 @@ class HasteMap extends EventEmitter { /** * Watch mode */ - _watch( - hasteMap: InternalHasteMap, - hasteFS: HasteFS, - moduleMap: ModuleMap, - ): Promise { + private _watch(hasteMap: InternalHasteMap): Promise { if (!this._options.watch) { return Promise.resolve(); } @@ -751,7 +748,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' @@ -761,12 +758,17 @@ class HasteMap extends EventEmitter { const ignorePattern = this._options.ignorePattern; const rootDir = this._options.rootDir; - let changeQueue = Promise.resolve(); - let eventsQueue = []; + let changeQueue: Promise = Promise.resolve(); + 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 => { + // @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), @@ -809,9 +811,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 +833,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())), ) ) { @@ -850,7 +852,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); @@ -894,10 +899,10 @@ 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, + stat ? stat.mtime.getTime() : -1, + stat ? stat.size : 0, 0, [], null, @@ -924,7 +929,7 @@ class HasteMap extends EventEmitter { } return null; }) - .catch(error => { + .catch((error: Error) => { this._console.error( `jest-haste-map: watch error:\n ${error.stack}\n`, ); @@ -947,7 +952,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, @@ -985,7 +990,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; @@ -996,6 +1001,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(); @@ -1013,7 +1019,7 @@ class HasteMap extends EventEmitter { /** * Helpers */ - _ignore(filePath: Path): boolean { + private _ignore(filePath: Config.Path): boolean { const ignorePattern = this._options.ignorePattern; const ignoreMatched = ignorePattern instanceof RegExp @@ -1026,7 +1032,7 @@ class HasteMap extends EventEmitter { ); } - _isNodeModulesDir(filePath: Path): boolean { + private _isNodeModulesDir(filePath: Config.Path): boolean { if (!filePath.includes(NODE_MODULES)) { return false; } @@ -1048,7 +1054,7 @@ class HasteMap extends EventEmitter { return true; } - _createEmptyMap(): InternalHasteMap { + private _createEmptyMap(): InternalHasteMap { return { clocks: new Map(), duplicates: new Map(), @@ -1059,10 +1065,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..c5e85fc8d9b9 --- /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 | undefined; +}; + +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 85% rename from packages/jest-haste-map/src/worker.js rename to packages/jest-haste-map/src/worker.ts index 1b0165f19425..4f3772d1db03 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 @@ -37,15 +34,14 @@ export async function worker(data: WorkerMessage): Promise { throw new Error('jest-haste-map: hasteImplModulePath changed'); } hasteImplModulePath = data.hasteImplModulePath; - // $FlowFixMe: dynamic require - hasteImpl = (require(hasteImplModulePath): HasteImpl); + hasteImpl = require(hasteImplModulePath); } - let content; - let dependencies; - let id; - let module; - let sha1; + let content: string | undefined; + let dependencies: WorkerMetadata['dependencies']; + let id: WorkerMetadata['id']; + let module: WorkerMetadata['module']; + let sha1: WorkerMetadata['sha1']; const {computeDependencies, computeSha1, rootDir, filePath} = data; @@ -80,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, 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/**/*"] } 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==