JavascriptModulesPlugin.js 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { SyncWaterfallHook, SyncHook, SyncBailHook } = require("tapable");
  7. const vm = require("vm");
  8. const {
  9. ConcatSource,
  10. OriginalSource,
  11. PrefixSource,
  12. RawSource,
  13. CachedSource
  14. } = require("webpack-sources");
  15. const Compilation = require("../Compilation");
  16. const { tryRunOrWebpackError } = require("../HookWebpackError");
  17. const HotUpdateChunk = require("../HotUpdateChunk");
  18. const InitFragment = require("../InitFragment");
  19. const {
  20. JAVASCRIPT_MODULE_TYPE_AUTO,
  21. JAVASCRIPT_MODULE_TYPE_DYNAMIC,
  22. JAVASCRIPT_MODULE_TYPE_ESM
  23. } = require("../ModuleTypeConstants");
  24. const RuntimeGlobals = require("../RuntimeGlobals");
  25. const Template = require("../Template");
  26. const { last, someInIterable } = require("../util/IterableHelpers");
  27. const StringXor = require("../util/StringXor");
  28. const { compareModulesByIdentifier } = require("../util/comparators");
  29. const createHash = require("../util/createHash");
  30. const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
  31. const { intersectRuntime } = require("../util/runtime");
  32. const JavascriptGenerator = require("./JavascriptGenerator");
  33. const JavascriptParser = require("./JavascriptParser");
  34. /** @typedef {import("webpack-sources").Source} Source */
  35. /** @typedef {import("../Chunk")} Chunk */
  36. /** @typedef {import("../ChunkGraph")} ChunkGraph */
  37. /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
  38. /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
  39. /** @typedef {import("../Compiler")} Compiler */
  40. /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
  41. /** @typedef {import("../Module")} Module */
  42. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  43. /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
  44. /** @typedef {import("../util/Hash")} Hash */
  45. /**
  46. * @param {Chunk} chunk a chunk
  47. * @param {ChunkGraph} chunkGraph the chunk graph
  48. * @returns {boolean} true, when a JS file is needed for this chunk
  49. */
  50. const chunkHasJs = (chunk, chunkGraph) => {
  51. if (chunkGraph.getNumberOfEntryModules(chunk) > 0) return true;
  52. return chunkGraph.getChunkModulesIterableBySourceType(chunk, "javascript")
  53. ? true
  54. : false;
  55. };
  56. const printGeneratedCodeForStack = (module, code) => {
  57. const lines = code.split("\n");
  58. const n = `${lines.length}`.length;
  59. return `\n\nGenerated code for ${module.identifier()}\n${lines
  60. .map((line, i, lines) => {
  61. const iStr = `${i + 1}`;
  62. return `${" ".repeat(n - iStr.length)}${iStr} | ${line}`;
  63. })
  64. .join("\n")}`;
  65. };
  66. /**
  67. * @typedef {Object} RenderContext
  68. * @property {Chunk} chunk the chunk
  69. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  70. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  71. * @property {ModuleGraph} moduleGraph the module graph
  72. * @property {ChunkGraph} chunkGraph the chunk graph
  73. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  74. * @property {boolean} strictMode rendering in strict context
  75. */
  76. /**
  77. * @typedef {Object} MainRenderContext
  78. * @property {Chunk} chunk the chunk
  79. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  80. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  81. * @property {ModuleGraph} moduleGraph the module graph
  82. * @property {ChunkGraph} chunkGraph the chunk graph
  83. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  84. * @property {string} hash hash to be used for render call
  85. * @property {boolean} strictMode rendering in strict context
  86. */
  87. /**
  88. * @typedef {Object} ChunkRenderContext
  89. * @property {Chunk} chunk the chunk
  90. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  91. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  92. * @property {ModuleGraph} moduleGraph the module graph
  93. * @property {ChunkGraph} chunkGraph the chunk graph
  94. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  95. * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
  96. * @property {boolean} strictMode rendering in strict context
  97. */
  98. /**
  99. * @typedef {Object} RenderBootstrapContext
  100. * @property {Chunk} chunk the chunk
  101. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  102. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  103. * @property {ModuleGraph} moduleGraph the module graph
  104. * @property {ChunkGraph} chunkGraph the chunk graph
  105. * @property {string} hash hash to be used for render call
  106. */
  107. /** @typedef {RenderContext & { inlined: boolean }} StartupRenderContext */
  108. /**
  109. * @typedef {Object} CompilationHooks
  110. * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContent
  111. * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContainer
  112. * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModulePackage
  113. * @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
  114. * @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
  115. * @property {SyncWaterfallHook<[Source, RenderContext]>} renderContent
  116. * @property {SyncWaterfallHook<[Source, RenderContext]>} render
  117. * @property {SyncWaterfallHook<[Source, Module, StartupRenderContext]>} renderStartup
  118. * @property {SyncWaterfallHook<[string, RenderBootstrapContext]>} renderRequire
  119. * @property {SyncBailHook<[Module, RenderBootstrapContext], string>} inlineInRuntimeBailout
  120. * @property {SyncBailHook<[Module, RenderContext], string>} embedInRuntimeBailout
  121. * @property {SyncBailHook<[RenderContext], string>} strictRuntimeBailout
  122. * @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
  123. * @property {SyncBailHook<[Chunk, RenderContext], boolean>} useSourceMap
  124. */
  125. /** @type {WeakMap<Compilation, CompilationHooks>} */
  126. const compilationHooksMap = new WeakMap();
  127. const PLUGIN_NAME = "JavascriptModulesPlugin";
  128. class JavascriptModulesPlugin {
  129. /**
  130. * @param {Compilation} compilation the compilation
  131. * @returns {CompilationHooks} the attached hooks
  132. */
  133. static getCompilationHooks(compilation) {
  134. if (!(compilation instanceof Compilation)) {
  135. throw new TypeError(
  136. "The 'compilation' argument must be an instance of Compilation"
  137. );
  138. }
  139. let hooks = compilationHooksMap.get(compilation);
  140. if (hooks === undefined) {
  141. hooks = {
  142. renderModuleContent: new SyncWaterfallHook([
  143. "source",
  144. "module",
  145. "renderContext"
  146. ]),
  147. renderModuleContainer: new SyncWaterfallHook([
  148. "source",
  149. "module",
  150. "renderContext"
  151. ]),
  152. renderModulePackage: new SyncWaterfallHook([
  153. "source",
  154. "module",
  155. "renderContext"
  156. ]),
  157. render: new SyncWaterfallHook(["source", "renderContext"]),
  158. renderContent: new SyncWaterfallHook(["source", "renderContext"]),
  159. renderStartup: new SyncWaterfallHook([
  160. "source",
  161. "module",
  162. "startupRenderContext"
  163. ]),
  164. renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
  165. renderMain: new SyncWaterfallHook(["source", "renderContext"]),
  166. renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
  167. inlineInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
  168. embedInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
  169. strictRuntimeBailout: new SyncBailHook(["renderContext"]),
  170. chunkHash: new SyncHook(["chunk", "hash", "context"]),
  171. useSourceMap: new SyncBailHook(["chunk", "renderContext"])
  172. };
  173. compilationHooksMap.set(compilation, hooks);
  174. }
  175. return hooks;
  176. }
  177. constructor(options = {}) {
  178. this.options = options;
  179. /** @type {WeakMap<Source, TODO>} */
  180. this._moduleFactoryCache = new WeakMap();
  181. }
  182. /**
  183. * Apply the plugin
  184. * @param {Compiler} compiler the compiler instance
  185. * @returns {void}
  186. */
  187. apply(compiler) {
  188. compiler.hooks.compilation.tap(
  189. PLUGIN_NAME,
  190. (compilation, { normalModuleFactory }) => {
  191. const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
  192. normalModuleFactory.hooks.createParser
  193. .for(JAVASCRIPT_MODULE_TYPE_AUTO)
  194. .tap(PLUGIN_NAME, options => {
  195. return new JavascriptParser("auto");
  196. });
  197. normalModuleFactory.hooks.createParser
  198. .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
  199. .tap(PLUGIN_NAME, options => {
  200. return new JavascriptParser("script");
  201. });
  202. normalModuleFactory.hooks.createParser
  203. .for(JAVASCRIPT_MODULE_TYPE_ESM)
  204. .tap(PLUGIN_NAME, options => {
  205. return new JavascriptParser("module");
  206. });
  207. normalModuleFactory.hooks.createGenerator
  208. .for(JAVASCRIPT_MODULE_TYPE_AUTO)
  209. .tap(PLUGIN_NAME, () => {
  210. return new JavascriptGenerator();
  211. });
  212. normalModuleFactory.hooks.createGenerator
  213. .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
  214. .tap(PLUGIN_NAME, () => {
  215. return new JavascriptGenerator();
  216. });
  217. normalModuleFactory.hooks.createGenerator
  218. .for(JAVASCRIPT_MODULE_TYPE_ESM)
  219. .tap(PLUGIN_NAME, () => {
  220. return new JavascriptGenerator();
  221. });
  222. compilation.hooks.renderManifest.tap(PLUGIN_NAME, (result, options) => {
  223. const {
  224. hash,
  225. chunk,
  226. chunkGraph,
  227. moduleGraph,
  228. runtimeTemplate,
  229. dependencyTemplates,
  230. outputOptions,
  231. codeGenerationResults
  232. } = options;
  233. const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
  234. let render;
  235. const filenameTemplate =
  236. JavascriptModulesPlugin.getChunkFilenameTemplate(
  237. chunk,
  238. outputOptions
  239. );
  240. if (hotUpdateChunk) {
  241. render = () =>
  242. this.renderChunk(
  243. {
  244. chunk,
  245. dependencyTemplates,
  246. runtimeTemplate,
  247. moduleGraph,
  248. chunkGraph,
  249. codeGenerationResults,
  250. strictMode: runtimeTemplate.isModule()
  251. },
  252. hooks
  253. );
  254. } else if (chunk.hasRuntime()) {
  255. render = () =>
  256. this.renderMain(
  257. {
  258. hash,
  259. chunk,
  260. dependencyTemplates,
  261. runtimeTemplate,
  262. moduleGraph,
  263. chunkGraph,
  264. codeGenerationResults,
  265. strictMode: runtimeTemplate.isModule()
  266. },
  267. hooks,
  268. compilation
  269. );
  270. } else {
  271. if (!chunkHasJs(chunk, chunkGraph)) {
  272. return result;
  273. }
  274. render = () =>
  275. this.renderChunk(
  276. {
  277. chunk,
  278. dependencyTemplates,
  279. runtimeTemplate,
  280. moduleGraph,
  281. chunkGraph,
  282. codeGenerationResults,
  283. strictMode: runtimeTemplate.isModule()
  284. },
  285. hooks
  286. );
  287. }
  288. result.push({
  289. render,
  290. filenameTemplate,
  291. pathOptions: {
  292. hash,
  293. runtime: chunk.runtime,
  294. chunk,
  295. contentHashType: "javascript"
  296. },
  297. info: {
  298. javascriptModule: compilation.runtimeTemplate.isModule()
  299. },
  300. identifier: hotUpdateChunk
  301. ? `hotupdatechunk${chunk.id}`
  302. : `chunk${chunk.id}`,
  303. hash: chunk.contentHash.javascript
  304. });
  305. return result;
  306. });
  307. compilation.hooks.chunkHash.tap(PLUGIN_NAME, (chunk, hash, context) => {
  308. hooks.chunkHash.call(chunk, hash, context);
  309. if (chunk.hasRuntime()) {
  310. this.updateHashWithBootstrap(
  311. hash,
  312. {
  313. hash: "0000",
  314. chunk,
  315. codeGenerationResults: context.codeGenerationResults,
  316. chunkGraph: context.chunkGraph,
  317. moduleGraph: context.moduleGraph,
  318. runtimeTemplate: context.runtimeTemplate
  319. },
  320. hooks
  321. );
  322. }
  323. });
  324. compilation.hooks.contentHash.tap(PLUGIN_NAME, chunk => {
  325. const {
  326. chunkGraph,
  327. codeGenerationResults,
  328. moduleGraph,
  329. runtimeTemplate,
  330. outputOptions: {
  331. hashSalt,
  332. hashDigest,
  333. hashDigestLength,
  334. hashFunction
  335. }
  336. } = compilation;
  337. const hash = createHash(hashFunction);
  338. if (hashSalt) hash.update(hashSalt);
  339. if (chunk.hasRuntime()) {
  340. this.updateHashWithBootstrap(
  341. hash,
  342. {
  343. hash: "0000",
  344. chunk,
  345. codeGenerationResults,
  346. chunkGraph: compilation.chunkGraph,
  347. moduleGraph: compilation.moduleGraph,
  348. runtimeTemplate: compilation.runtimeTemplate
  349. },
  350. hooks
  351. );
  352. } else {
  353. hash.update(`${chunk.id} `);
  354. hash.update(chunk.ids ? chunk.ids.join(",") : "");
  355. }
  356. hooks.chunkHash.call(chunk, hash, {
  357. chunkGraph,
  358. codeGenerationResults,
  359. moduleGraph,
  360. runtimeTemplate
  361. });
  362. const modules = chunkGraph.getChunkModulesIterableBySourceType(
  363. chunk,
  364. "javascript"
  365. );
  366. if (modules) {
  367. const xor = new StringXor();
  368. for (const m of modules) {
  369. xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
  370. }
  371. xor.updateHash(hash);
  372. }
  373. const runtimeModules = chunkGraph.getChunkModulesIterableBySourceType(
  374. chunk,
  375. "runtime"
  376. );
  377. if (runtimeModules) {
  378. const xor = new StringXor();
  379. for (const m of runtimeModules) {
  380. xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
  381. }
  382. xor.updateHash(hash);
  383. }
  384. const digest = /** @type {string} */ (hash.digest(hashDigest));
  385. chunk.contentHash.javascript = nonNumericOnlyHash(
  386. digest,
  387. hashDigestLength
  388. );
  389. });
  390. compilation.hooks.additionalTreeRuntimeRequirements.tap(
  391. PLUGIN_NAME,
  392. (chunk, set, { chunkGraph }) => {
  393. if (
  394. !set.has(RuntimeGlobals.startupNoDefault) &&
  395. chunkGraph.hasChunkEntryDependentChunks(chunk)
  396. ) {
  397. set.add(RuntimeGlobals.onChunksLoaded);
  398. set.add(RuntimeGlobals.require);
  399. }
  400. }
  401. );
  402. compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
  403. const source = options.codeGenerationResult.sources.get("javascript");
  404. if (source === undefined) return;
  405. const { module, moduleObject } = options;
  406. const code = source.source();
  407. const fn = vm.runInThisContext(
  408. `(function(${module.moduleArgument}, ${module.exportsArgument}, __webpack_require__) {\n${code}\n/**/})`,
  409. {
  410. filename: module.identifier(),
  411. lineOffset: -1
  412. }
  413. );
  414. try {
  415. fn.call(
  416. moduleObject.exports,
  417. moduleObject,
  418. moduleObject.exports,
  419. context.__webpack_require__
  420. );
  421. } catch (e) {
  422. e.stack += printGeneratedCodeForStack(options.module, code);
  423. throw e;
  424. }
  425. });
  426. compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
  427. const source = options.codeGenerationResult.sources.get("runtime");
  428. if (source === undefined) return;
  429. let code = source.source();
  430. if (typeof code !== "string") code = code.toString();
  431. const fn = vm.runInThisContext(
  432. `(function(__webpack_require__) {\n${code}\n/**/})`,
  433. {
  434. filename: options.module.identifier(),
  435. lineOffset: -1
  436. }
  437. );
  438. try {
  439. fn.call(null, context.__webpack_require__);
  440. } catch (e) {
  441. e.stack += printGeneratedCodeForStack(options.module, code);
  442. throw e;
  443. }
  444. });
  445. }
  446. );
  447. }
  448. static getChunkFilenameTemplate(chunk, outputOptions) {
  449. if (chunk.filenameTemplate) {
  450. return chunk.filenameTemplate;
  451. } else if (chunk instanceof HotUpdateChunk) {
  452. return outputOptions.hotUpdateChunkFilename;
  453. } else if (chunk.canBeInitial()) {
  454. return outputOptions.filename;
  455. } else {
  456. return outputOptions.chunkFilename;
  457. }
  458. }
  459. /**
  460. * @param {Module} module the rendered module
  461. * @param {ChunkRenderContext} renderContext options object
  462. * @param {CompilationHooks} hooks hooks
  463. * @param {boolean} factory true: renders as factory method, false: pure module content
  464. * @returns {Source} the newly generated source from rendering
  465. */
  466. renderModule(module, renderContext, hooks, factory) {
  467. const {
  468. chunk,
  469. chunkGraph,
  470. runtimeTemplate,
  471. codeGenerationResults,
  472. strictMode
  473. } = renderContext;
  474. try {
  475. const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
  476. const moduleSource = codeGenResult.sources.get("javascript");
  477. if (!moduleSource) return null;
  478. if (codeGenResult.data !== undefined) {
  479. const chunkInitFragments = codeGenResult.data.get("chunkInitFragments");
  480. if (chunkInitFragments) {
  481. for (const i of chunkInitFragments)
  482. renderContext.chunkInitFragments.push(i);
  483. }
  484. }
  485. const moduleSourcePostContent = tryRunOrWebpackError(
  486. () =>
  487. hooks.renderModuleContent.call(moduleSource, module, renderContext),
  488. "JavascriptModulesPlugin.getCompilationHooks().renderModuleContent"
  489. );
  490. let moduleSourcePostContainer;
  491. if (factory) {
  492. const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
  493. module,
  494. chunk.runtime
  495. );
  496. const needModule = runtimeRequirements.has(RuntimeGlobals.module);
  497. const needExports = runtimeRequirements.has(RuntimeGlobals.exports);
  498. const needRequire =
  499. runtimeRequirements.has(RuntimeGlobals.require) ||
  500. runtimeRequirements.has(RuntimeGlobals.requireScope);
  501. const needThisAsExports = runtimeRequirements.has(
  502. RuntimeGlobals.thisAsExports
  503. );
  504. const needStrict = module.buildInfo.strict && !strictMode;
  505. const cacheEntry = this._moduleFactoryCache.get(
  506. moduleSourcePostContent
  507. );
  508. let source;
  509. if (
  510. cacheEntry &&
  511. cacheEntry.needModule === needModule &&
  512. cacheEntry.needExports === needExports &&
  513. cacheEntry.needRequire === needRequire &&
  514. cacheEntry.needThisAsExports === needThisAsExports &&
  515. cacheEntry.needStrict === needStrict
  516. ) {
  517. source = cacheEntry.source;
  518. } else {
  519. const factorySource = new ConcatSource();
  520. const args = [];
  521. if (needExports || needRequire || needModule)
  522. args.push(
  523. needModule
  524. ? module.moduleArgument
  525. : "__unused_webpack_" + module.moduleArgument
  526. );
  527. if (needExports || needRequire)
  528. args.push(
  529. needExports
  530. ? module.exportsArgument
  531. : "__unused_webpack_" + module.exportsArgument
  532. );
  533. if (needRequire) args.push("__webpack_require__");
  534. if (!needThisAsExports && runtimeTemplate.supportsArrowFunction()) {
  535. factorySource.add("/***/ ((" + args.join(", ") + ") => {\n\n");
  536. } else {
  537. factorySource.add("/***/ (function(" + args.join(", ") + ") {\n\n");
  538. }
  539. if (needStrict) {
  540. factorySource.add('"use strict";\n');
  541. }
  542. factorySource.add(moduleSourcePostContent);
  543. factorySource.add("\n\n/***/ })");
  544. source = new CachedSource(factorySource);
  545. this._moduleFactoryCache.set(moduleSourcePostContent, {
  546. source,
  547. needModule,
  548. needExports,
  549. needRequire,
  550. needThisAsExports,
  551. needStrict
  552. });
  553. }
  554. moduleSourcePostContainer = tryRunOrWebpackError(
  555. () => hooks.renderModuleContainer.call(source, module, renderContext),
  556. "JavascriptModulesPlugin.getCompilationHooks().renderModuleContainer"
  557. );
  558. } else {
  559. moduleSourcePostContainer = moduleSourcePostContent;
  560. }
  561. return tryRunOrWebpackError(
  562. () =>
  563. hooks.renderModulePackage.call(
  564. moduleSourcePostContainer,
  565. module,
  566. renderContext
  567. ),
  568. "JavascriptModulesPlugin.getCompilationHooks().renderModulePackage"
  569. );
  570. } catch (e) {
  571. e.module = module;
  572. throw e;
  573. }
  574. }
  575. /**
  576. * @param {RenderContext} renderContext the render context
  577. * @param {CompilationHooks} hooks hooks
  578. * @returns {Source} the rendered source
  579. */
  580. renderChunk(renderContext, hooks) {
  581. const { chunk, chunkGraph } = renderContext;
  582. const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType(
  583. chunk,
  584. "javascript",
  585. compareModulesByIdentifier
  586. );
  587. const allModules = modules ? Array.from(modules) : [];
  588. let strictHeader;
  589. let allStrict = renderContext.strictMode;
  590. if (!allStrict && allModules.every(m => m.buildInfo.strict)) {
  591. const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
  592. strictHeader = strictBailout
  593. ? `// runtime can't be in strict mode because ${strictBailout}.\n`
  594. : '"use strict";\n';
  595. if (!strictBailout) allStrict = true;
  596. }
  597. /** @type {ChunkRenderContext} */
  598. const chunkRenderContext = {
  599. ...renderContext,
  600. chunkInitFragments: [],
  601. strictMode: allStrict
  602. };
  603. const moduleSources =
  604. Template.renderChunkModules(chunkRenderContext, allModules, module =>
  605. this.renderModule(module, chunkRenderContext, hooks, true)
  606. ) || new RawSource("{}");
  607. let source = tryRunOrWebpackError(
  608. () => hooks.renderChunk.call(moduleSources, chunkRenderContext),
  609. "JavascriptModulesPlugin.getCompilationHooks().renderChunk"
  610. );
  611. source = tryRunOrWebpackError(
  612. () => hooks.renderContent.call(source, chunkRenderContext),
  613. "JavascriptModulesPlugin.getCompilationHooks().renderContent"
  614. );
  615. if (!source) {
  616. throw new Error(
  617. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
  618. );
  619. }
  620. source = InitFragment.addToSource(
  621. source,
  622. chunkRenderContext.chunkInitFragments,
  623. chunkRenderContext
  624. );
  625. source = tryRunOrWebpackError(
  626. () => hooks.render.call(source, chunkRenderContext),
  627. "JavascriptModulesPlugin.getCompilationHooks().render"
  628. );
  629. if (!source) {
  630. throw new Error(
  631. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
  632. );
  633. }
  634. chunk.rendered = true;
  635. return strictHeader
  636. ? new ConcatSource(strictHeader, source, ";")
  637. : renderContext.runtimeTemplate.isModule()
  638. ? source
  639. : new ConcatSource(source, ";");
  640. }
  641. /**
  642. * @param {MainRenderContext} renderContext options object
  643. * @param {CompilationHooks} hooks hooks
  644. * @param {Compilation} compilation the compilation
  645. * @returns {Source} the newly generated source from rendering
  646. */
  647. renderMain(renderContext, hooks, compilation) {
  648. const { chunk, chunkGraph, runtimeTemplate } = renderContext;
  649. const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
  650. const iife = runtimeTemplate.isIIFE();
  651. const bootstrap = this.renderBootstrap(renderContext, hooks);
  652. const useSourceMap = hooks.useSourceMap.call(chunk, renderContext);
  653. const allModules = Array.from(
  654. chunkGraph.getOrderedChunkModulesIterableBySourceType(
  655. chunk,
  656. "javascript",
  657. compareModulesByIdentifier
  658. ) || []
  659. );
  660. const hasEntryModules = chunkGraph.getNumberOfEntryModules(chunk) > 0;
  661. let inlinedModules;
  662. if (bootstrap.allowInlineStartup && hasEntryModules) {
  663. inlinedModules = new Set(chunkGraph.getChunkEntryModulesIterable(chunk));
  664. }
  665. let source = new ConcatSource();
  666. let prefix;
  667. if (iife) {
  668. if (runtimeTemplate.supportsArrowFunction()) {
  669. source.add("/******/ (() => { // webpackBootstrap\n");
  670. } else {
  671. source.add("/******/ (function() { // webpackBootstrap\n");
  672. }
  673. prefix = "/******/ \t";
  674. } else {
  675. prefix = "/******/ ";
  676. }
  677. let allStrict = renderContext.strictMode;
  678. if (!allStrict && allModules.every(m => m.buildInfo.strict)) {
  679. const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
  680. if (strictBailout) {
  681. source.add(
  682. prefix +
  683. `// runtime can't be in strict mode because ${strictBailout}.\n`
  684. );
  685. } else {
  686. allStrict = true;
  687. source.add(prefix + '"use strict";\n');
  688. }
  689. }
  690. /** @type {ChunkRenderContext} */
  691. const chunkRenderContext = {
  692. ...renderContext,
  693. chunkInitFragments: [],
  694. strictMode: allStrict
  695. };
  696. const chunkModules = Template.renderChunkModules(
  697. chunkRenderContext,
  698. inlinedModules
  699. ? allModules.filter(m => !inlinedModules.has(m))
  700. : allModules,
  701. module => this.renderModule(module, chunkRenderContext, hooks, true),
  702. prefix
  703. );
  704. if (
  705. chunkModules ||
  706. runtimeRequirements.has(RuntimeGlobals.moduleFactories) ||
  707. runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly) ||
  708. runtimeRequirements.has(RuntimeGlobals.require)
  709. ) {
  710. source.add(prefix + "var __webpack_modules__ = (");
  711. source.add(chunkModules || "{}");
  712. source.add(");\n");
  713. source.add(
  714. "/************************************************************************/\n"
  715. );
  716. }
  717. if (bootstrap.header.length > 0) {
  718. const header = Template.asString(bootstrap.header) + "\n";
  719. source.add(
  720. new PrefixSource(
  721. prefix,
  722. useSourceMap
  723. ? new OriginalSource(header, "webpack/bootstrap")
  724. : new RawSource(header)
  725. )
  726. );
  727. source.add(
  728. "/************************************************************************/\n"
  729. );
  730. }
  731. const runtimeModules =
  732. renderContext.chunkGraph.getChunkRuntimeModulesInOrder(chunk);
  733. if (runtimeModules.length > 0) {
  734. source.add(
  735. new PrefixSource(
  736. prefix,
  737. Template.renderRuntimeModules(runtimeModules, chunkRenderContext)
  738. )
  739. );
  740. source.add(
  741. "/************************************************************************/\n"
  742. );
  743. // runtimeRuntimeModules calls codeGeneration
  744. for (const module of runtimeModules) {
  745. compilation.codeGeneratedModules.add(module);
  746. }
  747. }
  748. if (inlinedModules) {
  749. if (bootstrap.beforeStartup.length > 0) {
  750. const beforeStartup = Template.asString(bootstrap.beforeStartup) + "\n";
  751. source.add(
  752. new PrefixSource(
  753. prefix,
  754. useSourceMap
  755. ? new OriginalSource(beforeStartup, "webpack/before-startup")
  756. : new RawSource(beforeStartup)
  757. )
  758. );
  759. }
  760. const lastInlinedModule = last(inlinedModules);
  761. const startupSource = new ConcatSource();
  762. startupSource.add(`var __webpack_exports__ = {};\n`);
  763. for (const m of inlinedModules) {
  764. const renderedModule = this.renderModule(
  765. m,
  766. chunkRenderContext,
  767. hooks,
  768. false
  769. );
  770. if (renderedModule) {
  771. const innerStrict = !allStrict && m.buildInfo.strict;
  772. const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
  773. m,
  774. chunk.runtime
  775. );
  776. const exports = runtimeRequirements.has(RuntimeGlobals.exports);
  777. const webpackExports =
  778. exports && m.exportsArgument === "__webpack_exports__";
  779. let iife = innerStrict
  780. ? "it need to be in strict mode."
  781. : inlinedModules.size > 1
  782. ? // TODO check globals and top-level declarations of other entries and chunk modules
  783. // to make a better decision
  784. "it need to be isolated against other entry modules."
  785. : chunkModules
  786. ? "it need to be isolated against other modules in the chunk."
  787. : exports && !webpackExports
  788. ? `it uses a non-standard name for the exports (${m.exportsArgument}).`
  789. : hooks.embedInRuntimeBailout.call(m, renderContext);
  790. let footer;
  791. if (iife !== undefined) {
  792. startupSource.add(
  793. `// This entry need to be wrapped in an IIFE because ${iife}\n`
  794. );
  795. const arrow = runtimeTemplate.supportsArrowFunction();
  796. if (arrow) {
  797. startupSource.add("(() => {\n");
  798. footer = "\n})();\n\n";
  799. } else {
  800. startupSource.add("!function() {\n");
  801. footer = "\n}();\n";
  802. }
  803. if (innerStrict) startupSource.add('"use strict";\n');
  804. } else {
  805. footer = "\n";
  806. }
  807. if (exports) {
  808. if (m !== lastInlinedModule)
  809. startupSource.add(`var ${m.exportsArgument} = {};\n`);
  810. else if (m.exportsArgument !== "__webpack_exports__")
  811. startupSource.add(
  812. `var ${m.exportsArgument} = __webpack_exports__;\n`
  813. );
  814. }
  815. startupSource.add(renderedModule);
  816. startupSource.add(footer);
  817. }
  818. }
  819. if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
  820. startupSource.add(
  821. `__webpack_exports__ = ${RuntimeGlobals.onChunksLoaded}(__webpack_exports__);\n`
  822. );
  823. }
  824. source.add(
  825. hooks.renderStartup.call(startupSource, lastInlinedModule, {
  826. ...renderContext,
  827. inlined: true
  828. })
  829. );
  830. if (bootstrap.afterStartup.length > 0) {
  831. const afterStartup = Template.asString(bootstrap.afterStartup) + "\n";
  832. source.add(
  833. new PrefixSource(
  834. prefix,
  835. useSourceMap
  836. ? new OriginalSource(afterStartup, "webpack/after-startup")
  837. : new RawSource(afterStartup)
  838. )
  839. );
  840. }
  841. } else {
  842. const lastEntryModule = last(
  843. chunkGraph.getChunkEntryModulesIterable(chunk)
  844. );
  845. const toSource = useSourceMap
  846. ? (content, name) =>
  847. new OriginalSource(Template.asString(content), name)
  848. : content => new RawSource(Template.asString(content));
  849. source.add(
  850. new PrefixSource(
  851. prefix,
  852. new ConcatSource(
  853. toSource(bootstrap.beforeStartup, "webpack/before-startup"),
  854. "\n",
  855. hooks.renderStartup.call(
  856. toSource(bootstrap.startup.concat(""), "webpack/startup"),
  857. lastEntryModule,
  858. {
  859. ...renderContext,
  860. inlined: false
  861. }
  862. ),
  863. toSource(bootstrap.afterStartup, "webpack/after-startup"),
  864. "\n"
  865. )
  866. )
  867. );
  868. }
  869. if (
  870. hasEntryModules &&
  871. runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime)
  872. ) {
  873. source.add(`${prefix}return __webpack_exports__;\n`);
  874. }
  875. if (iife) {
  876. source.add("/******/ })()\n");
  877. }
  878. /** @type {Source} */
  879. let finalSource = tryRunOrWebpackError(
  880. () => hooks.renderMain.call(source, renderContext),
  881. "JavascriptModulesPlugin.getCompilationHooks().renderMain"
  882. );
  883. if (!finalSource) {
  884. throw new Error(
  885. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderMain plugins should return something"
  886. );
  887. }
  888. finalSource = tryRunOrWebpackError(
  889. () => hooks.renderContent.call(finalSource, renderContext),
  890. "JavascriptModulesPlugin.getCompilationHooks().renderContent"
  891. );
  892. if (!finalSource) {
  893. throw new Error(
  894. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
  895. );
  896. }
  897. finalSource = InitFragment.addToSource(
  898. finalSource,
  899. chunkRenderContext.chunkInitFragments,
  900. chunkRenderContext
  901. );
  902. finalSource = tryRunOrWebpackError(
  903. () => hooks.render.call(finalSource, renderContext),
  904. "JavascriptModulesPlugin.getCompilationHooks().render"
  905. );
  906. if (!finalSource) {
  907. throw new Error(
  908. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
  909. );
  910. }
  911. chunk.rendered = true;
  912. return iife ? new ConcatSource(finalSource, ";") : finalSource;
  913. }
  914. /**
  915. * @param {Hash} hash the hash to be updated
  916. * @param {RenderBootstrapContext} renderContext options object
  917. * @param {CompilationHooks} hooks hooks
  918. */
  919. updateHashWithBootstrap(hash, renderContext, hooks) {
  920. const bootstrap = this.renderBootstrap(renderContext, hooks);
  921. for (const key of Object.keys(bootstrap)) {
  922. hash.update(key);
  923. if (Array.isArray(bootstrap[key])) {
  924. for (const line of bootstrap[key]) {
  925. hash.update(line);
  926. }
  927. } else {
  928. hash.update(JSON.stringify(bootstrap[key]));
  929. }
  930. }
  931. }
  932. /**
  933. * @param {RenderBootstrapContext} renderContext options object
  934. * @param {CompilationHooks} hooks hooks
  935. * @returns {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} the generated source of the bootstrap code
  936. */
  937. renderBootstrap(renderContext, hooks) {
  938. const {
  939. chunkGraph,
  940. codeGenerationResults,
  941. moduleGraph,
  942. chunk,
  943. runtimeTemplate
  944. } = renderContext;
  945. const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
  946. const requireFunction = runtimeRequirements.has(RuntimeGlobals.require);
  947. const moduleCache = runtimeRequirements.has(RuntimeGlobals.moduleCache);
  948. const moduleFactories = runtimeRequirements.has(
  949. RuntimeGlobals.moduleFactories
  950. );
  951. const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
  952. const requireScopeUsed = runtimeRequirements.has(
  953. RuntimeGlobals.requireScope
  954. );
  955. const interceptModuleExecution = runtimeRequirements.has(
  956. RuntimeGlobals.interceptModuleExecution
  957. );
  958. const useRequire =
  959. requireFunction || interceptModuleExecution || moduleUsed;
  960. const result = {
  961. header: [],
  962. beforeStartup: [],
  963. startup: [],
  964. afterStartup: [],
  965. allowInlineStartup: true
  966. };
  967. let { header: buf, startup, beforeStartup, afterStartup } = result;
  968. if (result.allowInlineStartup && moduleFactories) {
  969. startup.push(
  970. "// module factories are used so entry inlining is disabled"
  971. );
  972. result.allowInlineStartup = false;
  973. }
  974. if (result.allowInlineStartup && moduleCache) {
  975. startup.push("// module cache are used so entry inlining is disabled");
  976. result.allowInlineStartup = false;
  977. }
  978. if (result.allowInlineStartup && interceptModuleExecution) {
  979. startup.push(
  980. "// module execution is intercepted so entry inlining is disabled"
  981. );
  982. result.allowInlineStartup = false;
  983. }
  984. if (useRequire || moduleCache) {
  985. buf.push("// The module cache");
  986. buf.push("var __webpack_module_cache__ = {};");
  987. buf.push("");
  988. }
  989. if (useRequire) {
  990. buf.push("// The require function");
  991. buf.push(`function __webpack_require__(moduleId) {`);
  992. buf.push(Template.indent(this.renderRequire(renderContext, hooks)));
  993. buf.push("}");
  994. buf.push("");
  995. } else if (runtimeRequirements.has(RuntimeGlobals.requireScope)) {
  996. buf.push("// The require scope");
  997. buf.push("var __webpack_require__ = {};");
  998. buf.push("");
  999. }
  1000. if (
  1001. moduleFactories ||
  1002. runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly)
  1003. ) {
  1004. buf.push("// expose the modules object (__webpack_modules__)");
  1005. buf.push(`${RuntimeGlobals.moduleFactories} = __webpack_modules__;`);
  1006. buf.push("");
  1007. }
  1008. if (moduleCache) {
  1009. buf.push("// expose the module cache");
  1010. buf.push(`${RuntimeGlobals.moduleCache} = __webpack_module_cache__;`);
  1011. buf.push("");
  1012. }
  1013. if (interceptModuleExecution) {
  1014. buf.push("// expose the module execution interceptor");
  1015. buf.push(`${RuntimeGlobals.interceptModuleExecution} = [];`);
  1016. buf.push("");
  1017. }
  1018. if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
  1019. if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
  1020. /** @type {string[]} */
  1021. const buf2 = [];
  1022. const runtimeRequirements =
  1023. chunkGraph.getTreeRuntimeRequirements(chunk);
  1024. buf2.push("// Load entry module and return exports");
  1025. let i = chunkGraph.getNumberOfEntryModules(chunk);
  1026. for (const [
  1027. entryModule,
  1028. entrypoint
  1029. ] of chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)) {
  1030. const chunks = entrypoint.chunks.filter(c => c !== chunk);
  1031. if (result.allowInlineStartup && chunks.length > 0) {
  1032. buf2.push(
  1033. "// This entry module depends on other loaded chunks and execution need to be delayed"
  1034. );
  1035. result.allowInlineStartup = false;
  1036. }
  1037. if (
  1038. result.allowInlineStartup &&
  1039. someInIterable(
  1040. moduleGraph.getIncomingConnectionsByOriginModule(entryModule),
  1041. ([originModule, connections]) =>
  1042. originModule &&
  1043. connections.some(c => c.isTargetActive(chunk.runtime)) &&
  1044. someInIterable(
  1045. chunkGraph.getModuleRuntimes(originModule),
  1046. runtime =>
  1047. intersectRuntime(runtime, chunk.runtime) !== undefined
  1048. )
  1049. )
  1050. ) {
  1051. buf2.push(
  1052. "// This entry module is referenced by other modules so it can't be inlined"
  1053. );
  1054. result.allowInlineStartup = false;
  1055. }
  1056. let data;
  1057. if (codeGenerationResults.has(entryModule, chunk.runtime)) {
  1058. const result = codeGenerationResults.get(
  1059. entryModule,
  1060. chunk.runtime
  1061. );
  1062. data = result.data;
  1063. }
  1064. if (
  1065. result.allowInlineStartup &&
  1066. (!data || !data.get("topLevelDeclarations")) &&
  1067. (!entryModule.buildInfo ||
  1068. !entryModule.buildInfo.topLevelDeclarations)
  1069. ) {
  1070. buf2.push(
  1071. "// This entry module doesn't tell about it's top-level declarations so it can't be inlined"
  1072. );
  1073. result.allowInlineStartup = false;
  1074. }
  1075. if (result.allowInlineStartup) {
  1076. const bailout = hooks.inlineInRuntimeBailout.call(
  1077. entryModule,
  1078. renderContext
  1079. );
  1080. if (bailout !== undefined) {
  1081. buf2.push(
  1082. `// This entry module can't be inlined because ${bailout}`
  1083. );
  1084. result.allowInlineStartup = false;
  1085. }
  1086. }
  1087. i--;
  1088. const moduleId = chunkGraph.getModuleId(entryModule);
  1089. const entryRuntimeRequirements =
  1090. chunkGraph.getModuleRuntimeRequirements(entryModule, chunk.runtime);
  1091. let moduleIdExpr = JSON.stringify(moduleId);
  1092. if (runtimeRequirements.has(RuntimeGlobals.entryModuleId)) {
  1093. moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
  1094. }
  1095. if (
  1096. result.allowInlineStartup &&
  1097. entryRuntimeRequirements.has(RuntimeGlobals.module)
  1098. ) {
  1099. result.allowInlineStartup = false;
  1100. buf2.push(
  1101. "// This entry module used 'module' so it can't be inlined"
  1102. );
  1103. }
  1104. if (chunks.length > 0) {
  1105. buf2.push(
  1106. `${i === 0 ? "var __webpack_exports__ = " : ""}${
  1107. RuntimeGlobals.onChunksLoaded
  1108. }(undefined, ${JSON.stringify(
  1109. chunks.map(c => c.id)
  1110. )}, ${runtimeTemplate.returningFunction(
  1111. `__webpack_require__(${moduleIdExpr})`
  1112. )})`
  1113. );
  1114. } else if (useRequire) {
  1115. buf2.push(
  1116. `${
  1117. i === 0 ? "var __webpack_exports__ = " : ""
  1118. }__webpack_require__(${moduleIdExpr});`
  1119. );
  1120. } else {
  1121. if (i === 0) buf2.push("var __webpack_exports__ = {};");
  1122. if (requireScopeUsed) {
  1123. buf2.push(
  1124. `__webpack_modules__[${moduleIdExpr}](0, ${
  1125. i === 0 ? "__webpack_exports__" : "{}"
  1126. }, __webpack_require__);`
  1127. );
  1128. } else if (entryRuntimeRequirements.has(RuntimeGlobals.exports)) {
  1129. buf2.push(
  1130. `__webpack_modules__[${moduleIdExpr}](0, ${
  1131. i === 0 ? "__webpack_exports__" : "{}"
  1132. });`
  1133. );
  1134. } else {
  1135. buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
  1136. }
  1137. }
  1138. }
  1139. if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
  1140. buf2.push(
  1141. `__webpack_exports__ = ${RuntimeGlobals.onChunksLoaded}(__webpack_exports__);`
  1142. );
  1143. }
  1144. if (
  1145. runtimeRequirements.has(RuntimeGlobals.startup) ||
  1146. (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) &&
  1147. runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter))
  1148. ) {
  1149. result.allowInlineStartup = false;
  1150. buf.push("// the startup function");
  1151. buf.push(
  1152. `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction("", [
  1153. ...buf2,
  1154. "return __webpack_exports__;"
  1155. ])};`
  1156. );
  1157. buf.push("");
  1158. startup.push("// run startup");
  1159. startup.push(
  1160. `var __webpack_exports__ = ${RuntimeGlobals.startup}();`
  1161. );
  1162. } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
  1163. buf.push("// the startup function");
  1164. buf.push(
  1165. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
  1166. );
  1167. beforeStartup.push("// run runtime startup");
  1168. beforeStartup.push(`${RuntimeGlobals.startup}();`);
  1169. startup.push("// startup");
  1170. startup.push(Template.asString(buf2));
  1171. } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)) {
  1172. buf.push("// the startup function");
  1173. buf.push(
  1174. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
  1175. );
  1176. startup.push("// startup");
  1177. startup.push(Template.asString(buf2));
  1178. afterStartup.push("// run runtime startup");
  1179. afterStartup.push(`${RuntimeGlobals.startup}();`);
  1180. } else {
  1181. startup.push("// startup");
  1182. startup.push(Template.asString(buf2));
  1183. }
  1184. } else if (
  1185. runtimeRequirements.has(RuntimeGlobals.startup) ||
  1186. runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
  1187. runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
  1188. ) {
  1189. buf.push(
  1190. "// the startup function",
  1191. "// It's empty as no entry modules are in this chunk",
  1192. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`,
  1193. ""
  1194. );
  1195. }
  1196. } else if (
  1197. runtimeRequirements.has(RuntimeGlobals.startup) ||
  1198. runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
  1199. runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
  1200. ) {
  1201. result.allowInlineStartup = false;
  1202. buf.push(
  1203. "// the startup function",
  1204. "// It's empty as some runtime module handles the default behavior",
  1205. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
  1206. );
  1207. startup.push("// run startup");
  1208. startup.push(`var __webpack_exports__ = ${RuntimeGlobals.startup}();`);
  1209. }
  1210. return result;
  1211. }
  1212. /**
  1213. * @param {RenderBootstrapContext} renderContext options object
  1214. * @param {CompilationHooks} hooks hooks
  1215. * @returns {string} the generated source of the require function
  1216. */
  1217. renderRequire(renderContext, hooks) {
  1218. const {
  1219. chunk,
  1220. chunkGraph,
  1221. runtimeTemplate: { outputOptions }
  1222. } = renderContext;
  1223. const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
  1224. const moduleExecution = runtimeRequirements.has(
  1225. RuntimeGlobals.interceptModuleExecution
  1226. )
  1227. ? Template.asString([
  1228. "var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };",
  1229. `${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
  1230. "module = execOptions.module;",
  1231. "execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
  1232. ])
  1233. : runtimeRequirements.has(RuntimeGlobals.thisAsExports)
  1234. ? Template.asString([
  1235. "__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);"
  1236. ])
  1237. : Template.asString([
  1238. "__webpack_modules__[moduleId](module, module.exports, __webpack_require__);"
  1239. ]);
  1240. const needModuleId = runtimeRequirements.has(RuntimeGlobals.moduleId);
  1241. const needModuleLoaded = runtimeRequirements.has(
  1242. RuntimeGlobals.moduleLoaded
  1243. );
  1244. const content = Template.asString([
  1245. "// Check if module is in cache",
  1246. "var cachedModule = __webpack_module_cache__[moduleId];",
  1247. "if (cachedModule !== undefined) {",
  1248. outputOptions.strictModuleErrorHandling
  1249. ? Template.indent([
  1250. "if (cachedModule.error !== undefined) throw cachedModule.error;",
  1251. "return cachedModule.exports;"
  1252. ])
  1253. : Template.indent("return cachedModule.exports;"),
  1254. "}",
  1255. "// Create a new module (and put it into the cache)",
  1256. "var module = __webpack_module_cache__[moduleId] = {",
  1257. Template.indent([
  1258. needModuleId ? "id: moduleId," : "// no module.id needed",
  1259. needModuleLoaded ? "loaded: false," : "// no module.loaded needed",
  1260. "exports: {}"
  1261. ]),
  1262. "};",
  1263. "",
  1264. outputOptions.strictModuleExceptionHandling
  1265. ? Template.asString([
  1266. "// Execute the module function",
  1267. "var threw = true;",
  1268. "try {",
  1269. Template.indent([moduleExecution, "threw = false;"]),
  1270. "} finally {",
  1271. Template.indent([
  1272. "if(threw) delete __webpack_module_cache__[moduleId];"
  1273. ]),
  1274. "}"
  1275. ])
  1276. : outputOptions.strictModuleErrorHandling
  1277. ? Template.asString([
  1278. "// Execute the module function",
  1279. "try {",
  1280. Template.indent(moduleExecution),
  1281. "} catch(e) {",
  1282. Template.indent(["module.error = e;", "throw e;"]),
  1283. "}"
  1284. ])
  1285. : Template.asString([
  1286. "// Execute the module function",
  1287. moduleExecution
  1288. ]),
  1289. needModuleLoaded
  1290. ? Template.asString([
  1291. "",
  1292. "// Flag the module as loaded",
  1293. "module.loaded = true;",
  1294. ""
  1295. ])
  1296. : "",
  1297. "// Return the exports of the module",
  1298. "return module.exports;"
  1299. ]);
  1300. return tryRunOrWebpackError(
  1301. () => hooks.renderRequire.call(content, renderContext),
  1302. "JavascriptModulesPlugin.getCompilationHooks().renderRequire"
  1303. );
  1304. }
  1305. }
  1306. module.exports = JavascriptModulesPlugin;
  1307. module.exports.chunkHasJs = chunkHasJs;