CommonJsRequireDependencyParserPlugin.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const CommonJsRequireDependency = require("./CommonJsRequireDependency");
  7. const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
  8. const RequireHeaderDependency = require("./RequireHeaderDependency");
  9. const LocalModuleDependency = require("./LocalModuleDependency");
  10. const ContextDependencyHelpers = require("./ContextDependencyHelpers");
  11. const LocalModulesHelpers = require("./LocalModulesHelpers");
  12. const ParserHelpers = require("../ParserHelpers");
  13. class CommonJsRequireDependencyParserPlugin {
  14. constructor(options) {
  15. this.options = options;
  16. }
  17. apply(parser) {
  18. const options = this.options;
  19. const processItem = (expr, param) => {
  20. if (param.isString()) {
  21. const dep = new CommonJsRequireDependency(param.string, param.range);
  22. dep.loc = expr.loc;
  23. dep.optional = !!parser.scope.inTry;
  24. parser.state.current.addDependency(dep);
  25. return true;
  26. }
  27. };
  28. const processContext = (expr, param) => {
  29. const dep = ContextDependencyHelpers.create(
  30. CommonJsRequireContextDependency,
  31. expr.range,
  32. param,
  33. expr,
  34. options
  35. );
  36. if (!dep) return;
  37. dep.loc = expr.loc;
  38. dep.optional = !!parser.scope.inTry;
  39. parser.state.current.addDependency(dep);
  40. return true;
  41. };
  42. parser.hooks.expression
  43. .for("require.cache")
  44. .tap(
  45. "CommonJsRequireDependencyParserPlugin",
  46. ParserHelpers.toConstantDependencyWithWebpackRequire(
  47. parser,
  48. "__webpack_require__.c"
  49. )
  50. );
  51. parser.hooks.expression
  52. .for("require")
  53. .tap("CommonJsRequireDependencyParserPlugin", expr => {
  54. const dep = new CommonJsRequireContextDependency(
  55. {
  56. request: options.unknownContextRequest,
  57. recursive: options.unknownContextRecursive,
  58. regExp: options.unknownContextRegExp,
  59. mode: "sync"
  60. },
  61. expr.range
  62. );
  63. dep.critical =
  64. options.unknownContextCritical &&
  65. "require function is used in a way in which dependencies cannot be statically extracted";
  66. dep.loc = expr.loc;
  67. dep.optional = !!parser.scope.inTry;
  68. parser.state.current.addDependency(dep);
  69. return true;
  70. });
  71. const createHandler = callNew => expr => {
  72. if (expr.arguments.length !== 1) return;
  73. let localModule;
  74. const param = parser.evaluateExpression(expr.arguments[0]);
  75. if (param.isConditional()) {
  76. let isExpression = false;
  77. const prevLength = parser.state.current.dependencies.length;
  78. const dep = new RequireHeaderDependency(expr.callee.range);
  79. dep.loc = expr.loc;
  80. parser.state.current.addDependency(dep);
  81. for (const p of param.options) {
  82. const result = processItem(expr, p);
  83. if (result === undefined) {
  84. isExpression = true;
  85. }
  86. }
  87. if (isExpression) {
  88. parser.state.current.dependencies.length = prevLength;
  89. } else {
  90. return true;
  91. }
  92. }
  93. if (
  94. param.isString() &&
  95. (localModule = LocalModulesHelpers.getLocalModule(
  96. parser.state,
  97. param.string
  98. ))
  99. ) {
  100. const dep = new LocalModuleDependency(localModule, expr.range, callNew);
  101. dep.loc = expr.loc;
  102. parser.state.current.addDependency(dep);
  103. return true;
  104. } else {
  105. const result = processItem(expr, param);
  106. if (result === undefined) {
  107. processContext(expr, param);
  108. } else {
  109. const dep = new RequireHeaderDependency(expr.callee.range);
  110. dep.loc = expr.loc;
  111. parser.state.current.addDependency(dep);
  112. }
  113. return true;
  114. }
  115. };
  116. parser.hooks.call
  117. .for("require")
  118. .tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
  119. parser.hooks.new
  120. .for("require")
  121. .tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
  122. parser.hooks.call
  123. .for("module.require")
  124. .tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
  125. parser.hooks.new
  126. .for("module.require")
  127. .tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
  128. }
  129. }
  130. module.exports = CommonJsRequireDependencyParserPlugin;