metro-file-map 0.84.4 → 0.85.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 (38) hide show
  1. package/package.json +3 -3
  2. package/src/Watcher.d.ts +1 -2
  3. package/src/Watcher.js +0 -1
  4. package/src/Watcher.js.flow +6 -6
  5. package/src/cache/DiskCacheManager.js.flow +2 -2
  6. package/src/crawlers/node/index.js +9 -92
  7. package/src/crawlers/node/index.js.flow +9 -98
  8. package/src/flow-types.d.ts +3 -5
  9. package/src/flow-types.js.flow +13 -15
  10. package/src/index.d.ts +1 -2
  11. package/src/index.js +0 -3
  12. package/src/index.js.flow +8 -12
  13. package/src/lib/FileProcessor.js.flow +2 -2
  14. package/src/lib/FileSystemChangeAggregator.js.flow +6 -6
  15. package/src/lib/RootPathUtils.js +8 -2
  16. package/src/lib/RootPathUtils.js.flow +16 -4
  17. package/src/lib/TreeFS.js +13 -5
  18. package/src/lib/TreeFS.js.flow +25 -10
  19. package/src/lib/rootRelativeCacheKeys.js +0 -1
  20. package/src/lib/rootRelativeCacheKeys.js.flow +0 -1
  21. package/src/plugins/DependencyPlugin.js +6 -2
  22. package/src/plugins/DependencyPlugin.js.flow +7 -2
  23. package/src/plugins/FileDataPlugin.js.flow +2 -2
  24. package/src/plugins/HastePlugin.js.flow +11 -11
  25. package/src/plugins/MockPlugin.js.flow +5 -5
  26. package/src/plugins/dependencies/worker.js +7 -2
  27. package/src/plugins/dependencies/worker.js.flow +8 -3
  28. package/src/plugins/haste/worker.js +3 -1
  29. package/src/plugins/haste/worker.js.flow +4 -2
  30. package/src/watchers/AbstractWatcher.js.flow +5 -5
  31. package/src/watchers/FallbackWatcher.js.flow +4 -3
  32. package/src/watchers/NativeWatcher.d.ts +1 -2
  33. package/src/watchers/WatchmanWatcher.js.flow +2 -2
  34. package/src/worker.js +3 -1
  35. package/src/worker.js.flow +3 -1
  36. package/src/crawlers/node/hasNativeFindSupport.d.ts +0 -19
  37. package/src/crawlers/node/hasNativeFindSupport.js +0 -36
  38. package/src/crawlers/node/hasNativeFindSupport.js.flow +0 -41
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metro-file-map",
3
- "version": "0.84.4",
3
+ "version": "0.85.0",
4
4
  "description": "[Experimental] - 🚇 File crawling, watching and mapping for Metro",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/facebook/metro.git",
13
+ "url": "git+https://github.com/react/metro.git",
14
14
  "directory": "packages/metro-file-map"
15
15
  },
16
16
  "scripts": {
@@ -33,6 +33,6 @@
33
33
  "slash": "^3.0.0"
34
34
  },
35
35
  "engines": {
36
- "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
36
+ "node": "^22.13.0 || ^24.3.0 || >= 26.0.0"
37
37
  }
38
38
  }
package/src/Watcher.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  * @noformat
8
- * @generated SignedSource<<25fee66c7d26ad53cdd5bbab454fe50b>>
8
+ * @generated SignedSource<<7e33ffd7eec05b9c9c072189d2ed3ec2>>
9
9
  *
10
10
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
11
11
  * Original file: packages/metro-file-map/src/Watcher.js
@@ -30,7 +30,6 @@ type WatcherOptions = {
30
30
  console: Console;
31
31
  enableSymlinks: boolean;
32
32
  extensions: ReadonlyArray<string>;
33
- forceNodeFilesystemAPI: boolean;
34
33
  healthCheckFilePrefix: string;
35
34
  ignoreForCrawl: (filePath: string) => boolean;
36
35
  ignorePatternForWatch: RegExp;
package/src/Watcher.js CHANGED
@@ -103,7 +103,6 @@ class Watcher extends _events.default {
103
103
  console: options.console,
104
104
  includeSymlinks: options.enableSymlinks,
105
105
  extensions: options.extensions,
106
- forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
107
106
  ignore: ignoreForCrawl,
108
107
  onStatus: (status) => {
109
108
  this.emit("status", status);
@@ -49,7 +49,6 @@ type WatcherOptions = {
49
49
  console: Console,
50
50
  enableSymlinks: boolean,
51
51
  extensions: ReadonlyArray<string>,
52
- forceNodeFilesystemAPI: boolean,
53
52
  healthCheckFilePrefix: string,
54
53
  ignoreForCrawl: (filePath: string) => boolean,
55
54
  ignorePatternForWatch: RegExp,
@@ -72,11 +71,13 @@ export type HealthCheckResult =
72
71
  export class Watcher extends EventEmitter {
73
72
  #activeWatcher: ?string;
74
73
  #backends: ReadonlyArray<WatcherBackend> = [];
75
- +#instanceId: number;
74
+ readonly #instanceId: number;
76
75
  #nextHealthCheckId: number = 0;
77
- +#options: WatcherOptions;
78
- +#pendingHealthChecks: Map</* basename */ string, /* resolve */ () => void> =
79
- new Map();
76
+ readonly #options: WatcherOptions;
77
+ readonly #pendingHealthChecks: Map<
78
+ /* basename */ string,
79
+ /* resolve */ () => void,
80
+ > = new Map();
80
81
 
81
82
  constructor(options: WatcherOptions) {
82
83
  super();
@@ -131,7 +132,6 @@ export class Watcher extends EventEmitter {
131
132
  console: options.console,
132
133
  includeSymlinks: options.enableSymlinks,
133
134
  extensions: options.extensions,
134
- forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
135
135
  ignore: ignoreForCrawl,
136
136
  onStatus: status => {
137
137
  this.emit('status', status);
@@ -42,8 +42,8 @@ const DEFAULT_DIRECTORY = tmpdir();
42
42
  const DEFAULT_AUTO_SAVE_DEBOUNCE_MS = 5000;
43
43
 
44
44
  export class DiskCacheManager implements CacheManager {
45
- +#autoSaveOpts: ?AutoSaveOptions;
46
- +#cachePath: string;
45
+ readonly #autoSaveOpts: ?AutoSaveOptions;
46
+ readonly #cachePath: string;
47
47
  #debounceTimeout: ?Timeout = null;
48
48
  #writePromise: Promise<void> = Promise.resolve();
49
49
  #hasUnwrittenChanges: boolean = false;
@@ -5,12 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = nodeCrawl;
7
7
  var _RootPathUtils = require("../../lib/RootPathUtils");
8
- var _hasNativeFindSupport = _interopRequireDefault(
9
- require("./hasNativeFindSupport"),
10
- );
11
- var _child_process = require("child_process");
12
8
  var fs = _interopRequireWildcard(require("graceful-fs"));
13
- var _os = require("os");
14
9
  var path = _interopRequireWildcard(require("path"));
15
10
  function _interopRequireWildcard(e, t) {
16
11
  if ("function" == typeof WeakMap)
@@ -39,10 +34,6 @@ function _interopRequireWildcard(e, t) {
39
34
  return f;
40
35
  })(e, t);
41
36
  }
42
- function _interopRequireDefault(e) {
43
- return e && e.__esModule ? e : { default: e };
44
- }
45
- const debug = require("debug")("Metro:NodeCrawler");
46
37
  function find(
47
38
  roots,
48
39
  extensions,
@@ -115,68 +106,11 @@ function find(
115
106
  callback(result);
116
107
  }
117
108
  }
118
- function findNative(
119
- roots,
120
- extensions,
121
- ignore,
122
- includeSymlinks,
123
- rootDir,
124
- console,
125
- callback,
126
- ) {
127
- const extensionClause = extensions.length
128
- ? `( ${extensions.map((ext) => `-iname *.${ext}`).join(" -o ")} )`
129
- : "";
130
- const expression = `( ( -type f ${extensionClause} ) ${includeSymlinks ? "-o -type l " : ""})`;
131
- const pathUtils = new _RootPathUtils.RootPathUtils(rootDir);
132
- const child = (0, _child_process.spawn)(
133
- "find",
134
- roots.concat(expression.split(" ")),
135
- );
136
- let stdout = "";
137
- if (child.stdout == null) {
138
- throw new Error(
139
- "stdout is null - this should never happen. Please open up an issue at https://github.com/facebook/metro",
140
- );
141
- }
142
- child.stdout.setEncoding("utf-8");
143
- child.stdout.on("data", (data) => (stdout += data));
144
- child.stdout.on("close", () => {
145
- const lines = stdout
146
- .trim()
147
- .split("\n")
148
- .filter((x) => !ignore(x));
149
- const result = new Map();
150
- let count = lines.length;
151
- if (!count) {
152
- callback(new Map());
153
- } else {
154
- lines.forEach((path) => {
155
- fs.lstat(path, (err, stat) => {
156
- if (!err && stat) {
157
- result.set(pathUtils.absoluteToNormal(path), [
158
- stat.mtime.getTime(),
159
- stat.size,
160
- 0,
161
- null,
162
- stat.isSymbolicLink() ? 1 : 0,
163
- null,
164
- ]);
165
- }
166
- if (--count === 0) {
167
- callback(result);
168
- }
169
- });
170
- });
171
- }
172
- });
173
- }
174
109
  async function nodeCrawl(options) {
175
110
  const {
176
111
  console,
177
112
  previousState,
178
113
  extensions,
179
- forceNodeFilesystemAPI,
180
114
  ignore,
181
115
  rootDir,
182
116
  includeSymlinks,
@@ -187,11 +121,6 @@ async function nodeCrawl(options) {
187
121
  } = options;
188
122
  abortSignal?.throwIfAborted();
189
123
  perfLogger?.point("nodeCrawl_start");
190
- const useNativeFind =
191
- !forceNodeFilesystemAPI &&
192
- (0, _os.platform)() !== "win32" &&
193
- (await (0, _hasNativeFindSupport.default)());
194
- debug("Using system find: %s", useNativeFind);
195
124
  return new Promise((resolve, reject) => {
196
125
  const callback = (fileData) => {
197
126
  const difference = previousState.fileSystem.getDifference(fileData, {
@@ -205,26 +134,14 @@ async function nodeCrawl(options) {
205
134
  }
206
135
  resolve(difference);
207
136
  };
208
- if (useNativeFind) {
209
- findNative(
210
- roots,
211
- extensions,
212
- ignore,
213
- includeSymlinks,
214
- rootDir,
215
- console,
216
- callback,
217
- );
218
- } else {
219
- find(
220
- roots,
221
- extensions,
222
- ignore,
223
- includeSymlinks,
224
- rootDir,
225
- console,
226
- callback,
227
- );
228
- }
137
+ find(
138
+ roots,
139
+ extensions,
140
+ ignore,
141
+ includeSymlinks,
142
+ rootDir,
143
+ console,
144
+ callback,
145
+ );
229
146
  });
230
147
  }
@@ -18,15 +18,9 @@ import type {
18
18
  } from '../../flow-types';
19
19
 
20
20
  import {RootPathUtils} from '../../lib/RootPathUtils';
21
- import hasNativeFindSupport from './hasNativeFindSupport';
22
- import {spawn} from 'child_process';
23
21
  import * as fs from 'graceful-fs';
24
- import {platform} from 'os';
25
22
  import * as path from 'path';
26
23
 
27
- // eslint-disable-next-line import/no-commonjs
28
- const debug = require('debug')('Metro:NodeCrawler');
29
-
30
24
  type Callback = (result: FileData) => void;
31
25
 
32
26
  function find(
@@ -106,70 +100,6 @@ function find(
106
100
  }
107
101
  }
108
102
 
109
- function findNative(
110
- roots: ReadonlyArray<string>,
111
- extensions: ReadonlyArray<string>,
112
- ignore: IgnoreMatcher,
113
- includeSymlinks: boolean,
114
- rootDir: string,
115
- console: Console,
116
- callback: Callback,
117
- ): void {
118
- // Examples:
119
- // ( ( -type f ( -iname *.js ) ) )
120
- // ( ( -type f ( -iname *.js -o -iname *.ts ) ) )
121
- // ( ( -type f ( -iname *.js ) ) -o -type l )
122
- // ( ( -type f ) -o -type l )
123
- const extensionClause = extensions.length
124
- ? `( ${extensions.map(ext => `-iname *.${ext}`).join(' -o ')} )`
125
- : ''; // Empty inner expressions eg "( )" are not allowed
126
- const expression = `( ( -type f ${extensionClause} ) ${
127
- includeSymlinks ? '-o -type l ' : ''
128
- })`;
129
-
130
- const pathUtils = new RootPathUtils(rootDir);
131
-
132
- const child = spawn('find', roots.concat(expression.split(' ')));
133
- let stdout = '';
134
- if (child.stdout == null) {
135
- throw new Error(
136
- 'stdout is null - this should never happen. Please open up an issue at https://github.com/facebook/metro',
137
- );
138
- }
139
- child.stdout.setEncoding('utf-8');
140
- child.stdout.on('data', data => (stdout += data));
141
-
142
- child.stdout.on('close', () => {
143
- const lines = stdout
144
- .trim()
145
- .split('\n')
146
- .filter(x => !ignore(x));
147
- const result: FileData = new Map();
148
- let count = lines.length;
149
- if (!count) {
150
- callback(new Map());
151
- } else {
152
- lines.forEach(path => {
153
- fs.lstat(path, (err, stat) => {
154
- if (!err && stat) {
155
- result.set(pathUtils.absoluteToNormal(path), [
156
- stat.mtime.getTime(),
157
- stat.size,
158
- 0,
159
- null,
160
- stat.isSymbolicLink() ? 1 : 0,
161
- null,
162
- ]);
163
- }
164
- if (--count === 0) {
165
- callback(result);
166
- }
167
- });
168
- });
169
- }
170
- });
171
- }
172
-
173
103
  export default async function nodeCrawl(
174
104
  options: CrawlerOptions,
175
105
  ): Promise<CrawlResult> {
@@ -177,7 +107,6 @@ export default async function nodeCrawl(
177
107
  console,
178
108
  previousState,
179
109
  extensions,
180
- forceNodeFilesystemAPI,
181
110
  ignore,
182
111
  rootDir,
183
112
  includeSymlinks,
@@ -190,12 +119,6 @@ export default async function nodeCrawl(
190
119
  abortSignal?.throwIfAborted();
191
120
 
192
121
  perfLogger?.point('nodeCrawl_start');
193
- const useNativeFind =
194
- !forceNodeFilesystemAPI &&
195
- platform() !== 'win32' &&
196
- (await hasNativeFindSupport());
197
-
198
- debug('Using system find: %s', useNativeFind);
199
122
 
200
123
  return new Promise((resolve, reject) => {
201
124
  const callback: Callback = fileData => {
@@ -214,26 +137,14 @@ export default async function nodeCrawl(
214
137
  resolve(difference);
215
138
  };
216
139
 
217
- if (useNativeFind) {
218
- findNative(
219
- roots,
220
- extensions,
221
- ignore,
222
- includeSymlinks,
223
- rootDir,
224
- console,
225
- callback,
226
- );
227
- } else {
228
- find(
229
- roots,
230
- extensions,
231
- ignore,
232
- includeSymlinks,
233
- rootDir,
234
- console,
235
- callback,
236
- );
237
- }
140
+ find(
141
+ roots,
142
+ extensions,
143
+ ignore,
144
+ includeSymlinks,
145
+ rootDir,
146
+ console,
147
+ callback,
148
+ );
238
149
  });
239
150
  }
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<b3646c81d37188726a1fc27777dcbede>>
9
+ * @generated SignedSource<<6ff16bb65883df0a1cb70e6ca94461eb>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro-file-map/src/flow-types.js
@@ -22,7 +22,6 @@ export type BuildParameters = Readonly<{
22
22
  computeSha1: boolean;
23
23
  enableSymlinks: boolean;
24
24
  extensions: ReadonlyArray<string>;
25
- forceNodeFilesystemAPI: boolean;
26
25
  ignorePattern: RegExp;
27
26
  plugins: ReadonlyArray<InputFileMapPlugin>;
28
27
  retainAllFiles: boolean;
@@ -95,7 +94,6 @@ export type CrawlerOptions = {
95
94
  computeSha1: boolean;
96
95
  console: Console;
97
96
  extensions: ReadonlyArray<string>;
98
- forceNodeFilesystemAPI: boolean;
99
97
  ignore: IgnoreMatcher;
100
98
  includeSymlinks: boolean;
101
99
  perfLogger?: null | undefined | PerfLogger;
@@ -192,12 +190,12 @@ export interface FileMapPlugin<
192
190
  }
193
191
  export type InputFileMapPlugin = FileMapPlugin<
194
192
  /**
195
- * > 235 | export type InputFileMapPlugin = FileMapPlugin<empty, empty>;
193
+ * > 233 | export type InputFileMapPlugin = FileMapPlugin<empty, empty>;
196
194
  * | ^^^^^ Unsupported feature: Translating "empty type" is currently not supported.
197
195
  **/
198
196
  any,
199
197
  /**
200
- * > 235 | export type InputFileMapPlugin = FileMapPlugin<empty, empty>;
198
+ * > 233 | export type InputFileMapPlugin = FileMapPlugin<empty, empty>;
201
199
  * | ^^^^^ Unsupported feature: Translating "empty type" is currently not supported.
202
200
  **/
203
201
  any
@@ -19,7 +19,6 @@ export type BuildParameters = Readonly<{
19
19
  computeSha1: boolean,
20
20
  enableSymlinks: boolean,
21
21
  extensions: ReadonlyArray<string>,
22
- forceNodeFilesystemAPI: boolean,
23
22
  ignorePattern: RegExp,
24
23
  plugins: ReadonlyArray<InputFileMapPlugin>,
25
24
  retainAllFiles: boolean,
@@ -114,7 +113,6 @@ export type CrawlerOptions = {
114
113
  computeSha1: boolean,
115
114
  console: Console,
116
115
  extensions: ReadonlyArray<string>,
117
- forceNodeFilesystemAPI: boolean,
118
116
  ignore: IgnoreMatcher,
119
117
  includeSymlinks: boolean,
120
118
  perfLogger?: ?PerfLogger,
@@ -171,8 +169,8 @@ export type DuplicatesSet = Map<string, /* type */ number>;
171
169
  export type DuplicatesIndex = Map<string, Map<string, DuplicatesSet>>;
172
170
 
173
171
  export type FileMapPluginInitOptions<
174
- +SerializableState,
175
- +PerFileData = void,
172
+ out SerializableState,
173
+ out PerFileData = void,
176
174
  > = Readonly<{
177
175
  files: Readonly<{
178
176
  fileIterator(
@@ -183,13 +181,13 @@ export type FileMapPluginInitOptions<
183
181
  ): Iterable<{
184
182
  baseName: string,
185
183
  canonicalPath: string,
186
- +pluginData: ?PerFileData,
184
+ readonly pluginData: ?PerFileData,
187
185
  }>,
188
186
  lookup(
189
187
  mixedPath: string,
190
188
  ):
191
189
  | {exists: false}
192
- | {exists: true, type: 'f', +pluginData: PerFileData}
190
+ | {exists: true, type: 'f', readonly pluginData: PerFileData}
193
191
  | {exists: true, type: 'd'},
194
192
  }>,
195
193
  pluginState: ?SerializableState,
@@ -214,10 +212,10 @@ export type V8Serializable =
214
212
  | Readonly<{[key: string]: V8Serializable}>;
215
213
 
216
214
  export interface FileMapPlugin<
217
- -SerializableState extends void | V8Serializable = void | V8Serializable,
218
- -PerFileData extends void | V8Serializable = void | V8Serializable,
215
+ in SerializableState extends void | V8Serializable = void | V8Serializable,
216
+ in PerFileData extends void | V8Serializable = void | V8Serializable,
219
217
  > {
220
- +name: string;
218
+ readonly name: string;
221
219
  initialize(
222
220
  initOptions: FileMapPluginInitOptions<SerializableState, PerFileData>,
223
221
  ): Promise<void>;
@@ -461,13 +459,13 @@ export interface FileSystemListener {
461
459
  fileRemoved(canonicalPath: CanonicalPath, data: FileMetadata): void;
462
460
  }
463
461
 
464
- export interface ReadonlyFileSystemChanges<+T = FileMetadata> {
465
- +addedDirectories: Iterable<CanonicalPath>;
466
- +removedDirectories: Iterable<CanonicalPath>;
462
+ export interface ReadonlyFileSystemChanges<out T = FileMetadata> {
463
+ readonly addedDirectories: Iterable<CanonicalPath>;
464
+ readonly removedDirectories: Iterable<CanonicalPath>;
467
465
 
468
- +addedFiles: Iterable<Readonly<[CanonicalPath, T]>>;
469
- +modifiedFiles: Iterable<Readonly<[CanonicalPath, T]>>;
470
- +removedFiles: Iterable<Readonly<[CanonicalPath, T]>>;
466
+ readonly addedFiles: Iterable<Readonly<[CanonicalPath, T]>>;
467
+ readonly modifiedFiles: Iterable<Readonly<[CanonicalPath, T]>>;
468
+ readonly removedFiles: Iterable<Readonly<[CanonicalPath, T]>>;
471
469
  }
472
470
 
473
471
  export interface MutableFileSystem extends FileSystem {
package/src/index.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<806d228988308075b7a911c3dfb513d3>>
9
+ * @generated SignedSource<<220686ad19cc94bec3b8d89f49fa6304>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro-file-map/src/index.js
@@ -49,7 +49,6 @@ export type InputOptions = Readonly<{
49
49
  computeSha1?: null | undefined | boolean;
50
50
  enableSymlinks?: null | undefined | boolean;
51
51
  extensions: ReadonlyArray<string>;
52
- forceNodeFilesystemAPI?: null | undefined | boolean;
53
52
  ignorePattern?: null | undefined | RegExp;
54
53
  plugins?: ReadonlyArray<InputFileMapPlugin>;
55
54
  retainAllFiles: boolean;
package/src/index.js CHANGED
@@ -164,7 +164,6 @@ class FileMap extends _events.default {
164
164
  computeSha1: options.computeSha1 || false,
165
165
  enableSymlinks: options.enableSymlinks || false,
166
166
  extensions: options.extensions,
167
- forceNodeFilesystemAPI: !!options.forceNodeFilesystemAPI,
168
167
  ignorePattern,
169
168
  plugins,
170
169
  retainAllFiles: options.retainAllFiles,
@@ -335,7 +334,6 @@ class FileMap extends _events.default {
335
334
  computeSha1,
336
335
  enableSymlinks,
337
336
  extensions,
338
- forceNodeFilesystemAPI,
339
337
  ignorePattern,
340
338
  retainAllFiles,
341
339
  roots,
@@ -349,7 +347,6 @@ class FileMap extends _events.default {
349
347
  console: this.#console,
350
348
  enableSymlinks,
351
349
  extensions,
352
- forceNodeFilesystemAPI,
353
350
  healthCheckFilePrefix: this.#options.healthCheck.filePrefix,
354
351
  ignoreForCrawl: (filePath) => {
355
352
  const ignoreMatched = ignorePattern.test(filePath);
package/src/index.js.flow CHANGED
@@ -78,7 +78,6 @@ export type InputOptions = Readonly<{
78
78
  computeSha1?: ?boolean,
79
79
  enableSymlinks?: ?boolean,
80
80
  extensions: ReadonlyArray<string>,
81
- forceNodeFilesystemAPI?: ?boolean,
82
81
  ignorePattern?: ?RegExp,
83
82
  plugins?: ReadonlyArray<InputFileMapPlugin>,
84
83
  retainAllFiles: boolean,
@@ -249,18 +248,18 @@ const WATCHMAN_REQUIRED_CAPABILITIES = [
249
248
  */
250
249
  export default class FileMap extends EventEmitter {
251
250
  #buildPromise: ?Promise<BuildResult>;
252
- +#cacheManager: CacheManager;
251
+ readonly #cacheManager: CacheManager;
253
252
  #canUseWatchmanPromise: Promise<boolean>;
254
253
  #changeID: number;
255
254
  #changeInterval: ?IntervalID;
256
- +#console: Console;
257
- +#crawlerAbortController: AbortController;
258
- +#fileProcessor: FileProcessor;
255
+ readonly #console: Console;
256
+ readonly #crawlerAbortController: AbortController;
257
+ readonly #fileProcessor: FileProcessor;
259
258
  #healthCheckInterval: ?IntervalID;
260
- +#options: InternalOptions;
261
- +#pathUtils: RootPathUtils;
262
- +#plugins: ReadonlyArray<IndexedPlugin>;
263
- +#startupPerfLogger: ?PerfLogger;
259
+ readonly #options: InternalOptions;
260
+ readonly #pathUtils: RootPathUtils;
261
+ readonly #plugins: ReadonlyArray<IndexedPlugin>;
262
+ readonly #startupPerfLogger: ?PerfLogger;
264
263
  #watcher: ?Watcher;
265
264
 
266
265
  static create(options: InputOptions): FileMap {
@@ -318,7 +317,6 @@ export default class FileMap extends EventEmitter {
318
317
  computeSha1: options.computeSha1 || false,
319
318
  enableSymlinks: options.enableSymlinks || false,
320
319
  extensions: options.extensions,
321
- forceNodeFilesystemAPI: !!options.forceNodeFilesystemAPI,
322
320
  ignorePattern,
323
321
  plugins,
324
322
  retainAllFiles: options.retainAllFiles,
@@ -515,7 +513,6 @@ export default class FileMap extends EventEmitter {
515
513
  computeSha1,
516
514
  enableSymlinks,
517
515
  extensions,
518
- forceNodeFilesystemAPI,
519
516
  ignorePattern,
520
517
  retainAllFiles,
521
518
  roots,
@@ -530,7 +527,6 @@ export default class FileMap extends EventEmitter {
530
527
  console: this.#console,
531
528
  enableSymlinks,
532
529
  extensions,
533
- forceNodeFilesystemAPI,
534
530
  healthCheckFilePrefix: this.#options.healthCheck.filePrefix,
535
531
  // TODO: Refactor out the two different ignore strategies here.
536
532
  ignoreForCrawl: filePath => {
@@ -40,8 +40,8 @@ type ProcessFileRequest = Readonly<{
40
40
  }>;
41
41
 
42
42
  interface AsyncWorker {
43
- +processFile: WorkerMessage => Promise<WorkerMetadata>;
44
- +end: () => Promise<void>;
43
+ readonly processFile: WorkerMessage => Promise<WorkerMetadata>;
44
+ readonly end: () => Promise<void>;
45
45
  }
46
46
 
47
47
  interface MaybeCodedError extends Error {
@@ -18,16 +18,16 @@ import type {
18
18
 
19
19
  export class FileSystemChangeAggregator implements FileSystemListener {
20
20
  // Mutually exclusive with removedDirectories
21
- +#addedDirectories: Set<CanonicalPath> = new Set();
21
+ readonly #addedDirectories: Set<CanonicalPath> = new Set();
22
22
  // Mutually exclusive with addedDirectories
23
- +#removedDirectories: Set<CanonicalPath> = new Set();
23
+ readonly #removedDirectories: Set<CanonicalPath> = new Set();
24
24
 
25
25
  // Mutually exclusive with modified and removed files
26
- +#addedFiles: Map<CanonicalPath, FileMetadata> = new Map();
26
+ readonly #addedFiles: Map<CanonicalPath, FileMetadata> = new Map();
27
27
  // Mutually exclusive with added and removed files
28
- +#modifiedFiles: Map<CanonicalPath, FileMetadata> = new Map();
28
+ readonly #modifiedFiles: Map<CanonicalPath, FileMetadata> = new Map();
29
29
  // Mutually exclusive with added and modified files
30
- +#removedFiles: Map<CanonicalPath, FileMetadata> = new Map();
30
+ readonly #removedFiles: Map<CanonicalPath, FileMetadata> = new Map();
31
31
 
32
32
  // Removed files must be paired with the file's metadata the last time it was
33
33
  // observable by consumers - ie, immediately *before* this batch. To report
@@ -36,7 +36,7 @@ export class FileSystemChangeAggregator implements FileSystemListener {
36
36
  // re-added, modified and removed again, we still have the initial metadata.
37
37
  // This is particularly important if, say, a regular file is replaced by a
38
38
  // symlink, or vice-versa.
39
- +#initialMetadata: Map<CanonicalPath, FileMetadata> = new Map();
39
+ readonly #initialMetadata: Map<CanonicalPath, FileMetadata> = new Map();
40
40
 
41
41
  directoryAdded(canonicalPath: CanonicalPath): void {
42
42
  // Only add to newDirectories if this directory wasn't previously removed
@@ -40,6 +40,8 @@ const UP_FRAGMENT_SEP = ".." + path.sep;
40
40
  const SEP_UP_FRAGMENT = path.sep + "..";
41
41
  const UP_FRAGMENT_SEP_LENGTH = UP_FRAGMENT_SEP.length;
42
42
  const CURRENT_FRAGMENT = "." + path.sep;
43
+ const IS_WIN32 = path.sep === "\\";
44
+ const ROOT_BASE_IDX = IS_WIN32 ? 0 : 1;
43
45
  class RootPathUtils {
44
46
  #rootDir;
45
47
  #rootDirnames;
@@ -114,6 +116,8 @@ class RootPathUtils {
114
116
  const right = pos === 0 ? normalPath : normalPath.slice(pos);
115
117
  if (right.length === 0) {
116
118
  return left;
119
+ } else if (IS_WIN32 && pos > this.#rootDepth * UP_FRAGMENT_SEP_LENGTH) {
120
+ return right;
117
121
  }
118
122
  if (i === this.#rootDepth) {
119
123
  return left + right;
@@ -152,7 +156,9 @@ class RootPathUtils {
152
156
  normalPath,
153
157
  };
154
158
  }
155
- const left = normalPath + path.sep;
159
+ const left = normalPath.endsWith(path.sep)
160
+ ? normalPath
161
+ : normalPath + path.sep;
156
162
  const rawPath = left + relativePath;
157
163
  if (normalPath === ".." || normalPath.endsWith(SEP_UP_FRAGMENT)) {
158
164
  const collapsed = this.#tryCollapseIndirectionsInSuffix(rawPath, 0, 0);
@@ -230,7 +236,7 @@ class RootPathUtils {
230
236
  collapsedSegments,
231
237
  };
232
238
  }
233
- if (totalUpIndirections < this.#rootParts.length - 1) {
239
+ if (totalUpIndirections < this.#rootParts.length - ROOT_BASE_IDX) {
234
240
  totalUpIndirections++;
235
241
  }
236
242
  if (nextIndirection !== pos + 1 || fullPath[pos] !== ".") {
@@ -46,6 +46,9 @@ const SEP_UP_FRAGMENT = path.sep + '..';
46
46
  const UP_FRAGMENT_SEP_LENGTH = UP_FRAGMENT_SEP.length;
47
47
  const CURRENT_FRAGMENT = '.' + path.sep;
48
48
 
49
+ const IS_WIN32 = path.sep === '\\';
50
+ const ROOT_BASE_IDX = IS_WIN32 ? 0 : 1;
51
+
49
52
  export class RootPathUtils {
50
53
  #rootDir: string;
51
54
  #rootDirnames: ReadonlyArray<string>;
@@ -149,6 +152,12 @@ export class RootPathUtils {
149
152
  const right = pos === 0 ? normalPath : normalPath.slice(pos);
150
153
  if (right.length === 0) {
151
154
  return left;
155
+ } else if (IS_WIN32 && pos > this.#rootDepth * UP_FRAGMENT_SEP_LENGTH) {
156
+ // On a real file system, navigating to `..` at the top level (posix `/`
157
+ // or Windows drive) is a no-op, but we can't respect that on Windows
158
+ // because Metro uses e.g. `..\..\D:\foo` to represent cross-drive
159
+ // relative paths.
160
+ return right;
152
161
  }
153
162
  // left may already end in a path separator only if it is a filesystem root,
154
163
  // '/' or 'X:\'.
@@ -198,7 +207,9 @@ export class RootPathUtils {
198
207
  if (relativePath === '') {
199
208
  return {collapsedSegments: 0, normalPath};
200
209
  }
201
- const left = normalPath + path.sep;
210
+ const left = normalPath.endsWith(path.sep)
211
+ ? normalPath
212
+ : normalPath + path.sep;
202
213
  const rawPath = left + relativePath;
203
214
  if (normalPath === '..' || normalPath.endsWith(SEP_UP_FRAGMENT)) {
204
215
  const collapsed = this.#tryCollapseIndirectionsInSuffix(rawPath, 0, 0);
@@ -299,9 +310,10 @@ export class RootPathUtils {
299
310
  };
300
311
  }
301
312
 
302
- // Cap the number of indirections at the total number of root segments.
303
- // File systems treat '..' at the root as '.'.
304
- if (totalUpIndirections < this.#rootParts.length - 1) {
313
+ // Cap the number of indirections at the total number of root parts.
314
+ // File systems treat '..' at the root as '.'. For Windows, cross-device
315
+ // paths need to survive this.
316
+ if (totalUpIndirections < this.#rootParts.length - ROOT_BASE_IDX) {
305
317
  totalUpIndirections++;
306
318
  }
307
319
 
package/src/lib/TreeFS.js CHANGED
@@ -341,6 +341,9 @@ class TreeFS {
341
341
  }
342
342
  remove(mixedPath, changeListener) {
343
343
  const normalPath = this.#normalizePath(mixedPath);
344
+ this.#removeNormalPath(normalPath, changeListener);
345
+ }
346
+ #removeNormalPath(normalPath, changeListener) {
344
347
  const result = this.#lookupByNormalPath(normalPath, {
345
348
  followLeaf: false,
346
349
  });
@@ -350,7 +353,7 @@ class TreeFS {
350
353
  const { parentNode, canonicalPath, node } = result;
351
354
  if (isDirectory(node) && node.size > 0) {
352
355
  for (const basename of node.keys()) {
353
- this.remove(
356
+ this.#removeNormalPath(
354
357
  canonicalPath + _path.default.sep + basename,
355
358
  changeListener,
356
359
  );
@@ -367,7 +370,10 @@ class TreeFS {
367
370
  }
368
371
  parentNode.delete(_path.default.basename(canonicalPath));
369
372
  if (parentNode.size === 0 && parentNode !== this.#rootNode) {
370
- this.remove(_path.default.dirname(canonicalPath), changeListener);
373
+ this.#removeNormalPath(
374
+ _path.default.dirname(canonicalPath),
375
+ changeListener,
376
+ );
371
377
  }
372
378
  }
373
379
  }
@@ -831,14 +837,16 @@ class TreeFS {
831
837
  typeof literalSymlinkTarget === "string",
832
838
  "Expected symlink target to be populated.",
833
839
  );
834
- const absoluteSymlinkTarget = _path.default.resolve(
840
+ let absoluteSymlinkTarget = _path.default.resolve(
835
841
  this.#rootDir,
836
842
  canonicalPathOfSymlink,
837
843
  "..",
838
844
  literalSymlinkTarget,
839
845
  );
840
- const normalSymlinkTarget = _path.default.relative(
841
- this.#rootDir,
846
+ if (absoluteSymlinkTarget.endsWith(_path.default.sep)) {
847
+ absoluteSymlinkTarget = absoluteSymlinkTarget.slice(0, -1);
848
+ }
849
+ const normalSymlinkTarget = this.#pathUtils.absoluteToNormal(
842
850
  absoluteSymlinkTarget,
843
851
  );
844
852
  const result = {
@@ -124,11 +124,13 @@ type MetadataIteratorOptions = Readonly<{
124
124
  * a trailing slash
125
125
  */
126
126
  export default class TreeFS implements MutableFileSystem {
127
- +#cachedNormalSymlinkTargets: WeakMap<FileNode, NormalizedSymlinkTarget> =
128
- new WeakMap();
129
- +#pathUtils: RootPathUtils;
130
- +#processFile: ProcessFileFunction;
131
- +#rootDir: Path;
127
+ readonly #cachedNormalSymlinkTargets: WeakMap<
128
+ FileNode,
129
+ NormalizedSymlinkTarget,
130
+ > = new WeakMap();
131
+ readonly #pathUtils: RootPathUtils;
132
+ readonly #processFile: ProcessFileFunction;
133
+ readonly #rootDir: Path;
132
134
  #rootNode: DirectoryNode = new Map();
133
135
 
134
136
  constructor(opts: TreeFSOptions) {
@@ -493,6 +495,13 @@ export default class TreeFS implements MutableFileSystem {
493
495
 
494
496
  remove(mixedPath: Path, changeListener?: FileSystemListener): void {
495
497
  const normalPath = this.#normalizePath(mixedPath);
498
+ this.#removeNormalPath(normalPath, changeListener);
499
+ }
500
+
501
+ #removeNormalPath(
502
+ normalPath: string,
503
+ changeListener?: FileSystemListener,
504
+ ): void {
496
505
  const result = this.#lookupByNormalPath(normalPath, {followLeaf: false});
497
506
  if (!result.exists) {
498
507
  return;
@@ -501,7 +510,10 @@ export default class TreeFS implements MutableFileSystem {
501
510
 
502
511
  if (isDirectory(node) && node.size > 0) {
503
512
  for (const basename of node.keys()) {
504
- this.remove(canonicalPath + path.sep + basename, changeListener);
513
+ this.#removeNormalPath(
514
+ canonicalPath + path.sep + basename,
515
+ changeListener,
516
+ );
505
517
  }
506
518
  // Removing the last file will delete this directory
507
519
  return;
@@ -521,7 +533,7 @@ export default class TreeFS implements MutableFileSystem {
521
533
  // that's not expected to be a case common enough to justify
522
534
  // implementation complexity, or slowing down more common uses of
523
535
  // _lookupByNormalPath.
524
- this.remove(path.dirname(canonicalPath), changeListener);
536
+ this.#removeNormalPath(path.dirname(canonicalPath), changeListener);
525
537
  }
526
538
  }
527
539
  }
@@ -1224,16 +1236,19 @@ export default class TreeFS implements MutableFileSystem {
1224
1236
  typeof literalSymlinkTarget === 'string',
1225
1237
  'Expected symlink target to be populated.',
1226
1238
  );
1227
- const absoluteSymlinkTarget = path.resolve(
1239
+ let absoluteSymlinkTarget = path.resolve(
1228
1240
  this.#rootDir,
1229
1241
  canonicalPathOfSymlink,
1230
1242
  '..', // Symlink target is relative to its containing directory.
1231
1243
  literalSymlinkTarget, // May be absolute, in which case the above are ignored
1232
1244
  );
1233
- const normalSymlinkTarget = path.relative(
1234
- this.#rootDir,
1245
+ if (absoluteSymlinkTarget.endsWith(path.sep)) {
1246
+ absoluteSymlinkTarget = absoluteSymlinkTarget.slice(0, -1);
1247
+ }
1248
+ const normalSymlinkTarget = this.#pathUtils.absoluteToNormal(
1235
1249
  absoluteSymlinkTarget,
1236
1250
  );
1251
+
1237
1252
  const result = {
1238
1253
  ancestorOfRootIdx:
1239
1254
  this.#pathUtils.getAncestorOfRootIdx(normalSymlinkTarget),
@@ -32,7 +32,6 @@ function rootRelativeCacheKeys(buildParameters) {
32
32
  case "extensions":
33
33
  case "computeSha1":
34
34
  case "enableSymlinks":
35
- case "forceNodeFilesystemAPI":
36
35
  case "retainAllFiles":
37
36
  return buildParameters[key] ?? null;
38
37
  case "ignorePattern":
@@ -39,7 +39,6 @@ export default function rootRelativeCacheKeys(
39
39
  case 'extensions':
40
40
  case 'computeSha1':
41
41
  case 'enableSymlinks':
42
- case 'forceNodeFilesystemAPI':
43
42
  case 'retainAllFiles':
44
43
  return buildParameters[key] ?? null;
45
44
  case 'ignorePattern':
@@ -16,8 +16,12 @@ class DependencyPlugin extends _FileDataPlugin.default {
16
16
  const { dependencyExtractor, computeDependencies } = options;
17
17
  let cacheKey;
18
18
  if (dependencyExtractor != null) {
19
- const extractor = require(dependencyExtractor);
20
- cacheKey = extractor.getCacheKey?.() ?? dependencyExtractor;
19
+ const mod = require(dependencyExtractor);
20
+ let getCacheKey = mod?.getCacheKey;
21
+ if (getCacheKey == null && mod?.__esModule === true) {
22
+ getCacheKey = mod.default?.getCacheKey;
23
+ }
24
+ cacheKey = getCacheKey?.() ?? dependencyExtractor;
21
25
  } else {
22
26
  cacheKey = "default-dependency-extractor";
23
27
  }
@@ -28,8 +28,13 @@ export default class DependencyPlugin extends FileDataPlugin<ReadonlyArray<strin
28
28
  let cacheKey: string;
29
29
  if (dependencyExtractor != null) {
30
30
  // $FlowFixMe[unsupported-syntax] - dynamic require
31
- const extractor = require(dependencyExtractor);
32
- cacheKey = extractor.getCacheKey?.() ?? dependencyExtractor;
31
+ const mod = require(dependencyExtractor);
32
+ let getCacheKey = mod?.getCacheKey; // CJS export or ESM named export
33
+ // Allow for getCacheKey as a prop of an ESM default export
34
+ if (getCacheKey == null && mod?.__esModule === true) {
35
+ getCacheKey = mod.default?.getCacheKey;
36
+ }
37
+ cacheKey = getCacheKey?.() ?? dependencyExtractor;
33
38
  } else {
34
39
  cacheKey = 'default-dependency-extractor';
35
40
  }
@@ -29,10 +29,10 @@ export type FileDataPluginOptions = Readonly<{
29
29
  * of lifecycle methods that subclasses can override as needed.
30
30
  */
31
31
  export default class FileDataPlugin<
32
- -PerFileData extends void | V8Serializable = void | V8Serializable,
32
+ in PerFileData extends void | V8Serializable = void | V8Serializable,
33
33
  > implements FileMapPlugin<null, PerFileData>
34
34
  {
35
- +name: string;
35
+ readonly name: string;
36
36
 
37
37
  #worker: FileMapPluginWorker;
38
38
  #cacheKey: string;
@@ -55,19 +55,19 @@ export type HasteMapOptions = Readonly<{
55
55
  export default class HastePlugin
56
56
  implements HasteMap, FileMapPlugin<null, string | null>
57
57
  {
58
- +name: 'haste' = 'haste';
58
+ readonly name: 'haste' = 'haste';
59
59
 
60
- +#console: ?Console;
61
- +#duplicates: DuplicatesIndex = new Map();
62
- +#enableHastePackages: boolean;
63
- +#failValidationOnConflicts: boolean;
60
+ readonly #console: ?Console;
61
+ readonly #duplicates: DuplicatesIndex = new Map();
62
+ readonly #enableHastePackages: boolean;
63
+ readonly #failValidationOnConflicts: boolean;
64
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;
65
+ readonly #hasteImplModulePath: ?string;
66
+ readonly #map: Map<string, HasteMapItem> = new Map();
67
+ readonly #pathUtils: RootPathUtils;
68
+ readonly #perfLogger: ?PerfLogger;
69
+ readonly #platforms: ReadonlySet<string>;
70
+ readonly #rootDir: Path;
71
71
 
72
72
  constructor(options: HasteMapOptions) {
73
73
  this.#console = options.console ?? global.console;
@@ -39,13 +39,13 @@ export type MockMapOptions = Readonly<{
39
39
  export default class MockPlugin
40
40
  implements FileMapPlugin<RawMockMap, void>, IMockMap
41
41
  {
42
- +name: 'mocks' = 'mocks';
42
+ readonly name: 'mocks' = 'mocks';
43
43
 
44
- +#mocksPattern: RegExp;
44
+ readonly #mocksPattern: RegExp;
45
45
  #raw: RawMockMap;
46
- +#rootDir: Path;
47
- +#pathUtils: RootPathUtils;
48
- +#console: typeof console;
46
+ readonly #rootDir: Path;
47
+ readonly #pathUtils: RootPathUtils;
48
+ readonly #console: typeof console;
49
49
  #throwOnModuleCollision: boolean;
50
50
 
51
51
  constructor({
@@ -5,7 +5,12 @@ module.exports = class DependencyExtractorWorker {
5
5
  #dependencyExtractor;
6
6
  constructor({ dependencyExtractor }) {
7
7
  if (dependencyExtractor != null) {
8
- this.#dependencyExtractor = require(dependencyExtractor);
8
+ const mod = require(dependencyExtractor);
9
+ let extract = mod?.extract;
10
+ if (extract == null && mod?.__esModule === true) {
11
+ extract = mod.default?.extract;
12
+ }
13
+ this.#dependencyExtractor = extract;
9
14
  }
10
15
  }
11
16
  processFile(data, utils) {
@@ -13,7 +18,7 @@ module.exports = class DependencyExtractorWorker {
13
18
  const { filePath } = data;
14
19
  const dependencies =
15
20
  this.#dependencyExtractor != null
16
- ? this.#dependencyExtractor.extract(
21
+ ? this.#dependencyExtractor(
17
22
  content,
18
23
  filePath,
19
24
  defaultDependencyExtractor.extract,
@@ -20,14 +20,19 @@ import type {MetadataWorker, WorkerMessage, V8Serializable, DependencyExtractor}
20
20
  */
21
21
 
22
22
  module.exports = class DependencyExtractorWorker /*:: implements MetadataWorker */ {
23
- /*:: + */ #dependencyExtractor /*: ?DependencyExtractor */;
23
+ /*:: readonly */ #dependencyExtractor /*: ?DependencyExtractor['extract'] */;
24
24
 
25
25
  constructor(
26
26
  {dependencyExtractor} /*: Readonly<{dependencyExtractor: ?string}> */,
27
27
  ) {
28
28
  if (dependencyExtractor != null) {
29
29
  // $FlowFixMe[unsupported-syntax] - dynamic require
30
- this.#dependencyExtractor = require(dependencyExtractor);
30
+ const mod = require(dependencyExtractor);
31
+ let extract = mod?.extract; // CJS export or ESM named export
32
+ if (extract == null && mod?.__esModule === true) {
33
+ extract = mod.default?.extract;
34
+ }
35
+ this.#dependencyExtractor = extract;
31
36
  }
32
37
  }
33
38
 
@@ -40,7 +45,7 @@ module.exports = class DependencyExtractorWorker /*:: implements MetadataWorker
40
45
 
41
46
  const dependencies =
42
47
  this.#dependencyExtractor != null
43
- ? this.#dependencyExtractor.extract(
48
+ ? this.#dependencyExtractor(
44
49
  content,
45
50
  filePath,
46
51
  defaultDependencyExtractor.extract,
@@ -7,7 +7,9 @@ module.exports = class Worker {
7
7
  #hasteImpl = null;
8
8
  constructor({ hasteImplModulePath }) {
9
9
  if (hasteImplModulePath != null) {
10
- this.#hasteImpl = require(hasteImplModulePath);
10
+ const mod = require(hasteImplModulePath);
11
+ this.#hasteImpl =
12
+ mod.__esModule === true && "default" in mod ? mod.default : mod;
11
13
  }
12
14
  }
13
15
  processFile(data, utils) {
@@ -22,7 +22,7 @@ import type {MetadataWorker, WorkerMessage, V8Serializable} from '../../flow-typ
22
22
  const PACKAGE_JSON = path.sep + 'package.json';
23
23
 
24
24
  module.exports = class Worker /*:: implements MetadataWorker */ {
25
- /*:: + */ #hasteImpl /*: ?Readonly<{getHasteName: string => ?string}> */ =
25
+ /*:: readonly */ #hasteImpl /*: ?Readonly<{getHasteName: string => ?string}> */ =
26
26
  null;
27
27
 
28
28
  constructor(
@@ -30,7 +30,9 @@ module.exports = class Worker /*:: implements MetadataWorker */ {
30
30
  ) {
31
31
  if (hasteImplModulePath != null) {
32
32
  // $FlowFixMe[unsupported-syntax] - dynamic require
33
- this.#hasteImpl = require(hasteImplModulePath);
33
+ const mod = require(hasteImplModulePath);
34
+ this.#hasteImpl =
35
+ mod.__esModule === true && 'default' in mod ? mod.default : mod;
34
36
  }
35
37
  }
36
38
 
@@ -24,11 +24,11 @@ export type Listeners = Readonly<{
24
24
  }>;
25
25
 
26
26
  export class AbstractWatcher implements WatcherBackend {
27
- +root: string;
28
- +ignored: ?RegExp;
29
- +globs: ReadonlyArray<string>;
30
- +dot: boolean;
31
- +doIgnore: (path: string) => boolean;
27
+ readonly root: string;
28
+ readonly ignored: ?RegExp;
29
+ readonly globs: ReadonlyArray<string>;
30
+ readonly dot: boolean;
31
+ readonly doIgnore: (path: string) => boolean;
32
32
 
33
33
  #emitter: EventEmitter = new EventEmitter();
34
34
 
@@ -42,12 +42,13 @@ const DELETE_EVENT = common.DELETE_EVENT;
42
42
  const DEBOUNCE_MS = 100;
43
43
 
44
44
  export default class FallbackWatcher extends AbstractWatcher {
45
- +#changeTimers: Map<string, TimeoutID> = new Map();
46
- +#dirRegistry: {
45
+ readonly #changeTimers: Map<string, TimeoutID> = new Map();
46
+ readonly #dirRegistry: {
47
47
  [directory: string]: {[file: string]: true, __proto__: null},
48
48
  __proto__: null,
49
49
  } = Object.create(null);
50
- +#watched: {[key: string]: FSWatcher, __proto__: null} = Object.create(null);
50
+ readonly #watched: {[key: string]: FSWatcher, __proto__: null} =
51
+ Object.create(null);
51
52
 
52
53
  async startWatching(): Promise<void> {
53
54
  this.#watchdir(this.root);
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  * @noformat
8
- * @generated SignedSource<<b68c5620efd3f5bec83279059d0d1b4e>>
8
+ * @generated SignedSource<<6297e6ebfbeb2920f00b15cba9acbce2>>
9
9
  *
10
10
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
11
11
  * Original file: packages/metro-file-map/src/watchers/NativeWatcher.js
@@ -50,6 +50,5 @@ declare class NativeWatcher extends AbstractWatcher {
50
50
  * End watching.
51
51
  */
52
52
  stopWatching(): Promise<void>;
53
- _handleEvent(event: string, relativePath: string): void;
54
53
  }
55
54
  export default NativeWatcher;
@@ -41,12 +41,12 @@ const SUB_PREFIX = 'metro-file-map';
41
41
  */
42
42
  export default class WatchmanWatcher extends AbstractWatcher {
43
43
  #client: Client;
44
- +subscriptionName: string;
44
+ readonly subscriptionName: string;
45
45
  #watchProjectInfo: ?Readonly<{
46
46
  relativePath: string,
47
47
  root: string,
48
48
  }>;
49
- +#watchmanDeferStates: ReadonlyArray<string>;
49
+ readonly #watchmanDeferStates: ReadonlyArray<string>;
50
50
  #deferringStates: ?Set<string> = null;
51
51
 
52
52
  constructor(dir: string, opts: WatcherOptions) {
package/src/worker.js CHANGED
@@ -9,7 +9,9 @@ class Worker {
9
9
  #plugins;
10
10
  constructor({ plugins = [] }) {
11
11
  this.#plugins = plugins.map(({ modulePath, setupArgs }) => {
12
- const PluginWorker = require(modulePath);
12
+ const mod = require(modulePath);
13
+ const PluginWorker =
14
+ mod.__esModule === true && "default" in mod ? mod.default : mod;
13
15
  return new PluginWorker(setupArgs);
14
16
  });
15
17
  }
@@ -36,7 +36,9 @@ class Worker {
36
36
  constructor({plugins = []} /*: WorkerSetupArgs */) {
37
37
  this.#plugins = plugins.map(({modulePath, setupArgs}) => {
38
38
  // $FlowFixMe[unsupported-syntax] - dynamic require
39
- const PluginWorker = require(modulePath);
39
+ const mod = require(modulePath);
40
+ const PluginWorker =
41
+ mod.__esModule === true && 'default' in mod ? mod.default : mod;
40
42
  return new PluginWorker(setupArgs);
41
43
  });
42
44
  }
@@ -1,19 +0,0 @@
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
- * @noformat
8
- * @oncall react_native
9
- * @generated SignedSource<<8b6ff8a24f9156cd7991006c72edd296>>
10
- *
11
- * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
- * Original file: packages/metro-file-map/src/crawlers/node/hasNativeFindSupport.js
13
- * To regenerate, run:
14
- * js1 build metro-ts-defs (internal) OR
15
- * yarn run build-ts-defs (OSS)
16
- */
17
-
18
- declare function hasNativeFindSupport(): Promise<boolean>;
19
- export default hasNativeFindSupport;
@@ -1,36 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true,
5
- });
6
- exports.default = hasNativeFindSupport;
7
- var _child_process = require("child_process");
8
- async function hasNativeFindSupport() {
9
- try {
10
- return await new Promise((resolve) => {
11
- const args = [
12
- ".",
13
- "-type",
14
- "f",
15
- "(",
16
- "-iname",
17
- "*.ts",
18
- "-o",
19
- "-iname",
20
- "*.js",
21
- ")",
22
- ];
23
- const child = (0, _child_process.spawn)("find", args, {
24
- cwd: __dirname,
25
- });
26
- child.on("error", () => {
27
- resolve(false);
28
- });
29
- child.on("exit", (code) => {
30
- resolve(code === 0);
31
- });
32
- });
33
- } catch {
34
- return false;
35
- }
36
- }
@@ -1,41 +0,0 @@
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
- import {spawn} from 'child_process';
13
-
14
- export default async function hasNativeFindSupport(): Promise<boolean> {
15
- try {
16
- return await new Promise(resolve => {
17
- // Check the find binary supports the non-POSIX -iname parameter wrapped in parens.
18
- const args = [
19
- '.',
20
- '-type',
21
- 'f',
22
- '(',
23
- '-iname',
24
- '*.ts',
25
- '-o',
26
- '-iname',
27
- '*.js',
28
- ')',
29
- ];
30
- const child = spawn('find', args, {cwd: __dirname});
31
- child.on('error', () => {
32
- resolve(false);
33
- });
34
- child.on('exit', code => {
35
- resolve(code === 0);
36
- });
37
- });
38
- } catch {
39
- return false;
40
- }
41
- }