metro-file-map 0.84.3 → 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 (41) 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.d.ts +5 -25
  22. package/src/plugins/DependencyPlugin.js +29 -45
  23. package/src/plugins/DependencyPlugin.js.flow +27 -85
  24. package/src/plugins/FileDataPlugin.d.ts +55 -0
  25. package/src/plugins/FileDataPlugin.js +41 -0
  26. package/src/plugins/FileDataPlugin.js.flow +76 -0
  27. package/src/plugins/HastePlugin.js.flow +11 -11
  28. package/src/plugins/MockPlugin.js.flow +5 -5
  29. package/src/plugins/dependencies/worker.js +7 -2
  30. package/src/plugins/dependencies/worker.js.flow +8 -3
  31. package/src/plugins/haste/worker.js +3 -1
  32. package/src/plugins/haste/worker.js.flow +4 -2
  33. package/src/watchers/AbstractWatcher.js.flow +5 -5
  34. package/src/watchers/FallbackWatcher.js.flow +4 -3
  35. package/src/watchers/NativeWatcher.d.ts +1 -2
  36. package/src/watchers/WatchmanWatcher.js.flow +2 -2
  37. package/src/worker.js +3 -1
  38. package/src/worker.js.flow +3 -1
  39. package/src/crawlers/node/hasNativeFindSupport.d.ts +0 -19
  40. package/src/crawlers/node/hasNativeFindSupport.js +0 -36
  41. package/src/crawlers/node/hasNativeFindSupport.js.flow +0 -41
@@ -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':
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<e07a9c061b0224fc44191d956461bd6f>>
9
+ * @generated SignedSource<<344b340710d6da24bcb609058e7ce8d6>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro-file-map/src/plugins/DependencyPlugin.js
@@ -15,38 +15,18 @@
15
15
  * yarn run build-ts-defs (OSS)
16
16
  */
17
17
 
18
- import type {
19
- FileMapPlugin,
20
- FileMapPluginInitOptions,
21
- FileMapPluginWorker,
22
- Path,
23
- } from '../flow-types';
18
+ import type {Path} from '../flow-types';
19
+
20
+ import FileDataPlugin from './FileDataPlugin';
24
21
 
25
22
  export type DependencyPluginOptions = Readonly<{
26
23
  /** Path to custom dependency extractor module */
27
24
  dependencyExtractor: null | undefined | string;
28
25
  /** Whether to compute dependencies (performance optimization) */
29
26
  computeDependencies: boolean;
30
- rootDir: Path;
31
27
  }>;
32
- declare class DependencyPlugin
33
- implements FileMapPlugin<null, ReadonlyArray<string> | null>
34
- {
35
- readonly name: 'dependencies';
28
+ declare class DependencyPlugin extends FileDataPlugin<ReadonlyArray<string> | null> {
36
29
  constructor(options: DependencyPluginOptions);
37
- initialize(
38
- initOptions: FileMapPluginInitOptions<null, ReadonlyArray<string> | null>,
39
- ): Promise<void>;
40
- getSerializableSnapshot(): null;
41
- onChanged(): void;
42
- assertValid(): void;
43
- getCacheKey(): string;
44
- getWorker(): FileMapPluginWorker;
45
- /**
46
- * Get the list of dependencies for a given file.
47
- * @param mixedPath Absolute or project-relative path to the file
48
- * @returns Array of dependency module names, or null if the file doesn't exist
49
- */
50
30
  getDependencies(mixedPath: Path): null | undefined | ReadonlyArray<string>;
51
31
  }
52
32
  export default DependencyPlugin;
@@ -4,70 +4,54 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true,
5
5
  });
6
6
  exports.default = void 0;
7
- class DependencyPlugin {
8
- name = "dependencies";
9
- #dependencyExtractor;
10
- #computeDependencies;
11
- #getDependencies;
12
- #rootDir;
7
+ var _workerExclusionList = _interopRequireDefault(
8
+ require("../workerExclusionList"),
9
+ );
10
+ var _FileDataPlugin = _interopRequireDefault(require("./FileDataPlugin"));
11
+ function _interopRequireDefault(e) {
12
+ return e && e.__esModule ? e : { default: e };
13
+ }
14
+ class DependencyPlugin extends _FileDataPlugin.default {
13
15
  constructor(options) {
14
- this.#dependencyExtractor = options.dependencyExtractor;
15
- this.#computeDependencies = options.computeDependencies;
16
- this.#rootDir = options.rootDir;
17
- }
18
- async initialize(initOptions) {
19
- const { files } = initOptions;
20
- this.#getDependencies = (mixedPath) => {
21
- const result = files.lookup(mixedPath);
22
- if (result.exists && result.type === "f") {
23
- return result.pluginData ?? [];
16
+ const { dependencyExtractor, computeDependencies } = options;
17
+ let cacheKey;
18
+ if (dependencyExtractor != null) {
19
+ const mod = require(dependencyExtractor);
20
+ let getCacheKey = mod?.getCacheKey;
21
+ if (getCacheKey == null && mod?.__esModule === true) {
22
+ getCacheKey = mod.default?.getCacheKey;
24
23
  }
25
- return null;
26
- };
27
- }
28
- getSerializableSnapshot() {
29
- return null;
30
- }
31
- onChanged() {}
32
- assertValid() {}
33
- getCacheKey() {
34
- if (this.#dependencyExtractor != null) {
35
- const extractor = require(this.#dependencyExtractor);
36
- return JSON.stringify({
37
- extractorKey: extractor.getCacheKey?.() ?? null,
38
- extractorPath: this.#dependencyExtractor,
39
- });
24
+ cacheKey = getCacheKey?.() ?? dependencyExtractor;
25
+ } else {
26
+ cacheKey = "default-dependency-extractor";
40
27
  }
41
- return "default-dependency-extractor";
42
- }
43
- getWorker() {
44
- const excludedExtensions = require("../workerExclusionList");
45
- return {
28
+ super({
29
+ name: "dependencies",
30
+ cacheKey,
46
31
  worker: {
47
32
  modulePath: require.resolve("./dependencies/worker.js"),
48
33
  setupArgs: {
49
- dependencyExtractor: this.#dependencyExtractor ?? null,
34
+ dependencyExtractor: dependencyExtractor ?? null,
50
35
  },
51
36
  },
52
37
  filter: ({ normalPath, isNodeModules }) => {
53
- if (!this.#computeDependencies) {
38
+ if (!computeDependencies) {
54
39
  return false;
55
40
  }
56
41
  if (isNodeModules) {
57
42
  return false;
58
43
  }
59
44
  const ext = normalPath.substr(normalPath.lastIndexOf("."));
60
- return !excludedExtensions.has(ext);
45
+ return !_workerExclusionList.default.has(ext);
61
46
  },
62
- };
47
+ });
63
48
  }
64
49
  getDependencies(mixedPath) {
65
- if (this.#getDependencies == null) {
66
- throw new Error(
67
- "DependencyPlugin has not been initialized before getDependencies",
68
- );
50
+ const result = this.getFileSystem().lookup(mixedPath);
51
+ if (result.exists && result.type === "f") {
52
+ return result.pluginData ?? [];
69
53
  }
70
- return this.#getDependencies(mixedPath);
54
+ return null;
71
55
  }
72
56
  }
73
57
  exports.default = DependencyPlugin;
@@ -9,121 +9,63 @@
9
9
  * @oncall react_native
10
10
  */
11
11
 
12
- import type {
13
- FileMapPlugin,
14
- FileMapPluginInitOptions,
15
- FileMapPluginWorker,
16
- Path,
17
- } from '../flow-types';
12
+ import type {Path} from '../flow-types';
13
+
14
+ import excludedExtensions from '../workerExclusionList';
15
+ import FileDataPlugin from './FileDataPlugin';
18
16
 
19
17
  export type DependencyPluginOptions = Readonly<{
20
18
  /** Path to custom dependency extractor module */
21
19
  dependencyExtractor: ?string,
22
20
  /** Whether to compute dependencies (performance optimization) */
23
21
  computeDependencies: boolean,
24
- rootDir: Path,
25
22
  }>;
26
23
 
27
- export default class DependencyPlugin
28
- implements FileMapPlugin<null, ReadonlyArray<string> | null>
29
- {
30
- +name: 'dependencies' = 'dependencies';
31
-
32
- #dependencyExtractor: ?string;
33
- #computeDependencies: boolean;
34
- #getDependencies: Path => ?ReadonlyArray<string>;
35
- #rootDir: Path;
36
-
24
+ export default class DependencyPlugin extends FileDataPlugin<ReadonlyArray<string> | null> {
37
25
  constructor(options: DependencyPluginOptions) {
38
- this.#dependencyExtractor = options.dependencyExtractor;
39
- this.#computeDependencies = options.computeDependencies;
40
- this.#rootDir = options.rootDir;
41
- }
42
-
43
- async initialize(
44
- initOptions: FileMapPluginInitOptions<null, ReadonlyArray<string> | null>,
45
- ): Promise<void> {
46
- const {files} = initOptions;
47
- // Create closure to access dependencies from file metadata plugin data
48
- this.#getDependencies = (mixedPath: Path) => {
49
- const result = files.lookup(mixedPath);
50
- if (result.exists && result.type === 'f') {
51
- // Backwards compatibility: distinguish an extant file that we've not
52
- // run the worker on (probably because it fails the extension filter)
53
- // from a missing file. Non-source files are expected to have empty
54
- // dependencies.
55
- return result.pluginData ?? [];
56
- }
57
- return null;
58
- };
59
- }
60
-
61
- getSerializableSnapshot(): null {
62
- // Dependencies stored in plugin data, no separate serialization needed
63
- return null;
64
- }
26
+ const {dependencyExtractor, computeDependencies} = options;
65
27
 
66
- onChanged(): void {
67
- // No-op: Worker already populated plugin data
68
- // Plugin data is write-only from worker
69
- }
70
-
71
- assertValid(): void {
72
- // No validation needed
73
- }
74
-
75
- getCacheKey(): string {
76
- if (this.#dependencyExtractor != null) {
77
- // Dynamic require to get extractor's cache key
28
+ let cacheKey: string;
29
+ if (dependencyExtractor != null) {
78
30
  // $FlowFixMe[unsupported-syntax] - dynamic require
79
- const extractor = require(this.#dependencyExtractor);
80
- return JSON.stringify({
81
- extractorKey: extractor.getCacheKey?.() ?? null,
82
- extractorPath: this.#dependencyExtractor,
83
- });
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;
38
+ } else {
39
+ cacheKey = 'default-dependency-extractor';
84
40
  }
85
- return 'default-dependency-extractor';
86
- }
87
-
88
- getWorker(): FileMapPluginWorker {
89
- const excludedExtensions = require('../workerExclusionList');
90
41
 
91
- return {
42
+ super({
43
+ name: 'dependencies',
44
+ cacheKey,
92
45
  worker: {
93
46
  modulePath: require.resolve('./dependencies/worker.js'),
94
47
  setupArgs: {
95
- dependencyExtractor: this.#dependencyExtractor ?? null,
48
+ dependencyExtractor: dependencyExtractor ?? null,
96
49
  },
97
50
  },
98
51
  filter: ({normalPath, isNodeModules}) => {
99
- // Respect computeDependencies flag
100
- if (!this.#computeDependencies) {
52
+ if (!computeDependencies) {
101
53
  return false;
102
54
  }
103
-
104
- // Never process node_modules
105
55
  if (isNodeModules) {
106
56
  return false;
107
57
  }
108
-
109
- // Skip excluded extensions
110
58
  const ext = normalPath.substr(normalPath.lastIndexOf('.'));
111
59
  return !excludedExtensions.has(ext);
112
60
  },
113
- };
61
+ });
114
62
  }
115
63
 
116
- /**
117
- * Get the list of dependencies for a given file.
118
- * @param mixedPath Absolute or project-relative path to the file
119
- * @returns Array of dependency module names, or null if the file doesn't exist
120
- */
121
64
  getDependencies(mixedPath: Path): ?ReadonlyArray<string> {
122
- if (this.#getDependencies == null) {
123
- throw new Error(
124
- 'DependencyPlugin has not been initialized before getDependencies',
125
- );
65
+ const result = this.getFileSystem().lookup(mixedPath);
66
+ if (result.exists && result.type === 'f') {
67
+ return result.pluginData ?? [];
126
68
  }
127
- return this.#getDependencies(mixedPath);
69
+ return null;
128
70
  }
129
71
  }
@@ -0,0 +1,55 @@
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<<8833f226ec9fa3a4c96370862ca4d59f>>
10
+ *
11
+ * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
+ * Original file: packages/metro-file-map/src/plugins/FileDataPlugin.js
13
+ * To regenerate, run:
14
+ * js1 build metro-ts-defs (internal) OR
15
+ * yarn run build-ts-defs (OSS)
16
+ */
17
+
18
+ import type {
19
+ FileMapPlugin,
20
+ FileMapPluginInitOptions,
21
+ FileMapPluginWorker,
22
+ ReadonlyFileSystemChanges,
23
+ V8Serializable,
24
+ } from '../flow-types';
25
+
26
+ export type FileDataPluginOptions = Readonly<
27
+ Omit<FileMapPluginWorker, keyof {name: string; cacheKey: string}> & {
28
+ name: string;
29
+ cacheKey: string;
30
+ }
31
+ >;
32
+ /**
33
+ * Base class for FileMap plugins that store per-file data via a worker and
34
+ * have no separate serializable state. Provides default no-op implementations
35
+ * of lifecycle methods that subclasses can override as needed.
36
+ */
37
+ declare class FileDataPlugin<
38
+ PerFileData extends void | V8Serializable = void | V8Serializable,
39
+ > implements FileMapPlugin<null, PerFileData>
40
+ {
41
+ readonly name: string;
42
+ constructor($$PARAM_0$$: FileDataPluginOptions);
43
+ initialize(
44
+ initOptions: FileMapPluginInitOptions<null, PerFileData>,
45
+ ): Promise<void>;
46
+ getFileSystem(): FileMapPluginInitOptions<null, PerFileData>['files'];
47
+ onChanged(
48
+ _changes: ReadonlyFileSystemChanges<null | undefined | PerFileData>,
49
+ ): void;
50
+ assertValid(): void;
51
+ getSerializableSnapshot(): null;
52
+ getCacheKey(): string;
53
+ getWorker(): FileMapPluginWorker;
54
+ }
55
+ export default FileDataPlugin;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ exports.default = void 0;
7
+ class FileDataPlugin {
8
+ #worker;
9
+ #cacheKey;
10
+ #files;
11
+ constructor({ name, worker, filter, cacheKey }) {
12
+ this.name = name;
13
+ this.#worker = {
14
+ worker,
15
+ filter,
16
+ };
17
+ this.#cacheKey = cacheKey;
18
+ }
19
+ async initialize(initOptions) {
20
+ this.#files = initOptions.files;
21
+ }
22
+ getFileSystem() {
23
+ const files = this.#files;
24
+ if (files == null) {
25
+ throw new Error(`${this.name} plugin has not been initialized`);
26
+ }
27
+ return files;
28
+ }
29
+ onChanged(_changes) {}
30
+ assertValid() {}
31
+ getSerializableSnapshot() {
32
+ return null;
33
+ }
34
+ getCacheKey() {
35
+ return this.#cacheKey;
36
+ }
37
+ getWorker() {
38
+ return this.#worker;
39
+ }
40
+ }
41
+ exports.default = FileDataPlugin;
@@ -0,0 +1,76 @@
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 type {
13
+ FileMapPlugin,
14
+ FileMapPluginInitOptions,
15
+ FileMapPluginWorker,
16
+ ReadonlyFileSystemChanges,
17
+ V8Serializable,
18
+ } from '../flow-types';
19
+
20
+ export type FileDataPluginOptions = Readonly<{
21
+ ...FileMapPluginWorker,
22
+ name: string,
23
+ cacheKey: string,
24
+ }>;
25
+
26
+ /**
27
+ * Base class for FileMap plugins that store per-file data via a worker and
28
+ * have no separate serializable state. Provides default no-op implementations
29
+ * of lifecycle methods that subclasses can override as needed.
30
+ */
31
+ export default class FileDataPlugin<
32
+ in PerFileData extends void | V8Serializable = void | V8Serializable,
33
+ > implements FileMapPlugin<null, PerFileData>
34
+ {
35
+ readonly name: string;
36
+
37
+ #worker: FileMapPluginWorker;
38
+ #cacheKey: string;
39
+ #files: ?FileMapPluginInitOptions<null, PerFileData>['files'];
40
+
41
+ constructor({name, worker, filter, cacheKey}: FileDataPluginOptions) {
42
+ this.name = name;
43
+ this.#worker = {worker, filter};
44
+ this.#cacheKey = cacheKey;
45
+ }
46
+
47
+ async initialize(
48
+ initOptions: FileMapPluginInitOptions<null, PerFileData>,
49
+ ): Promise<void> {
50
+ this.#files = initOptions.files;
51
+ }
52
+
53
+ getFileSystem(): FileMapPluginInitOptions<null, PerFileData>['files'] {
54
+ const files = this.#files;
55
+ if (files == null) {
56
+ throw new Error(`${this.name} plugin has not been initialized`);
57
+ }
58
+ return files;
59
+ }
60
+
61
+ onChanged(_changes: ReadonlyFileSystemChanges<?PerFileData>): void {}
62
+
63
+ assertValid(): void {}
64
+
65
+ getSerializableSnapshot(): null {
66
+ return null;
67
+ }
68
+
69
+ getCacheKey(): string {
70
+ return this.#cacheKey;
71
+ }
72
+
73
+ getWorker(): FileMapPluginWorker {
74
+ return this.#worker;
75
+ }
76
+ }