index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. 'use strict';
  2. var _fs;
  3. function _load_fs() {
  4. return (_fs = _interopRequireDefault(require('fs')));
  5. }
  6. var _path;
  7. function _load_path() {
  8. return (_path = _interopRequireDefault(require('path')));
  9. }
  10. var _node_modules_paths;
  11. function _load_node_modules_paths() {
  12. return (_node_modules_paths = _interopRequireDefault(
  13. require('./node_modules_paths')
  14. ));
  15. }
  16. var _is_builtin_module;
  17. function _load_is_builtin_module() {
  18. return (_is_builtin_module = _interopRequireDefault(
  19. require('./is_builtin_module')
  20. ));
  21. }
  22. var _default_resolver;
  23. function _load_default_resolver() {
  24. return (_default_resolver = _interopRequireDefault(
  25. require('./default_resolver.js')
  26. ));
  27. }
  28. var _chalk;
  29. function _load_chalk() {
  30. return (_chalk = _interopRequireDefault(require('chalk')));
  31. }
  32. function _interopRequireDefault(obj) {
  33. return obj && obj.__esModule ? obj : {default: obj};
  34. }
  35. function _toConsumableArray(arr) {
  36. if (Array.isArray(arr)) {
  37. for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++)
  38. arr2[i] = arr[i];
  39. return arr2;
  40. } else {
  41. return Array.from(arr);
  42. }
  43. }
  44. /**
  45. * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
  46. *
  47. * This source code is licensed under the MIT license found in the
  48. * LICENSE file in the root directory of this source tree.
  49. *
  50. *
  51. */
  52. const NATIVE_PLATFORM = 'native';
  53. // We might be inside a symlink.
  54. const cwd = process.cwd();
  55. const resolvedCwd = (_fs || _load_fs()).default.realpathSync(cwd) || cwd;
  56. const nodePaths = process.env.NODE_PATH
  57. ? process.env.NODE_PATH.split((_path || _load_path()).default.delimiter)
  58. .filter(Boolean)
  59. // The resolver expects absolute paths.
  60. .map(p => (_path || _load_path()).default.resolve(resolvedCwd, p))
  61. : null;
  62. class Resolver {
  63. constructor(moduleMap, options) {
  64. this._options = {
  65. browser: options.browser,
  66. defaultPlatform: options.defaultPlatform,
  67. extensions: options.extensions,
  68. hasCoreModules:
  69. options.hasCoreModules === undefined ? true : options.hasCoreModules,
  70. moduleDirectories: options.moduleDirectories || ['node_modules'],
  71. moduleNameMapper: options.moduleNameMapper,
  72. modulePaths: options.modulePaths,
  73. platforms: options.platforms,
  74. resolver: options.resolver,
  75. rootDir: options.rootDir
  76. };
  77. this._moduleMap = moduleMap;
  78. this._moduleIDCache = Object.create(null);
  79. this._moduleNameCache = Object.create(null);
  80. this._modulePathCache = Object.create(null);
  81. }
  82. static findNodeModule(path, options) {
  83. const resolver = options.resolver /* $FlowFixMe */
  84. ? require(options.resolver)
  85. : (_default_resolver || _load_default_resolver()).default;
  86. const paths = options.paths;
  87. try {
  88. return resolver(path, {
  89. basedir: options.basedir,
  90. browser: options.browser,
  91. extensions: options.extensions,
  92. moduleDirectory: options.moduleDirectory,
  93. paths: paths ? (nodePaths || []).concat(paths) : nodePaths,
  94. rootDir: options.rootDir
  95. });
  96. } catch (e) {}
  97. return null;
  98. }
  99. resolveModuleFromDirIfExists(dirname, moduleName, options) {
  100. const paths = (options && options.paths) || this._options.modulePaths;
  101. const moduleDirectory = this._options.moduleDirectories;
  102. const key =
  103. dirname + (_path || _load_path()).default.delimiter + moduleName;
  104. const defaultPlatform = this._options.defaultPlatform;
  105. const extensions = this._options.extensions.slice();
  106. if (this._supportsNativePlatform()) {
  107. extensions.unshift.apply(
  108. extensions,
  109. _toConsumableArray(
  110. this._options.extensions.map(ext => '.' + NATIVE_PLATFORM + ext)
  111. )
  112. );
  113. }
  114. if (defaultPlatform) {
  115. extensions.unshift.apply(
  116. extensions,
  117. _toConsumableArray(
  118. this._options.extensions.map(ext => '.' + defaultPlatform + ext)
  119. )
  120. );
  121. }
  122. // 0. If we have already resolved this module for this directory name,
  123. // return a value from the cache.
  124. if (this._moduleNameCache[key]) {
  125. return this._moduleNameCache[key];
  126. }
  127. // 1. Check if the module is a haste module.
  128. let module = this.getModule(moduleName);
  129. if (module) {
  130. return (this._moduleNameCache[key] = module);
  131. }
  132. // 2. Check if the module is a node module and resolve it based on
  133. // the node module resolution algorithm.
  134. // If skipNodeResolution is given we ignore all modules that look like
  135. // node modules (ie. are not relative requires). This enables us to speed
  136. // up resolution when we build a dependency graph because we don't have
  137. // to look at modules that may not exist and aren't mocked.
  138. const skipResolution =
  139. options &&
  140. options.skipNodeResolution &&
  141. !moduleName.includes((_path || _load_path()).default.sep);
  142. const resolveNodeModule = name =>
  143. Resolver.findNodeModule(name, {
  144. basedir: dirname,
  145. browser: this._options.browser,
  146. extensions: extensions,
  147. moduleDirectory: moduleDirectory,
  148. paths: paths,
  149. resolver: this._options.resolver,
  150. rootDir: this._options.rootDir
  151. });
  152. if (!skipResolution) {
  153. module = resolveNodeModule(moduleName);
  154. if (module) {
  155. return (this._moduleNameCache[key] = module);
  156. }
  157. }
  158. // 3. Resolve "haste packages" which are `package.json` files outside of
  159. // `node_modules` folders anywhere in the file system.
  160. const parts = moduleName.split('/');
  161. const hastePackage = this.getPackage(parts.shift());
  162. if (hastePackage) {
  163. try {
  164. const module = (_path || _load_path()).default.join.apply(
  165. (_path || _load_path()).default,
  166. [(_path || _load_path()).default.dirname(hastePackage)].concat(parts)
  167. );
  168. // try resolving with custom resolver first to support extensions,
  169. // then fallback to require.resolve
  170. return (this._moduleNameCache[key] =
  171. resolveNodeModule(module) || require.resolve(module));
  172. } catch (ignoredError) {}
  173. }
  174. return null;
  175. }
  176. resolveModule(from, moduleName, options) {
  177. const dirname = (_path || _load_path()).default.dirname(from);
  178. const module = this.resolveModuleFromDirIfExists(
  179. dirname,
  180. moduleName,
  181. options
  182. );
  183. if (module) return module;
  184. // (4.) Throw an error if the module could not be found. `resolve.sync`
  185. // only produces an error based on the dirname but we have the actual
  186. // current module name available.
  187. const relativePath = (_path || _load_path()).default.relative(
  188. dirname,
  189. from
  190. );
  191. const err = new Error(
  192. `Cannot find module '${moduleName}' from '${relativePath || '.'}'`
  193. );
  194. err.code = 'MODULE_NOT_FOUND';
  195. throw err;
  196. }
  197. isCoreModule(moduleName) {
  198. return (
  199. this._options.hasCoreModules &&
  200. (0, (_is_builtin_module || _load_is_builtin_module()).default)(moduleName)
  201. );
  202. }
  203. getModule(name) {
  204. return this._moduleMap.getModule(
  205. name,
  206. this._options.defaultPlatform,
  207. this._supportsNativePlatform()
  208. );
  209. }
  210. getModulePath(from, moduleName) {
  211. if (
  212. moduleName[0] !== '.' ||
  213. (_path || _load_path()).default.isAbsolute(moduleName)
  214. ) {
  215. return moduleName;
  216. }
  217. return (_path || _load_path()).default.normalize(
  218. (_path || _load_path()).default.dirname(from) + '/' + moduleName
  219. );
  220. }
  221. getPackage(name) {
  222. return this._moduleMap.getPackage(
  223. name,
  224. this._options.defaultPlatform,
  225. this._supportsNativePlatform()
  226. );
  227. }
  228. getMockModule(from, name) {
  229. const mock = this._moduleMap.getMockModule(name);
  230. if (mock) {
  231. return mock;
  232. } else {
  233. const moduleName = this._resolveStubModuleName(from, name);
  234. if (moduleName) {
  235. return this.getModule(moduleName) || moduleName;
  236. }
  237. }
  238. return null;
  239. }
  240. getModulePaths(from) {
  241. if (!this._modulePathCache[from]) {
  242. const moduleDirectory = this._options.moduleDirectories;
  243. const paths = (0,
  244. (_node_modules_paths || _load_node_modules_paths()).default)(from, {
  245. moduleDirectory: moduleDirectory
  246. });
  247. if (paths[paths.length - 1] === undefined) {
  248. // circumvent node-resolve bug that adds `undefined` as last item.
  249. paths.pop();
  250. }
  251. this._modulePathCache[from] = paths;
  252. }
  253. return this._modulePathCache[from];
  254. }
  255. getModuleID(virtualMocks, from, _moduleName) {
  256. const moduleName = _moduleName || '';
  257. const key = from + (_path || _load_path()).default.delimiter + moduleName;
  258. if (this._moduleIDCache[key]) {
  259. return this._moduleIDCache[key];
  260. }
  261. const moduleType = this._getModuleType(moduleName);
  262. const absolutePath = this._getAbsolutePath(virtualMocks, from, moduleName);
  263. const mockPath = this._getMockPath(from, moduleName);
  264. const sep = (_path || _load_path()).default.delimiter;
  265. const id =
  266. moduleType +
  267. sep +
  268. (absolutePath ? absolutePath + sep : '') +
  269. (mockPath ? mockPath + sep : '');
  270. return (this._moduleIDCache[key] = id);
  271. }
  272. _getModuleType(moduleName) {
  273. return this.isCoreModule(moduleName) ? 'node' : 'user';
  274. }
  275. _getAbsolutePath(virtualMocks, from, moduleName) {
  276. if (this.isCoreModule(moduleName)) {
  277. return moduleName;
  278. }
  279. return this._isModuleResolved(from, moduleName)
  280. ? this.getModule(moduleName)
  281. : this._getVirtualMockPath(virtualMocks, from, moduleName);
  282. }
  283. _getMockPath(from, moduleName) {
  284. return !this.isCoreModule(moduleName)
  285. ? this.getMockModule(from, moduleName)
  286. : null;
  287. }
  288. _getVirtualMockPath(virtualMocks, from, moduleName) {
  289. const virtualMockPath = this.getModulePath(from, moduleName);
  290. return virtualMocks[virtualMockPath]
  291. ? virtualMockPath
  292. : moduleName
  293. ? this.resolveModule(from, moduleName)
  294. : from;
  295. }
  296. _isModuleResolved(from, moduleName) {
  297. return !!(
  298. this.getModule(moduleName) || this.getMockModule(from, moduleName)
  299. );
  300. }
  301. _resolveStubModuleName(from, moduleName) {
  302. const dirname = (_path || _load_path()).default.dirname(from);
  303. const paths = this._options.modulePaths;
  304. const extensions = this._options.extensions;
  305. const moduleDirectory = this._options.moduleDirectories;
  306. const moduleNameMapper = this._options.moduleNameMapper;
  307. const resolver = this._options.resolver;
  308. if (moduleNameMapper) {
  309. for (const _ref of moduleNameMapper) {
  310. const mappedModuleName = _ref.moduleName;
  311. const regex = _ref.regex;
  312. if (regex.test(moduleName)) {
  313. // Note: once a moduleNameMapper matches the name, it must result
  314. // in a module, or else an error is thrown.
  315. const matches = moduleName.match(regex);
  316. const updatedName = matches
  317. ? mappedModuleName.replace(
  318. /\$([0-9]+)/g,
  319. (_, index) => matches[parseInt(index, 10)]
  320. )
  321. : mappedModuleName;
  322. const module =
  323. this.getModule(updatedName) ||
  324. Resolver.findNodeModule(updatedName, {
  325. basedir: dirname,
  326. browser: this._options.browser,
  327. extensions: extensions,
  328. moduleDirectory: moduleDirectory,
  329. paths: paths,
  330. resolver: resolver,
  331. rootDir: this._options.rootDir
  332. });
  333. if (!module) {
  334. throw createNoMappedModuleFoundError(
  335. moduleName,
  336. updatedName,
  337. mappedModuleName,
  338. regex,
  339. resolver
  340. );
  341. }
  342. return module;
  343. }
  344. }
  345. }
  346. return null;
  347. }
  348. _supportsNativePlatform() {
  349. return (this._options.platforms || []).indexOf(NATIVE_PLATFORM) !== -1;
  350. }
  351. }
  352. const createNoMappedModuleFoundError = (
  353. moduleName,
  354. updatedName,
  355. mappedModuleName,
  356. regex,
  357. resolver
  358. ) => {
  359. const error = new Error(
  360. (_chalk || _load_chalk()).default.red(`${(
  361. _chalk || _load_chalk()
  362. ).default.bold('Configuration error')}:
  363. Could not locate module ${(_chalk || _load_chalk()).default.bold(
  364. moduleName
  365. )} mapped as:
  366. ${(_chalk || _load_chalk()).default.bold(updatedName)}.
  367. Please check your configuration for these entries:
  368. {
  369. "moduleNameMapper": {
  370. "${regex.toString()}": "${(_chalk || _load_chalk()).default.bold(
  371. mappedModuleName
  372. )}"
  373. },
  374. "resolver": ${(_chalk || _load_chalk()).default.bold(String(resolver))}
  375. }`)
  376. );
  377. error.name = '';
  378. return error;
  379. };
  380. module.exports = Resolver;