/** * 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;