metro 0.84.2 → 0.84.3

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.
@@ -18,7 +18,7 @@ import CountingSet from './CountingSet';
18
18
  import countLines from './countLines';
19
19
  import nullthrows from 'nullthrows';
20
20
 
21
- type Options<T: number | string> = Readonly<{
21
+ type Options<T extends number | string> = Readonly<{
22
22
  asyncRequireModulePath: string,
23
23
  createModuleId: string => T,
24
24
  getRunModuleStatement: (moduleId: T, globalPrefix: string) => string,
@@ -33,7 +33,7 @@ type Options<T: number | string> = Readonly<{
33
33
  ...
34
34
  }>;
35
35
 
36
- export default function getAppendScripts<T: number | string>(
36
+ export default function getAppendScripts<T extends number | string>(
37
37
  entryPoint: string,
38
38
  modules: ReadonlyArray<Module<>>,
39
39
  options: Options<T>,
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<d5224d8913b7e0c52ac84b215b356422>>
9
+ * @generated SignedSource<<0024fd05b95efe19a24f9acc84ff474b>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro/src/node-haste/DependencyGraph/ModuleResolution.js
@@ -32,19 +32,7 @@ import type {
32
32
  import type {PackageForModule, PackageJson} from 'metro-resolver/private/types';
33
33
 
34
34
  export type DirExistsFn = (filePath: string) => boolean;
35
- export type Packageish = {path: string; read(): PackageJson};
36
- export type Moduleish = {readonly path: string};
37
- export type PackageishCache<TPackage> = {
38
- getPackage(
39
- name: string,
40
- platform?: string,
41
- supportsNativePlatform?: boolean,
42
- ): TPackage;
43
- getPackageOf(
44
- absolutePath: string,
45
- ): null | undefined | {pkg: TPackage; packageRelativePath: string};
46
- };
47
- type Options<TPackage> = Readonly<{
35
+ type Options = Readonly<{
48
36
  assetExts: ReadonlySet<string>;
49
37
  dirExists: DirExistsFn;
50
38
  disableHierarchicalLookup: boolean;
@@ -61,7 +49,10 @@ type Options<TPackage> = Readonly<{
61
49
  platform: null | undefined | string,
62
50
  ) => null | undefined | string;
63
51
  mainFields: ReadonlyArray<string>;
64
- packageCache: PackageishCache<TPackage>;
52
+ getPackage: (packageJsonPath: string) => null | undefined | PackageJson;
53
+ getPackageForModule: (
54
+ absolutePath: string,
55
+ ) => null | undefined | PackageForModule;
65
56
  nodeModulesPaths: ReadonlyArray<string>;
66
57
  preferNativePlatform: boolean;
67
58
  projectRoot: string;
@@ -76,11 +67,11 @@ type Options<TPackage> = Readonly<{
76
67
  unstable_enablePackageExports: boolean;
77
68
  unstable_incrementalResolution: boolean;
78
69
  }>;
79
- export declare class ModuleResolver<TPackage extends Packageish> {
80
- _options: Options<TPackage>;
70
+ export declare class ModuleResolver {
71
+ _options: Options;
81
72
  _projectRootFakeModulePath: string;
82
73
  _cachedEmptyModule: null | undefined | BundlerResolution;
83
- constructor(options: Options<TPackage>);
74
+ constructor(options: Options);
84
75
  _getEmptyModule(): BundlerResolution;
85
76
  resolveDependency(
86
77
  originModulePath: string,
@@ -89,10 +80,6 @@ export declare class ModuleResolver<TPackage extends Packageish> {
89
80
  platform: string | null,
90
81
  resolverOptions: ResolverInputOptions,
91
82
  ): BundlerResolution;
92
- _getPackage: (packageJsonPath: string) => null | undefined | PackageJson;
93
- _getPackageForModule: (
94
- absolutePath: string,
95
- ) => null | undefined | PackageForModule;
96
83
  /**
97
84
  * TODO: Return Resolution instead of coercing to BundlerResolution here
98
85
  */
@@ -86,6 +86,8 @@ class ModuleResolver {
86
86
  doesFileExist,
87
87
  extraNodeModules,
88
88
  fileSystemLookup,
89
+ getPackage,
90
+ getPackageForModule,
89
91
  mainFields,
90
92
  nodeModulesPaths,
91
93
  preferNativePlatform,
@@ -109,9 +111,8 @@ class ModuleResolver {
109
111
  doesFileExist,
110
112
  extraNodeModules,
111
113
  fileSystemLookup,
112
- getPackage: this._getPackage,
113
- getPackageForModule: (absoluteModulePath) =>
114
- this._getPackageForModule(absoluteModulePath),
114
+ getPackage,
115
+ getPackageForModule,
115
116
  isESMImport: dependency.data.isESMImport,
116
117
  mainFields,
117
118
  nodeModulesPaths,
@@ -191,25 +192,6 @@ class ModuleResolver {
191
192
  throw error;
192
193
  }
193
194
  }
194
- _getPackage = (packageJsonPath) => {
195
- try {
196
- return this._options.packageCache.getPackage(packageJsonPath).read();
197
- } catch (e) {}
198
- return null;
199
- };
200
- _getPackageForModule = (absolutePath) => {
201
- let result;
202
- try {
203
- result = this._options.packageCache.getPackageOf(absolutePath);
204
- } catch (e) {}
205
- return result != null
206
- ? {
207
- packageJson: result.pkg.read(),
208
- packageRelativePath: result.packageRelativePath,
209
- rootPath: _path.default.dirname(result.pkg.path),
210
- }
211
- : null;
212
- };
213
195
  _getFileResolvedModule(resolution) {
214
196
  switch (resolution.type) {
215
197
  case "sourceFile":
@@ -35,28 +35,7 @@ import util from 'util';
35
35
 
36
36
  export type DirExistsFn = (filePath: string) => boolean;
37
37
 
38
- export type Packageish = interface {
39
- path: string,
40
- read(): PackageJson,
41
- };
42
-
43
- export type Moduleish = interface {
44
- +path: string,
45
- };
46
-
47
- export type PackageishCache<TPackage> = interface {
48
- getPackage(
49
- name: string,
50
- platform?: string,
51
- supportsNativePlatform?: boolean,
52
- ): TPackage,
53
- getPackageOf(absolutePath: string): ?{
54
- pkg: TPackage,
55
- packageRelativePath: string,
56
- },
57
- };
58
-
59
- type Options<TPackage> = Readonly<{
38
+ type Options = Readonly<{
60
39
  assetExts: ReadonlySet<string>,
61
40
  dirExists: DirExistsFn,
62
41
  disableHierarchicalLookup: boolean,
@@ -67,7 +46,8 @@ type Options<TPackage> = Readonly<{
67
46
  getHasteModulePath: (name: string, platform: ?string) => ?string,
68
47
  getHastePackagePath: (name: string, platform: ?string) => ?string,
69
48
  mainFields: ReadonlyArray<string>,
70
- packageCache: PackageishCache<TPackage>,
49
+ getPackage: (packageJsonPath: string) => ?PackageJson,
50
+ getPackageForModule: (absolutePath: string) => ?PackageForModule,
71
51
  nodeModulesPaths: ReadonlyArray<string>,
72
52
  preferNativePlatform: boolean,
73
53
  projectRoot: string,
@@ -83,14 +63,14 @@ type Options<TPackage> = Readonly<{
83
63
  unstable_incrementalResolution: boolean,
84
64
  }>;
85
65
 
86
- export class ModuleResolver<TPackage: Packageish> {
87
- _options: Options<TPackage>;
66
+ export class ModuleResolver {
67
+ _options: Options;
88
68
  // A module representing the project root, used as the origin when resolving `emptyModulePath`.
89
69
  _projectRootFakeModulePath: string;
90
70
  // An empty module, the result of resolving `emptyModulePath` from the project root.
91
71
  _cachedEmptyModule: ?BundlerResolution;
92
72
 
93
- constructor(options: Options<TPackage>) {
73
+ constructor(options: Options) {
94
74
  this._options = options;
95
75
  const {projectRoot} = this._options;
96
76
  this._projectRootFakeModulePath = path.join(projectRoot, '_');
@@ -132,6 +112,8 @@ export class ModuleResolver<TPackage: Packageish> {
132
112
  doesFileExist,
133
113
  extraNodeModules,
134
114
  fileSystemLookup,
115
+ getPackage,
116
+ getPackageForModule,
135
117
  mainFields,
136
118
  nodeModulesPaths,
137
119
  preferNativePlatform,
@@ -156,9 +138,8 @@ export class ModuleResolver<TPackage: Packageish> {
156
138
  doesFileExist,
157
139
  extraNodeModules,
158
140
  fileSystemLookup,
159
- getPackage: this._getPackage,
160
- getPackageForModule: (absoluteModulePath: string) =>
161
- this._getPackageForModule(absoluteModulePath),
141
+ getPackage,
142
+ getPackageForModule,
162
143
  isESMImport: dependency.data.isESMImport,
163
144
  mainFields,
164
145
  nodeModulesPaths,
@@ -240,36 +221,6 @@ export class ModuleResolver<TPackage: Packageish> {
240
221
  }
241
222
  }
242
223
 
243
- _getPackage = (packageJsonPath: string): ?PackageJson => {
244
- try {
245
- return this._options.packageCache.getPackage(packageJsonPath).read();
246
- } catch (e) {
247
- // Do nothing. The standard module cache does not trigger any error, but
248
- // the ModuleGraph one does, if the module does not exist.
249
- }
250
-
251
- return null;
252
- };
253
-
254
- _getPackageForModule = (absolutePath: string): ?PackageForModule => {
255
- let result;
256
-
257
- try {
258
- result = this._options.packageCache.getPackageOf(absolutePath);
259
- } catch (e) {
260
- // Do nothing. The standard module cache does not trigger any error, but
261
- // the ModuleGraph one does, if the module does not exist.
262
- }
263
-
264
- return result != null
265
- ? {
266
- packageJson: result.pkg.read(),
267
- packageRelativePath: result.packageRelativePath,
268
- rootPath: path.dirname(result.pkg.path),
269
- }
270
- : null;
271
- };
272
-
273
224
  /**
274
225
  * TODO: Return Resolution instead of coercing to BundlerResolution here
275
226
  */
@@ -71,7 +71,7 @@ function createFileMap(config, options) {
71
71
  const { enabled: autoSaveEnabled, ...autoSaveOpts } =
72
72
  config.watcher.unstable_autoSaveCache ?? {};
73
73
  const autoSave = watch && autoSaveEnabled ? autoSaveOpts : false;
74
- const plugins = [];
74
+ const plugins = [...(config.unstable_fileMapPlugins ?? [])];
75
75
  let dependencyPlugin = null;
76
76
  if (
77
77
  config.resolver.dependencyExtractor != null &&
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import type {ConfigT} from 'metro-config';
13
- import type {HasteMap} from 'metro-file-map';
13
+ import type {HasteMap, InputFileMapPlugin} from 'metro-file-map';
14
14
 
15
15
  import ci from 'ci-info';
16
16
  import MetroFileMap, {
@@ -75,7 +75,9 @@ export default function createFileMap(
75
75
  config.watcher.unstable_autoSaveCache ?? {};
76
76
  const autoSave = watch && autoSaveEnabled ? autoSaveOpts : false;
77
77
 
78
- const plugins: Array<DependencyPlugin | HastePlugin> = [];
78
+ const plugins: Array<InputFileMapPlugin> = [
79
+ ...(config.unstable_fileMapPlugins ?? []),
80
+ ];
79
81
 
80
82
  let dependencyPlugin = null;
81
83
  // Add DependencyPlugin if dependencies should be extracted
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<eb945b3566e9ed370894adaada197736>>
9
+ * @generated SignedSource<<13f1483d2a732241f8d9eae463399b0e>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro/src/node-haste/DependencyGraph.js
@@ -20,7 +20,6 @@ import type {
20
20
  TransformResultDependency,
21
21
  } from '../DeltaBundler/types';
22
22
  import type {ResolverInputOptions} from '../shared/types';
23
- import type Package from './Package';
24
23
  import type {ConfigT} from 'metro-config';
25
24
  import type {
26
25
  ChangeEvent,
@@ -32,7 +31,6 @@ import type {
32
31
  } from 'metro-file-map';
33
32
 
34
33
  import {ModuleResolver} from './DependencyGraph/ModuleResolution';
35
- import {PackageCache} from './PackageCache';
36
34
  import EventEmitter from 'events';
37
35
 
38
36
  declare class DependencyGraph extends EventEmitter {
@@ -40,7 +38,7 @@ declare class DependencyGraph extends EventEmitter {
40
38
  _haste: MetroFileMap;
41
39
  _fileSystem: FileSystem;
42
40
  _hasteMap: HasteMap;
43
- _moduleResolver: ModuleResolver<Package>;
41
+ _moduleResolver: ModuleResolver;
44
42
  _resolutionCache: Map<
45
43
  string | symbol,
46
44
  Map<
@@ -64,7 +62,6 @@ declare class DependencyGraph extends EventEmitter {
64
62
  _getClosestPackage(
65
63
  absoluteModulePath: string,
66
64
  ): null | undefined | {packageJsonPath: string; packageRelativePath: string};
67
- _createPackageCache(): PackageCache;
68
65
  getAllFiles(): Array<string>;
69
66
  /**
70
67
  * Used when watcher.unstable_lazySha1 is true
@@ -71,7 +71,10 @@ class DependencyGraph extends _events.default {
71
71
  this._onWatcherHealthCheck(result),
72
72
  );
73
73
  this._resolutionCache = new Map();
74
- this.#packageCache = this._createPackageCache();
74
+ this.#packageCache = new _PackageCache.PackageCache({
75
+ getClosestPackage: (absoluteModulePath) =>
76
+ this._getClosestPackage(absoluteModulePath),
77
+ });
75
78
  this._createModuleResolver();
76
79
  });
77
80
  }
@@ -90,10 +93,14 @@ class DependencyGraph extends _events.default {
90
93
  async ready() {
91
94
  await this._initializedPromise;
92
95
  }
93
- _onHasteChange({ eventsQueue }) {
96
+ _onHasteChange({ changes, rootDir }) {
94
97
  this._resolutionCache = new Map();
95
- eventsQueue.forEach(({ filePath }) =>
96
- this.#packageCache.invalidate(filePath),
98
+ [
99
+ ...changes.addedFiles,
100
+ ...changes.modifiedFiles,
101
+ ...changes.removedFiles,
102
+ ].forEach(([canonicalPath]) =>
103
+ this.#packageCache.invalidate(_path.default.join(rootDir, canonicalPath)),
97
104
  );
98
105
  this._createModuleResolver();
99
106
  this.emit("change");
@@ -130,9 +137,19 @@ class DependencyGraph extends _events.default {
130
137
  this._hasteMap.getModule(name, platform, true),
131
138
  getHastePackagePath: (name, platform) =>
132
139
  this._hasteMap.getPackage(name, platform, true),
140
+ getPackage: (packageJsonPath) => {
141
+ try {
142
+ return (
143
+ this.#packageCache.getPackage(packageJsonPath).packageJson ?? null
144
+ );
145
+ } catch {
146
+ return null;
147
+ }
148
+ },
149
+ getPackageForModule: (absolutePath) =>
150
+ this.#packageCache.getPackageForModule(absolutePath),
133
151
  mainFields: this._config.resolver.resolverMainFields,
134
152
  nodeModulesPaths: this._config.resolver.nodeModulesPaths,
135
- packageCache: this.#packageCache,
136
153
  preferNativePlatform: true,
137
154
  projectRoot: this._config.projectRoot,
138
155
  reporter: this._config.reporter,
@@ -176,12 +193,6 @@ class DependencyGraph extends _events.default {
176
193
  }
177
194
  : null;
178
195
  }
179
- _createPackageCache() {
180
- return new _PackageCache.PackageCache({
181
- getClosestPackage: (absolutePath) =>
182
- this._getClosestPackage(absolutePath),
183
- });
184
- }
185
196
  getAllFiles() {
186
197
  return (0, _nullthrows.default)(this._fileSystem).getAllFiles();
187
198
  }
@@ -14,7 +14,6 @@ import type {
14
14
  TransformResultDependency,
15
15
  } from '../DeltaBundler/types';
16
16
  import type {ResolverInputOptions} from '../shared/types';
17
- import type Package from './Package';
18
17
  import type {ConfigT} from 'metro-config';
19
18
  import type {
20
19
  ChangeEvent,
@@ -66,7 +65,7 @@ export default class DependencyGraph extends EventEmitter {
66
65
  #packageCache: PackageCache;
67
66
  _hasteMap: HasteMap;
68
67
  #dependencyPlugin: ?DependencyPlugin;
69
- _moduleResolver: ModuleResolver<Package>;
68
+ _moduleResolver: ModuleResolver;
70
69
  _resolutionCache: Map<
71
70
  // Custom resolver options
72
71
  string | symbol,
@@ -131,7 +130,10 @@ export default class DependencyGraph extends EventEmitter {
131
130
  this._onWatcherHealthCheck(result),
132
131
  );
133
132
  this._resolutionCache = new Map();
134
- this.#packageCache = this._createPackageCache();
133
+ this.#packageCache = new PackageCache({
134
+ getClosestPackage: absoluteModulePath =>
135
+ this._getClosestPackage(absoluteModulePath),
136
+ });
135
137
  this._createModuleResolver();
136
138
  });
137
139
  }
@@ -150,10 +152,14 @@ export default class DependencyGraph extends EventEmitter {
150
152
  await this._initializedPromise;
151
153
  }
152
154
 
153
- _onHasteChange({eventsQueue}: ChangeEvent) {
155
+ _onHasteChange({changes, rootDir}: ChangeEvent) {
154
156
  this._resolutionCache = new Map();
155
- eventsQueue.forEach(({filePath}) =>
156
- this.#packageCache.invalidate(filePath),
157
+ [
158
+ ...changes.addedFiles,
159
+ ...changes.modifiedFiles,
160
+ ...changes.removedFiles,
161
+ ].forEach(([canonicalPath]) =>
162
+ this.#packageCache.invalidate(path.join(rootDir, canonicalPath)),
157
163
  );
158
164
  this._createModuleResolver();
159
165
  this.emit('change');
@@ -190,9 +196,20 @@ export default class DependencyGraph extends EventEmitter {
190
196
  this._hasteMap.getModule(name, platform, true),
191
197
  getHastePackagePath: (name, platform) =>
192
198
  this._hasteMap.getPackage(name, platform, true),
199
+ getPackage: (packageJsonPath: string) => {
200
+ try {
201
+ return (
202
+ this.#packageCache.getPackage(packageJsonPath).packageJson ?? null
203
+ );
204
+ } catch {
205
+ // Non-existence or malformed JSON, we treat both as non-existent
206
+ return null;
207
+ }
208
+ },
209
+ getPackageForModule: (absolutePath: string) =>
210
+ this.#packageCache.getPackageForModule(absolutePath),
193
211
  mainFields: this._config.resolver.resolverMainFields,
194
212
  nodeModulesPaths: this._config.resolver.nodeModulesPaths,
195
- packageCache: this.#packageCache,
196
213
  preferNativePlatform: true,
197
214
  projectRoot: this._config.projectRoot,
198
215
  reporter: this._config.reporter,
@@ -241,12 +258,6 @@ export default class DependencyGraph extends EventEmitter {
241
258
  : null;
242
259
  }
243
260
 
244
- _createPackageCache(): PackageCache {
245
- return new PackageCache({
246
- getClosestPackage: absolutePath => this._getClosestPackage(absolutePath),
247
- });
248
- }
249
-
250
261
  getAllFiles(): Array<string> {
251
262
  return nullthrows(this._fileSystem).getAllFiles();
252
263
  }
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<eaea6d7e01d54353f700cdadd60c4bf2>>
9
+ * @generated SignedSource<<768dba0958b531c8edd43c2df24e25f6>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro/src/node-haste/PackageCache.js
@@ -15,27 +15,23 @@
15
15
  * yarn run build-ts-defs (OSS)
16
16
  */
17
17
 
18
- import Package from './Package';
18
+ import type {PackageJson} from 'metro-resolver/private/types';
19
19
 
20
20
  type GetClosestPackageFn = (
21
21
  absoluteFilePath: string,
22
22
  ) => null | undefined | {packageJsonPath: string; packageRelativePath: string};
23
+ type PackageForModule = Readonly<{
24
+ packageJson: PackageJson;
25
+ rootPath: string;
26
+ packageRelativePath: string;
27
+ }>;
23
28
  export declare class PackageCache {
24
- _getClosestPackage: GetClosestPackageFn;
25
- _packageCache: {[filePath: string]: Package};
26
- _packagePathAndSubpathByModulePath: {
27
- [filePath: string]:
28
- | null
29
- | undefined
30
- | {packageJsonPath: string; packageRelativePath: string};
31
- };
32
- _modulePathsByPackagePath: {
33
- [filePath: string]: Set<string>;
34
- };
35
29
  constructor(options: {getClosestPackage: GetClosestPackageFn});
36
- getPackage(filePath: string): Package;
37
- getPackageOf(
30
+ getPackage(
31
+ filePath: string,
32
+ ): Readonly<{rootPath: string; packageJson: PackageJson}>;
33
+ getPackageForModule(
38
34
  absoluteModulePath: string,
39
- ): null | undefined | {pkg: Package; packageRelativePath: string};
35
+ ): null | undefined | PackageForModule;
40
36
  invalidate(filePath: string): void;
41
37
  }
@@ -4,78 +4,89 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true,
5
5
  });
6
6
  exports.PackageCache = void 0;
7
- var _Package = _interopRequireDefault(require("./Package"));
8
- function _interopRequireDefault(e) {
9
- return e && e.__esModule ? e : { default: e };
10
- }
7
+ var _fs = require("fs");
8
+ var _path = require("path");
11
9
  class PackageCache {
10
+ #getClosestPackage;
11
+ #packageCache;
12
+ #resultByModulePath;
13
+ #modulePathsByPackagePath;
14
+ #modulePathsWithNoPackage;
12
15
  constructor(options) {
13
- this._getClosestPackage = options.getClosestPackage;
14
- this._packageCache = Object.create(null);
15
- this._packagePathAndSubpathByModulePath = Object.create(null);
16
- this._modulePathsByPackagePath = Object.create(null);
16
+ this.#getClosestPackage = options.getClosestPackage;
17
+ this.#packageCache = new Map();
18
+ this.#resultByModulePath = new Map();
19
+ this.#modulePathsByPackagePath = new Map();
20
+ this.#modulePathsWithNoPackage = new Set();
17
21
  }
18
22
  getPackage(filePath) {
19
- if (!this._packageCache[filePath]) {
20
- this._packageCache[filePath] = new _Package.default({
21
- file: filePath,
22
- });
23
+ let cached = this.#packageCache.get(filePath);
24
+ if (cached == null) {
25
+ cached = {
26
+ rootPath: (0, _path.dirname)(filePath),
27
+ packageJson: JSON.parse((0, _fs.readFileSync)(filePath, "utf8")),
28
+ };
29
+ this.#packageCache.set(filePath, cached);
23
30
  }
24
- return this._packageCache[filePath];
31
+ return cached;
25
32
  }
26
- getPackageOf(absoluteModulePath) {
27
- let packagePathAndSubpath =
28
- this._packagePathAndSubpathByModulePath[absoluteModulePath];
29
- if (
30
- packagePathAndSubpath &&
31
- this._packageCache[packagePathAndSubpath.packageJsonPath]
32
- ) {
33
- return {
34
- pkg: this._packageCache[packagePathAndSubpath.packageJsonPath],
35
- packageRelativePath: packagePathAndSubpath.packageRelativePath,
36
- };
33
+ getPackageForModule(absoluteModulePath) {
34
+ const cached = this.#resultByModulePath.get(absoluteModulePath);
35
+ if (cached !== undefined) {
36
+ return cached;
37
37
  }
38
- packagePathAndSubpath = this._getClosestPackage(absoluteModulePath);
39
- if (!packagePathAndSubpath) {
38
+ const closest = this.#getClosestPackage(absoluteModulePath);
39
+ if (closest == null) {
40
+ this.#resultByModulePath.set(absoluteModulePath, null);
41
+ this.#modulePathsWithNoPackage.add(absoluteModulePath);
40
42
  return null;
41
43
  }
42
- const packagePath = packagePathAndSubpath.packageJsonPath;
43
- this._packagePathAndSubpathByModulePath[absoluteModulePath] =
44
- packagePathAndSubpath;
45
- const modulePaths =
46
- this._modulePathsByPackagePath[packagePath] ?? new Set();
44
+ const packagePath = closest.packageJsonPath;
45
+ let modulePaths = this.#modulePathsByPackagePath.get(packagePath);
46
+ if (modulePaths == null) {
47
+ modulePaths = new Set();
48
+ this.#modulePathsByPackagePath.set(packagePath, modulePaths);
49
+ }
47
50
  modulePaths.add(absoluteModulePath);
48
- this._modulePathsByPackagePath[packagePath] = modulePaths;
49
- return {
50
- pkg: this.getPackage(packagePath),
51
- packageRelativePath: packagePathAndSubpath.packageRelativePath,
51
+ const pkg = this.getPackage(packagePath);
52
+ if (pkg == null) {
53
+ return null;
54
+ }
55
+ const result = {
56
+ packageJson: pkg.packageJson,
57
+ packageRelativePath: closest.packageRelativePath,
58
+ rootPath: pkg.rootPath,
52
59
  };
60
+ this.#resultByModulePath.set(absoluteModulePath, result);
61
+ return result;
53
62
  }
54
63
  invalidate(filePath) {
55
- if (this._packageCache[filePath]) {
56
- this._packageCache[filePath].invalidate();
57
- delete this._packageCache[filePath];
58
- }
59
- const packagePathAndSubpath =
60
- this._packagePathAndSubpathByModulePath[filePath];
61
- if (packagePathAndSubpath) {
62
- const packagePath = packagePathAndSubpath.packageJsonPath;
63
- delete this._packagePathAndSubpathByModulePath[filePath];
64
- const modulePaths = this._modulePathsByPackagePath[packagePath];
65
- if (modulePaths) {
66
- modulePaths.delete(filePath);
67
- if (modulePaths.size === 0) {
68
- delete this._modulePathsByPackagePath[packagePath];
64
+ this.#packageCache.delete(filePath);
65
+ const cachedResult = this.#resultByModulePath.get(filePath);
66
+ this.#resultByModulePath.delete(filePath);
67
+ this.#modulePathsWithNoPackage.delete(filePath);
68
+ if (cachedResult != null) {
69
+ const packagePath = cachedResult.rootPath + _path.sep + "package.json";
70
+ const modules = this.#modulePathsByPackagePath.get(packagePath);
71
+ if (modules != null) {
72
+ modules.delete(filePath);
73
+ if (modules.size === 0) {
74
+ this.#modulePathsByPackagePath.delete(packagePath);
69
75
  }
70
76
  }
71
77
  }
72
- if (this._modulePathsByPackagePath[filePath]) {
73
- const modulePaths = this._modulePathsByPackagePath[filePath];
78
+ const modulePaths = this.#modulePathsByPackagePath.get(filePath);
79
+ if (modulePaths != null) {
74
80
  for (const modulePath of modulePaths) {
75
- delete this._packagePathAndSubpathByModulePath[modulePath];
81
+ this.#resultByModulePath.delete(modulePath);
82
+ }
83
+ this.#modulePathsByPackagePath.delete(filePath);
84
+ }
85
+ if (filePath.endsWith(_path.sep + "package.json")) {
86
+ for (const modulePath of this.#modulePathsWithNoPackage) {
87
+ this.#resultByModulePath.delete(modulePath);
76
88
  }
77
- modulePaths.clear();
78
- delete this._modulePathsByPackagePath[filePath];
89
+ this.#modulePathsWithNoPackage.clear();
79
90
  }
80
91
  }
81
92
  }