JavascriptModulesPlugin.js 44 KB

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