You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.3 KiB

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
* @oncall react_native
*/
"use strict";
const Module = require("./Module");
const Package = require("./Package");
class ModuleCache {
// Cache for "closest package.json" queries by module path.
// The inverse of _packagePathByModulePath.
constructor(options) {
this._getClosestPackage = options.getClosestPackage;
this._moduleCache = Object.create(null);
this._packageCache = Object.create(null);
this._packagePathByModulePath = Object.create(null);
this._modulePathsByPackagePath = Object.create(null);
}
getModule(filePath) {
if (!this._moduleCache[filePath]) {
this._moduleCache[filePath] = new Module(filePath, this);
}
return this._moduleCache[filePath];
}
getPackage(filePath) {
if (!this._packageCache[filePath]) {
this._packageCache[filePath] = new Package({
file: filePath,
});
}
return this._packageCache[filePath];
}
getPackageForModule(module) {
return this.getPackageOf(module.path);
}
getPackageOf(modulePath) {
var _this$_modulePathsByP;
let packagePath = this._packagePathByModulePath[modulePath];
if (packagePath && this._packageCache[packagePath]) {
return this._packageCache[packagePath];
}
packagePath = this._getClosestPackage(modulePath);
if (!packagePath) {
return null;
}
this._packagePathByModulePath[modulePath] = packagePath;
const modulePaths =
(_this$_modulePathsByP = this._modulePathsByPackagePath[packagePath]) !==
null && _this$_modulePathsByP !== void 0
? _this$_modulePathsByP
: new Set();
modulePaths.add(modulePath);
this._modulePathsByPackagePath[packagePath] = modulePaths;
return this.getPackage(packagePath);
}
invalidate(filePath) {
if (this._moduleCache[filePath]) {
this._moduleCache[filePath].invalidate();
delete this._moduleCache[filePath];
}
if (this._packageCache[filePath]) {
this._packageCache[filePath].invalidate();
delete this._packageCache[filePath];
}
if (this._packagePathByModulePath[filePath]) {
// filePath is a module inside a package.
const packagePath = this._packagePathByModulePath[filePath];
delete this._packagePathByModulePath[filePath];
// This change doesn't invalidate any cached "closest package.json"
// queries for the package's other modules. Clean up only this module.
const modulePaths = this._modulePathsByPackagePath[packagePath];
if (modulePaths) {
modulePaths.delete(filePath);
if (modulePaths.size === 0) {
delete this._modulePathsByPackagePath[packagePath];
}
}
}
if (this._modulePathsByPackagePath[filePath]) {
// filePath is a package. This change invalidates all cached "closest
// package.json" queries for modules inside this package.
const modulePaths = this._modulePathsByPackagePath[filePath];
for (const modulePath of modulePaths) {
delete this._packagePathByModulePath[modulePath];
}
modulePaths.clear();
delete this._modulePathsByPackagePath[filePath];
}
}
}
module.exports = ModuleCache;