Skip to content

Commit

Permalink
chore: use Maps throughout jest-runtime (#10968)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Dec 22, 2020
1 parent ec820c3 commit 1678cd9
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 92 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -62,6 +62,7 @@
- `[jest-resolve]` [**BREAKING**] Migrate to ESM ([#10688](https://github.com/facebook/jest/pull/10688))
- `[jest-resolve-dependencies]` [**BREAKING**] Migrate to ESM ([#10876](https://github.com/facebook/jest/pull/10876))
- `[jest-mock]` [**BREAKING**] Migrate to ESM ([#10887](https://github.com/facebook/jest/pull/10887))
- `[jest-resolve, jest-runtime]` [**BREAKING**] Use `Map`s instead of objects for all cached resources ([#10968](https://github.com/facebook/jest/pull/10968))
- `[jest-runner]` [**BREAKING**] Migrate to ESM ([#10900](https://github.com/facebook/jest/pull/10900))
- `[jest-runtime]` [**BREAKING**] Remove deprecated and unnused `getSourceMapInfo` from Runtime ([#9969](https://github.com/facebook/jest/pull/9969))
- `[jest-util]` No longer checking `enumerable` when adding `process.domain` ([#10862](https://github.com/facebook/jest/pull/10862))
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-repl/src/cli/runtime-cli.ts
Expand Up @@ -91,7 +91,7 @@ export async function run(
config,
environment,
hasteMap.resolver,
undefined,
new Map(),
undefined,
filePath,
);
Expand Down
11 changes: 4 additions & 7 deletions packages/jest-resolve/src/index.ts
Expand Up @@ -31,9 +31,6 @@ type FindNodeModuleConfig = {
throwIfNotFound?: boolean;
};

// TODO: replace with a Map in Jest 27
type BooleanObject = Record<string, boolean>;

export type ResolveModuleConfig = {
skipNodeResolution?: boolean;
paths?: Array<Config.Path>;
Expand Down Expand Up @@ -314,7 +311,7 @@ class Resolver {
}

getModuleID(
virtualMocks: BooleanObject,
virtualMocks: Map<string, boolean>,
from: Config.Path,
_moduleName?: string,
): string {
Expand Down Expand Up @@ -346,7 +343,7 @@ class Resolver {
}

private _getAbsolutePath(
virtualMocks: BooleanObject,
virtualMocks: Map<string, boolean>,
from: Config.Path,
moduleName: string,
): Config.Path | null {
Expand All @@ -368,12 +365,12 @@ class Resolver {
}

private _getVirtualMockPath(
virtualMocks: BooleanObject,
virtualMocks: Map<string, boolean>,
from: Config.Path,
moduleName: string,
): Config.Path {
const virtualMockPath = this.getModulePath(from, moduleName);
return virtualMocks[virtualMockPath]
return virtualMocks.get(virtualMockPath)
? virtualMockPath
: moduleName
? this.resolveModule(from, moduleName)
Expand Down
5 changes: 2 additions & 3 deletions packages/jest-runner/src/runTest.ts
Expand Up @@ -146,7 +146,7 @@ async function runTestInternal(
? new LeakDetector(environment)
: null;

const cacheFS = {[path]: testSource};
const cacheFS = new Map([[path, testSource]]);
setGlobal(environment.global, 'console', testConsole);

const runtime = new Runtime(
Expand Down Expand Up @@ -182,8 +182,7 @@ async function runTestInternal(
environment: 'node',
handleUncaughtExceptions: false,
retrieveSourceMap: source => {
const sourceMaps = runtime.getSourceMaps();
const sourceMapSource = sourceMaps && sourceMaps[source];
const sourceMapSource = runtime.getSourceMaps()?.get(source);

if (sourceMapSource) {
try {
Expand Down
66 changes: 25 additions & 41 deletions packages/jest-runtime/src/__mocks__/createRuntime.js
Expand Up @@ -35,27 +35,14 @@ const setupModuleNameMapper = (config, rootDir) => {
};

const setupTransform = (config, rootDir) => {
if (config && config.transform) {
if (config?.transform) {
const transform = config.transform;
return Object.keys(transform).map(regex => [
regex,
path.resolve(rootDir, transform[regex]),
]);
}
return [
[
'^.+\\.[jt]sx?$',
path.resolve(
__dirname,
'..',
'..',
'..',
'babel-jest',
'build',
'index.js',
),
],
];
return [['^.+\\.[jt]sx?$', require.resolve('babel-jest')]];
};

module.exports = async function createRuntime(filename, config) {
Expand All @@ -67,32 +54,29 @@ module.exports = async function createRuntime(filename, config) {
const moduleNameMapper = setupModuleNameMapper(config, rootDir);
const transform = setupTransform(config, rootDir);

config = makeProjectConfig(
{
cacheDirectory: getCacheDirectory(),
cwd: path.resolve(__dirname, '..', '..', '..', '..'),
haste: {
hasteImplModulePath: path.resolve(
__dirname,
'..',
'..',
'..',
'jest-haste-map',
'src',
'__tests__',
'haste_impl.js',
),
},
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
name: 'Runtime-' + filename.replace(/\W/, '-') + '.tests',
rootDir,
...config,
moduleNameMapper,
transform,
config = makeProjectConfig({
cacheDirectory: getCacheDirectory(),
cwd: path.resolve(__dirname, '..', '..', '..', '..'),
haste: {
hasteImplModulePath: path.resolve(
__dirname,
'..',
'..',
'..',
'jest-haste-map',
'src',
'__tests__',
'haste_impl.js',
),
},
{},
);
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'node'],
name: 'Runtime-' + filename.replace(/\W/, '-') + '.tests',
rootDir,
...config,
moduleNameMapper,
transform,
});

if (!config.roots.length) {
config.roots = [config.rootDir];
Expand All @@ -110,7 +94,7 @@ module.exports = async function createRuntime(filename, config) {
config,
environment,
Runtime.createResolver(config, hasteMap.moduleMap),
undefined,
new Map(),
undefined,
filename,
);
Expand Down
Expand Up @@ -6,7 +6,7 @@ exports[`Runtime requireModule with no extension throws error pointing out file
However, Jest was able to find:
'./RegularModuleWithWrongExt.txt'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'jsx', 'ts', 'tsx', 'json', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring"
`;
66 changes: 31 additions & 35 deletions packages/jest-runtime/src/index.ts
Expand Up @@ -102,18 +102,6 @@ type ResolveOptions = Parameters<typeof require.resolve>[1] & {
[JEST_RESOLVE_OUTSIDE_VM_OPTION]?: true;
};

type StringMap = Map<string, string>;
type BooleanMap = Map<string, boolean>;

const fromEntries: typeof Object.fromEntries =
Object.fromEntries ??
function fromEntries<T>(iterable: Iterable<[string, T]>) {
return [...iterable].reduce<Record<string, T>>((obj, [key, val]) => {
obj[key] = val;
return obj;
}, {});
};

const testTimeoutSymbol = Symbol.for('TEST_TIMEOUT_SYMBOL');
const retryTimesSymbol = Symbol.for('RETRY_TIMES');

Expand Down Expand Up @@ -154,12 +142,12 @@ const supportsTopLevelAwait =
})();

export default class Runtime {
private readonly _cacheFS: StringMap;
private readonly _cacheFS: Map<string, string>;
private readonly _config: Config.ProjectConfig;
private readonly _coverageOptions: ShouldInstrumentOptions;
private _currentlyExecutingModulePath: string;
private readonly _environment: JestEnvironment;
private readonly _explicitShouldMock: BooleanMap;
private readonly _explicitShouldMock: Map<string, boolean>;
private _fakeTimersImplementation:
| LegacyFakeTimers<unknown>
| ModernFakeTimers
Expand All @@ -181,16 +169,19 @@ export default class Runtime {
private readonly _testPath: Config.Path | undefined;
private readonly _resolver: Resolver;
private _shouldAutoMock: boolean;
private readonly _shouldMockModuleCache: BooleanMap;
private readonly _shouldUnmockTransitiveDependenciesCache: BooleanMap;
private readonly _sourceMapRegistry: StringMap;
private readonly _shouldMockModuleCache: Map<string, boolean>;
private readonly _shouldUnmockTransitiveDependenciesCache: Map<
string,
boolean
>;
private readonly _sourceMapRegistry: Map<string, string>;
private readonly _scriptTransformer: ScriptTransformer;
private readonly _fileTransforms: Map<string, RuntimeTransformResult>;
private _v8CoverageInstrumenter: CoverageInstrumenter | undefined;
private _v8CoverageResult: V8Coverage | undefined;
private readonly _transitiveShouldMock: BooleanMap;
private readonly _transitiveShouldMock: Map<string, boolean>;
private _unmockList: RegExp | undefined;
private readonly _virtualMocks: BooleanMap;
private readonly _virtualMocks: Map<string, boolean>;
private _moduleImplementation?: typeof nativeModule.Module;
private readonly jestObjectCaches: Map<string, Jest>;
private jestGlobals?: JestGlobals;
Expand All @@ -199,12 +190,12 @@ export default class Runtime {
config: Config.ProjectConfig,
environment: JestEnvironment,
resolver: Resolver,
cacheFS: Record<string, string> = {},
cacheFS: Map<string, string>,
coverageOptions?: ShouldInstrumentOptions,
// TODO: Make mandatory in Jest 27
testPath?: Config.Path,
) {
this._cacheFS = new Map(Object.entries(cacheFS));
this._cacheFS = cacheFS;
this._config = config;
this._coverageOptions = coverageOptions || {
changedFiles: undefined,
Expand All @@ -222,8 +213,11 @@ export default class Runtime {
this._mainModule = null;
this._mockFactories = new Map();
this._mockRegistry = new Map();
// during setup, this cannot be null (and it's fine to explode if it is)
this._moduleMocker = this._environment.moduleMocker!;
invariant(
this._environment.moduleMocker,
'`moduleMocker` must be set on an environment when created',
);
this._moduleMocker = this._environment.moduleMocker;
this._isolatedModuleRegistry = null;
this._isolatedMockRegistry = null;
this._moduleRegistry = new Map();
Expand Down Expand Up @@ -256,10 +250,12 @@ export default class Runtime {
}

if (config.automock) {
const virtualMocks = fromEntries(this._virtualMocks);
config.setupFiles.forEach(filePath => {
if (filePath && filePath.includes(NODE_MODULES)) {
const moduleID = this._resolver.getModuleID(virtualMocks, filePath);
if (filePath.includes(NODE_MODULES)) {
const moduleID = this._resolver.getModuleID(
this._virtualMocks,
filePath,
);
this._transitiveShouldMock.set(moduleID, false);
}
});
Expand Down Expand Up @@ -575,7 +571,7 @@ export default class Runtime {
isRequireActual?: boolean | null,
): T {
const moduleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
moduleName,
);
Expand Down Expand Up @@ -670,7 +666,7 @@ export default class Runtime {

requireMock<T = unknown>(from: Config.Path, moduleName: string): T {
const moduleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
moduleName,
);
Expand Down Expand Up @@ -922,7 +918,7 @@ export default class Runtime {
}

getSourceMaps(): SourceMapRegistry {
return fromEntries(this._sourceMapRegistry);
return this._sourceMapRegistry;
}

setMock(
Expand All @@ -937,7 +933,7 @@ export default class Runtime {
this._virtualMocks.set(mockPath, true);
}
const moduleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
moduleName,
);
Expand Down Expand Up @@ -1365,7 +1361,7 @@ export default class Runtime {
private _shouldMock(from: Config.Path, moduleName: string): boolean {
const explicitShouldMock = this._explicitShouldMock;
const moduleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
moduleName,
);
Expand Down Expand Up @@ -1408,7 +1404,7 @@ export default class Runtime {

// transitive unmocking for package managers that store flat packages (npm3)
const currentModuleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
);
if (
Expand Down Expand Up @@ -1493,7 +1489,7 @@ export default class Runtime {
};
const unmock = (moduleName: string) => {
const moduleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
moduleName,
);
Expand All @@ -1502,7 +1498,7 @@ export default class Runtime {
};
const deepUnmock = (moduleName: string) => {
const moduleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
moduleName,
);
Expand All @@ -1516,7 +1512,7 @@ export default class Runtime {
}

const moduleID = this._resolver.getModuleID(
fromEntries(this._virtualMocks),
this._virtualMocks,
from,
moduleName,
);
Expand Down
4 changes: 2 additions & 2 deletions packages/jest-source-map/src/__tests__/getCallsite.test.ts
Expand Up @@ -31,7 +31,7 @@ describe('getCallsite', () => {
throw new Error('Mock error');
});

const site = getCallsite(0, {[__filename]: 'mockedSourceMapFile'});
const site = getCallsite(0, new Map([[__filename, 'mockedSourceMapFile']]));

expect(site.getFileName()).toEqual(__filename);
expect(site.getColumnNumber()).toEqual(expect.any(Number));
Expand Down Expand Up @@ -59,7 +59,7 @@ describe('getCallsite', () => {
}
};

const site = getCallsite(0, {[__filename]: 'mockedSourceMapFile'});
const site = getCallsite(0, new Map([[__filename, 'mockedSourceMapFile']]));

expect(site.getFileName()).toEqual(__filename);
expect(site.getColumnNumber()).toEqual(sourceMapColumn);
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-source-map/src/getCallsite.ts
Expand Up @@ -52,7 +52,7 @@ export default (
): callsites.CallSite => {
const levelAfterThisCall = level + 1;
const stack = callsites()[levelAfterThisCall];
const sourceMapFileName = sourceMaps && sourceMaps[stack.getFileName() || ''];
const sourceMapFileName = sourceMaps?.get(stack.getFileName() || '');

if (sourceMapFileName) {
try {
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-source-map/src/types.ts
Expand Up @@ -5,4 +5,4 @@
* LICENSE file in the root directory of this source tree.
*/

export type SourceMapRegistry = Record<string, string>;
export type SourceMapRegistry = Map<string, string>;

0 comments on commit 1678cd9

Please sign in to comment.