add: unit and integration testing

This commit is contained in:
odweta
2026-09-07 18:09:36 +02:00
parent 76fde42334
commit 52a25aeaf5
7230 changed files with 561560 additions and 135112 deletions
+22
View File
@@ -0,0 +1,22 @@
MIT License
Copyright (c) Meta Platforms, Inc. and affiliates.
Copyright Contributors to the Jest project.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+92
View File
@@ -0,0 +1,92 @@
# jest-haste-map
`jest-haste-map` is a module used by Jest, a popular JavaScript testing framework, to create a fast lookup of files in a project. It helps Jest efficiently locate and track changes in files during testing, making it particularly useful for large projects with many files.
## why jest-haste-map ?
- **Parallel crawling and analysis:** jest-haste-map crawls the entire project, extracts dependencies, and analyzes files in parallel across worker processes.This can significantly improve the performance of the map building process.
- **Cached file system:** jest-haste-map keeps a cache of the file system in memory and on disk. This allows for fast file related operations, such as resolving module imports and checking for changes.
- **Minimal work**: jest-haste-map only does the minimal amount of work necessary when files change. When using [watchman](https://facebook.github.io/watchman/) (recommended for large projects), Jest asks watchman for changed files instead of crawling the file system. Without watchman, [@parcel/watcher](https://github.com/parcel-bundler/watcher) is used — it picks the best native backend for the platform (`fs-events` on macOS, `inotify` on Linux, `windows` on Windows).
- **File system watching:** jest-haste-map can watch the file system for changes. This is useful for building interactive tools, such as watch mode.
## Installation
with npm :
```bash
npm install jest-haste-map --save-dev
```
with yarn :
```bash
yarn add jest-haste-map --dev
```
## usage
`jest-haste-map` is compatible with both `ES modules` and `CommonJS`
### simple usage
```javascript
const map = new HasteMap.default({
// options
});
```
### Example usage (get all files with .js extension in the project)
```javascript
import HasteMap from 'jest-haste-map';
import os from 'os';
import {dirname} from 'path';
import {fileURLToPath} from 'url';
const root = dirname(fileURLToPath(import.meta.url));
const map = new HasteMap.default({
id: 'myproject', //Used for caching.
extensions: ['js'], // Tells jest-haste-map to only crawl .js files.
maxWorkers: os.availableParallelism(), //Parallelizes across all available CPUs.
platforms: [], // This is only used for React Native, you can leave it empty.
roots: [root], // Can be used to only search a subset of files within `rootDir`
retainAllFiles: true,
rootDir: root, //The project root.
});
const {hasteFS} = await map.build();
const files = hasteFS.getAllFiles();
console.log(files);
```
### options
| Option | Type | Required | Default Value |
| ---------------------- | ------------------- | -------- | ------------- |
| cacheDirectory | string | No | `os.tmpdir()` |
| computeDependencies | boolean | No | `true` |
| computeSha1 | boolean | No | `false` |
| console | Console | No | - |
| dependencyExtractor | string \| null | No | `null` |
| enableSymlinks | boolean | No | `false` |
| extensions | Array<string> | Yes | - |
| forceNodeFilesystemAPI | boolean | No | `false` |
| hasteImplModulePath | string | No | - |
| hasteMapModulePath | string | No | - |
| id | string | Yes | - |
| ignorePattern | HasteRegExp | No | - |
| maxWorkers | number | Yes | - |
| mocksPattern | string | No | - |
| platforms | Array<string> | Yes | - |
| resetCache | boolean | No | - |
| retainAllFiles | boolean | Yes | - |
| rootDir | string | Yes | - |
| roots | Array<string> | Yes | - |
| skipPackageJson | boolean | No | `false` |
| throwOnModuleCollision | boolean | No | `false` |
| useWatchman | boolean | No | `true` |
For more, you can check [github](https://github.com/jestjs/jest/tree/main/packages/jest-haste-map)
+164
View File
@@ -0,0 +1,164 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Measures what a reported removal costs `buildHasteMap`. A removal makes it
* discard `map`/`mocks` and walk every tracked file; without one it walks only
* `changedFiles`. Both runs do the same useful work — one changed file — so the
* gap between them is the price of the full pass.
*
* Nothing here touches the disk: every file is already `visited` with its haste
* name in `map`, which is the case the shortcut in `processFile` is built for.
*
* No build needed — unlike the other benchmarks in the repo this reads `src`
* through babel, because `FileProcessor` is internal and the built entry point
* does not expose it.
*
* To start the test, run:
* node test.js 1000
* node test.js 100000
*
* Measured on an M-series laptop, median of 5, with deep paths:
*
* 1 000 files 0.4 ms
* 10 000 files 6.2 ms
* 100 000 files ~60 ms
*
* Handling removals incrementally instead was considered and dropped: ~60 ms
* once at startup, on runs that saw a deletion, did not justify trusting the
* cached `map`/`mocks` rather than re-deriving them. Re-run this before
* revisiting that.
*/
'use strict';
const assert = require('node:assert');
const path = require('node:path');
const {performance} = require('node:perf_hooks');
require('@babel/register')({
cwd: path.resolve(__dirname, '../../..'),
extensions: ['.ts', '.js'],
});
const {FileProcessor} = require('../src/lib/FileProcessor');
const {WorkerPool} = require('../src/lib/WorkerPool');
assert(process.argv[2], 'Pass the number of files');
const fileCount = Number(process.argv[2]);
const iterations = 5;
const ROOT = path.join(path.sep, 'root');
function makeOptions() {
return {
computeDependencies: true,
computeSha1: false,
dependencyExtractor: null,
hasteImplModulePath: undefined,
// Real runs configure this, and it is tested per file, so keep the cost in.
mocksPattern: new RegExp(`${path.sep}__mocks__${path.sep}`),
platforms: [],
retainAllFiles: false,
rootDir: ROOT,
skipPackageJson: false,
throwOnModuleCollision: false,
};
}
// Every file is visited and present in `map`, so `processFile` returns without
// dispatching to a worker. Rebuilt per iteration because buildHasteMap mutates.
function makeHasteMap() {
const files = new Map();
const map = new Map();
for (let i = 0; i < fileCount; i++) {
const relativeFilePath = path.join(
'packages',
`pkg${i % 50}`,
'src',
'components',
`module${i}.js`,
);
const moduleName = `module${i}`;
files.set(relativeFilePath, [moduleName, 1000 + i, 42, 1, '', null]);
map.set(moduleName, {g: [relativeFilePath, 0]});
}
return {
clocks: new Map(),
duplicates: new Map(),
files,
map,
mocks: new Map(),
};
}
async function time(withRemoval) {
const durations = [];
for (let i = 0; i < iterations; i++) {
const hasteMap = makeHasteMap();
const [firstFile, firstMetadata] = hasteMap.files.entries().next().value;
// A removal only has to be reported to trigger the full pass; the file is
// already absent from `files`, exactly as the crawlers leave it.
const removedFiles = withRemoval
? new Map([[path.join('src', 'gone.js'), ['gone', 1, 42, 1, '', null]]])
: new Map();
const fileProcessor = new FileProcessor(
makeOptions(),
console,
new WorkerPool({
maxWorkers: 1,
workerPath: require.resolve('../src/worker'),
}),
);
const startTime = performance.now();
const result = await fileProcessor.buildHasteMap(
{
changedFiles: new Map([[firstFile, firstMetadata]]),
hasteMap,
removedFiles,
},
() => {},
);
durations.push(performance.now() - startTime);
// Guard against timing a no-op: the surviving files must still be mapped.
assert.strictEqual(result.map.size, fileCount);
}
durations.sort((a, b) => a - b);
return durations[Math.floor(durations.length / 2)];
}
async function main() {
// Warm up so the first measured run does not absorb the JIT cost.
await time(true);
const withoutRemoval = await time(false);
const withRemoval = await time(true);
console.log('-'.repeat(75));
console.log(`median of ${iterations} runs over ${fileCount} files`);
console.log(
'one changed file, no removal:',
`${withoutRemoval.toFixed(1)} ms`,
);
console.log('one changed file, one removal:', `${withRemoval.toFixed(1)} ms`);
console.log('-'.repeat(75));
console.log(
'cost of the full pass a removal forces:',
`${(withRemoval - withoutRemoval).toFixed(1)} ms`,
);
}
main().catch(error => {
console.error(error);
process.exitCode = 1;
});
+240
View File
@@ -0,0 +1,240 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {Stats} from 'node:fs';
import {Config} from '@jest/types';
declare type ChangeEvent = {
eventsQueue: EventsQueue;
hasteFS: HasteFS;
moduleMap: ModuleMap_2;
};
export declare class DuplicateError extends Error {
mockPath1: string;
mockPath2: string;
constructor(mockPath1: string, mockPath2: string);
}
declare class DuplicateHasteCandidatesError extends Error {
hasteName: string;
platform: string | null;
supportsNativePlatform: boolean;
duplicatesSet: DuplicatesSet;
constructor(
name: string,
platform: string,
supportsNativePlatform: boolean,
duplicatesSet: DuplicatesSet,
);
}
declare type DuplicatesIndex = Map<string, Map<string, DuplicatesSet>>;
declare type DuplicatesSet = Map<string, /* type */ number>;
declare type EventsQueue = Array<{
filePath: string;
stat: Stats | undefined;
type: string;
}>;
declare type FileData = Map<string, FileMetaData>;
declare type FileMetaData = [
id: string,
mtime: number,
size: number,
visited: 0 | 1,
dependencies: string,
sha1: string | null | undefined,
];
declare class HasteFS implements IHasteFS {
private readonly _rootDir;
private readonly _files;
constructor({rootDir, files}: {rootDir: string; files: FileData});
getModuleName(file: string): string | null;
getSize(file: string): number | null;
getDependencies(file: string): Array<string> | null;
getSha1(file: string): string | null;
exists(file: string): boolean;
getAllFiles(): Array<string>;
getFileIterator(): Iterable<string>;
getAbsoluteFileIterator(): Iterable<string>;
matchFiles(pattern: RegExp | string): Array<string>;
matchFilesWithGlob(globs: Array<string>, root: string | null): Set<string>;
private _getFileData;
}
declare type HasteMapStatic<S = SerializableModuleMap> = {
getCacheFilePath(
tmpdir: string,
name: string,
...extra: Array<string>
): string;
getModuleMapFromJSON(json: S): IModuleMap<S>;
};
declare type HasteRegExp = RegExp | ((str: string) => boolean);
declare 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';
DEPENDENCY_DELIM: '\0';
};
declare type HTypeValue = HType[keyof HType];
export declare interface IHasteFS {
exists(path: string): boolean;
getAbsoluteFileIterator(): Iterable<string>;
getAllFiles(): Array<string>;
getDependencies(file: string): Array<string> | null;
getSize(path: string): number | null;
matchFiles(pattern: RegExp | string): Array<string>;
matchFilesWithGlob(
globs: ReadonlyArray<string>,
root: string | null,
): Set<string>;
getModuleName(file: string): string | null;
}
export declare interface IHasteMap {
on(eventType: 'change', handler: (event: ChangeEvent) => void): void;
build(): Promise<{
hasteFS: IHasteFS;
moduleMap: IModuleMap;
}>;
}
declare type IJestHasteMap = HasteMapStatic & {
create(options: Options): Promise<IHasteMap>;
getStatic(config: Config.ProjectConfig): HasteMapStatic;
};
export declare interface IModuleMap<S = SerializableModuleMap> {
getModule(
name: string,
platform?: string | null,
supportsNativePlatform?: boolean | null,
type?: HTypeValue | null,
): string | null;
getPackage(
name: string,
platform: string | null | undefined,
_supportsNativePlatform: boolean | null,
): string | null;
getMockModule(name: string): string | undefined;
getRawModuleMap(): RawModuleMap;
toJSON(): S;
}
declare const JestHasteMap: IJestHasteMap;
export default JestHasteMap;
declare type MockData = Map<string, string>;
export declare const ModuleMap: {
create: (rootPath: string) => IModuleMap;
};
declare class ModuleMap_2 implements IModuleMap {
static DuplicateHasteCandidatesError: typeof DuplicateHasteCandidatesError;
private readonly _raw;
private json;
private static mapToArrayRecursive;
private static mapFromArrayRecursive;
constructor(raw: RawModuleMap);
getModule(
name: string,
platform?: string | null,
supportsNativePlatform?: boolean | null,
type?: HTypeValue | null,
): string | null;
getPackage(
name: string,
platform: string | null | undefined,
_supportsNativePlatform: boolean | null,
): string | null;
getMockModule(name: string): string | undefined;
getRawModuleMap(): RawModuleMap;
toJSON(): SerializableModuleMap;
static fromJSON(serializableModuleMap: SerializableModuleMap): ModuleMap_2;
/**
* 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.
*/
private _getModuleMetadata;
private _assertNoDuplicates;
static create(rootDir: string): ModuleMap_2;
}
declare type ModuleMapData = Map<string, ModuleMapItem>;
declare type ModuleMapItem = {
[platform: string]: ModuleMetaData;
};
declare type ModuleMetaData = [path: string, type: number];
declare type Options = {
cacheDirectory?: string;
computeDependencies?: boolean;
computeSha1?: boolean;
console?: Console;
dependencyExtractor?: string | null;
enableSymlinks?: boolean;
extensions: Array<string>;
forceNodeFilesystemAPI?: boolean;
hasteImplModulePath?: string;
hasteMapModulePath?: string;
id: string;
ignorePattern?: HasteRegExp;
maxWorkers: number;
mocksPattern?: string;
platforms: Array<string>;
resetCache?: boolean;
retainAllFiles: boolean;
rootDir: string;
roots: Array<string>;
skipPackageJson?: boolean;
throwOnModuleCollision?: boolean;
useWatchman?: boolean;
watch?: boolean;
workerThreads?: boolean;
};
declare type RawModuleMap = {
rootDir: string;
duplicates: DuplicatesIndex;
map: ModuleMapData;
mocks: MockData;
};
export declare type SerializableModuleMap = {
duplicates: ReadonlyArray<[string, [string, [string, [string, number]]]]>;
map: ReadonlyArray<[string, ValueType<ModuleMapData>]>;
mocks: ReadonlyArray<[string, ValueType<MockData>]>;
rootDir: string;
};
declare type ValueType<T> = T extends Map<string, infer V> ? V : never;
+3680
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
import cjsModule from './index.js';
export const DuplicateError = cjsModule.DuplicateError;
export const ModuleMap = cjsModule.ModuleMap;
export default cjsModule.default;
+311
View File
@@ -0,0 +1,311 @@
/*!
* /**
* * Copyright (c) Meta Platforms, Inc. and affiliates.
* *
* * This source code is licensed under the MIT license found in the
* * LICENSE file in the root directory of this source tree.
* * /
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/blacklist.ts"
(__unused_webpack_module, exports) {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports["default"] = void 0;
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* 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.
//
// Feel free to add any extensions that cannot be a Haste module.
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 = exports["default"] = extensions;
/***/ },
/***/ "./src/constants.ts"
(__unused_webpack_module, exports) {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports["default"] = void 0;
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/*
* 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.
*/
/* eslint-disable sort-keys */
const constants = {
/* dependency serialization */
DEPENDENCY_DELIM: '\0',
/* 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'
};
/* eslint-enable */
var _default = exports["default"] = constants;
/***/ },
/***/ "./src/lib/dependencyExtractor.ts"
(__unused_webpack_module, exports) {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.extractor = void 0;
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const NOT_A_DOT = '(?<!\\.\\s*)';
const CAPTURE_STRING_LITERAL = pos => `([\`'"])([^'"\`]*?)(?:\\${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('jest\\s*\\.\\s*(?:requireActual|requireMock|createMockFromModule)'), CAPTURE_STRING_LITERAL(1), WHITESPACE, OPTIONAL_COMMA, RIGHT_PARENTHESIS], 'g');
const extractor = exports.extractor = {
extract(code) {
const dependencies = new Set();
const addDependency = (match, _, dep) => {
dependencies.add(dep);
return match;
};
code.replaceAll(BLOCK_COMMENT_RE, '').replaceAll(LINE_COMMENT_RE, '').replace(IMPORT_OR_EXPORT_RE, addDependency).replace(REQUIRE_OR_DYNAMIC_IMPORT_RE, addDependency).replace(JEST_EXTENSIONS_RE, addDependency);
return dependencies;
}
};
/***/ }
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ const __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ const cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ const module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
let __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
(() => {
let exports = __webpack_exports__;
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.getSha1 = getSha1;
exports.worker = worker;
function _nodeCrypto() {
const data = require("node:crypto");
_nodeCrypto = function () {
return data;
};
return data;
}
function path() {
const data = _interopRequireWildcard(require("node:path"));
path = function () {
return data;
};
return data;
}
function fs() {
const data = _interopRequireWildcard(require("graceful-fs"));
fs = function () {
return data;
};
return data;
}
function _jestUtil() {
const data = require("jest-util");
_jestUtil = function () {
return data;
};
return data;
}
var _blacklist = _interopRequireDefault(__webpack_require__("./src/blacklist.ts"));
var _constants = _interopRequireDefault(__webpack_require__("./src/constants.ts"));
var _dependencyExtractor = __webpack_require__("./src/lib/dependencyExtractor.ts");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const PACKAGE_JSON = `${path().sep}package.json`;
function sha1hex(content) {
return (0, _nodeCrypto().createHash)('sha1').update(content).digest('hex');
}
async function worker(data) {
const hasteImpl = data.hasteImplModulePath ? require(data.hasteImplModulePath) : null;
let content;
let dependencies;
let id;
let module;
let sha1;
const {
computeDependencies,
computeSha1,
rootDir,
filePath
} = data;
const getContent = () => {
if (content === undefined) {
content = fs().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().relative(rootDir, filePath);
id = fileData.name;
module = [relativeFilePath, _constants.default.PACKAGE];
}
} catch (error) {
throw new Error(`Cannot parse ${filePath} as JSON: ${error.message}`, {
cause: error
});
}
} else if (!_blacklist.default.has(filePath.slice(filePath.lastIndexOf('.')))) {
// Process a random file that is returned as a MODULE.
if (hasteImpl) {
id = hasteImpl.getHasteName(filePath);
}
if (computeDependencies) {
const content = getContent();
const extractor = data.dependencyExtractor ? await (0, _jestUtil().requireOrImportModule)(data.dependencyExtractor, false) : _dependencyExtractor.extractor;
dependencies = [...extractor.extract(content, filePath, _dependencyExtractor.extractor.extract)];
}
if (id) {
const relativeFilePath = path().relative(rootDir, filePath);
module = [relativeFilePath, _constants.default.MODULE];
}
}
// If a SHA-1 is requested on update, compute it.
if (computeSha1) {
sha1 = sha1hex(content || fs().readFileSync(filePath));
}
return {
dependencies,
id,
module,
sha1
};
}
async function getSha1(data) {
const sha1 = data.computeSha1 ? sha1hex(fs().readFileSync(data.filePath)) : null;
return {
dependencies: undefined,
id: undefined,
module: undefined,
sha1
};
}
})();
module.exports = __webpack_exports__;
/******/ })()
;
+47
View File
@@ -0,0 +1,47 @@
{
"name": "jest-haste-map",
"version": "30.5.1",
"repository": {
"type": "git",
"url": "https://github.com/jestjs/jest.git",
"directory": "packages/jest-haste-map"
},
"license": "MIT",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"exports": {
".": {
"types": "./build/index.d.ts",
"require": "./build/index.js",
"import": "./build/index.mjs",
"default": "./build/index.js"
},
"./package.json": "./package.json"
},
"dependencies": {
"@jest/types": "30.5.1",
"@parcel/watcher": "^2.6.0",
"@types/node": "*",
"anymatch": "^3.1.3",
"fb-watchman": "^2.0.2",
"fdir": "^6.5.0",
"graceful-fs": "^4.2.11",
"jest-regex-util": "30.5.0",
"jest-util": "30.5.1",
"jest-worker": "30.5.1",
"picomatch": "^4.0.3"
},
"devDependencies": {
"@types/fb-watchman": "^2.0.5",
"@types/graceful-fs": "^4.1.9",
"@types/picomatch": "^4.0.0",
"slash": "^3.0.0"
},
"engines": {
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
},
"publishConfig": {
"access": "public"
},
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
}