AMDPlugin.js 7.1 KB

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