metro-file-map 0.83.3 → 0.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/src/Watcher.js +59 -52
- package/src/Watcher.js.flow +39 -39
- package/src/cache/DiskCacheManager.js.flow +3 -3
- package/src/constants.js +9 -8
- package/src/constants.js.flow +6 -18
- package/src/crawlers/node/index.js +27 -25
- package/src/crawlers/node/index.js.flow +6 -8
- package/src/crawlers/watchman/index.js +26 -22
- package/src/crawlers/watchman/index.js.flow +3 -4
- package/src/crawlers/watchman/planQuery.d.ts +24 -0
- package/src/crawlers/watchman/planQuery.js.flow +4 -4
- package/src/flow-types.js.flow +125 -87
- package/src/index.js +267 -235
- package/src/index.js.flow +269 -275
- package/src/lib/FileProcessor.js +76 -54
- package/src/lib/FileProcessor.js.flow +93 -72
- package/src/lib/RootPathUtils.js +25 -21
- package/src/lib/RootPathUtils.js.flow +4 -4
- package/src/lib/TreeFS.js +72 -77
- package/src/lib/TreeFS.js.flow +104 -124
- package/src/lib/checkWatchmanCapabilities.js.flow +4 -4
- package/src/lib/dependencyExtractor.d.ts +14 -0
- package/src/lib/normalizePathSeparatorsToPosix.js +25 -21
- package/src/lib/normalizePathSeparatorsToPosix.js.flow +3 -3
- package/src/lib/normalizePathSeparatorsToSystem.js +25 -21
- package/src/lib/normalizePathSeparatorsToSystem.js.flow +3 -3
- package/src/lib/rootRelativeCacheKeys.js +0 -20
- package/src/lib/rootRelativeCacheKeys.js.flow +1 -23
- package/src/plugins/DependencyPlugin.js +75 -0
- package/src/plugins/DependencyPlugin.js.flow +144 -0
- package/src/plugins/HastePlugin.js +83 -38
- package/src/plugins/HastePlugin.js.flow +105 -51
- package/src/plugins/MockPlugin.js +7 -4
- package/src/plugins/MockPlugin.js.flow +24 -15
- package/src/plugins/dependencies/dependencyExtractor.d.ts +14 -0
- package/src/{lib → plugins/dependencies}/dependencyExtractor.js.flow +3 -6
- package/src/plugins/dependencies/worker.d.ts +24 -0
- package/src/plugins/dependencies/worker.js +24 -0
- package/src/plugins/dependencies/worker.js.flow +53 -0
- package/src/plugins/haste/HasteConflictsError.js.flow +2 -2
- package/src/plugins/haste/computeConflicts.js +2 -1
- package/src/plugins/haste/computeConflicts.js.flow +11 -12
- package/src/plugins/haste/getPlatformExtension.js.flow +2 -2
- package/src/plugins/haste/worker.d.ts +24 -0
- package/src/plugins/haste/worker.js +35 -0
- package/src/plugins/haste/worker.js.flow +64 -0
- package/src/plugins/mocks/getMockName.js +27 -23
- package/src/plugins/mocks/getMockName.js.flow +2 -4
- package/src/watchers/AbstractWatcher.js +27 -22
- package/src/watchers/AbstractWatcher.js.flow +6 -5
- package/src/watchers/FallbackWatcher.js +88 -84
- package/src/watchers/FallbackWatcher.js.flow +65 -65
- package/src/watchers/NativeWatcher.js +25 -21
- package/src/watchers/NativeWatcher.js.flow +3 -3
- package/src/watchers/RecrawlWarning.js.flow +1 -1
- package/src/watchers/WatchmanWatcher.js +61 -53
- package/src/watchers/WatchmanWatcher.js.flow +39 -38
- package/src/watchers/common.js.flow +5 -5
- package/src/worker.d.ts +36 -0
- package/src/worker.js +16 -58
- package/src/worker.js.flow +19 -69
- package/src/workerExclusionList.d.ts +12 -0
- package/src/workerExclusionList.js.flow +1 -1
- package/src/Watcher.d.ts +0 -24
- package/src/cache/DiskCacheManager.d.ts +0 -38
- package/src/flow-types.d.ts +0 -353
- package/src/index.d.ts +0 -97
- package/src/lib/DuplicateHasteCandidatesError.d.ts +0 -24
- /package/src/{lib → plugins/dependencies}/dependencyExtractor.js +0 -0
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
FileMapDelta,
|
|
17
17
|
FileMapPlugin,
|
|
18
18
|
FileMapPluginInitOptions,
|
|
19
|
-
|
|
19
|
+
FileMapPluginWorker,
|
|
20
20
|
HasteConflict,
|
|
21
21
|
HasteMap,
|
|
22
22
|
HasteMapItem,
|
|
@@ -34,39 +34,45 @@ import getPlatformExtension from './haste/getPlatformExtension';
|
|
|
34
34
|
import {HasteConflictsError} from './haste/HasteConflictsError';
|
|
35
35
|
import path from 'path';
|
|
36
36
|
|
|
37
|
-
const EMPTY_OBJ:
|
|
38
|
-
const EMPTY_MAP:
|
|
37
|
+
const EMPTY_OBJ: Readonly<{[string]: HasteMapItemMetadata}> = {};
|
|
38
|
+
const EMPTY_MAP: ReadonlyMap<string, DuplicatesSet> = new Map();
|
|
39
|
+
const PACKAGE_JSON = /(?:[/\\]|^)package\.json$/;
|
|
39
40
|
|
|
40
41
|
// Periodically yield to the event loop to allow parallel I/O, etc.
|
|
41
42
|
// Based on 200k files taking up to 800ms => max 40ms between yields.
|
|
42
43
|
const YIELD_EVERY_NUM_HASTE_FILES = 10000;
|
|
43
44
|
|
|
44
|
-
type HasteMapOptions =
|
|
45
|
+
export type HasteMapOptions = Readonly<{
|
|
45
46
|
console?: ?Console,
|
|
46
47
|
enableHastePackages: boolean,
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
hasteImplModulePath: ?string,
|
|
49
|
+
perfLogger?: ?PerfLogger,
|
|
50
|
+
platforms: ReadonlySet<string>,
|
|
49
51
|
rootDir: Path,
|
|
50
52
|
failValidationOnConflicts: boolean,
|
|
51
53
|
}>;
|
|
52
54
|
|
|
53
|
-
export default class HastePlugin
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
+#map: Map<string, HasteMapItem> = new Map();
|
|
58
|
-
+#duplicates: DuplicatesIndex = new Map();
|
|
55
|
+
export default class HastePlugin
|
|
56
|
+
implements HasteMap, FileMapPlugin<null, string | null>
|
|
57
|
+
{
|
|
58
|
+
+name: 'haste' = 'haste';
|
|
59
59
|
|
|
60
60
|
+#console: ?Console;
|
|
61
|
+
+#duplicates: DuplicatesIndex = new Map();
|
|
61
62
|
+#enableHastePackages: boolean;
|
|
62
|
-
+#perfLogger: ?PerfLogger;
|
|
63
|
-
+#pathUtils: RootPathUtils;
|
|
64
|
-
+#platforms: $ReadOnlySet<string>;
|
|
65
63
|
+#failValidationOnConflicts: boolean;
|
|
64
|
+
#getModuleNameByPath: string => ?string;
|
|
65
|
+
+#hasteImplModulePath: ?string;
|
|
66
|
+
+#map: Map<string, HasteMapItem> = new Map();
|
|
67
|
+
+#pathUtils: RootPathUtils;
|
|
68
|
+
+#perfLogger: ?PerfLogger;
|
|
69
|
+
+#platforms: ReadonlySet<string>;
|
|
70
|
+
+#rootDir: Path;
|
|
66
71
|
|
|
67
72
|
constructor(options: HasteMapOptions) {
|
|
68
|
-
this.#console = options.console ??
|
|
73
|
+
this.#console = options.console ?? global.console;
|
|
69
74
|
this.#enableHastePackages = options.enableHastePackages;
|
|
75
|
+
this.#hasteImplModulePath = options.hasteImplModulePath;
|
|
70
76
|
this.#perfLogger = options.perfLogger;
|
|
71
77
|
this.#platforms = options.platforms;
|
|
72
78
|
this.#rootDir = options.rootDir;
|
|
@@ -74,26 +80,41 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
74
80
|
this.#failValidationOnConflicts = options.failValidationOnConflicts;
|
|
75
81
|
}
|
|
76
82
|
|
|
77
|
-
async initialize({
|
|
83
|
+
async initialize({
|
|
84
|
+
files,
|
|
85
|
+
}: FileMapPluginInitOptions<null, string | null>): Promise<void> {
|
|
78
86
|
this.#perfLogger?.point('constructHasteMap_start');
|
|
79
87
|
let hasteFiles = 0;
|
|
80
|
-
for (const {
|
|
88
|
+
for (const {
|
|
89
|
+
baseName,
|
|
90
|
+
canonicalPath,
|
|
91
|
+
pluginData: hasteId,
|
|
92
|
+
} of files.fileIterator({
|
|
81
93
|
// Symlinks and node_modules are never Haste modules or packages.
|
|
82
94
|
includeNodeModules: false,
|
|
83
95
|
includeSymlinks: false,
|
|
84
96
|
})) {
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
if (hasteId == null) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
this.setModule(hasteId, [
|
|
101
|
+
canonicalPath,
|
|
102
|
+
this.#enableHastePackages && baseName === 'package.json'
|
|
103
|
+
? H.PACKAGE
|
|
104
|
+
: H.MODULE,
|
|
105
|
+
]);
|
|
106
|
+
if (++hasteFiles % YIELD_EVERY_NUM_HASTE_FILES === 0) {
|
|
107
|
+
await new Promise(setImmediate);
|
|
95
108
|
}
|
|
96
109
|
}
|
|
110
|
+
this.#getModuleNameByPath = mixedPath => {
|
|
111
|
+
const result = files.lookup(mixedPath);
|
|
112
|
+
return result.exists &&
|
|
113
|
+
result.type === 'f' &&
|
|
114
|
+
typeof result.pluginData === 'string'
|
|
115
|
+
? result.pluginData
|
|
116
|
+
: null;
|
|
117
|
+
};
|
|
97
118
|
this.#perfLogger?.point('constructHasteMap_end');
|
|
98
119
|
this.#perfLogger?.annotate({int: {hasteFiles}});
|
|
99
120
|
}
|
|
@@ -112,7 +133,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
112
133
|
supportsNativePlatform?: ?boolean,
|
|
113
134
|
type?: ?HTypeValue,
|
|
114
135
|
): ?Path {
|
|
115
|
-
const module = this
|
|
136
|
+
const module = this.#getModuleMetadata(
|
|
116
137
|
name,
|
|
117
138
|
platform,
|
|
118
139
|
!!supportsNativePlatform,
|
|
@@ -126,6 +147,15 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
126
147
|
return null;
|
|
127
148
|
}
|
|
128
149
|
|
|
150
|
+
getModuleNameByPath(mixedPath: Path): ?string {
|
|
151
|
+
if (this.#getModuleNameByPath == null) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
'HastePlugin has not been initialized before getModuleNameByPath',
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
return this.#getModuleNameByPath(mixedPath) ?? null;
|
|
157
|
+
}
|
|
158
|
+
|
|
129
159
|
getPackage(
|
|
130
160
|
name: string,
|
|
131
161
|
platform: ?string,
|
|
@@ -142,7 +172,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
142
172
|
* extra sure. If metadata exists both in the `duplicates` object and the
|
|
143
173
|
* `map`, this would be a bug.
|
|
144
174
|
*/
|
|
145
|
-
|
|
175
|
+
#getModuleMetadata(
|
|
146
176
|
name: string,
|
|
147
177
|
platform: ?string,
|
|
148
178
|
supportsNativePlatform: boolean,
|
|
@@ -150,7 +180,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
150
180
|
const map = this.#map.get(name) || EMPTY_OBJ;
|
|
151
181
|
const dupMap = this.#duplicates.get(name) || EMPTY_MAP;
|
|
152
182
|
if (platform != null) {
|
|
153
|
-
this
|
|
183
|
+
this.#assertNoDuplicates(
|
|
154
184
|
name,
|
|
155
185
|
platform,
|
|
156
186
|
supportsNativePlatform,
|
|
@@ -161,7 +191,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
161
191
|
}
|
|
162
192
|
}
|
|
163
193
|
if (supportsNativePlatform) {
|
|
164
|
-
this
|
|
194
|
+
this.#assertNoDuplicates(
|
|
165
195
|
name,
|
|
166
196
|
H.NATIVE_PLATFORM,
|
|
167
197
|
supportsNativePlatform,
|
|
@@ -171,7 +201,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
171
201
|
return map[H.NATIVE_PLATFORM];
|
|
172
202
|
}
|
|
173
203
|
}
|
|
174
|
-
this
|
|
204
|
+
this.#assertNoDuplicates(
|
|
175
205
|
name,
|
|
176
206
|
H.GENERIC_PLATFORM,
|
|
177
207
|
supportsNativePlatform,
|
|
@@ -183,7 +213,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
183
213
|
return null;
|
|
184
214
|
}
|
|
185
215
|
|
|
186
|
-
|
|
216
|
+
#assertNoDuplicates(
|
|
187
217
|
name: string,
|
|
188
218
|
platform: string,
|
|
189
219
|
supportsNativePlatform: boolean,
|
|
@@ -207,19 +237,19 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
207
237
|
);
|
|
208
238
|
}
|
|
209
239
|
|
|
210
|
-
async bulkUpdate(delta: FileMapDelta): Promise<void> {
|
|
240
|
+
async bulkUpdate(delta: FileMapDelta<?string>): Promise<void> {
|
|
211
241
|
// Process removals first so that moves aren't treated as duplicates.
|
|
212
|
-
for (const [normalPath,
|
|
213
|
-
this.onRemovedFile(normalPath,
|
|
242
|
+
for (const [normalPath, maybeHasteId] of delta.removed) {
|
|
243
|
+
this.onRemovedFile(normalPath, maybeHasteId);
|
|
214
244
|
}
|
|
215
|
-
for (const [normalPath,
|
|
216
|
-
this.onNewOrModifiedFile(normalPath,
|
|
245
|
+
for (const [normalPath, maybeHasteId] of delta.addedOrModified) {
|
|
246
|
+
this.onNewOrModifiedFile(normalPath, maybeHasteId);
|
|
217
247
|
}
|
|
218
248
|
}
|
|
219
249
|
|
|
220
|
-
onNewOrModifiedFile(relativeFilePath: string,
|
|
221
|
-
const id = fileMetadata[H.ID] || null; // Empty string indicates no module
|
|
250
|
+
onNewOrModifiedFile(relativeFilePath: string, id: ?string) {
|
|
222
251
|
if (id == null) {
|
|
252
|
+
// Not a Haste module or package
|
|
223
253
|
return;
|
|
224
254
|
}
|
|
225
255
|
|
|
@@ -238,7 +268,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
238
268
|
let hasteMapItem = this.#map.get(id);
|
|
239
269
|
if (!hasteMapItem) {
|
|
240
270
|
// $FlowFixMe[unclear-type] - Add type coverage
|
|
241
|
-
hasteMapItem =
|
|
271
|
+
hasteMapItem = Object.create(null) as any;
|
|
242
272
|
this.#map.set(id, hasteMapItem);
|
|
243
273
|
}
|
|
244
274
|
const platform =
|
|
@@ -294,9 +324,9 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
294
324
|
hasteMapItem[platform] = module;
|
|
295
325
|
}
|
|
296
326
|
|
|
297
|
-
onRemovedFile(relativeFilePath: string,
|
|
298
|
-
const moduleName = fileMetadata[H.ID] || null; // Empty string indicates no module
|
|
327
|
+
onRemovedFile(relativeFilePath: string, moduleName: ?string) {
|
|
299
328
|
if (moduleName == null) {
|
|
329
|
+
// Not a Haste module or package
|
|
300
330
|
return;
|
|
301
331
|
}
|
|
302
332
|
|
|
@@ -314,7 +344,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
314
344
|
}
|
|
315
345
|
}
|
|
316
346
|
|
|
317
|
-
this
|
|
347
|
+
this.#recoverDuplicates(moduleName, relativeFilePath);
|
|
318
348
|
}
|
|
319
349
|
|
|
320
350
|
assertValid(): void {
|
|
@@ -335,7 +365,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
335
365
|
* remaining in the group, then we want to restore that single file as the
|
|
336
366
|
* correct resolution for its ID, and cleanup the duplicates index.
|
|
337
367
|
*/
|
|
338
|
-
|
|
368
|
+
#recoverDuplicates(moduleName: string, relativeFilePath: string) {
|
|
339
369
|
let dupsByPlatform = this.#duplicates.get(moduleName);
|
|
340
370
|
if (dupsByPlatform == null) {
|
|
341
371
|
return;
|
|
@@ -369,7 +399,7 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
369
399
|
let dedupMap: ?HasteMapItem = this.#map.get(moduleName);
|
|
370
400
|
|
|
371
401
|
if (dedupMap == null) {
|
|
372
|
-
dedupMap =
|
|
402
|
+
dedupMap = Object.create(null) as HasteMapItem;
|
|
373
403
|
this.#map.set(moduleName, dedupMap);
|
|
374
404
|
}
|
|
375
405
|
dedupMap[platform] = uniqueModule;
|
|
@@ -386,12 +416,12 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
386
416
|
for (const [id, dupsByPlatform] of this.#duplicates.entries()) {
|
|
387
417
|
for (const [platform, conflictingModules] of dupsByPlatform) {
|
|
388
418
|
conflicts.push({
|
|
389
|
-
id,
|
|
390
|
-
platform: platform === H.GENERIC_PLATFORM ? null : platform,
|
|
391
419
|
absolutePaths: [...conflictingModules.keys()]
|
|
392
420
|
.map(modulePath => this.#pathUtils.normalToAbsolute(modulePath))
|
|
393
421
|
// Sort for ease of testing
|
|
394
422
|
.sort(),
|
|
423
|
+
id,
|
|
424
|
+
platform: platform === H.GENERIC_PLATFORM ? null : platform,
|
|
395
425
|
type: 'duplicate',
|
|
396
426
|
});
|
|
397
427
|
}
|
|
@@ -428,12 +458,12 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
428
458
|
}
|
|
429
459
|
if (conflictPaths.size) {
|
|
430
460
|
conflicts.push({
|
|
431
|
-
id,
|
|
432
|
-
platform: null,
|
|
433
461
|
absolutePaths: [...new Set([...conflictPaths, ...basePaths])]
|
|
434
462
|
.map(modulePath => this.#pathUtils.normalToAbsolute(modulePath))
|
|
435
463
|
// Sort for ease of testing
|
|
436
464
|
.sort(),
|
|
465
|
+
id,
|
|
466
|
+
platform: null,
|
|
437
467
|
type: 'shadowing',
|
|
438
468
|
});
|
|
439
469
|
}
|
|
@@ -454,7 +484,31 @@ export default class HastePlugin implements HasteMap, FileMapPlugin<null> {
|
|
|
454
484
|
getCacheKey(): string {
|
|
455
485
|
return JSON.stringify([
|
|
456
486
|
this.#enableHastePackages,
|
|
487
|
+
this.#hasteImplModulePath != null
|
|
488
|
+
? // $FlowFixMe[unsupported-syntax] - dynamic require
|
|
489
|
+
require(this.#hasteImplModulePath).getCacheKey()
|
|
490
|
+
: null,
|
|
457
491
|
[...this.#platforms].sort(),
|
|
458
492
|
]);
|
|
459
493
|
}
|
|
494
|
+
|
|
495
|
+
getWorker(): FileMapPluginWorker {
|
|
496
|
+
return {
|
|
497
|
+
worker: {
|
|
498
|
+
modulePath: require.resolve('./haste/worker.js'),
|
|
499
|
+
setupArgs: {
|
|
500
|
+
hasteImplModulePath: this.#hasteImplModulePath ?? null,
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
filter: ({isNodeModules, normalPath}) => {
|
|
504
|
+
if (isNodeModules) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
if (PACKAGE_JSON.test(normalPath)) {
|
|
508
|
+
return this.#enableHastePackages;
|
|
509
|
+
}
|
|
510
|
+
return this.#hasteImplModulePath != null;
|
|
511
|
+
},
|
|
512
|
+
};
|
|
513
|
+
}
|
|
460
514
|
}
|
|
@@ -30,8 +30,8 @@ class MockPlugin {
|
|
|
30
30
|
console,
|
|
31
31
|
mocksPattern,
|
|
32
32
|
rawMockMap = {
|
|
33
|
-
mocks: new Map(),
|
|
34
33
|
duplicates: new Map(),
|
|
34
|
+
mocks: new Map(),
|
|
35
35
|
version: CACHE_VERSION,
|
|
36
36
|
},
|
|
37
37
|
rootDir,
|
|
@@ -53,11 +53,11 @@ class MockPlugin {
|
|
|
53
53
|
} else {
|
|
54
54
|
await this.bulkUpdate({
|
|
55
55
|
addedOrModified: [
|
|
56
|
-
...files.
|
|
56
|
+
...files.fileIterator({
|
|
57
57
|
includeNodeModules: false,
|
|
58
58
|
includeSymlinks: false,
|
|
59
59
|
}),
|
|
60
|
-
].map(({ canonicalPath
|
|
60
|
+
].map(({ canonicalPath }) => [canonicalPath, null]),
|
|
61
61
|
removed: [],
|
|
62
62
|
});
|
|
63
63
|
}
|
|
@@ -129,10 +129,10 @@ class MockPlugin {
|
|
|
129
129
|
}
|
|
130
130
|
getSerializableSnapshot() {
|
|
131
131
|
return {
|
|
132
|
-
mocks: new Map(this.#raw.mocks),
|
|
133
132
|
duplicates: new Map(
|
|
134
133
|
[...this.#raw.duplicates].map(([k, v]) => [k, new Set(v)]),
|
|
135
134
|
),
|
|
135
|
+
mocks: new Map(this.#raw.mocks),
|
|
136
136
|
version: this.#raw.version,
|
|
137
137
|
};
|
|
138
138
|
}
|
|
@@ -175,5 +175,8 @@ class MockPlugin {
|
|
|
175
175
|
this.#mocksPattern.flags
|
|
176
176
|
);
|
|
177
177
|
}
|
|
178
|
+
getWorker() {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
178
181
|
}
|
|
179
182
|
exports.default = MockPlugin;
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
FileMapDelta,
|
|
14
14
|
FileMapPlugin,
|
|
15
15
|
FileMapPluginInitOptions,
|
|
16
|
+
FileMapPluginWorker,
|
|
16
17
|
MockMap as IMockMap,
|
|
17
18
|
Path,
|
|
18
19
|
RawMockMap,
|
|
@@ -27,8 +28,18 @@ import path from 'path';
|
|
|
27
28
|
|
|
28
29
|
export const CACHE_VERSION = 2;
|
|
29
30
|
|
|
30
|
-
export
|
|
31
|
-
|
|
31
|
+
export type MockMapOptions = Readonly<{
|
|
32
|
+
console: typeof console,
|
|
33
|
+
mocksPattern: RegExp,
|
|
34
|
+
rawMockMap?: RawMockMap,
|
|
35
|
+
rootDir: Path,
|
|
36
|
+
throwOnModuleCollision: boolean,
|
|
37
|
+
}>;
|
|
38
|
+
|
|
39
|
+
export default class MockPlugin
|
|
40
|
+
implements FileMapPlugin<RawMockMap, void>, IMockMap
|
|
41
|
+
{
|
|
42
|
+
+name: 'mocks' = 'mocks';
|
|
32
43
|
|
|
33
44
|
+#mocksPattern: RegExp;
|
|
34
45
|
#raw: RawMockMap;
|
|
@@ -41,19 +52,13 @@ export default class MockPlugin implements FileMapPlugin<RawMockMap>, IMockMap {
|
|
|
41
52
|
console,
|
|
42
53
|
mocksPattern,
|
|
43
54
|
rawMockMap = {
|
|
44
|
-
mocks: new Map(),
|
|
45
55
|
duplicates: new Map(),
|
|
56
|
+
mocks: new Map(),
|
|
46
57
|
version: CACHE_VERSION,
|
|
47
58
|
},
|
|
48
59
|
rootDir,
|
|
49
60
|
throwOnModuleCollision,
|
|
50
|
-
}:
|
|
51
|
-
console: typeof console,
|
|
52
|
-
mocksPattern: RegExp,
|
|
53
|
-
rawMockMap?: RawMockMap,
|
|
54
|
-
rootDir: Path,
|
|
55
|
-
throwOnModuleCollision: boolean,
|
|
56
|
-
}>) {
|
|
61
|
+
}: MockMapOptions) {
|
|
57
62
|
this.#mocksPattern = mocksPattern;
|
|
58
63
|
if (rawMockMap.version !== CACHE_VERSION) {
|
|
59
64
|
throw new Error('Incompatible state passed to MockPlugin');
|
|
@@ -76,11 +81,11 @@ export default class MockPlugin implements FileMapPlugin<RawMockMap>, IMockMap {
|
|
|
76
81
|
// Otherwise, traverse all files to rebuild
|
|
77
82
|
await this.bulkUpdate({
|
|
78
83
|
addedOrModified: [
|
|
79
|
-
...files.
|
|
84
|
+
...files.fileIterator({
|
|
80
85
|
includeNodeModules: false,
|
|
81
86
|
includeSymlinks: false,
|
|
82
87
|
}),
|
|
83
|
-
].map(({canonicalPath
|
|
88
|
+
].map(({canonicalPath}) => [canonicalPath, null]),
|
|
84
89
|
removed: [],
|
|
85
90
|
});
|
|
86
91
|
}
|
|
@@ -97,7 +102,7 @@ export default class MockPlugin implements FileMapPlugin<RawMockMap>, IMockMap {
|
|
|
97
102
|
);
|
|
98
103
|
}
|
|
99
104
|
|
|
100
|
-
async bulkUpdate(delta: FileMapDelta): Promise<void> {
|
|
105
|
+
async bulkUpdate(delta: FileMapDelta<>): Promise<void> {
|
|
101
106
|
// Process removals first so that moves aren't treated as duplicates.
|
|
102
107
|
for (const [relativeFilePath] of delta.removed) {
|
|
103
108
|
this.onRemovedFile(relativeFilePath);
|
|
@@ -160,10 +165,10 @@ export default class MockPlugin implements FileMapPlugin<RawMockMap>, IMockMap {
|
|
|
160
165
|
|
|
161
166
|
getSerializableSnapshot(): RawMockMap {
|
|
162
167
|
return {
|
|
163
|
-
mocks: new Map(this.#raw.mocks),
|
|
164
168
|
duplicates: new Map(
|
|
165
169
|
[...this.#raw.duplicates].map(([k, v]) => [k, new Set(v)]),
|
|
166
170
|
),
|
|
171
|
+
mocks: new Map(this.#raw.mocks),
|
|
167
172
|
version: this.#raw.version,
|
|
168
173
|
};
|
|
169
174
|
}
|
|
@@ -186,7 +191,7 @@ export default class MockPlugin implements FileMapPlugin<RawMockMap>, IMockMap {
|
|
|
186
191
|
|
|
187
192
|
#getMessageForDuplicates(
|
|
188
193
|
mockName: string,
|
|
189
|
-
relativePosixPaths:
|
|
194
|
+
relativePosixPaths: ReadonlySet<string>,
|
|
190
195
|
): string {
|
|
191
196
|
return (
|
|
192
197
|
'Duplicate manual mock found for `' +
|
|
@@ -213,4 +218,8 @@ export default class MockPlugin implements FileMapPlugin<RawMockMap>, IMockMap {
|
|
|
213
218
|
this.#mocksPattern.flags
|
|
214
219
|
);
|
|
215
220
|
}
|
|
221
|
+
|
|
222
|
+
getWorker(): ?FileMapPluginWorker {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
216
225
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare const dependencyExtractor: {
|
|
11
|
+
extract(code: string): Set<string>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export = dependencyExtractor;
|
|
@@ -22,18 +22,15 @@ const RIGHT_PARENTHESIS = '\\)';
|
|
|
22
22
|
const WHITESPACE = '\\s*';
|
|
23
23
|
const OPTIONAL_COMMA = '(:?,\\s*)?';
|
|
24
24
|
|
|
25
|
-
function createRegExp(
|
|
26
|
-
parts /*: $ReadOnlyArray<string> */,
|
|
27
|
-
flags /*: string */,
|
|
28
|
-
) {
|
|
25
|
+
function createRegExp(parts /*: ReadonlyArray<string> */, flags /*: string */) {
|
|
29
26
|
return new RegExp(parts.join(''), flags);
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
function alternatives(...parts /*:
|
|
29
|
+
function alternatives(...parts /*: ReadonlyArray<string> */) {
|
|
33
30
|
return `(?:${parts.join('|')})`;
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
function functionCallStart(...names /*:
|
|
33
|
+
function functionCallStart(...names /*: ReadonlyArray<string> */) {
|
|
37
34
|
return [
|
|
38
35
|
NOT_A_DOT,
|
|
39
36
|
WORD_SEPARATOR,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall react_native
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
MetadataWorker,
|
|
13
|
+
V8Serializable,
|
|
14
|
+
WorkerMessage,
|
|
15
|
+
} from '../../flow-types';
|
|
16
|
+
|
|
17
|
+
declare class DependencyExtractorWorker implements MetadataWorker {
|
|
18
|
+
constructor(opts: Readonly<{dependencyExtractor: null | undefined | string}>);
|
|
19
|
+
processFile(
|
|
20
|
+
data: WorkerMessage,
|
|
21
|
+
utils: Readonly<{getContent: () => Buffer}>,
|
|
22
|
+
): V8Serializable;
|
|
23
|
+
}
|
|
24
|
+
export = DependencyExtractorWorker;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const defaultDependencyExtractor = require("./dependencyExtractor");
|
|
4
|
+
module.exports = class DependencyExtractorWorker {
|
|
5
|
+
#dependencyExtractor;
|
|
6
|
+
constructor({ dependencyExtractor }) {
|
|
7
|
+
if (dependencyExtractor != null) {
|
|
8
|
+
this.#dependencyExtractor = require(dependencyExtractor);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
processFile(data, utils) {
|
|
12
|
+
const content = utils.getContent().toString();
|
|
13
|
+
const { filePath } = data;
|
|
14
|
+
const dependencies =
|
|
15
|
+
this.#dependencyExtractor != null
|
|
16
|
+
? this.#dependencyExtractor.extract(
|
|
17
|
+
content,
|
|
18
|
+
filePath,
|
|
19
|
+
defaultDependencyExtractor.extract,
|
|
20
|
+
)
|
|
21
|
+
: defaultDependencyExtractor.extract(content);
|
|
22
|
+
return Array.from(dependencies);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/* eslint-disable import/no-commonjs */
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const defaultDependencyExtractor = require('./dependencyExtractor');
|
|
17
|
+
|
|
18
|
+
/*::
|
|
19
|
+
import type {MetadataWorker, WorkerMessage, V8Serializable, DependencyExtractor} from '../../flow-types';
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
module.exports = class DependencyExtractorWorker /*:: implements MetadataWorker */ {
|
|
23
|
+
/*:: + */ #dependencyExtractor /*: ?DependencyExtractor */;
|
|
24
|
+
|
|
25
|
+
constructor(
|
|
26
|
+
{dependencyExtractor} /*: Readonly<{dependencyExtractor: ?string}> */,
|
|
27
|
+
) {
|
|
28
|
+
if (dependencyExtractor != null) {
|
|
29
|
+
// $FlowFixMe[unsupported-syntax] - dynamic require
|
|
30
|
+
this.#dependencyExtractor = require(dependencyExtractor);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
processFile(
|
|
35
|
+
data /*: WorkerMessage */,
|
|
36
|
+
utils /*: Readonly<{getContent: () => Buffer}> */,
|
|
37
|
+
) /*: V8Serializable */ {
|
|
38
|
+
const content = utils.getContent().toString();
|
|
39
|
+
const {filePath} = data;
|
|
40
|
+
|
|
41
|
+
const dependencies =
|
|
42
|
+
this.#dependencyExtractor != null
|
|
43
|
+
? this.#dependencyExtractor.extract(
|
|
44
|
+
content,
|
|
45
|
+
filePath,
|
|
46
|
+
defaultDependencyExtractor.extract,
|
|
47
|
+
)
|
|
48
|
+
: defaultDependencyExtractor.extract(content);
|
|
49
|
+
|
|
50
|
+
// Return as array (PerFileData type)
|
|
51
|
+
return Array.from(dependencies);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
@@ -14,9 +14,9 @@ import type {HasteConflict} from '../../flow-types';
|
|
|
14
14
|
import path from 'path';
|
|
15
15
|
|
|
16
16
|
export class HasteConflictsError extends Error {
|
|
17
|
-
#conflicts:
|
|
17
|
+
#conflicts: ReadonlyArray<HasteConflict>;
|
|
18
18
|
|
|
19
|
-
constructor(conflicts:
|
|
19
|
+
constructor(conflicts: ReadonlyArray<HasteConflict>) {
|
|
20
20
|
super(
|
|
21
21
|
`Found ${conflicts.length} Haste conflict(s). Haste module IDs must be globally unique in the codebase.`,
|
|
22
22
|
);
|
|
@@ -10,7 +10,8 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
10
10
|
function _interopRequireDefault(e) {
|
|
11
11
|
return e && e.__esModule ? e : { default: e };
|
|
12
12
|
}
|
|
13
|
-
function computeHasteConflicts(
|
|
13
|
+
function computeHasteConflicts(options) {
|
|
14
|
+
const { duplicates, map, rootDir } = options;
|
|
14
15
|
const conflicts = [];
|
|
15
16
|
for (const [id, dupsByPlatform] of duplicates.entries()) {
|
|
16
17
|
for (const [platform, conflictingModules] of dupsByPlatform) {
|
|
@@ -21,18 +21,17 @@ type Conflict = {
|
|
|
21
21
|
type: 'duplicate' | 'shadowing',
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
export function computeHasteConflicts(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
string,
|
|
31
|
-
|
|
32
|
-
>,
|
|
33
|
-
|
|
34
|
-
rootDir
|
|
35
|
-
}>): Array<Conflict> {
|
|
24
|
+
export function computeHasteConflicts(
|
|
25
|
+
options: Readonly<{
|
|
26
|
+
duplicates: ReadonlyMap<
|
|
27
|
+
string,
|
|
28
|
+
ReadonlyMap<string, ReadonlyMap<string, number>>,
|
|
29
|
+
>,
|
|
30
|
+
map: ReadonlyMap<string, HasteMapItem>,
|
|
31
|
+
rootDir: string,
|
|
32
|
+
}>,
|
|
33
|
+
): Array<Conflict> {
|
|
34
|
+
const {duplicates, map, rootDir} = options;
|
|
36
35
|
const conflicts: Array<Conflict> = [];
|
|
37
36
|
|
|
38
37
|
// Add duplicates reported by metro-file-map
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @format
|
|
8
7
|
* @flow strict
|
|
8
|
+
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
// Extract platform extension: index.ios.js -> ios
|
|
12
12
|
export default function getPlatformExtension(
|
|
13
13
|
file: string,
|
|
14
|
-
platforms:
|
|
14
|
+
platforms: ReadonlySet<string>,
|
|
15
15
|
): ?string {
|
|
16
16
|
const last = file.lastIndexOf('.');
|
|
17
17
|
const secondToLast = file.lastIndexOf('.', last - 1);
|