提交学习笔记专用
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.

212 lines
7.0 KiB

  1. var isCore = require('is-core-module');
  2. var fs = require('fs');
  3. var path = require('path');
  4. var getHomedir = require('./homedir');
  5. var caller = require('./caller');
  6. var nodeModulesPaths = require('./node-modules-paths');
  7. var normalizeOptions = require('./normalize-options');
  8. var realpathFS = process.platform !== 'win32' && fs.realpathSync && typeof fs.realpathSync.native === 'function' ? fs.realpathSync.native : fs.realpathSync;
  9. var relativePathRegex = /^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/;
  10. var windowsDriveRegex = /^\w:[/\\]*$/;
  11. var nodeModulesRegex = /[/\\]node_modules[/\\]*$/;
  12. var homedir = getHomedir();
  13. var defaultPaths = function () {
  14. return [
  15. path.join(homedir, '.node_modules'),
  16. path.join(homedir, '.node_libraries')
  17. ];
  18. };
  19. var defaultIsFile = function isFile(file) {
  20. try {
  21. var stat = fs.statSync(file, { throwIfNoEntry: false });
  22. } catch (e) {
  23. if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) return false;
  24. throw e;
  25. }
  26. return !!stat && (stat.isFile() || stat.isFIFO());
  27. };
  28. var defaultIsDir = function isDirectory(dir) {
  29. try {
  30. var stat = fs.statSync(dir, { throwIfNoEntry: false });
  31. } catch (e) {
  32. if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) return false;
  33. throw e;
  34. }
  35. return !!stat && stat.isDirectory();
  36. };
  37. var defaultRealpathSync = function realpathSync(x) {
  38. try {
  39. return realpathFS(x);
  40. } catch (realpathErr) {
  41. if (realpathErr.code !== 'ENOENT') {
  42. throw realpathErr;
  43. }
  44. }
  45. return x;
  46. };
  47. var maybeRealpathSync = function maybeRealpathSync(realpathSync, x, opts) {
  48. if (opts && opts.preserveSymlinks === false) {
  49. return realpathSync(x);
  50. }
  51. return x;
  52. };
  53. var defaultReadPackageSync = function defaultReadPackageSync(readFileSync, pkgfile) {
  54. var body = readFileSync(pkgfile);
  55. try {
  56. var pkg = JSON.parse(body);
  57. return pkg;
  58. } catch (jsonErr) {}
  59. };
  60. var getPackageCandidates = function getPackageCandidates(x, start, opts) {
  61. var dirs = nodeModulesPaths(start, opts, x);
  62. for (var i = 0; i < dirs.length; i++) {
  63. dirs[i] = path.join(dirs[i], x);
  64. }
  65. return dirs;
  66. };
  67. module.exports = function resolveSync(x, options) {
  68. if (typeof x !== 'string') {
  69. throw new TypeError('Path must be a string.');
  70. }
  71. var opts = normalizeOptions(x, options);
  72. var isFile = opts.isFile || defaultIsFile;
  73. var readFileSync = opts.readFileSync || fs.readFileSync;
  74. var isDirectory = opts.isDirectory || defaultIsDir;
  75. var realpathSync = opts.realpathSync || defaultRealpathSync;
  76. var readPackageSync = opts.readPackageSync || defaultReadPackageSync;
  77. if (opts.readFileSync && opts.readPackageSync) {
  78. throw new TypeError('`readFileSync` and `readPackageSync` are mutually exclusive.');
  79. }
  80. var packageIterator = opts.packageIterator;
  81. var extensions = opts.extensions || ['.js'];
  82. var includeCoreModules = opts.includeCoreModules !== false;
  83. var basedir = opts.basedir || path.dirname(caller());
  84. var parent = opts.filename || basedir;
  85. opts.paths = opts.paths || defaultPaths();
  86. // ensure that `basedir` is an absolute path at this point, resolving against the process' current working directory
  87. var absoluteStart = maybeRealpathSync(realpathSync, path.resolve(basedir), opts);
  88. if (relativePathRegex.test(x)) {
  89. var res = path.resolve(absoluteStart, x);
  90. if (x === '.' || x === '..' || x.slice(-1) === '/') res += '/';
  91. var m = loadAsFileSync(res) || loadAsDirectorySync(res);
  92. if (m) return maybeRealpathSync(realpathSync, m, opts);
  93. } else if (includeCoreModules && isCore(x)) {
  94. return x;
  95. } else {
  96. var n = loadNodeModulesSync(x, absoluteStart);
  97. if (n) return maybeRealpathSync(realpathSync, n, opts);
  98. }
  99. var err = new Error("Cannot find module '" + x + "' from '" + parent + "'");
  100. err.code = 'MODULE_NOT_FOUND';
  101. throw err;
  102. function loadAsFileSync(x) {
  103. var pkg = loadpkg(path.dirname(x));
  104. if (pkg && pkg.dir && pkg.pkg && opts.pathFilter) {
  105. var rfile = path.relative(pkg.dir, x);
  106. var r = opts.pathFilter(pkg.pkg, x, rfile);
  107. if (r) {
  108. x = path.resolve(pkg.dir, r); // eslint-disable-line no-param-reassign
  109. }
  110. }
  111. if (isFile(x)) {
  112. return x;
  113. }
  114. for (var i = 0; i < extensions.length; i++) {
  115. var file = x + extensions[i];
  116. if (isFile(file)) {
  117. return file;
  118. }
  119. }
  120. }
  121. function loadpkg(dir) {
  122. if (dir === '' || dir === '/') return;
  123. if (process.platform === 'win32' && windowsDriveRegex.test(dir)) {
  124. return;
  125. }
  126. if (nodeModulesRegex.test(dir)) return;
  127. var pkgfile = path.join(maybeRealpathSync(realpathSync, dir, opts), 'package.json');
  128. if (!isFile(pkgfile)) {
  129. return loadpkg(path.dirname(dir));
  130. }
  131. var pkg = readPackageSync(readFileSync, pkgfile);
  132. if (pkg && opts.packageFilter) {
  133. // v2 will pass pkgfile
  134. pkg = opts.packageFilter(pkg, /*pkgfile,*/ dir); // eslint-disable-line spaced-comment
  135. }
  136. return { pkg: pkg, dir: dir };
  137. }
  138. function loadAsDirectorySync(x) {
  139. var pkgfile = path.join(maybeRealpathSync(realpathSync, x, opts), '/package.json');
  140. if (isFile(pkgfile)) {
  141. try {
  142. var pkg = readPackageSync(readFileSync, pkgfile);
  143. } catch (e) {}
  144. if (pkg && opts.packageFilter) {
  145. // v2 will pass pkgfile
  146. pkg = opts.packageFilter(pkg, /*pkgfile,*/ x); // eslint-disable-line spaced-comment
  147. }
  148. if (pkg && pkg.main) {
  149. if (typeof pkg.main !== 'string') {
  150. var mainError = new TypeError('package “' + pkg.name + '” `main` must be a string');
  151. mainError.code = 'INVALID_PACKAGE_MAIN';
  152. throw mainError;
  153. }
  154. if (pkg.main === '.' || pkg.main === './') {
  155. pkg.main = 'index';
  156. }
  157. try {
  158. var m = loadAsFileSync(path.resolve(x, pkg.main));
  159. if (m) return m;
  160. var n = loadAsDirectorySync(path.resolve(x, pkg.main));
  161. if (n) return n;
  162. } catch (e) {}
  163. }
  164. }
  165. return loadAsFileSync(path.join(x, '/index'));
  166. }
  167. function loadNodeModulesSync(x, start) {
  168. var thunk = function () { return getPackageCandidates(x, start, opts); };
  169. var dirs = packageIterator ? packageIterator(x, start, thunk, opts) : thunk();
  170. for (var i = 0; i < dirs.length; i++) {
  171. var dir = dirs[i];
  172. if (isDirectory(path.dirname(dir))) {
  173. var m = loadAsFileSync(dir);
  174. if (m) return m;
  175. var n = loadAsDirectorySync(dir);
  176. if (n) return n;
  177. }
  178. }
  179. }
  180. };