APIPlugin.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. JAVASCRIPT_MODULE_TYPE_ESM
  10. } = require("./ModuleTypeConstants");
  11. const RuntimeGlobals = require("./RuntimeGlobals");
  12. const WebpackError = require("./WebpackError");
  13. const ConstDependency = require("./dependencies/ConstDependency");
  14. const BasicEvaluatedExpression = require("./javascript/BasicEvaluatedExpression");
  15. const {
  16. toConstantDependency,
  17. evaluateToString
  18. } = require("./javascript/JavascriptParserHelpers");
  19. const ChunkNameRuntimeModule = require("./runtime/ChunkNameRuntimeModule");
  20. const GetFullHashRuntimeModule = require("./runtime/GetFullHashRuntimeModule");
  21. /** @typedef {import("./Compiler")} Compiler */
  22. /** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
  23. /* eslint-disable camelcase */
  24. const REPLACEMENTS = {
  25. __webpack_require__: {
  26. expr: RuntimeGlobals.require,
  27. req: [RuntimeGlobals.require],
  28. type: "function",
  29. assign: false
  30. },
  31. __webpack_public_path__: {
  32. expr: RuntimeGlobals.publicPath,
  33. req: [RuntimeGlobals.publicPath],
  34. type: "string",
  35. assign: true
  36. },
  37. __webpack_base_uri__: {
  38. expr: RuntimeGlobals.baseURI,
  39. req: [RuntimeGlobals.baseURI],
  40. type: "string",
  41. assign: true
  42. },
  43. __webpack_modules__: {
  44. expr: RuntimeGlobals.moduleFactories,
  45. req: [RuntimeGlobals.moduleFactories],
  46. type: "object",
  47. assign: false
  48. },
  49. __webpack_chunk_load__: {
  50. expr: RuntimeGlobals.ensureChunk,
  51. req: [RuntimeGlobals.ensureChunk],
  52. type: "function",
  53. assign: true
  54. },
  55. __non_webpack_require__: {
  56. expr: "require",
  57. req: null,
  58. type: undefined, // type is not known, depends on environment
  59. assign: true
  60. },
  61. __webpack_nonce__: {
  62. expr: RuntimeGlobals.scriptNonce,
  63. req: [RuntimeGlobals.scriptNonce],
  64. type: "string",
  65. assign: true
  66. },
  67. __webpack_hash__: {
  68. expr: `${RuntimeGlobals.getFullHash}()`,
  69. req: [RuntimeGlobals.getFullHash],
  70. type: "string",
  71. assign: false
  72. },
  73. __webpack_chunkname__: {
  74. expr: RuntimeGlobals.chunkName,
  75. req: [RuntimeGlobals.chunkName],
  76. type: "string",
  77. assign: false
  78. },
  79. __webpack_get_script_filename__: {
  80. expr: RuntimeGlobals.getChunkScriptFilename,
  81. req: [RuntimeGlobals.getChunkScriptFilename],
  82. type: "function",
  83. assign: true
  84. },
  85. __webpack_runtime_id__: {
  86. expr: RuntimeGlobals.runtimeId,
  87. req: [RuntimeGlobals.runtimeId],
  88. assign: false
  89. },
  90. "require.onError": {
  91. expr: RuntimeGlobals.uncaughtErrorHandler,
  92. req: [RuntimeGlobals.uncaughtErrorHandler],
  93. type: undefined, // type is not known, could be function or undefined
  94. assign: true // is never a pattern
  95. },
  96. __system_context__: {
  97. expr: RuntimeGlobals.systemContext,
  98. req: [RuntimeGlobals.systemContext],
  99. type: "object",
  100. assign: false
  101. },
  102. __webpack_share_scopes__: {
  103. expr: RuntimeGlobals.shareScopeMap,
  104. req: [RuntimeGlobals.shareScopeMap],
  105. type: "object",
  106. assign: false
  107. },
  108. __webpack_init_sharing__: {
  109. expr: RuntimeGlobals.initializeSharing,
  110. req: [RuntimeGlobals.initializeSharing],
  111. type: "function",
  112. assign: true
  113. }
  114. };
  115. /* eslint-enable camelcase */
  116. const PLUGIN_NAME = "APIPlugin";
  117. class APIPlugin {
  118. /**
  119. * Apply the plugin
  120. * @param {Compiler} compiler the compiler instance
  121. * @returns {void}
  122. */
  123. apply(compiler) {
  124. compiler.hooks.compilation.tap(
  125. PLUGIN_NAME,
  126. (compilation, { normalModuleFactory }) => {
  127. compilation.dependencyTemplates.set(
  128. ConstDependency,
  129. new ConstDependency.Template()
  130. );
  131. compilation.hooks.runtimeRequirementInTree
  132. .for(RuntimeGlobals.chunkName)
  133. .tap(PLUGIN_NAME, chunk => {
  134. compilation.addRuntimeModule(
  135. chunk,
  136. new ChunkNameRuntimeModule(chunk.name)
  137. );
  138. return true;
  139. });
  140. compilation.hooks.runtimeRequirementInTree
  141. .for(RuntimeGlobals.getFullHash)
  142. .tap(PLUGIN_NAME, (chunk, set) => {
  143. compilation.addRuntimeModule(chunk, new GetFullHashRuntimeModule());
  144. return true;
  145. });
  146. /**
  147. * @param {JavascriptParser} parser the parser
  148. */
  149. const handler = parser => {
  150. Object.keys(REPLACEMENTS).forEach(key => {
  151. const info = REPLACEMENTS[key];
  152. parser.hooks.expression
  153. .for(key)
  154. .tap(
  155. PLUGIN_NAME,
  156. toConstantDependency(parser, info.expr, info.req)
  157. );
  158. if (info.assign === false) {
  159. parser.hooks.assign.for(key).tap(PLUGIN_NAME, expr => {
  160. const err = new WebpackError(`${key} must not be assigned`);
  161. err.loc = expr.loc;
  162. throw err;
  163. });
  164. }
  165. if (info.type) {
  166. parser.hooks.evaluateTypeof
  167. .for(key)
  168. .tap(PLUGIN_NAME, evaluateToString(info.type));
  169. }
  170. });
  171. parser.hooks.expression
  172. .for("__webpack_layer__")
  173. .tap(PLUGIN_NAME, expr => {
  174. const dep = new ConstDependency(
  175. JSON.stringify(parser.state.module.layer),
  176. expr.range
  177. );
  178. dep.loc = expr.loc;
  179. parser.state.module.addPresentationalDependency(dep);
  180. return true;
  181. });
  182. parser.hooks.evaluateIdentifier
  183. .for("__webpack_layer__")
  184. .tap(PLUGIN_NAME, expr =>
  185. (parser.state.module.layer === null
  186. ? new BasicEvaluatedExpression().setNull()
  187. : new BasicEvaluatedExpression().setString(
  188. parser.state.module.layer
  189. )
  190. ).setRange(expr.range)
  191. );
  192. parser.hooks.evaluateTypeof
  193. .for("__webpack_layer__")
  194. .tap(PLUGIN_NAME, expr =>
  195. new BasicEvaluatedExpression()
  196. .setString(
  197. parser.state.module.layer === null ? "object" : "string"
  198. )
  199. .setRange(expr.range)
  200. );
  201. parser.hooks.expression
  202. .for("__webpack_module__.id")
  203. .tap(PLUGIN_NAME, expr => {
  204. parser.state.module.buildInfo.moduleConcatenationBailout =
  205. "__webpack_module__.id";
  206. const dep = new ConstDependency(
  207. parser.state.module.moduleArgument + ".id",
  208. expr.range,
  209. [RuntimeGlobals.moduleId]
  210. );
  211. dep.loc = expr.loc;
  212. parser.state.module.addPresentationalDependency(dep);
  213. return true;
  214. });
  215. parser.hooks.expression
  216. .for("__webpack_module__")
  217. .tap(PLUGIN_NAME, expr => {
  218. parser.state.module.buildInfo.moduleConcatenationBailout =
  219. "__webpack_module__";
  220. const dep = new ConstDependency(
  221. parser.state.module.moduleArgument,
  222. expr.range,
  223. [RuntimeGlobals.module]
  224. );
  225. dep.loc = expr.loc;
  226. parser.state.module.addPresentationalDependency(dep);
  227. return true;
  228. });
  229. parser.hooks.evaluateTypeof
  230. .for("__webpack_module__")
  231. .tap(PLUGIN_NAME, evaluateToString("object"));
  232. };
  233. normalModuleFactory.hooks.parser
  234. .for(JAVASCRIPT_MODULE_TYPE_AUTO)
  235. .tap(PLUGIN_NAME, handler);
  236. normalModuleFactory.hooks.parser
  237. .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
  238. .tap(PLUGIN_NAME, handler);
  239. normalModuleFactory.hooks.parser
  240. .for(JAVASCRIPT_MODULE_TYPE_ESM)
  241. .tap(PLUGIN_NAME, handler);
  242. }
  243. );
  244. }
  245. }
  246. module.exports = APIPlugin;