AMDPlugin.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const {
  7. JAVASCRIPT_MODULE_TYPE_AUTO,
  8. JAVASCRIPT_MODULE_TYPE_DYNAMIC
  9. } = require("../ModuleTypeConstants");
  10. const RuntimeGlobals = require("../RuntimeGlobals");
  11. const {
  12. approve,
  13. evaluateToIdentifier,
  14. evaluateToString,
  15. toConstantDependency
  16. } = require("../javascript/JavascriptParserHelpers");
  17. const AMDDefineDependency = require("./AMDDefineDependency");
  18. const AMDDefineDependencyParserPlugin = require("./AMDDefineDependencyParserPlugin");
  19. const AMDRequireArrayDependency = require("./AMDRequireArrayDependency");
  20. const AMDRequireContextDependency = require("./AMDRequireContextDependency");
  21. const AMDRequireDependenciesBlockParserPlugin = require("./AMDRequireDependenciesBlockParserPlugin");
  22. const AMDRequireDependency = require("./AMDRequireDependency");
  23. const AMDRequireItemDependency = require("./AMDRequireItemDependency");
  24. const {
  25. AMDDefineRuntimeModule,
  26. AMDOptionsRuntimeModule
  27. } = require("./AMDRuntimeModules");
  28. const ConstDependency = require("./ConstDependency");
  29. const LocalModuleDependency = require("./LocalModuleDependency");
  30. const UnsupportedDependency = require("./UnsupportedDependency");
  31. /** @typedef {import("../../declarations/WebpackOptions").Amd} Amd */
  32. /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
  33. /** @typedef {import("../Compiler")} Compiler */
  34. /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
  35. /** @typedef {import("../javascript/JavascriptParser")} Parser */
  36. /** @typedef {import("../javascript/JavascriptParser").Range} Range */
  37. /** @typedef {import("../javascript/BasicEvaluatedExpression").GetMembers} GetMembers */
  38. const PLUGIN_NAME = "AMDPlugin";
  39. /** @typedef {Exclude<Amd, false>} AmdOptions */
  40. class AMDPlugin {
  41. /**
  42. * Creates an instance of AMDPlugin.
  43. * @param {AmdOptions} amdOptions the AMD options
  44. */
  45. constructor(amdOptions) {
  46. this.amdOptions = amdOptions;
  47. }
  48. /**
  49. * Applies the plugin by registering its hooks on the compiler.
  50. * @param {Compiler} compiler the compiler instance
  51. * @returns {void}
  52. */
  53. apply(compiler) {
  54. const { amdOptions } = this;
  55. compiler.hooks.compilation.tap(
  56. PLUGIN_NAME,
  57. (compilation, { contextModuleFactory, normalModuleFactory }) => {
  58. compilation.dependencyTemplates.set(
  59. AMDRequireDependency,
  60. new AMDRequireDependency.Template()
  61. );
  62. compilation.dependencyFactories.set(
  63. AMDRequireItemDependency,
  64. normalModuleFactory
  65. );
  66. compilation.dependencyTemplates.set(
  67. AMDRequireItemDependency,
  68. new AMDRequireItemDependency.Template()
  69. );
  70. compilation.dependencyTemplates.set(
  71. AMDRequireArrayDependency,
  72. new AMDRequireArrayDependency.Template()
  73. );
  74. compilation.dependencyFactories.set(
  75. AMDRequireContextDependency,
  76. contextModuleFactory
  77. );
  78. compilation.dependencyTemplates.set(
  79. AMDRequireContextDependency,
  80. new AMDRequireContextDependency.Template()
  81. );
  82. compilation.dependencyTemplates.set(
  83. AMDDefineDependency,
  84. new AMDDefineDependency.Template()
  85. );
  86. compilation.dependencyTemplates.set(
  87. UnsupportedDependency,
  88. new UnsupportedDependency.Template()
  89. );
  90. compilation.dependencyTemplates.set(
  91. LocalModuleDependency,
  92. new LocalModuleDependency.Template()
  93. );
  94. compilation.hooks.runtimeRequirementInModule
  95. .for(RuntimeGlobals.amdDefine)
  96. .tap(PLUGIN_NAME, (module, set) => {
  97. set.add(RuntimeGlobals.require);
  98. });
  99. compilation.hooks.runtimeRequirementInModule
  100. .for(RuntimeGlobals.amdOptions)
  101. .tap(PLUGIN_NAME, (module, set) => {
  102. set.add(RuntimeGlobals.requireScope);
  103. });
  104. compilation.hooks.runtimeRequirementInTree
  105. .for(RuntimeGlobals.amdDefine)
  106. .tap(PLUGIN_NAME, (chunk, _set) => {
  107. compilation.addRuntimeModule(chunk, new AMDDefineRuntimeModule());
  108. });
  109. compilation.hooks.runtimeRequirementInTree
  110. .for(RuntimeGlobals.amdOptions)
  111. .tap(PLUGIN_NAME, (chunk, _set) => {
  112. compilation.addRuntimeModule(
  113. chunk,
  114. new AMDOptionsRuntimeModule(amdOptions)
  115. );
  116. });
  117. /**
  118. * Handles the hook callback for this code path.
  119. * @param {Parser} parser parser parser
  120. * @param {JavascriptParserOptions} parserOptions parserOptions
  121. * @returns {void}
  122. */
  123. const handler = (parser, parserOptions) => {
  124. if (parserOptions.amd !== undefined && !parserOptions.amd) return;
  125. /**
  126. * Processes the provided option expr.
  127. * @param {string} optionExpr option expression
  128. * @param {string} rootName root name
  129. * @param {GetMembers} getMembers callback
  130. */
  131. const tapOptionsHooks = (optionExpr, rootName, getMembers) => {
  132. parser.hooks.expression
  133. .for(optionExpr)
  134. .tap(
  135. PLUGIN_NAME,
  136. toConstantDependency(parser, RuntimeGlobals.amdOptions, [
  137. RuntimeGlobals.amdOptions
  138. ])
  139. );
  140. parser.hooks.evaluateIdentifier
  141. .for(optionExpr)
  142. .tap(PLUGIN_NAME, (expr) =>
  143. evaluateToIdentifier(
  144. optionExpr,
  145. rootName,
  146. getMembers,
  147. true
  148. )(expr)
  149. );
  150. parser.hooks.evaluateTypeof
  151. .for(optionExpr)
  152. .tap(PLUGIN_NAME, evaluateToString("object"));
  153. parser.hooks.typeof
  154. .for(optionExpr)
  155. .tap(
  156. PLUGIN_NAME,
  157. toConstantDependency(parser, JSON.stringify("object"))
  158. );
  159. };
  160. new AMDRequireDependenciesBlockParserPlugin(parserOptions).apply(
  161. parser
  162. );
  163. new AMDDefineDependencyParserPlugin(parserOptions).apply(parser);
  164. tapOptionsHooks("define.amd", "define", () => ["amd"]);
  165. tapOptionsHooks("require.amd", "require", () => ["amd"]);
  166. tapOptionsHooks(
  167. "__webpack_amd_options__",
  168. "__webpack_amd_options__",
  169. () => []
  170. );
  171. parser.hooks.expression.for("define").tap(PLUGIN_NAME, (expr) => {
  172. const dep = new ConstDependency(
  173. RuntimeGlobals.amdDefine,
  174. /** @type {Range} */ (expr.range),
  175. [RuntimeGlobals.amdDefine]
  176. );
  177. dep.loc = /** @type {DependencyLocation} */ (expr.loc);
  178. parser.state.module.addPresentationalDependency(dep);
  179. return true;
  180. });
  181. parser.hooks.typeof
  182. .for("define")
  183. .tap(
  184. PLUGIN_NAME,
  185. toConstantDependency(parser, JSON.stringify("function"))
  186. );
  187. parser.hooks.evaluateTypeof
  188. .for("define")
  189. .tap(PLUGIN_NAME, evaluateToString("function"));
  190. parser.hooks.canRename.for("define").tap(PLUGIN_NAME, approve);
  191. parser.hooks.rename.for("define").tap(PLUGIN_NAME, (expr) => {
  192. const dep = new ConstDependency(
  193. RuntimeGlobals.amdDefine,
  194. /** @type {Range} */ (expr.range),
  195. [RuntimeGlobals.amdDefine]
  196. );
  197. dep.loc = /** @type {DependencyLocation} */ (expr.loc);
  198. parser.state.module.addPresentationalDependency(dep);
  199. return false;
  200. });
  201. parser.hooks.typeof
  202. .for("require")
  203. .tap(
  204. PLUGIN_NAME,
  205. toConstantDependency(parser, JSON.stringify("function"))
  206. );
  207. parser.hooks.evaluateTypeof
  208. .for("require")
  209. .tap(PLUGIN_NAME, evaluateToString("function"));
  210. };
  211. normalModuleFactory.hooks.parser
  212. .for(JAVASCRIPT_MODULE_TYPE_AUTO)
  213. .tap(PLUGIN_NAME, handler);
  214. normalModuleFactory.hooks.parser
  215. .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
  216. .tap(PLUGIN_NAME, handler);
  217. }
  218. );
  219. }
  220. }
  221. module.exports = AMDPlugin;