diff options
Diffstat (limited to 'node_modules/jest-haste-map/build/crawlers')
-rw-r--r-- | node_modules/jest-haste-map/build/crawlers/node.d.ts | 12 | ||||
-rw-r--r-- | node_modules/jest-haste-map/build/crawlers/node.js | 309 | ||||
-rw-r--r-- | node_modules/jest-haste-map/build/crawlers/watchman.d.ts | 13 | ||||
-rw-r--r-- | node_modules/jest-haste-map/build/crawlers/watchman.js | 385 |
4 files changed, 719 insertions, 0 deletions
diff --git a/node_modules/jest-haste-map/build/crawlers/node.d.ts b/node_modules/jest-haste-map/build/crawlers/node.d.ts new file mode 100644 index 0000000..ae0f21d --- /dev/null +++ b/node_modules/jest-haste-map/build/crawlers/node.d.ts @@ -0,0 +1,12 @@ +/** + * 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 type { CrawlerOptions, FileData, InternalHasteMap } from '../types'; +declare const _default: (options: CrawlerOptions) => Promise<{ + removedFiles: FileData; + hasteMap: InternalHasteMap; +}>; +export = _default; diff --git a/node_modules/jest-haste-map/build/crawlers/node.js b/node_modules/jest-haste-map/build/crawlers/node.js new file mode 100644 index 0000000..e8da794 --- /dev/null +++ b/node_modules/jest-haste-map/build/crawlers/node.js @@ -0,0 +1,309 @@ +'use strict'; + +function _child_process() { + const data = require('child_process'); + + _child_process = function () { + return data; + }; + + return data; +} + +function path() { + const data = _interopRequireWildcard(require('path')); + + path = function () { + return data; + }; + + return data; +} + +function fs() { + const data = _interopRequireWildcard(require('graceful-fs')); + + fs = function () { + return data; + }; + + return data; +} + +var _constants = _interopRequireDefault(require('../constants')); + +var fastPath = _interopRequireWildcard(require('../lib/fast_path')); + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== 'function') return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = function (nodeInterop) { + return nodeInterop ? cacheNodeInterop : cacheBabelInterop; + })(nodeInterop); +} + +function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) { + return {default: obj}; + } + var cache = _getRequireWildcardCache(nodeInterop); + if (cache && cache.has(obj)) { + return cache.get(obj); + } + var newObj = {}; + var hasPropertyDescriptor = + Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var key in obj) { + if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor + ? Object.getOwnPropertyDescriptor(obj, key) + : null; + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + newObj.default = obj; + if (cache) { + cache.set(obj, newObj); + } + return newObj; +} + +/** + * 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. + */ +async function hasNativeFindSupport(forceNodeFilesystemAPI) { + if (forceNodeFilesystemAPI) { + return false; + } + + try { + return await new Promise(resolve => { + // Check the find binary supports the non-POSIX -iname parameter wrapped in parens. + const args = [ + '.', + '-type', + 'f', + '(', + '-iname', + '*.ts', + '-o', + '-iname', + '*.js', + ')' + ]; + const child = (0, _child_process().spawn)('find', args, { + cwd: __dirname + }); + child.on('error', () => { + resolve(false); + }); + child.on('exit', code => { + resolve(code === 0); + }); + }); + } catch { + return false; + } +} + +function find(roots, extensions, ignore, enableSymlinks, callback) { + const result = []; + let activeCalls = 0; + + function search(directory) { + activeCalls++; + fs().readdir( + directory, + { + withFileTypes: true + }, + (err, entries) => { + activeCalls--; + + if (err) { + callback(result); + return; + } // node < v10.10 does not support the withFileTypes option, and + // entry will be a string. + + entries.forEach(entry => { + const file = path().join( + directory, + typeof entry === 'string' ? entry : entry.name + ); + + if (ignore(file)) { + return; + } + + if (typeof entry !== 'string') { + if (entry.isSymbolicLink()) { + return; + } + + if (entry.isDirectory()) { + search(file); + return; + } + } + + activeCalls++; + const stat = enableSymlinks ? fs().stat : fs().lstat; + stat(file, (err, stat) => { + activeCalls--; // This logic is unnecessary for node > v10.10, but leaving it in + // since we need it for backwards-compatibility still. + + if (!err && stat && !stat.isSymbolicLink()) { + if (stat.isDirectory()) { + search(file); + } else { + const ext = path().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, enableSymlinks, callback) { + const args = Array.from(roots); + + if (enableSymlinks) { + args.push('(', '-type', 'f', '-o', '-type', 'l', ')'); + } else { + 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 = ''; + + if (child.stdout === null) { + throw new Error( + 'stdout is null - this should never happen. Please open up an issue at https://github.com/facebook/jest' + ); + } + + 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().stat(path, (err, stat) => { + // Filter out symlinks that describe directories + if (!err && stat && !stat.isDirectory()) { + result.push([path, stat.mtime.getTime(), stat.size]); + } + + if (--count === 0) { + callback(result); + } + }); + }); + } + }); +} + +module.exports = async function nodeCrawl(options) { + const { + data, + extensions, + forceNodeFilesystemAPI, + ignore, + rootDir, + enableSymlinks, + roots + } = options; + const useNativeFind = await hasNativeFindSupport(forceNodeFilesystemAPI); + return new Promise(resolve => { + const callback = list => { + const files = new Map(); + const removedFiles = new Map(data.files); + list.forEach(fileData => { + const [filePath, mtime, size] = fileData; + 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]); + } + + removedFiles.delete(relativeFilePath); + }); + data.files = files; + resolve({ + hasteMap: data, + removedFiles + }); + }; + + if (useNativeFind) { + findNative(roots, extensions, ignore, enableSymlinks, callback); + } else { + find(roots, extensions, ignore, enableSymlinks, callback); + } + }); +}; diff --git a/node_modules/jest-haste-map/build/crawlers/watchman.d.ts b/node_modules/jest-haste-map/build/crawlers/watchman.d.ts new file mode 100644 index 0000000..bf261da --- /dev/null +++ b/node_modules/jest-haste-map/build/crawlers/watchman.d.ts @@ -0,0 +1,13 @@ +/** + * 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 type { CrawlerOptions, FileData, InternalHasteMap } from '../types'; +declare const _default: (options: CrawlerOptions) => Promise<{ + changedFiles?: FileData | undefined; + removedFiles: FileData; + hasteMap: InternalHasteMap; +}>; +export = _default; diff --git a/node_modules/jest-haste-map/build/crawlers/watchman.js b/node_modules/jest-haste-map/build/crawlers/watchman.js new file mode 100644 index 0000000..b58384d --- /dev/null +++ b/node_modules/jest-haste-map/build/crawlers/watchman.js @@ -0,0 +1,385 @@ +'use strict'; + +function path() { + const data = _interopRequireWildcard(require('path')); + + path = function () { + return data; + }; + + return data; +} + +function _fbWatchman() { + const data = _interopRequireDefault(require('fb-watchman')); + + _fbWatchman = function () { + return data; + }; + + return data; +} + +var _constants = _interopRequireDefault(require('../constants')); + +var fastPath = _interopRequireWildcard(require('../lib/fast_path')); + +var _normalizePathSep = _interopRequireDefault( + require('../lib/normalizePathSep') +); + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== 'function') return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = function (nodeInterop) { + return nodeInterop ? cacheNodeInterop : cacheBabelInterop; + })(nodeInterop); +} + +function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) { + return {default: obj}; + } + var cache = _getRequireWildcardCache(nodeInterop); + if (cache && cache.has(obj)) { + return cache.get(obj); + } + var newObj = {}; + var hasPropertyDescriptor = + Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var key in obj) { + if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor + ? Object.getOwnPropertyDescriptor(obj, key) + : null; + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + newObj.default = obj; + if (cache) { + cache.set(obj, newObj); + } + return newObj; +} + +/** + * 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 watchmanURL = 'https://facebook.github.io/watchman/docs/troubleshooting'; + +function WatchmanError(error) { + error.message = + `Watchman error: ${error.message.trim()}. Make sure watchman ` + + `is running for this project. See ${watchmanURL}.`; + return error; +} +/** + * Wrap watchman capabilityCheck method as a promise. + * + * @param client watchman client + * @param caps capabilities to verify + * @returns a promise resolving to a list of verified capabilities + */ + +async function capabilityCheck(client, caps) { + return new Promise((resolve, reject) => { + client.capabilityCheck( + // @ts-expect-error: incorrectly typed + caps, + (error, response) => { + if (error) { + reject(error); + } else { + resolve(response); + } + } + ); + }); +} + +module.exports = async function watchmanCrawl(options) { + const fields = ['name', 'exists', 'mtime_ms', 'size']; + const {data, extensions, ignore, rootDir, roots} = options; + const defaultWatchExpression = ['allof', ['type', 'f']]; + const clocks = data.clocks; + const client = new (_fbWatchman().default.Client)(); // https://facebook.github.io/watchman/docs/capabilities.html + // Check adds about ~28ms + + const capabilities = await capabilityCheck(client, { + // If a required capability is missing then an error will be thrown, + // we don't need this assertion, so using optional instead. + optional: ['suffix-set'] + }); + + if ( + capabilities !== null && + capabilities !== void 0 && + capabilities.capabilities['suffix-set'] + ) { + // If available, use the optimized `suffix-set` operation: + // https://facebook.github.io/watchman/docs/expr/suffix.html#suffix-set + defaultWatchExpression.push(['suffix', extensions]); + } else { + // Otherwise use the older and less optimal suffix tuple array + defaultWatchExpression.push([ + 'anyof', + ...extensions.map(extension => ['suffix', extension]) + ]); + } + + let clientError; + client.on('error', error => (clientError = WatchmanError(error))); + + const cmd = (...args) => + new Promise((resolve, reject) => + client.command(args, (error, result) => + error ? reject(WatchmanError(error)) : resolve(result) + ) + ); + + if (options.computeSha1) { + const {capabilities} = await cmd('list-capabilities'); + + if (capabilities.indexOf('field-content.sha1hex') !== -1) { + fields.push('content.sha1hex'); + } + } + + async function getWatchmanRoots(roots) { + const watchmanRoots = new Map(); + await Promise.all( + roots.map(async root => { + const response = await 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 watchmanRoots; + } + + async function queryWatchmanForDirs(rootProjectDirMappings) { + const results = new Map(); + let isFresh = false; + await Promise.all( + Array.from(rootProjectDirMappings).map( + async ([root, directoryFilters]) => { + var _since$scm; + + const expression = Array.from(defaultWatchExpression); + const glob = []; + + if (directoryFilters.length > 0) { + expression.push([ + 'anyof', + ...directoryFilters.map(dir => ['dirname', dir]) + ]); + + for (const directory of directoryFilters) { + for (const extension of extensions) { + glob.push(`${directory}/**/*.${extension}`); + } + } + } else { + for (const extension of extensions) { + glob.push(`**/*.${extension}`); + } + } // Jest is only going to store one type of clock; a string that + // represents a local clock. However, the Watchman crawler supports + // a second type of clock that can be written by automation outside of + // Jest, called an "scm query", which fetches changed files based on + // source control mergebases. The reason this is necessary is because + // local clocks are not portable across systems, but scm queries are. + // By using scm queries, we can create the haste map on a different + // system and import it, transforming the clock into a local clock. + + const since = clocks.get(fastPath.relative(rootDir, root)); + const query = + since !== undefined // Use the `since` generator if we have a clock available + ? { + expression, + fields, + since + } // Otherwise use the `glob` filter + : { + expression, + fields, + glob, + glob_includedotfiles: true + }; + const response = await cmd('query', root, query); + + if ('warning' in response) { + console.warn('watchman warning: ', response.warning); + } // When a source-control query is used, we ignore the "is fresh" + // response from Watchman because it will be true despite the query + // being incremental. + + const isSourceControlQuery = + typeof since !== 'string' && + (since === null || since === void 0 + ? void 0 + : (_since$scm = since.scm) === null || _since$scm === void 0 + ? void 0 + : _since$scm['mergebase-with']) !== undefined; + + if (!isSourceControlQuery) { + isFresh = isFresh || response.is_fresh_instance; + } + + results.set(root, response); + } + ) + ); + return { + isFresh, + results + }; + } + + let files = data.files; + let removedFiles = new Map(); + const changedFiles = new Map(); + let results; + let isFresh = false; + + try { + const watchmanRoots = await getWatchmanRoots(roots); + const watchmanFileResults = await queryWatchmanForDirs(watchmanRoots); // Reset the file map if watchman was restarted and sends us a list of + // files. + + if (watchmanFileResults.isFresh) { + files = new Map(); + removedFiles = new Map(data.files); + isFresh = true; + } + + results = watchmanFileResults.results; + } finally { + client.end(); + } + + if (clientError) { + throw clientError; + } + + for (const [watchRoot, response] of results) { + const fsRoot = (0, _normalizePathSep.default)(watchRoot); + const relativeFsRoot = fastPath.relative(rootDir, fsRoot); + clocks.set( + relativeFsRoot, // Ensure we persist only the local clock. + typeof response.clock === 'string' ? response.clock : response.clock.clock + ); + + for (const fileData of response.files) { + const filePath = + fsRoot + path().sep + (0, _normalizePathSep.default)(fileData.name); + const relativeFilePath = fastPath.relative(rootDir, filePath); + const existingFileData = data.files.get(relativeFilePath); // If watchman is fresh, the removed files map starts with all files + // and we remove them as we verify they still exist. + + if (isFresh && existingFileData && fileData.exists) { + removedFiles.delete(relativeFilePath); + } + + if (!fileData.exists) { + // No need to act on files that do not exist and were not tracked. + if (existingFileData) { + files.delete(relativeFilePath); // If watchman is not fresh, we will know what specific files were + // deleted since we last ran and can track only those files. + + if (!isFresh) { + removedFiles.set(relativeFilePath, existingFileData); + } + } + } 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 = undefined; + } + + 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 { + var _sha1hex; + + // See ../constants.ts + nextData = [ + '', + mtime, + size, + 0, + '', + (_sha1hex = sha1hex) !== null && _sha1hex !== void 0 + ? _sha1hex + : null + ]; + } + + files.set(relativeFilePath, nextData); + changedFiles.set(relativeFilePath, nextData); + } + } + } + + data.files = files; + return { + changedFiles: isFresh ? undefined : changedFiles, + hasteMap: data, + removedFiles + }; +}; |