|
8 | 8 |
|
9 | 9 | import {Config} from '@jest/types'; |
10 | 10 | import {SerializableError, TestResult} from '@jest/test-result'; |
11 | | -import HasteMap, {SerializableModuleMap, ModuleMap} from 'jest-haste-map'; |
| 11 | +import HasteMap, {ModuleMap, SerializableModuleMap} from 'jest-haste-map'; |
12 | 12 | import exit from 'exit'; |
13 | 13 | import {separateMessageFromStack} from 'jest-message-util'; |
14 | 14 | import Runtime from 'jest-runtime'; |
| 15 | +import Resolver from 'jest-resolve'; |
15 | 16 | import {ErrorWithCode, TestRunnerSerializedContext} from './types'; |
16 | 17 | import runTest from './runTest'; |
17 | 18 |
|
| 19 | +export type SerializableResolver = { |
| 20 | + config: Config.ProjectConfig; |
| 21 | + serializableModuleMap: SerializableModuleMap; |
| 22 | +}; |
| 23 | + |
18 | 24 | type WorkerData = { |
19 | 25 | config: Config.ProjectConfig; |
20 | 26 | globalConfig: Config.GlobalConfig; |
21 | 27 | path: Config.Path; |
22 | | - serializableModuleMap: SerializableModuleMap | null; |
23 | 28 | context?: TestRunnerSerializedContext; |
24 | 29 | }; |
25 | 30 |
|
@@ -47,45 +52,50 @@ const formatError = (error: string | ErrorWithCode): SerializableError => { |
47 | 52 | }; |
48 | 53 | }; |
49 | 54 |
|
50 | | -const resolvers = Object.create(null); |
51 | | -const getResolver = ( |
52 | | - config: Config.ProjectConfig, |
53 | | - moduleMap: ModuleMap | null, |
54 | | -) => { |
55 | | - // In watch mode, the raw module map with all haste modules is passed from |
56 | | - // the test runner to the watch command. This is because jest-haste-map's |
57 | | - // watch mode does not persist the haste map on disk after every file change. |
58 | | - // To make this fast and consistent, we pass it from the TestRunner. |
59 | | - if (moduleMap) { |
60 | | - return Runtime.createResolver(config, moduleMap); |
61 | | - } else { |
62 | | - const name = config.name; |
63 | | - if (!resolvers[name]) { |
64 | | - resolvers[name] = Runtime.createResolver( |
| 55 | +const resolvers = new Map<string, Resolver>(); |
| 56 | +const getResolver = (config: Config.ProjectConfig, moduleMap?: ModuleMap) => { |
| 57 | + const name = config.name; |
| 58 | + if (moduleMap || !resolvers.has(name)) { |
| 59 | + resolvers.set( |
| 60 | + name, |
| 61 | + Runtime.createResolver( |
65 | 62 | config, |
66 | | - Runtime.createHasteMap(config).readModuleMap(), |
67 | | - ); |
68 | | - } |
69 | | - return resolvers[name]; |
| 63 | + moduleMap || Runtime.createHasteMap(config).readModuleMap(), |
| 64 | + ), |
| 65 | + ); |
70 | 66 | } |
| 67 | + return resolvers.get(name)!; |
71 | 68 | }; |
72 | 69 |
|
| 70 | +export function setup(setupData?: { |
| 71 | + serializableResolvers: Array<SerializableResolver>; |
| 72 | +}) { |
| 73 | + // Setup data is only used in watch mode to pass the latest version of all |
| 74 | + // module maps that will be used during the test runs. Otherwise, module maps |
| 75 | + // are loaded from disk as needed. |
| 76 | + if (setupData) { |
| 77 | + for (const { |
| 78 | + config, |
| 79 | + serializableModuleMap, |
| 80 | + } of setupData.serializableResolvers) { |
| 81 | + const moduleMap = HasteMap.ModuleMap.fromJSON(serializableModuleMap); |
| 82 | + getResolver(config, moduleMap); |
| 83 | + } |
| 84 | + } |
| 85 | +} |
| 86 | + |
73 | 87 | export async function worker({ |
74 | 88 | config, |
75 | 89 | globalConfig, |
76 | 90 | path, |
77 | | - serializableModuleMap, |
78 | 91 | context, |
79 | 92 | }: WorkerData): Promise<TestResult> { |
80 | 93 | try { |
81 | | - const moduleMap = serializableModuleMap |
82 | | - ? HasteMap.ModuleMap.fromJSON(serializableModuleMap) |
83 | | - : null; |
84 | 94 | return await runTest( |
85 | 95 | path, |
86 | 96 | globalConfig, |
87 | 97 | config, |
88 | | - getResolver(config, moduleMap), |
| 98 | + getResolver(config), |
89 | 99 | context && { |
90 | 100 | ...context, |
91 | 101 | changedFiles: context.changedFiles && new Set(context.changedFiles), |
|
0 commit comments