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.
Files changed (70) hide show
  1. package/package.json +4 -3
  2. package/src/Watcher.js +59 -52
  3. package/src/Watcher.js.flow +39 -39
  4. package/src/cache/DiskCacheManager.js.flow +3 -3
  5. package/src/constants.js +9 -8
  6. package/src/constants.js.flow +6 -18
  7. package/src/crawlers/node/index.js +27 -25
  8. package/src/crawlers/node/index.js.flow +6 -8
  9. package/src/crawlers/watchman/index.js +26 -22
  10. package/src/crawlers/watchman/index.js.flow +3 -4
  11. package/src/crawlers/watchman/planQuery.d.ts +24 -0
  12. package/src/crawlers/watchman/planQuery.js.flow +4 -4
  13. package/src/flow-types.js.flow +125 -87
  14. package/src/index.js +267 -235
  15. package/src/index.js.flow +269 -275
  16. package/src/lib/FileProcessor.js +76 -54
  17. package/src/lib/FileProcessor.js.flow +93 -72
  18. package/src/lib/RootPathUtils.js +25 -21
  19. package/src/lib/RootPathUtils.js.flow +4 -4
  20. package/src/lib/TreeFS.js +72 -77
  21. package/src/lib/TreeFS.js.flow +104 -124
  22. package/src/lib/checkWatchmanCapabilities.js.flow +4 -4
  23. package/src/lib/dependencyExtractor.d.ts +14 -0
  24. package/src/lib/normalizePathSeparatorsToPosix.js +25 -21
  25. package/src/lib/normalizePathSeparatorsToPosix.js.flow +3 -3
  26. package/src/lib/normalizePathSeparatorsToSystem.js +25 -21
  27. package/src/lib/normalizePathSeparatorsToSystem.js.flow +3 -3
  28. package/src/lib/rootRelativeCacheKeys.js +0 -20
  29. package/src/lib/rootRelativeCacheKeys.js.flow +1 -23
  30. package/src/plugins/DependencyPlugin.js +75 -0
  31. package/src/plugins/DependencyPlugin.js.flow +144 -0
  32. package/src/plugins/HastePlugin.js +83 -38
  33. package/src/plugins/HastePlugin.js.flow +105 -51
  34. package/src/plugins/MockPlugin.js +7 -4
  35. package/src/plugins/MockPlugin.js.flow +24 -15
  36. package/src/plugins/dependencies/dependencyExtractor.d.ts +14 -0
  37. package/src/{lib → plugins/dependencies}/dependencyExtractor.js.flow +3 -6
  38. package/src/plugins/dependencies/worker.d.ts +24 -0
  39. package/src/plugins/dependencies/worker.js +24 -0
  40. package/src/plugins/dependencies/worker.js.flow +53 -0
  41. package/src/plugins/haste/HasteConflictsError.js.flow +2 -2
  42. package/src/plugins/haste/computeConflicts.js +2 -1
  43. package/src/plugins/haste/computeConflicts.js.flow +11 -12
  44. package/src/plugins/haste/getPlatformExtension.js.flow +2 -2
  45. package/src/plugins/haste/worker.d.ts +24 -0
  46. package/src/plugins/haste/worker.js +35 -0
  47. package/src/plugins/haste/worker.js.flow +64 -0
  48. package/src/plugins/mocks/getMockName.js +27 -23
  49. package/src/plugins/mocks/getMockName.js.flow +2 -4
  50. package/src/watchers/AbstractWatcher.js +27 -22
  51. package/src/watchers/AbstractWatcher.js.flow +6 -5
  52. package/src/watchers/FallbackWatcher.js +88 -84
  53. package/src/watchers/FallbackWatcher.js.flow +65 -65
  54. package/src/watchers/NativeWatcher.js +25 -21
  55. package/src/watchers/NativeWatcher.js.flow +3 -3
  56. package/src/watchers/RecrawlWarning.js.flow +1 -1
  57. package/src/watchers/WatchmanWatcher.js +61 -53
  58. package/src/watchers/WatchmanWatcher.js.flow +39 -38
  59. package/src/watchers/common.js.flow +5 -5
  60. package/src/worker.d.ts +36 -0
  61. package/src/worker.js +16 -58
  62. package/src/worker.js.flow +19 -69
  63. package/src/workerExclusionList.d.ts +12 -0
  64. package/src/workerExclusionList.js.flow +1 -1
  65. package/src/Watcher.d.ts +0 -24
  66. package/src/cache/DiskCacheManager.d.ts +0 -38
  67. package/src/flow-types.d.ts +0 -353
  68. package/src/index.d.ts +0 -97
  69. package/src/lib/DuplicateHasteCandidatesError.d.ts +0 -24
  70. /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
- FileMetadata,
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: $ReadOnly<{[string]: HasteMapItemMetadata}> = {};
38
- const EMPTY_MAP: $ReadOnlyMap<string, DuplicatesSet> = new 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 = $ReadOnly<{
45
+ export type HasteMapOptions = Readonly<{
45
46
  console?: ?Console,
46
47
  enableHastePackages: boolean,
47
- perfLogger: ?PerfLogger,
48
- platforms: $ReadOnlySet<string>,
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 implements HasteMap, FileMapPlugin<null> {
54
- +name = 'haste';
55
-
56
- +#rootDir: Path;
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 ?? null;
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({files}: FileMapPluginInitOptions<null>): Promise<void> {
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 {baseName, canonicalPath, metadata} of files.metadataIterator({
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 (metadata[H.ID]) {
86
- this.setModule(metadata[H.ID], [
87
- canonicalPath,
88
- this.#enableHastePackages && baseName === 'package.json'
89
- ? H.PACKAGE
90
- : H.MODULE,
91
- ]);
92
- if (++hasteFiles % YIELD_EVERY_NUM_HASTE_FILES === 0) {
93
- await new Promise(setImmediate);
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._getModuleMetadata(
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
- _getModuleMetadata(
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._assertNoDuplicates(
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._assertNoDuplicates(
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._assertNoDuplicates(
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
- _assertNoDuplicates(
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, metadata] of delta.removed) {
213
- this.onRemovedFile(normalPath, metadata);
242
+ for (const [normalPath, maybeHasteId] of delta.removed) {
243
+ this.onRemovedFile(normalPath, maybeHasteId);
214
244
  }
215
- for (const [normalPath, metadata] of delta.addedOrModified) {
216
- this.onNewOrModifiedFile(normalPath, metadata);
245
+ for (const [normalPath, maybeHasteId] of delta.addedOrModified) {
246
+ this.onNewOrModifiedFile(normalPath, maybeHasteId);
217
247
  }
218
248
  }
219
249
 
220
- onNewOrModifiedFile(relativeFilePath: string, fileMetadata: FileMetadata) {
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 = (Object.create(null): any);
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, fileMetadata: FileMetadata) {
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._recoverDuplicates(moduleName, relativeFilePath);
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
- _recoverDuplicates(moduleName: string, relativeFilePath: string) {
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 = (Object.create(null): HasteMapItem);
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.metadataIterator({
56
+ ...files.fileIterator({
57
57
  includeNodeModules: false,
58
58
  includeSymlinks: false,
59
59
  }),
60
- ].map(({ canonicalPath, metadata }) => [canonicalPath, metadata]),
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 default class MockPlugin implements FileMapPlugin<RawMockMap>, IMockMap {
31
- +name = 'mocks';
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
- }: $ReadOnly<{
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.metadataIterator({
84
+ ...files.fileIterator({
80
85
  includeNodeModules: false,
81
86
  includeSymlinks: false,
82
87
  }),
83
- ].map(({canonicalPath, metadata}) => [canonicalPath, metadata]),
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: $ReadOnlySet<string>,
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 /*: $ReadOnlyArray<string> */) {
29
+ function alternatives(...parts /*: ReadonlyArray<string> */) {
33
30
  return `(?:${parts.join('|')})`;
34
31
  }
35
32
 
36
- function functionCallStart(...names /*: $ReadOnlyArray<string> */) {
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: $ReadOnlyArray<HasteConflict>;
17
+ #conflicts: ReadonlyArray<HasteConflict>;
18
18
 
19
- constructor(conflicts: $ReadOnlyArray<HasteConflict>) {
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({ duplicates, map, rootDir }) {
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
- duplicates,
26
- map,
27
- rootDir,
28
- }: $ReadOnly<{
29
- duplicates: $ReadOnlyMap<
30
- string,
31
- $ReadOnlyMap<string, $ReadOnlyMap<string, number>>,
32
- >,
33
- map: $ReadOnlyMap<string, HasteMapItem>,
34
- rootDir: string,
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: $ReadOnlySet<string>,
14
+ platforms: ReadonlySet<string>,
15
15
  ): ?string {
16
16
  const last = file.lastIndexOf('.');
17
17
  const secondToLast = file.lastIndexOf('.', last - 1);