CommonJsRequireDependencyParserPlugin.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. parser
  37. );
  38. if (!dep) return;
  39. dep.loc = expr.loc;
  40. dep.optional = !!parser.scope.inTry;
  41. parser.state.current.addDependency(dep);
  42. return true;
  43. };
  44. parser.hooks.expression
  45. .for("require.cache")
  46. .tap(
  47. "CommonJsRequireDependencyParserPlugin",
  48. ParserHelpers.toConstantDependencyWithWebpackRequire(
  49. parser,
  50. "__webpack_require__.c"
  51. )
  52. );
  53. parser.hooks.expression
  54. .for("require")
  55. .tap("CommonJsRequireDependencyParserPlugin", expr => {
  56. const dep = new CommonJsRequireContextDependency(
  57. {
  58. request: options.unknownContextRequest,
  59. recursive: options.unknownContextRecursive,
  60. regExp: options.unknownContextRegExp,
  61. mode: "sync"
  62. },
  63. expr.range
  64. );
  65. dep.critical =
  66. options.unknownContextCritical &&
  67. "require function is used in a way in which dependencies cannot be statically extracted";
  68. dep.loc = expr.loc;
  69. dep.optional = !!parser.scope.inTry;
  70. parser.state.current.addDependency(dep);
  71. return true;
  72. });
  73. const createHandler = callNew => expr => {
  74. if (expr.arguments.length !== 1) return;
  75. let localModule;
  76. const param = parser.evaluateExpression(expr.arguments[0]);
  77. if (param.isConditional()) {
  78. let isExpression = false;
  79. const prevLength = parser.state.current.dependencies.length;
  80. const dep = new RequireHeaderDependency(expr.callee.range);
  81. dep.loc = expr.loc;
  82. parser.state.current.addDependency(dep);
  83. for (const p of param.options) {
  84. const result = processItem(expr, p);
  85. if (result === undefined) {
  86. isExpression = true;
  87. }
  88. }
  89. if (isExpression) {
  90. parser.state.current.dependencies.length = prevLength;
  91. } else {
  92. return true;
  93. }
  94. }
  95. if (
  96. param.isString() &&
  97. (localModule = LocalModulesHelpers.getLocalModule(
  98. parser.state,
  99. param.string
  100. ))
  101. ) {
  102. const dep = new LocalModuleDependency(localModule, expr.range, callNew);
  103. dep.loc = expr.loc;
  104. parser.state.current.addDependency(dep);
  105. return true;
  106. } else {
  107. const result = processItem(expr, param);
  108. if (result === undefined) {
  109. processContext(expr, param);
  110. } else {
  111. const dep = new RequireHeaderDependency(expr.callee.range);
  112. dep.loc = expr.loc;
  113. parser.state.current.addDependency(dep);
  114. }
  115. return true;
  116. }
  117. };
  118. parser.hooks.call
  119. .for("require")
  120. .tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
  121. parser.hooks.new
  122. .for("require")
  123. .tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
  124. parser.hooks.call
  125. .for("module.require")
  126. .tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
  127. parser.hooks.new
  128. .for("module.require")
  129. .tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
  130. }
  131. }
  132. module.exports = CommonJsRequireDependencyParserPlugin;