UNPKG

haste-resolver

Version:
465 lines (396 loc) 18.7 kB
/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ 'use strict'; var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var debug = require('debug')('DependencyGraph'); var util = require('util'); var path = require('../fastpath'); var realPath = require('path'); var isAbsolutePath = require('absolute-path'); var getAssetDataFromName = require('../utils/getAssetDataFromName'); var throat = require('throat')(Promise); var MAX_CONCURRENT_FILE_READS = 32; var getDependencies = throat(MAX_CONCURRENT_FILE_READS, function (module, transformOptions) { return module.getDependencies(transformOptions); }); var ResolutionRequest = (function () { function ResolutionRequest(_ref) { var platform = _ref.platform; var preferNativePlatform = _ref.preferNativePlatform; var entryPath = _ref.entryPath; var hasteMap = _ref.hasteMap; var deprecatedAssetMap = _ref.deprecatedAssetMap; var helpers = _ref.helpers; var moduleCache = _ref.moduleCache; var fastfs = _ref.fastfs; var shouldThrowOnUnresolvedErrors = _ref.shouldThrowOnUnresolvedErrors; _classCallCheck(this, ResolutionRequest); this._platform = platform; this._preferNativePlatform = preferNativePlatform; this._entryPath = entryPath; this._hasteMap = hasteMap; this._deprecatedAssetMap = deprecatedAssetMap; this._helpers = helpers; this._moduleCache = moduleCache; this._fastfs = fastfs; this._shouldThrowOnUnresolvedErrors = shouldThrowOnUnresolvedErrors; this._resetResolutionCache(); } _createClass(ResolutionRequest, [{ key: '_tryResolve', value: function _tryResolve(action, secondaryAction) { return action()['catch'](function (error) { if (error.type !== 'UnableToResolveError') { throw error; } return secondaryAction(); }); } }, { key: 'resolveDependency', value: function resolveDependency(fromModule, toModuleName) { var _this = this; var resHash = resolutionHash(fromModule.path, toModuleName); if (this._immediateResolutionCache[resHash]) { return Promise.resolve(this._immediateResolutionCache[resHash]); } var asset_DEPRECATED = this._deprecatedAssetMap.resolve(fromModule, toModuleName); if (asset_DEPRECATED) { return Promise.resolve(asset_DEPRECATED); } var cacheResult = function cacheResult(result) { _this._immediateResolutionCache[resHash] = result; return result; }; var forgive = function forgive(error) { if (error.type !== 'UnableToResolveError' || _this._shouldThrowOnUnresolvedErrors(_this._entryPath, _this._platform)) { throw error; } debug('Unable to resolve module %s from %s', toModuleName, fromModule.path); return null; }; if (!this._helpers.isNodeModulesDir(fromModule.path) && toModuleName[0] !== '.' && toModuleName[0] !== '/') { return this._tryResolve(function () { return _this._resolveHasteDependency(fromModule, toModuleName); }, function () { return _this._resolveNodeDependency(fromModule, toModuleName); }).then(cacheResult, forgive); } return this._resolveNodeDependency(fromModule, toModuleName).then(cacheResult, forgive); } }, { key: 'getOrderedDependencies', value: function getOrderedDependencies(_ref2) { var _this2 = this; var response = _ref2.response; var mocksPattern = _ref2.mocksPattern; var transformOptions = _ref2.transformOptions; var onProgress = _ref2.onProgress; var _ref2$recursive = _ref2.recursive; var recursive = _ref2$recursive === undefined ? true : _ref2$recursive; return this._getAllMocks(mocksPattern).then(function (allMocks) { var entry = _this2._moduleCache.getModule(_this2._entryPath); var mocks = Object.create(null); var visited = Object.create(null); visited[entry.hash()] = true; response.pushDependency(entry); var totalModules = 1; var finishedModules = 0; var collect = function collect(mod) { return getDependencies(mod, transformOptions).then(function (depNames) { return Promise.all(depNames.map(function (name) { return _this2.resolveDependency(mod, name); })).then(function (dependencies) { return [depNames, dependencies]; }); }).then(function (_ref3) { var _ref32 = _slicedToArray(_ref3, 2); var depNames = _ref32[0]; var dependencies = _ref32[1]; if (allMocks) { var list = [mod.getName()]; var pkg = mod.getPackage(); if (pkg) { list.push(pkg.getName()); } return Promise.all(list).then(function (names) { names.forEach(function (name) { if (allMocks[name] && !mocks[name]) { var mockModule = _this2._moduleCache.getModule(allMocks[name]); depNames.push(name); dependencies.push(mockModule); mocks[name] = allMocks[name]; } }); return [depNames, dependencies]; }); } return [depNames, dependencies]; }).then(function (_ref4) { var _ref42 = _slicedToArray(_ref4, 2); var depNames = _ref42[0]; var dependencies = _ref42[1]; var filteredPairs = []; dependencies.forEach(function (modDep, i) { var name = depNames[i]; if (modDep == null) { // It is possible to require mocks that don't have a real // module backing them. If a dependency cannot be found but there // exists a mock with the desired ID, resolve it and add it as // a dependency. if (allMocks && allMocks[name] && !mocks[name]) { var mockModule = _this2._moduleCache.getModule(allMocks[name]); mocks[name] = allMocks[name]; return filteredPairs.push([name, mockModule]); } debug('WARNING: Cannot find required module `%s` from module `%s`', name, mod.path); return false; } return filteredPairs.push([name, modDep]); }); response.setResolvedDependencyPairs(mod, filteredPairs); var newDependencies = filteredPairs.filter(function (_ref5) { var _ref52 = _slicedToArray(_ref5, 2); var modDep = _ref52[1]; return !visited[modDep.hash()]; }); if (onProgress) { finishedModules += 1; totalModules += newDependencies.length; onProgress(finishedModules, totalModules); } return Promise.all(newDependencies.map(function (_ref6) { var _ref62 = _slicedToArray(_ref6, 2); var depName = _ref62[0]; var modDep = _ref62[1]; visited[modDep.hash()] = true; return Promise.all([modDep, recursive ? collect(modDep) : []]); })); }); }; return collect(entry).then(function (deps) { recursiveFlatten(deps).forEach(function (dep) { return response.pushDependency(dep); }); response.setMocks(mocks); }); }); } }, { key: '_getAllMocks', value: function _getAllMocks(pattern) { // Take all mocks in all the roots into account. This is necessary // because currently mocks are global: any module can be mocked by // any mock in the system. var mocks = null; if (pattern) { mocks = Object.create(null); this._fastfs.matchFilesByPattern(pattern).forEach(function (file) { return mocks[path.basename(file, path.extname(file))] = file; }); } return Promise.resolve(mocks); } }, { key: '_resolveHasteDependency', value: function _resolveHasteDependency(fromModule, toModuleName) { var _this3 = this; toModuleName = normalizePath(toModuleName); var p = fromModule.getPackage(); if (p) { p = p.redirectRequire(toModuleName); } else { p = Promise.resolve(toModuleName); } return p.then(function (realModuleName) { var dep = _this3._hasteMap.getModule(realModuleName, _this3._platform); if (dep && dep.type === 'Module') { return dep; } var packageName = realModuleName; while (packageName && packageName !== '.') { dep = _this3._hasteMap.getModule(packageName, _this3._platform); if (dep && dep.type === 'Package') { break; } packageName = path.dirname(packageName); } if (dep && dep.type === 'Package') { var _ret = (function () { var potentialModulePath = path.join(dep.root, path.relative(packageName, realModuleName)); return { v: _this3._tryResolve(function () { return _this3._loadAsFile(potentialModulePath, fromModule, toModuleName); }, function () { return _this3._loadAsDir(potentialModulePath, fromModule, toModuleName); }) }; })(); if (typeof _ret === 'object') return _ret.v; } throw new UnableToResolveError(fromModule, toModuleName, 'Unable to resolve dependency'); }); } }, { key: '_redirectRequire', value: function _redirectRequire(fromModule, modulePath) { return Promise.resolve(fromModule.getPackage()).then(function (p) { if (p) { return p.redirectRequire(modulePath); } return modulePath; }); } }, { key: '_resolveFileOrDir', value: function _resolveFileOrDir(fromModule, toModuleName) { var _this4 = this; var potentialModulePath = isAbsolutePath(toModuleName) ? toModuleName : path.join(path.dirname(fromModule.path), toModuleName); return this._redirectRequire(fromModule, potentialModulePath).then(function (realModuleName) { return _this4._tryResolve(function () { return _this4._loadAsFile(realModuleName, fromModule, toModuleName); }, function () { return _this4._loadAsDir(realModuleName, fromModule, toModuleName); }); }); } }, { key: '_resolveNodeDependency', value: function _resolveNodeDependency(fromModule, toModuleName) { var _this5 = this; if (toModuleName[0] === '.' || toModuleName[1] === '/') { return this._resolveFileOrDir(fromModule, toModuleName); } else { return this._redirectRequire(fromModule, toModuleName).then(function (realModuleName) { if (realModuleName[0] === '.' || realModuleName[1] === '/') { // derive absolute path /.../node_modules/fromModuleDir/realModuleName var fromModuleParentIdx = fromModule.path.lastIndexOf('node_modules/') + 13; var fromModuleDir = fromModule.path.slice(0, fromModule.path.indexOf('/', fromModuleParentIdx)); var absPath = path.join(fromModuleDir, realModuleName); return _this5._resolveFileOrDir(fromModule, absPath); } var searchQueue = []; for (var currDir = path.dirname(fromModule.path); currDir !== realPath.parse(fromModule.path).root; currDir = path.dirname(currDir)) { searchQueue.push(path.join(currDir, 'node_modules', realModuleName)); } var p = Promise.reject(new UnableToResolveError(fromModule, toModuleName, 'Node module not found')); searchQueue.forEach(function (potentialModulePath) { p = _this5._tryResolve(function () { return _this5._tryResolve(function () { return p; }, function () { return _this5._loadAsFile(potentialModulePath, fromModule, toModuleName); }); }, function () { return _this5._loadAsDir(potentialModulePath, fromModule, toModuleName); }); }); return p; }); } } }, { key: '_loadAsFile', value: function _loadAsFile(potentialModulePath, fromModule, toModule) { var _this6 = this; return Promise.resolve().then(function () { if (_this6._helpers.isAssetFile(potentialModulePath)) { var dirname = path.dirname(potentialModulePath); if (!_this6._fastfs.dirExists(dirname)) { throw new UnableToResolveError(fromModule, toModule, 'Directory ' + dirname + ' doesn\'t exist'); } var _getAssetDataFromName = getAssetDataFromName(potentialModulePath); var _name = _getAssetDataFromName.name; var type = _getAssetDataFromName.type; var pattern = '^' + _name + '(@[\\d\\.]+x)?'; if (_this6._platform != null) { pattern += '(\\.' + _this6._platform + ')?'; } pattern += '\\.' + type; // We arbitrarly grab the first one, because scale selection // will happen somewhere var _fastfs$matches = _this6._fastfs.matches(dirname, new RegExp(pattern)); var _fastfs$matches2 = _slicedToArray(_fastfs$matches, 1); var assetFile = _fastfs$matches2[0]; if (assetFile) { return _this6._moduleCache.getAssetModule(assetFile); } } var file = undefined; if (_this6._fastfs.fileExists(potentialModulePath)) { file = potentialModulePath; } else if (_this6._platform != null && _this6._fastfs.fileExists(potentialModulePath + '.' + _this6._platform + '.js')) { file = potentialModulePath + '.' + _this6._platform + '.js'; } else if (_this6._preferNativePlatform && _this6._fastfs.fileExists(potentialModulePath + '.native.js')) { file = potentialModulePath + '.native.js'; } else if (_this6._fastfs.fileExists(potentialModulePath + '.js')) { file = potentialModulePath + '.js'; } else if (_this6._fastfs.fileExists(potentialModulePath + '.json')) { file = potentialModulePath + '.json'; } else { throw new UnableToResolveError(fromModule, toModule, 'File ' + potentialModulePath + ' doesnt exist'); } return _this6._moduleCache.getModule(file); }); } }, { key: '_loadAsDir', value: function _loadAsDir(potentialDirPath, fromModule, toModule) { var _this7 = this; return Promise.resolve().then(function () { if (!_this7._fastfs.dirExists(potentialDirPath)) { throw new UnableToResolveError(fromModule, toModule, 'Unable to find this module in its module map or any of the node_modules directories under ' + potentialDirPath + ' and its parent directories\n\nThis might be related to https://github.com/facebook/react-native/issues/4968\nTo resolve try the following:\n 1. Clear watchman watches: `watchman watch-del-all`.\n 2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.\n 3. Reset packager cache: `rm -fr $TMPDIR/react-*` or `npm start -- --reset-cache`.'); } var packageJsonPath = path.join(potentialDirPath, 'package.json'); if (_this7._fastfs.fileExists(packageJsonPath)) { return _this7._moduleCache.getPackage(packageJsonPath).getMain().then(function (main) { return _this7._tryResolve(function () { return _this7._loadAsFile(main, fromModule, toModule); }, function () { return _this7._loadAsDir(main, fromModule, toModule); }); }); } return _this7._loadAsFile(path.join(potentialDirPath, 'index'), fromModule, toModule); }); } }, { key: '_resetResolutionCache', value: function _resetResolutionCache() { this._immediateResolutionCache = Object.create(null); } }]); return ResolutionRequest; })(); function resolutionHash(modulePath, depName) { return path.resolve(modulePath) + ':' + depName; } function UnableToResolveError(fromModule, toModule, message) { Error.call(this); Error.captureStackTrace(this, this.constructor); this.message = util.format('Unable to resolve module %s from %s: %s', toModule, fromModule.path, message); this.type = this.name = 'UnableToResolveError'; } util.inherits(UnableToResolveError, Error); function normalizePath(modulePath) { if (path.sep === '/') { modulePath = path.normalize(modulePath); } else if (path.posix) { modulePath = path.posix.normalize(modulePath); } return modulePath.replace(/\/$/, ''); } function recursiveFlatten(array) { return Array.prototype.concat.apply(Array.prototype, array.map(function (item) { return Array.isArray(item) ? recursiveFlatten(item) : item; })); } module.exports = ResolutionRequest;