module.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const Module = require('module')
  2. const path = require('path')
  3. const semver = require('semver')
  4. // https://github.com/benmosher/eslint-plugin-import/pull/1591
  5. // https://github.com/benmosher/eslint-plugin-import/pull/1602
  6. // Polyfill Node's `Module.createRequireFromPath` if not present (added in Node v10.12.0)
  7. // Use `Module.createRequire` if available (added in Node v12.2.0)
  8. // eslint-disable-next-line node/no-deprecated-api
  9. const createRequire = Module.createRequire || Module.createRequireFromPath || function (filename) {
  10. const mod = new Module(filename, null)
  11. mod.filename = filename
  12. mod.paths = Module._nodeModulePaths(path.dirname(filename))
  13. mod._compile(`module.exports = require;`, filename)
  14. return mod.exports
  15. }
  16. function resolveFallback (request, options) {
  17. const isMain = false
  18. const fakeParent = new Module('', null)
  19. const paths = []
  20. for (let i = 0; i < options.paths.length; i++) {
  21. const p = options.paths[i]
  22. fakeParent.paths = Module._nodeModulePaths(p)
  23. const lookupPaths = Module._resolveLookupPaths(request, fakeParent, true)
  24. if (!paths.includes(p)) paths.push(p)
  25. for (let j = 0; j < lookupPaths.length; j++) {
  26. if (!paths.includes(lookupPaths[j])) paths.push(lookupPaths[j])
  27. }
  28. }
  29. const filename = Module._findPath(request, paths, isMain)
  30. if (!filename) {
  31. const err = new Error(`Cannot find module '${request}'`)
  32. err.code = 'MODULE_NOT_FOUND'
  33. throw err
  34. }
  35. return filename
  36. }
  37. const resolve = semver.satisfies(process.version, '>=10.0.0')
  38. ? require.resolve
  39. : resolveFallback
  40. exports.resolveModule = function (request, context) {
  41. // createRequire doesn't work with jest mock modules
  42. // (which we used in migrator for inquirer, and in tests for cli-service)
  43. // TODO: it's supported in Jest 25
  44. if (process.env.VUE_CLI_TEST && (request.endsWith('migrator') || context === '/')) {
  45. return request
  46. }
  47. let resolvedPath
  48. try {
  49. try {
  50. resolvedPath = createRequire(path.resolve(context, 'package.json')).resolve(request)
  51. } catch (e) {
  52. resolvedPath = resolve(request, { paths: [context] })
  53. }
  54. } catch (e) {}
  55. return resolvedPath
  56. }
  57. exports.loadModule = function (request, context, force = false) {
  58. // createRequire doesn't work with jest mocked fs
  59. // (which we used in tests for cli-service)
  60. if (process.env.VUE_CLI_TEST && context === '/') {
  61. return require(request)
  62. }
  63. try {
  64. return createRequire(path.resolve(context, 'package.json'))(request)
  65. } catch (e) {
  66. const resolvedPath = exports.resolveModule(request, context)
  67. if (resolvedPath) {
  68. if (force) {
  69. clearRequireCache(resolvedPath)
  70. }
  71. return require(resolvedPath)
  72. }
  73. }
  74. }
  75. exports.clearModule = function (request, context) {
  76. const resolvedPath = exports.resolveModule(request, context)
  77. if (resolvedPath) {
  78. clearRequireCache(resolvedPath)
  79. }
  80. }
  81. function clearRequireCache (id, map = new Map()) {
  82. const module = require.cache[id]
  83. if (module) {
  84. map.set(id, true)
  85. // Clear children modules
  86. module.children.forEach(child => {
  87. if (!map.get(child.id)) clearRequireCache(child.id, map)
  88. })
  89. delete require.cache[id]
  90. }
  91. }