diff --git a/build/tasks/generate-module-cache-task.coffee b/build/tasks/generate-module-cache-task.coffee new file mode 100644 index 000000000..6a21f9545 --- /dev/null +++ b/build/tasks/generate-module-cache-task.coffee @@ -0,0 +1,5 @@ +ModuleCache = require '../../src/module-cache' + +module.exports = (grunt) -> + grunt.registerTask 'generate-module-cache', 'Generate a module cache for all core modules', -> + ModuleCache.generateDependencies(process.cwd()) diff --git a/src/module-cache.coffee b/src/module-cache.coffee index 869787b2e..204cf3580 100644 --- a/src/module-cache.coffee +++ b/src/module-cache.coffee @@ -1,17 +1,77 @@ Module = require 'module' +path = require 'path' fs = require 'fs-plus' nativeModules = process.binding('natives') -try - resourcePath = JSON.parse(decodeURIComponent(location.search.substr(14)))?.resourcePath -catch error - return - originalResolveFilename = Module._resolveFilename +loadDependencies = (modulePath, rootPath, rootMetadata, moduleCache) -> + return unless fs.isDirectorySync(modulePath) + + nodeModulesPath = path.join(modulePath, 'node_modules') + return unless fs.isDirectorySync(nodeModulesPath) + + for child in fs.readdirSync(nodeModulesPath) + continue if child is '.bin' + continue if rootPath is modulePath and rootMetadata.packageDependencies?.hasOwnProperty(child) + + childPath = path.join(nodeModulesPath, child) + childMetadatapath = path.join(nodeModulesPath, child, 'package.json') + continue unless fs.isFileSync(childMetadatapath) + + childMetadata = JSON.parse(fs.readFileSync(childMetadatapath)) + if childMetadata?.version + relativePath = path.relative(rootPath, childPath) + moduleCache.dependencies[relativePath] = childMetadata.version + loadDependencies(childPath, rootPath, rootMetadata, moduleCache) + +loadFolderCompatibility = (modulePath, rootPath, rootMetadata, moduleCache) -> + return unless fs.isDirectorySync(modulePath) + + metadataPath = path.join(modulePath, 'package.json') + return unless fs.isFileSync(metadataPath) + + nodeModulesPath = path.join(modulePath, 'node_modules') + dependencies = JSON.parse(fs.readFileSync(metadataPath))?.dependencies ? {} + + onDirectory = (childPath) -> + path.basename(childPath) isnt 'node_modules' + + extensions = Object.keys(require.extensions) + paths = {} + onFile = (childPath) -> + if path.extname(childPath) in extensions + relativePath = path.relative(rootPath, path.dirname(childPath)) + paths[relativePath] = true + fs.traverseTreeSync(modulePath, onFile, onDirectory) + + moduleCache.folders ?= [] + paths = Object.keys(paths) + if paths.length > 0 and Object.keys(dependencies).length > 0 + moduleCache.folders.push({paths, dependencies}) + + if fs.isDirectorySync(nodeModulesPath) + for child in fs.readdirSync(nodeModulesPath) + continue if child is '.bin' + continue if rootPath is modulePath and rootMetadata.packageDependencies?.hasOwnProperty(child) + + loadFolderCompatibility(path.join(nodeModulesPath, child), rootPath, rootMetadata, moduleCache) + # Precompute versions of all modules in node_modules # Precompute the version each file is compatible +exports.generateDependencies = (modulePath) -> + metadataPath = path.join(modulePath, 'package.json') + metadata = JSON.parse(fs.readFileSync(metadataPath)) + + moduleCache = + version: 1 + dependencies: {} + loadDependencies(modulePath, modulePath, metadata, moduleCache) + loadFolderCompatibility(modulePath, modulePath, metadata, moduleCache) + + metadata._atomModuleCache = moduleCache + fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2)) getCachedModulePath = (relativePath, parentModule) -> return unless relativePath