JavascriptModulesPlugin.js 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const vm = require("vm");
  7. const eslintScope = require("eslint-scope");
  8. const { SyncBailHook, SyncHook, SyncWaterfallHook } = require("tapable");
  9. const {
  10. CachedSource,
  11. ConcatSource,
  12. OriginalSource,
  13. PrefixSource,
  14. RawSource,
  15. ReplaceSource
  16. } = require("webpack-sources");
  17. const Compilation = require("../Compilation");
  18. const { tryRunOrWebpackError } = require("../HookWebpackError");
  19. const HotUpdateChunk = require("../HotUpdateChunk");
  20. const InitFragment = require("../InitFragment");
  21. const { JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants");
  22. const {
  23. JAVASCRIPT_MODULE_TYPE_AUTO,
  24. JAVASCRIPT_MODULE_TYPE_DYNAMIC,
  25. JAVASCRIPT_MODULE_TYPE_ESM,
  26. WEBPACK_MODULE_TYPE_RUNTIME
  27. } = require("../ModuleTypeConstants");
  28. const NormalModule = require("../NormalModule");
  29. const RuntimeGlobals = require("../RuntimeGlobals");
  30. const Template = require("../Template");
  31. const { last, someInIterable } = require("../util/IterableHelpers");
  32. const StringXor = require("../util/StringXor");
  33. const { compareModulesByFullName } = require("../util/comparators");
  34. const {
  35. RESERVED_NAMES,
  36. addScopeSymbols,
  37. findNewName,
  38. getAllReferences,
  39. getPathInAst,
  40. getUsedNamesInScopeInfo
  41. } = require("../util/concatenate");
  42. const createHash = require("../util/createHash");
  43. const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
  44. const removeBOM = require("../util/removeBOM");
  45. const { intersectRuntime } = require("../util/runtime");
  46. const JavascriptGenerator = require("./JavascriptGenerator");
  47. const JavascriptParser = require("./JavascriptParser");
  48. /** @typedef {import("eslint-scope").Reference} Reference */
  49. /** @typedef {import("eslint-scope").Scope} Scope */
  50. /** @typedef {import("eslint-scope").Variable} Variable */
  51. /** @typedef {import("estree").Program} Program */
  52. /** @typedef {import("webpack-sources").Source} Source */
  53. /** @typedef {import("../config/defaults").OutputNormalizedWithDefaults} OutputOptions */
  54. /** @typedef {import("../Chunk")} Chunk */
  55. /** @typedef {import("../ChunkGraph")} ChunkGraph */
  56. /** @typedef {import("../ChunkGraph").EntryModuleWithChunkGroup} EntryModuleWithChunkGroup */
  57. /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
  58. /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
  59. /** @typedef {import("../Compilation").ExecuteModuleObject} ExecuteModuleObject */
  60. /** @typedef {import("../Compilation").WebpackRequire} WebpackRequire */
  61. /** @typedef {import("../Compiler")} Compiler */
  62. /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
  63. /** @typedef {import("../Entrypoint")} Entrypoint */
  64. /** @typedef {import("../Module")} Module */
  65. /** @typedef {import("../Module").BuildInfo} BuildInfo */
  66. /** @typedef {import("../Module").CodeGenerationResultData} CodeGenerationResultData */
  67. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  68. /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
  69. /** @typedef {import("../TemplatedPathPlugin").TemplatePath} TemplatePath */
  70. /** @typedef {import("../WebpackError")} WebpackError */
  71. /** @typedef {import("../javascript/JavascriptParser").Range} Range */
  72. /** @typedef {import("../util/Hash")} Hash */
  73. /** @typedef {import("../util/concatenate").ScopeSet} ScopeSet */
  74. /** @typedef {import("../util/concatenate").UsedNamesInScopeInfo} UsedNamesInScopeInfo */
  75. /** @type {WeakMap<ChunkGraph, WeakMap<Chunk, boolean>>} */
  76. const chunkHasJsCache = new WeakMap();
  77. /**
  78. * Returns true, when a JS file is needed for this chunk.
  79. * @param {Chunk} chunk a chunk
  80. * @param {ChunkGraph} chunkGraph the chunk graph
  81. * @returns {boolean} true, when a JS file is needed for this chunk
  82. */
  83. const _chunkHasJs = (chunk, chunkGraph) => {
  84. if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
  85. for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
  86. if (chunkGraph.getModuleSourceTypes(module).has(JAVASCRIPT_TYPE)) {
  87. return true;
  88. }
  89. }
  90. }
  91. return Boolean(
  92. chunkGraph.getChunkModulesIterableBySourceType(chunk, JAVASCRIPT_TYPE)
  93. );
  94. };
  95. /**
  96. * Returns true, when a JS file is needed for this chunk.
  97. * @param {Chunk} chunk a chunk
  98. * @param {ChunkGraph} chunkGraph the chunk graph
  99. * @returns {boolean} true, when a JS file is needed for this chunk
  100. */
  101. const chunkHasJs = (chunk, chunkGraph) => {
  102. let innerCache = chunkHasJsCache.get(chunkGraph);
  103. if (innerCache === undefined) {
  104. innerCache = new WeakMap();
  105. chunkHasJsCache.set(chunkGraph, innerCache);
  106. }
  107. const cachedResult = innerCache.get(chunk);
  108. if (cachedResult !== undefined) {
  109. return cachedResult;
  110. }
  111. const result = _chunkHasJs(chunk, chunkGraph);
  112. innerCache.set(chunk, result);
  113. return result;
  114. };
  115. /**
  116. * Chunk has runtime or js.
  117. * @param {Chunk} chunk a chunk
  118. * @param {ChunkGraph} chunkGraph the chunk graph
  119. * @returns {boolean} true, when a JS file is needed for this chunk
  120. */
  121. const chunkHasRuntimeOrJs = (chunk, chunkGraph) => {
  122. if (chunkHasJs(chunk, chunkGraph)) {
  123. return true;
  124. }
  125. if (
  126. chunkGraph.getChunkModulesIterableBySourceType(
  127. chunk,
  128. WEBPACK_MODULE_TYPE_RUNTIME
  129. )
  130. ) {
  131. for (const chunkGroup of chunk.groupsIterable) {
  132. for (const c of chunkGroup.chunks) {
  133. if (chunkHasJs(c, chunkGraph)) return true;
  134. }
  135. }
  136. return false;
  137. }
  138. return false;
  139. };
  140. /**
  141. * Print generated code for stack.
  142. * @param {Module} module a module
  143. * @param {string} code the code
  144. * @returns {string} generated code for the stack
  145. */
  146. const printGeneratedCodeForStack = (module, code) => {
  147. const lines = code.split("\n");
  148. const n = `${lines.length}`.length;
  149. return `\n\nGenerated code for ${module.identifier()}\n${lines
  150. .map(
  151. /**
  152. * Handles the callback logic for this hook.
  153. * @param {string} line the line
  154. * @param {number} i the index
  155. * @param {string[]} _lines the lines
  156. * @returns {string} the line with line number
  157. */
  158. (line, i, _lines) => {
  159. const iStr = `${i + 1}`;
  160. return `${" ".repeat(n - iStr.length)}${iStr} | ${line}`;
  161. }
  162. )
  163. .join("\n")}`;
  164. };
  165. /**
  166. * Defines the render context type used by this module.
  167. * @typedef {object} RenderContext
  168. * @property {Chunk} chunk the chunk
  169. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  170. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  171. * @property {ModuleGraph} moduleGraph the module graph
  172. * @property {ChunkGraph} chunkGraph the chunk graph
  173. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  174. * @property {boolean | undefined} strictMode rendering in strict context
  175. */
  176. /**
  177. * Defines the main render context type used by this module.
  178. * @typedef {object} MainRenderContext
  179. * @property {Chunk} chunk the chunk
  180. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  181. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  182. * @property {ModuleGraph} moduleGraph the module graph
  183. * @property {ChunkGraph} chunkGraph the chunk graph
  184. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  185. * @property {string} hash hash to be used for render call
  186. * @property {boolean | undefined} strictMode rendering in strict context
  187. */
  188. /**
  189. * Defines the chunk render context type used by this module.
  190. * @typedef {object} ChunkRenderContext
  191. * @property {Chunk} chunk the chunk
  192. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  193. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  194. * @property {ModuleGraph} moduleGraph the module graph
  195. * @property {ChunkGraph} chunkGraph the chunk graph
  196. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  197. * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
  198. * @property {boolean | undefined} strictMode rendering in strict context
  199. */
  200. /**
  201. * Defines the render bootstrap context type used by this module.
  202. * @typedef {object} RenderBootstrapContext
  203. * @property {Chunk} chunk the chunk
  204. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  205. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  206. * @property {ModuleGraph} moduleGraph the module graph
  207. * @property {ChunkGraph} chunkGraph the chunk graph
  208. * @property {string} hash hash to be used for render call
  209. */
  210. /**
  211. * Defines the startup render context type used by this module.
  212. * @typedef {object} StartupRenderContext
  213. * @property {Chunk} chunk the chunk
  214. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  215. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  216. * @property {ModuleGraph} moduleGraph the module graph
  217. * @property {ChunkGraph} chunkGraph the chunk graph
  218. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  219. * @property {boolean | undefined} strictMode rendering in strict context
  220. * @property {boolean=} inlined inlined
  221. * @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE
  222. * @property {boolean=} needExportsDeclaration whether the top-level exports declaration needs to be generated
  223. */
  224. /**
  225. * Defines the module render context type used by this module.
  226. * @typedef {object} ModuleRenderContext
  227. * @property {Chunk} chunk the chunk
  228. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  229. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  230. * @property {ModuleGraph} moduleGraph the module graph
  231. * @property {ChunkGraph} chunkGraph the chunk graph
  232. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  233. * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
  234. * @property {boolean | undefined} strictMode rendering in strict context
  235. * @property {boolean} factory true: renders as factory method, false: pure module content
  236. * @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE, existing only when `factory` is set to false
  237. * @property {boolean=} renderInObject render module in object container
  238. */
  239. /**
  240. * Defines the compilation hooks type used by this module.
  241. * @typedef {object} CompilationHooks
  242. * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModuleContent
  243. * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModuleContainer
  244. * @property {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>} renderModulePackage
  245. * @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
  246. * @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
  247. * @property {SyncWaterfallHook<[Source, RenderContext]>} renderContent
  248. * @property {SyncWaterfallHook<[Source, RenderContext]>} render
  249. * @property {SyncWaterfallHook<[Source, Module, StartupRenderContext]>} renderStartup
  250. * @property {SyncWaterfallHook<[string, RenderBootstrapContext]>} renderRequire
  251. * @property {SyncBailHook<[Module, Partial<RenderBootstrapContext>], string | void>} inlineInRuntimeBailout
  252. * @property {SyncBailHook<[Module, RenderContext], string | void>} embedInRuntimeBailout
  253. * @property {SyncBailHook<[RenderContext], string | void>} strictRuntimeBailout
  254. * @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
  255. * @property {SyncBailHook<[Chunk, RenderContext], boolean | void>} useSourceMap
  256. */
  257. /** @type {WeakMap<Compilation, CompilationHooks>} */
  258. const compilationHooksMap = new WeakMap();
  259. const PLUGIN_NAME = "JavascriptModulesPlugin";
  260. /** @typedef {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} Bootstrap */
  261. class JavascriptModulesPlugin {
  262. /**
  263. * Returns the attached hooks.
  264. * @param {Compilation} compilation the compilation
  265. * @returns {CompilationHooks} the attached hooks
  266. */
  267. static getCompilationHooks(compilation) {
  268. if (!(compilation instanceof Compilation)) {
  269. throw new TypeError(
  270. "The 'compilation' argument must be an instance of Compilation"
  271. );
  272. }
  273. let hooks = compilationHooksMap.get(compilation);
  274. if (hooks === undefined) {
  275. hooks = {
  276. renderModuleContent: new SyncWaterfallHook([
  277. "source",
  278. "module",
  279. "moduleRenderContext"
  280. ]),
  281. renderModuleContainer: new SyncWaterfallHook([
  282. "source",
  283. "module",
  284. "moduleRenderContext"
  285. ]),
  286. renderModulePackage: new SyncWaterfallHook([
  287. "source",
  288. "module",
  289. "moduleRenderContext"
  290. ]),
  291. render: new SyncWaterfallHook(["source", "renderContext"]),
  292. renderContent: new SyncWaterfallHook(["source", "renderContext"]),
  293. renderStartup: new SyncWaterfallHook([
  294. "source",
  295. "module",
  296. "startupRenderContext"
  297. ]),
  298. renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
  299. renderMain: new SyncWaterfallHook(["source", "renderContext"]),
  300. renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
  301. inlineInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
  302. embedInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
  303. strictRuntimeBailout: new SyncBailHook(["renderContext"]),
  304. chunkHash: new SyncHook(["chunk", "hash", "context"]),
  305. useSourceMap: new SyncBailHook(["chunk", "renderContext"])
  306. };
  307. compilationHooksMap.set(compilation, hooks);
  308. }
  309. return hooks;
  310. }
  311. constructor(options = {}) {
  312. this.options = options;
  313. /** @type {WeakMap<Source, { source: Source, needModule: boolean, needExports: boolean, needRequire: boolean, needThisAsExports: boolean, needStrict: boolean | undefined, renderShorthand: boolean }>} */
  314. this._moduleFactoryCache = new WeakMap();
  315. }
  316. /**
  317. * Applies the plugin by registering its hooks on the compiler.
  318. * @param {Compiler} compiler the compiler instance
  319. * @returns {void}
  320. */
  321. apply(compiler) {
  322. compiler.hooks.compilation.tap(
  323. PLUGIN_NAME,
  324. (compilation, { normalModuleFactory }) => {
  325. const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
  326. for (const type of [
  327. JAVASCRIPT_MODULE_TYPE_AUTO,
  328. JAVASCRIPT_MODULE_TYPE_DYNAMIC,
  329. JAVASCRIPT_MODULE_TYPE_ESM
  330. ]) {
  331. normalModuleFactory.hooks.createParser
  332. .for(type)
  333. .tap(PLUGIN_NAME, (options) => {
  334. switch (type) {
  335. case JAVASCRIPT_MODULE_TYPE_AUTO: {
  336. return new JavascriptParser("auto", { parse: options.parse });
  337. }
  338. case JAVASCRIPT_MODULE_TYPE_DYNAMIC: {
  339. return new JavascriptParser("script", {
  340. parse: options.parse
  341. });
  342. }
  343. case JAVASCRIPT_MODULE_TYPE_ESM: {
  344. return new JavascriptParser("module", {
  345. parse: options.parse
  346. });
  347. }
  348. }
  349. });
  350. normalModuleFactory.hooks.createGenerator
  351. .for(type)
  352. .tap(PLUGIN_NAME, () => new JavascriptGenerator());
  353. NormalModule.getCompilationHooks(compilation).processResult.tap(
  354. PLUGIN_NAME,
  355. (result, module) => {
  356. if (module.type === type) {
  357. const [source, ...rest] = result;
  358. return [removeBOM(source), ...rest];
  359. }
  360. return result;
  361. }
  362. );
  363. }
  364. compilation.hooks.renderManifest.tap(PLUGIN_NAME, (result, options) => {
  365. const {
  366. hash,
  367. chunk,
  368. chunkGraph,
  369. moduleGraph,
  370. runtimeTemplate,
  371. dependencyTemplates,
  372. outputOptions,
  373. codeGenerationResults
  374. } = options;
  375. const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
  376. const filenameTemplate =
  377. JavascriptModulesPlugin.getChunkFilenameTemplate(
  378. chunk,
  379. outputOptions
  380. );
  381. /** @type {() => Source} */
  382. let render;
  383. if (hotUpdateChunk) {
  384. render = () =>
  385. this.renderChunk(
  386. {
  387. chunk,
  388. dependencyTemplates,
  389. runtimeTemplate,
  390. moduleGraph,
  391. chunkGraph,
  392. codeGenerationResults,
  393. strictMode: runtimeTemplate.isModule()
  394. },
  395. hooks
  396. );
  397. } else if (chunk.hasRuntime()) {
  398. if (!chunkHasRuntimeOrJs(chunk, chunkGraph)) {
  399. return result;
  400. }
  401. render = () =>
  402. this.renderMain(
  403. {
  404. hash,
  405. chunk,
  406. dependencyTemplates,
  407. runtimeTemplate,
  408. moduleGraph,
  409. chunkGraph,
  410. codeGenerationResults,
  411. strictMode: runtimeTemplate.isModule()
  412. },
  413. hooks,
  414. compilation
  415. );
  416. } else {
  417. if (!chunkHasJs(chunk, chunkGraph)) {
  418. return result;
  419. }
  420. render = () =>
  421. this.renderChunk(
  422. {
  423. chunk,
  424. dependencyTemplates,
  425. runtimeTemplate,
  426. moduleGraph,
  427. chunkGraph,
  428. codeGenerationResults,
  429. strictMode: runtimeTemplate.isModule()
  430. },
  431. hooks
  432. );
  433. }
  434. result.push({
  435. render,
  436. filenameTemplate,
  437. pathOptions: {
  438. hash,
  439. runtime: chunk.runtime,
  440. chunk,
  441. contentHashType: "javascript"
  442. },
  443. info: {
  444. javascriptModule: compilation.runtimeTemplate.isModule()
  445. },
  446. identifier: hotUpdateChunk
  447. ? `hotupdatechunk${chunk.id}`
  448. : `chunk${chunk.id}`,
  449. hash: chunk.contentHash.javascript
  450. });
  451. return result;
  452. });
  453. compilation.hooks.chunkHash.tap(PLUGIN_NAME, (chunk, hash, context) => {
  454. hooks.chunkHash.call(chunk, hash, context);
  455. if (chunk.hasRuntime()) {
  456. this.updateHashWithBootstrap(
  457. hash,
  458. {
  459. hash: "0000",
  460. chunk,
  461. codeGenerationResults: context.codeGenerationResults,
  462. chunkGraph: context.chunkGraph,
  463. moduleGraph: context.moduleGraph,
  464. runtimeTemplate: context.runtimeTemplate
  465. },
  466. hooks
  467. );
  468. }
  469. });
  470. compilation.hooks.contentHash.tap(PLUGIN_NAME, (chunk) => {
  471. const {
  472. chunkGraph,
  473. moduleGraph,
  474. runtimeTemplate,
  475. outputOptions: {
  476. hashSalt,
  477. hashDigest,
  478. hashDigestLength,
  479. hashFunction
  480. }
  481. } = compilation;
  482. const codeGenerationResults =
  483. /** @type {CodeGenerationResults} */
  484. (compilation.codeGenerationResults);
  485. const hash = createHash(hashFunction);
  486. if (hashSalt) hash.update(hashSalt);
  487. if (chunk.hasRuntime()) {
  488. this.updateHashWithBootstrap(
  489. hash,
  490. {
  491. hash: "0000",
  492. chunk,
  493. codeGenerationResults,
  494. chunkGraph: compilation.chunkGraph,
  495. moduleGraph: compilation.moduleGraph,
  496. runtimeTemplate: compilation.runtimeTemplate
  497. },
  498. hooks
  499. );
  500. } else {
  501. hash.update(`${chunk.id} `);
  502. hash.update(chunk.ids ? chunk.ids.join(",") : "");
  503. }
  504. hooks.chunkHash.call(chunk, hash, {
  505. chunkGraph,
  506. codeGenerationResults,
  507. moduleGraph,
  508. runtimeTemplate
  509. });
  510. const modules = chunkGraph.getChunkModulesIterableBySourceType(
  511. chunk,
  512. JAVASCRIPT_TYPE
  513. );
  514. if (modules) {
  515. const xor = new StringXor();
  516. for (const m of modules) {
  517. xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
  518. }
  519. xor.updateHash(hash);
  520. }
  521. const runtimeModules = chunkGraph.getChunkModulesIterableBySourceType(
  522. chunk,
  523. WEBPACK_MODULE_TYPE_RUNTIME
  524. );
  525. if (runtimeModules) {
  526. const xor = new StringXor();
  527. for (const m of runtimeModules) {
  528. xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
  529. }
  530. xor.updateHash(hash);
  531. }
  532. const digest = hash.digest(hashDigest);
  533. chunk.contentHash.javascript = nonNumericOnlyHash(
  534. digest,
  535. hashDigestLength
  536. );
  537. });
  538. compilation.hooks.additionalTreeRuntimeRequirements.tap(
  539. PLUGIN_NAME,
  540. (chunk, set, { chunkGraph }) => {
  541. if (
  542. !set.has(RuntimeGlobals.startupNoDefault) &&
  543. chunkGraph.hasChunkEntryDependentChunks(chunk)
  544. ) {
  545. set.add(RuntimeGlobals.onChunksLoaded);
  546. set.add(RuntimeGlobals.exports);
  547. set.add(RuntimeGlobals.require);
  548. }
  549. }
  550. );
  551. compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
  552. const source =
  553. options.codeGenerationResult.sources.get(JAVASCRIPT_TYPE);
  554. if (source === undefined) return;
  555. const { module } = options;
  556. const code = source.source();
  557. /** @type {(this: ExecuteModuleObject["exports"], exports: ExecuteModuleObject["exports"], moduleObject: ExecuteModuleObject, webpackRequire: WebpackRequire) => void} */
  558. const fn = vm.runInThisContext(
  559. `(function(${module.moduleArgument}, ${module.exportsArgument}, ${RuntimeGlobals.require}) {\n${code}\n/**/})`,
  560. {
  561. filename: module.identifier(),
  562. lineOffset: -1
  563. }
  564. );
  565. const moduleObject =
  566. /** @type {ExecuteModuleObject} */
  567. (options.moduleObject);
  568. try {
  569. fn.call(
  570. moduleObject.exports,
  571. moduleObject,
  572. moduleObject.exports,
  573. /** @type {WebpackRequire} */
  574. (context.__webpack_require__)
  575. );
  576. } catch (err) {
  577. /** @type {Error} */
  578. (err).stack += printGeneratedCodeForStack(
  579. options.module,
  580. /** @type {string} */ (code)
  581. );
  582. throw err;
  583. }
  584. });
  585. compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
  586. const source = options.codeGenerationResult.sources.get("runtime");
  587. if (source === undefined) return;
  588. let code = source.source();
  589. if (typeof code !== "string") code = code.toString();
  590. /** @type {(this: null, webpackRequire: WebpackRequire) => void} */
  591. const fn = vm.runInThisContext(
  592. `(function(${RuntimeGlobals.require}) {\n${code}\n/**/})`,
  593. {
  594. filename: options.module.identifier(),
  595. lineOffset: -1
  596. }
  597. );
  598. try {
  599. // eslint-disable-next-line no-useless-call
  600. fn.call(
  601. null,
  602. /** @type {WebpackRequire} */
  603. (context.__webpack_require__)
  604. );
  605. } catch (err) {
  606. /** @type {Error} */
  607. (err).stack += printGeneratedCodeForStack(options.module, code);
  608. throw err;
  609. }
  610. });
  611. }
  612. );
  613. }
  614. /**
  615. * Gets chunk filename template.
  616. * @param {Chunk} chunk chunk
  617. * @param {OutputOptions} outputOptions output options
  618. * @returns {TemplatePath} used filename template
  619. */
  620. static getChunkFilenameTemplate(chunk, outputOptions) {
  621. if (chunk.filenameTemplate) {
  622. return chunk.filenameTemplate;
  623. } else if (chunk instanceof HotUpdateChunk) {
  624. return outputOptions.hotUpdateChunkFilename;
  625. } else if (chunk.canBeInitial()) {
  626. return outputOptions.filename;
  627. }
  628. return outputOptions.chunkFilename;
  629. }
  630. /**
  631. * Renders the newly generated source from rendering.
  632. * @param {Module} module the rendered module
  633. * @param {ModuleRenderContext} renderContext options object
  634. * @param {CompilationHooks} hooks hooks
  635. * @returns {Source | null} the newly generated source from rendering
  636. */
  637. renderModule(module, renderContext, hooks) {
  638. const {
  639. chunk,
  640. chunkGraph,
  641. runtimeTemplate,
  642. codeGenerationResults,
  643. strictMode,
  644. factory,
  645. renderInObject
  646. } = renderContext;
  647. try {
  648. const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
  649. const moduleSource = codeGenResult.sources.get(JAVASCRIPT_TYPE);
  650. if (!moduleSource) return null;
  651. if (codeGenResult.data !== undefined) {
  652. const chunkInitFragments = codeGenResult.data.get("chunkInitFragments");
  653. if (chunkInitFragments) {
  654. for (const i of chunkInitFragments) {
  655. renderContext.chunkInitFragments.push(i);
  656. }
  657. }
  658. }
  659. const moduleSourcePostContent = tryRunOrWebpackError(
  660. () =>
  661. hooks.renderModuleContent.call(moduleSource, module, renderContext),
  662. "JavascriptModulesPlugin.getCompilationHooks().renderModuleContent"
  663. );
  664. /** @type {Source} */
  665. let moduleSourcePostContainer;
  666. if (factory) {
  667. const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
  668. module,
  669. chunk.runtime
  670. );
  671. const needModule = runtimeRequirements.has(RuntimeGlobals.module);
  672. const needExports = runtimeRequirements.has(RuntimeGlobals.exports);
  673. const needRequire =
  674. runtimeRequirements.has(RuntimeGlobals.require) ||
  675. runtimeRequirements.has(RuntimeGlobals.requireScope);
  676. const needThisAsExports = runtimeRequirements.has(
  677. RuntimeGlobals.thisAsExports
  678. );
  679. const needStrict =
  680. /** @type {BuildInfo} */
  681. (module.buildInfo).strict && !strictMode;
  682. const cacheEntry = this._moduleFactoryCache.get(
  683. moduleSourcePostContent
  684. );
  685. const renderShorthand =
  686. renderInObject === true && runtimeTemplate.supportsMethodShorthand();
  687. /** @type {Source} */
  688. let source;
  689. if (
  690. cacheEntry &&
  691. cacheEntry.needModule === needModule &&
  692. cacheEntry.needExports === needExports &&
  693. cacheEntry.needRequire === needRequire &&
  694. cacheEntry.needThisAsExports === needThisAsExports &&
  695. cacheEntry.needStrict === needStrict &&
  696. cacheEntry.renderShorthand === renderShorthand
  697. ) {
  698. source = cacheEntry.source;
  699. } else {
  700. const factorySource = new ConcatSource();
  701. /** @type {string[]} */
  702. const args = [];
  703. if (needExports || needRequire || needModule) {
  704. args.push(
  705. needModule
  706. ? module.moduleArgument
  707. : `__unused_webpack_${module.moduleArgument}`
  708. );
  709. }
  710. if (needExports || needRequire) {
  711. args.push(
  712. needExports
  713. ? module.exportsArgument
  714. : `__unused_webpack_${module.exportsArgument}`
  715. );
  716. }
  717. if (needRequire) args.push(RuntimeGlobals.require);
  718. if (renderShorthand) {
  719. // we can optimize function to methodShorthand if render module factory in object
  720. factorySource.add(`(${args.join(", ")}) {\n\n`);
  721. } else if (
  722. !needThisAsExports &&
  723. runtimeTemplate.supportsArrowFunction()
  724. ) {
  725. factorySource.add(`/***/ ((${args.join(", ")}) => {\n\n`);
  726. } else {
  727. factorySource.add(`/***/ (function(${args.join(", ")}) {\n\n`);
  728. }
  729. if (needStrict) {
  730. factorySource.add('"use strict";\n');
  731. }
  732. factorySource.add(moduleSourcePostContent);
  733. factorySource.add(`\n\n/***/ }${renderShorthand ? "" : ")"}`);
  734. source = new CachedSource(factorySource);
  735. this._moduleFactoryCache.set(moduleSourcePostContent, {
  736. source,
  737. needModule,
  738. needExports,
  739. needRequire,
  740. needThisAsExports,
  741. needStrict,
  742. renderShorthand
  743. });
  744. }
  745. moduleSourcePostContainer = tryRunOrWebpackError(
  746. () => hooks.renderModuleContainer.call(source, module, renderContext),
  747. "JavascriptModulesPlugin.getCompilationHooks().renderModuleContainer"
  748. );
  749. } else {
  750. moduleSourcePostContainer = moduleSourcePostContent;
  751. }
  752. return tryRunOrWebpackError(
  753. () =>
  754. hooks.renderModulePackage.call(
  755. moduleSourcePostContainer,
  756. module,
  757. renderContext
  758. ),
  759. "JavascriptModulesPlugin.getCompilationHooks().renderModulePackage"
  760. );
  761. } catch (err) {
  762. /** @type {WebpackError} */
  763. (err).module = module;
  764. throw err;
  765. }
  766. }
  767. /**
  768. * Renders the rendered source.
  769. * @param {RenderContext} renderContext the render context
  770. * @param {CompilationHooks} hooks hooks
  771. * @returns {Source} the rendered source
  772. */
  773. renderChunk(renderContext, hooks) {
  774. const { chunk, chunkGraph, runtimeTemplate } = renderContext;
  775. const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType(
  776. chunk,
  777. JAVASCRIPT_TYPE,
  778. compareModulesByFullName(runtimeTemplate.compilation.compiler)
  779. );
  780. const allModules = modules ? [...modules] : [];
  781. /** @type {undefined | string} */
  782. let strictHeader;
  783. let allStrict = renderContext.strictMode;
  784. if (
  785. !allStrict &&
  786. allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict)
  787. ) {
  788. const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
  789. strictHeader = strictBailout
  790. ? `// runtime can't be in strict mode because ${strictBailout}.\n`
  791. : '"use strict";\n';
  792. if (!strictBailout) allStrict = true;
  793. }
  794. /** @type {ChunkRenderContext} */
  795. const chunkRenderContext = {
  796. ...renderContext,
  797. chunkInitFragments: [],
  798. strictMode: allStrict
  799. };
  800. const moduleSources =
  801. Template.renderChunkModules(
  802. chunkRenderContext,
  803. allModules,
  804. (module, renderInObject) =>
  805. this.renderModule(
  806. module,
  807. { ...chunkRenderContext, factory: true, renderInObject },
  808. hooks
  809. )
  810. ) || new RawSource("{}");
  811. let source = tryRunOrWebpackError(
  812. () => hooks.renderChunk.call(moduleSources, chunkRenderContext),
  813. "JavascriptModulesPlugin.getCompilationHooks().renderChunk"
  814. );
  815. source = tryRunOrWebpackError(
  816. () => hooks.renderContent.call(source, chunkRenderContext),
  817. "JavascriptModulesPlugin.getCompilationHooks().renderContent"
  818. );
  819. if (!source) {
  820. throw new Error(
  821. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
  822. );
  823. }
  824. source = InitFragment.addToSource(
  825. source,
  826. chunkRenderContext.chunkInitFragments,
  827. chunkRenderContext
  828. );
  829. source = tryRunOrWebpackError(
  830. () => hooks.render.call(source, chunkRenderContext),
  831. "JavascriptModulesPlugin.getCompilationHooks().render"
  832. );
  833. if (!source) {
  834. throw new Error(
  835. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
  836. );
  837. }
  838. chunk.rendered = true;
  839. return strictHeader
  840. ? new ConcatSource(strictHeader, source, ";")
  841. : renderContext.runtimeTemplate.isModule()
  842. ? source
  843. : new ConcatSource(source, ";");
  844. }
  845. /**
  846. * Renders the newly generated source from rendering.
  847. * @param {MainRenderContext} renderContext options object
  848. * @param {CompilationHooks} hooks hooks
  849. * @param {Compilation} compilation the compilation
  850. * @returns {Source} the newly generated source from rendering
  851. */
  852. renderMain(renderContext, hooks, compilation) {
  853. const { chunk, chunkGraph, runtimeTemplate } = renderContext;
  854. const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
  855. const iife = runtimeTemplate.isIIFE();
  856. const bootstrap = this.renderBootstrap(renderContext, hooks);
  857. const useSourceMap = hooks.useSourceMap.call(chunk, renderContext);
  858. /** @type {Module[]} */
  859. const allModules = [
  860. ...(chunkGraph.getOrderedChunkModulesIterableBySourceType(
  861. chunk,
  862. JAVASCRIPT_TYPE,
  863. compareModulesByFullName(runtimeTemplate.compilation.compiler)
  864. ) || [])
  865. ];
  866. const hasEntryModules = chunkGraph.getNumberOfEntryModules(chunk) > 0;
  867. /** @type {Set<Module> | undefined} */
  868. let inlinedModules;
  869. if (bootstrap.allowInlineStartup && hasEntryModules) {
  870. inlinedModules = new Set(chunkGraph.getChunkEntryModulesIterable(chunk));
  871. }
  872. const source = new ConcatSource();
  873. /** @type {string} */
  874. let prefix;
  875. if (iife) {
  876. if (runtimeTemplate.supportsArrowFunction()) {
  877. source.add("/******/ (() => { // webpackBootstrap\n");
  878. } else {
  879. source.add("/******/ (function() { // webpackBootstrap\n");
  880. }
  881. prefix = "/******/ \t";
  882. } else {
  883. prefix = "/******/ ";
  884. }
  885. let allStrict = renderContext.strictMode;
  886. if (
  887. !allStrict &&
  888. allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict)
  889. ) {
  890. const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
  891. if (strictBailout) {
  892. source.add(
  893. `${
  894. prefix
  895. }// runtime can't be in strict mode because ${strictBailout}.\n`
  896. );
  897. } else {
  898. allStrict = true;
  899. source.add(`${prefix}"use strict";\n`);
  900. }
  901. }
  902. /** @type {ChunkRenderContext} */
  903. const chunkRenderContext = {
  904. ...renderContext,
  905. chunkInitFragments: [],
  906. strictMode: allStrict
  907. };
  908. const chunkModules = Template.renderChunkModules(
  909. chunkRenderContext,
  910. inlinedModules
  911. ? allModules.filter(
  912. (m) => !(/** @type {Set<Module>} */ (inlinedModules).has(m))
  913. )
  914. : allModules,
  915. (module, renderInObject) =>
  916. this.renderModule(
  917. module,
  918. { ...chunkRenderContext, factory: true, renderInObject },
  919. hooks
  920. ),
  921. prefix
  922. );
  923. if (
  924. chunkModules ||
  925. runtimeRequirements.has(RuntimeGlobals.moduleFactories) ||
  926. runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly) ||
  927. runtimeRequirements.has(RuntimeGlobals.require)
  928. ) {
  929. source.add(`${prefix}var __webpack_modules__ = (`);
  930. source.add(chunkModules || "{}");
  931. source.add(");\n");
  932. source.add(
  933. "/************************************************************************/\n"
  934. );
  935. }
  936. if (bootstrap.header.length > 0) {
  937. const header = `${Template.asString(bootstrap.header)}\n`;
  938. source.add(
  939. new PrefixSource(
  940. prefix,
  941. useSourceMap
  942. ? new OriginalSource(header, "webpack/bootstrap")
  943. : new RawSource(header)
  944. )
  945. );
  946. source.add(
  947. "/************************************************************************/\n"
  948. );
  949. }
  950. const runtimeModules =
  951. renderContext.chunkGraph.getChunkRuntimeModulesInOrder(chunk);
  952. if (runtimeModules.length > 0) {
  953. source.add(
  954. new PrefixSource(
  955. prefix,
  956. Template.renderRuntimeModules(runtimeModules, chunkRenderContext)
  957. )
  958. );
  959. source.add(
  960. "/************************************************************************/\n"
  961. );
  962. // runtimeRuntimeModules calls codeGeneration
  963. for (const module of runtimeModules) {
  964. compilation.codeGeneratedModules.add(module);
  965. }
  966. }
  967. if (inlinedModules) {
  968. if (bootstrap.beforeStartup.length > 0) {
  969. const beforeStartup = `${Template.asString(bootstrap.beforeStartup)}\n`;
  970. source.add(
  971. new PrefixSource(
  972. prefix,
  973. useSourceMap
  974. ? new OriginalSource(beforeStartup, "webpack/before-startup")
  975. : new RawSource(beforeStartup)
  976. )
  977. );
  978. }
  979. const lastInlinedModule = /** @type {Module} */ (last(inlinedModules));
  980. const startupSource = new ConcatSource();
  981. const avoidEntryIife = compilation.options.optimization.avoidEntryIife;
  982. /** @type {Map<Module, Source> | false} */
  983. let renamedInlinedModule = false;
  984. let inlinedInIIFE = false;
  985. if (avoidEntryIife) {
  986. renamedInlinedModule = this._getRenamedInlineModule(
  987. compilation,
  988. allModules,
  989. renderContext,
  990. inlinedModules,
  991. chunkRenderContext,
  992. hooks,
  993. allStrict,
  994. Boolean(chunkModules)
  995. );
  996. }
  997. for (const m of inlinedModules) {
  998. const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
  999. m,
  1000. chunk.runtime
  1001. );
  1002. const exports = runtimeRequirements.has(RuntimeGlobals.exports);
  1003. const webpackExports =
  1004. exports && m.exportsArgument === RuntimeGlobals.exports;
  1005. const innerStrict =
  1006. !allStrict && /** @type {BuildInfo} */ (m.buildInfo).strict;
  1007. const iife = innerStrict
  1008. ? "it needs to be in strict mode."
  1009. : inlinedModules.size > 1
  1010. ? // TODO check globals and top-level declarations of other entries and chunk modules
  1011. // to make a better decision
  1012. "it needs to be isolated against other entry modules."
  1013. : chunkModules && !renamedInlinedModule
  1014. ? "it needs to be isolated against other modules in the chunk."
  1015. : exports && !webpackExports
  1016. ? `it uses a non-standard name for the exports (${m.exportsArgument}).`
  1017. : hooks.embedInRuntimeBailout.call(m, renderContext);
  1018. if (iife) {
  1019. inlinedInIIFE = true;
  1020. }
  1021. const renderedModule = renamedInlinedModule
  1022. ? renamedInlinedModule.get(m)
  1023. : this.renderModule(
  1024. m,
  1025. {
  1026. ...chunkRenderContext,
  1027. factory: false,
  1028. inlinedInIIFE
  1029. },
  1030. hooks
  1031. );
  1032. if (renderedModule) {
  1033. /** @type {string} */
  1034. let footer;
  1035. if (iife !== undefined) {
  1036. startupSource.add(
  1037. `// This entry needs to be wrapped in an IIFE because ${iife}\n`
  1038. );
  1039. const arrow = runtimeTemplate.supportsArrowFunction();
  1040. if (arrow) {
  1041. startupSource.add("(() => {\n");
  1042. footer = "\n})();\n\n";
  1043. } else {
  1044. startupSource.add("!function() {\n");
  1045. footer = "\n}();\n";
  1046. }
  1047. if (innerStrict) startupSource.add('"use strict";\n');
  1048. } else {
  1049. footer = "\n";
  1050. }
  1051. if (exports) {
  1052. if (m !== lastInlinedModule) {
  1053. startupSource.add(`var ${m.exportsArgument} = {};\n`);
  1054. } else if (m.exportsArgument !== RuntimeGlobals.exports) {
  1055. startupSource.add(
  1056. `var ${m.exportsArgument} = ${RuntimeGlobals.exports};\n`
  1057. );
  1058. }
  1059. }
  1060. startupSource.add(renderedModule);
  1061. startupSource.add(footer);
  1062. }
  1063. }
  1064. if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
  1065. startupSource.add(
  1066. `${RuntimeGlobals.exports} = ${RuntimeGlobals.onChunksLoaded}(${RuntimeGlobals.exports});\n`
  1067. );
  1068. }
  1069. /** @type {StartupRenderContext} */
  1070. const startupRenderContext = {
  1071. ...renderContext,
  1072. inlined: true,
  1073. inlinedInIIFE,
  1074. needExportsDeclaration: runtimeRequirements.has(RuntimeGlobals.exports)
  1075. };
  1076. let renderedStartup = hooks.renderStartup.call(
  1077. startupSource,
  1078. lastInlinedModule,
  1079. startupRenderContext
  1080. );
  1081. const lastInlinedModuleRequirements =
  1082. chunkGraph.getModuleRuntimeRequirements(
  1083. lastInlinedModule,
  1084. chunk.runtime
  1085. );
  1086. if (
  1087. // `onChunksLoaded` reads and reassigns `__webpack_exports__`
  1088. runtimeRequirements.has(RuntimeGlobals.onChunksLoaded) ||
  1089. // Top-level `__webpack_exports__` will be returned
  1090. runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime) ||
  1091. // Custom exports argument aliases from `__webpack_exports__`
  1092. (lastInlinedModuleRequirements.has(RuntimeGlobals.exports) &&
  1093. lastInlinedModule.exportsArgument !== RuntimeGlobals.exports)
  1094. ) {
  1095. startupRenderContext.needExportsDeclaration = true;
  1096. }
  1097. if (startupRenderContext.needExportsDeclaration) {
  1098. renderedStartup = new ConcatSource(
  1099. `var ${RuntimeGlobals.exports} = {};\n`,
  1100. renderedStartup
  1101. );
  1102. }
  1103. source.add(renderedStartup);
  1104. if (bootstrap.afterStartup.length > 0) {
  1105. const afterStartup = `${Template.asString(bootstrap.afterStartup)}\n`;
  1106. source.add(
  1107. new PrefixSource(
  1108. prefix,
  1109. useSourceMap
  1110. ? new OriginalSource(afterStartup, "webpack/after-startup")
  1111. : new RawSource(afterStartup)
  1112. )
  1113. );
  1114. }
  1115. } else {
  1116. const lastEntryModule =
  1117. /** @type {Module} */
  1118. (last(chunkGraph.getChunkEntryModulesIterable(chunk)));
  1119. /** @type {(content: string[], name: string) => Source} */
  1120. const toSource = useSourceMap
  1121. ? (content, name) =>
  1122. new OriginalSource(Template.asString(content), name)
  1123. : (content) => new RawSource(Template.asString(content));
  1124. source.add(
  1125. new PrefixSource(
  1126. prefix,
  1127. new ConcatSource(
  1128. toSource(bootstrap.beforeStartup, "webpack/before-startup"),
  1129. "\n",
  1130. hooks.renderStartup.call(
  1131. toSource([...bootstrap.startup, ""], "webpack/startup"),
  1132. lastEntryModule,
  1133. {
  1134. ...renderContext,
  1135. inlined: false,
  1136. needExportsDeclaration: true
  1137. }
  1138. ),
  1139. toSource(bootstrap.afterStartup, "webpack/after-startup"),
  1140. "\n"
  1141. )
  1142. )
  1143. );
  1144. }
  1145. if (
  1146. hasEntryModules &&
  1147. runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime)
  1148. ) {
  1149. source.add(`${prefix}return ${RuntimeGlobals.exports};\n`);
  1150. }
  1151. if (iife) {
  1152. source.add("/******/ })()\n");
  1153. }
  1154. /** @type {Source} */
  1155. let finalSource = tryRunOrWebpackError(
  1156. () => hooks.renderMain.call(source, renderContext),
  1157. "JavascriptModulesPlugin.getCompilationHooks().renderMain"
  1158. );
  1159. if (!finalSource) {
  1160. throw new Error(
  1161. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderMain plugins should return something"
  1162. );
  1163. }
  1164. finalSource = tryRunOrWebpackError(
  1165. () => hooks.renderContent.call(finalSource, renderContext),
  1166. "JavascriptModulesPlugin.getCompilationHooks().renderContent"
  1167. );
  1168. if (!finalSource) {
  1169. throw new Error(
  1170. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
  1171. );
  1172. }
  1173. finalSource = InitFragment.addToSource(
  1174. finalSource,
  1175. chunkRenderContext.chunkInitFragments,
  1176. chunkRenderContext
  1177. );
  1178. finalSource = tryRunOrWebpackError(
  1179. () => hooks.render.call(finalSource, renderContext),
  1180. "JavascriptModulesPlugin.getCompilationHooks().render"
  1181. );
  1182. if (!finalSource) {
  1183. throw new Error(
  1184. "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
  1185. );
  1186. }
  1187. chunk.rendered = true;
  1188. return iife ? new ConcatSource(finalSource, ";") : finalSource;
  1189. }
  1190. /**
  1191. * Updates hash with bootstrap.
  1192. * @param {Hash} hash the hash to be updated
  1193. * @param {RenderBootstrapContext} renderContext options object
  1194. * @param {CompilationHooks} hooks hooks
  1195. */
  1196. updateHashWithBootstrap(hash, renderContext, hooks) {
  1197. const bootstrap = this.renderBootstrap(renderContext, hooks);
  1198. for (const _k of Object.keys(bootstrap)) {
  1199. const key = /** @type {keyof Bootstrap} */ (_k);
  1200. hash.update(key);
  1201. if (Array.isArray(bootstrap[key])) {
  1202. for (const line of bootstrap[key]) {
  1203. hash.update(line);
  1204. }
  1205. } else {
  1206. hash.update(JSON.stringify(bootstrap[key]));
  1207. }
  1208. }
  1209. }
  1210. /**
  1211. * Renders the generated source of the bootstrap code.
  1212. * @param {RenderBootstrapContext} renderContext options object
  1213. * @param {CompilationHooks} hooks hooks
  1214. * @returns {Bootstrap} the generated source of the bootstrap code
  1215. */
  1216. renderBootstrap(renderContext, hooks) {
  1217. const {
  1218. chunkGraph,
  1219. codeGenerationResults,
  1220. moduleGraph,
  1221. chunk,
  1222. runtimeTemplate
  1223. } = renderContext;
  1224. const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
  1225. const requireFunction = runtimeRequirements.has(RuntimeGlobals.require);
  1226. const moduleCache = runtimeRequirements.has(RuntimeGlobals.moduleCache);
  1227. const moduleFactories = runtimeRequirements.has(
  1228. RuntimeGlobals.moduleFactories
  1229. );
  1230. const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
  1231. const requireScopeUsed = runtimeRequirements.has(
  1232. RuntimeGlobals.requireScope
  1233. );
  1234. const interceptModuleExecution = runtimeRequirements.has(
  1235. RuntimeGlobals.interceptModuleExecution
  1236. );
  1237. const useRequire =
  1238. requireFunction || interceptModuleExecution || moduleUsed;
  1239. /**
  1240. * @type {{ startup: string[], beforeStartup: string[], header: string[], afterStartup: string[], allowInlineStartup: boolean }}
  1241. */
  1242. const result = {
  1243. header: [],
  1244. beforeStartup: [],
  1245. startup: [],
  1246. afterStartup: [],
  1247. allowInlineStartup: true
  1248. };
  1249. const { header: buf, startup, beforeStartup, afterStartup } = result;
  1250. if (result.allowInlineStartup && moduleFactories) {
  1251. startup.push(
  1252. "// module factories are used so entry inlining is disabled"
  1253. );
  1254. result.allowInlineStartup = false;
  1255. }
  1256. if (result.allowInlineStartup && moduleCache) {
  1257. startup.push("// module cache are used so entry inlining is disabled");
  1258. result.allowInlineStartup = false;
  1259. }
  1260. if (result.allowInlineStartup && interceptModuleExecution) {
  1261. startup.push(
  1262. "// module execution is intercepted so entry inlining is disabled"
  1263. );
  1264. result.allowInlineStartup = false;
  1265. }
  1266. if (useRequire || moduleCache) {
  1267. buf.push("// The module cache");
  1268. buf.push("var __webpack_module_cache__ = {};");
  1269. buf.push("");
  1270. }
  1271. if (runtimeRequirements.has(RuntimeGlobals.makeDeferredNamespaceObject)) {
  1272. // in order to optimize of DeferredNamespaceObject, we remove all proxy handlers after the module initialize
  1273. // (see MakeDeferredNamespaceObjectRuntimeModule)
  1274. // This requires all deferred imports to a module can get the module export object before the module
  1275. // is evaluated.
  1276. buf.push("// The deferred module cache");
  1277. buf.push("var __webpack_module_deferred_exports__ = {};");
  1278. buf.push("");
  1279. }
  1280. if (useRequire) {
  1281. buf.push("// The require function");
  1282. buf.push(`function ${RuntimeGlobals.require}(moduleId) {`);
  1283. buf.push(Template.indent(this.renderRequire(renderContext, hooks)));
  1284. buf.push("}");
  1285. buf.push("");
  1286. } else if (runtimeRequirements.has(RuntimeGlobals.requireScope)) {
  1287. buf.push("// The require scope");
  1288. buf.push(`var ${RuntimeGlobals.require} = {};`);
  1289. buf.push("");
  1290. }
  1291. if (
  1292. moduleFactories ||
  1293. runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly)
  1294. ) {
  1295. buf.push("// expose the modules object (__webpack_modules__)");
  1296. buf.push(`${RuntimeGlobals.moduleFactories} = __webpack_modules__;`);
  1297. buf.push("");
  1298. }
  1299. if (moduleCache) {
  1300. buf.push("// expose the module cache");
  1301. buf.push(`${RuntimeGlobals.moduleCache} = __webpack_module_cache__;`);
  1302. buf.push("");
  1303. }
  1304. if (interceptModuleExecution) {
  1305. buf.push("// expose the module execution interceptor");
  1306. buf.push(`${RuntimeGlobals.interceptModuleExecution} = [];`);
  1307. buf.push("");
  1308. }
  1309. if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
  1310. if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
  1311. /** @type {string[]} */
  1312. const buf2 = [];
  1313. const runtimeRequirements =
  1314. chunkGraph.getTreeRuntimeRequirements(chunk);
  1315. buf2.push("// Load entry module and return exports");
  1316. /** @type {EntryModuleWithChunkGroup[]} */
  1317. const jsEntries = [];
  1318. for (const [
  1319. entryModule,
  1320. entrypoint
  1321. ] of chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)) {
  1322. if (
  1323. chunkGraph.getModuleSourceTypes(entryModule).has(JAVASCRIPT_TYPE)
  1324. ) {
  1325. jsEntries.push([entryModule, entrypoint]);
  1326. continue;
  1327. }
  1328. }
  1329. let i = jsEntries.length;
  1330. for (const [entryModule, entrypoint] of jsEntries) {
  1331. const chunks =
  1332. /** @type {Entrypoint} */
  1333. (entrypoint).chunks.filter((c) => c !== chunk);
  1334. if (result.allowInlineStartup && chunks.length > 0) {
  1335. buf2.push(
  1336. "// This entry module depends on other loaded chunks and execution need to be delayed"
  1337. );
  1338. result.allowInlineStartup = false;
  1339. }
  1340. if (
  1341. result.allowInlineStartup &&
  1342. someInIterable(
  1343. moduleGraph.getIncomingConnectionsByOriginModule(entryModule),
  1344. ([originModule, connections]) =>
  1345. originModule &&
  1346. connections.some((c) => c.isTargetActive(chunk.runtime)) &&
  1347. someInIterable(
  1348. chunkGraph.getModuleRuntimes(originModule),
  1349. (runtime) =>
  1350. intersectRuntime(runtime, chunk.runtime) !== undefined
  1351. )
  1352. )
  1353. ) {
  1354. buf2.push(
  1355. "// This entry module is referenced by other modules so it can't be inlined"
  1356. );
  1357. result.allowInlineStartup = false;
  1358. }
  1359. /** @type {undefined | CodeGenerationResultData} */
  1360. let data;
  1361. if (codeGenerationResults.has(entryModule, chunk.runtime)) {
  1362. const result = codeGenerationResults.get(
  1363. entryModule,
  1364. chunk.runtime
  1365. );
  1366. data = result.data;
  1367. }
  1368. if (
  1369. result.allowInlineStartup &&
  1370. (!data || !data.get("topLevelDeclarations")) &&
  1371. (!entryModule.buildInfo ||
  1372. !entryModule.buildInfo.topLevelDeclarations)
  1373. ) {
  1374. buf2.push(
  1375. "// This entry module doesn't tell about it's top-level declarations so it can't be inlined"
  1376. );
  1377. result.allowInlineStartup = false;
  1378. }
  1379. if (result.allowInlineStartup) {
  1380. const bailout = hooks.inlineInRuntimeBailout.call(
  1381. entryModule,
  1382. renderContext
  1383. );
  1384. if (bailout !== undefined) {
  1385. buf2.push(
  1386. `// This entry module can't be inlined because ${bailout}`
  1387. );
  1388. result.allowInlineStartup = false;
  1389. }
  1390. }
  1391. i--;
  1392. const moduleId = chunkGraph.getModuleId(entryModule);
  1393. const entryRuntimeRequirements =
  1394. chunkGraph.getModuleRuntimeRequirements(entryModule, chunk.runtime);
  1395. let moduleIdExpr = JSON.stringify(moduleId);
  1396. if (runtimeRequirements.has(RuntimeGlobals.entryModuleId)) {
  1397. moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
  1398. }
  1399. if (
  1400. result.allowInlineStartup &&
  1401. entryRuntimeRequirements.has(RuntimeGlobals.module)
  1402. ) {
  1403. result.allowInlineStartup = false;
  1404. buf2.push(
  1405. "// This entry module used 'module' so it can't be inlined"
  1406. );
  1407. }
  1408. if (
  1409. result.allowInlineStartup &&
  1410. entryRuntimeRequirements.has(RuntimeGlobals.thisAsExports)
  1411. ) {
  1412. buf2.push(
  1413. "// This entry module used `this` as exports so it can't be inlined"
  1414. );
  1415. result.allowInlineStartup = false;
  1416. }
  1417. if (chunks.length > 0) {
  1418. buf2.push(
  1419. `${i === 0 ? `var ${RuntimeGlobals.exports} = ` : ""}${
  1420. RuntimeGlobals.onChunksLoaded
  1421. }(undefined, ${JSON.stringify(
  1422. chunks.map((c) => c.id)
  1423. )}, ${runtimeTemplate.returningFunction(
  1424. `${RuntimeGlobals.require}(${moduleIdExpr})`
  1425. )})`
  1426. );
  1427. } else if (useRequire) {
  1428. buf2.push(
  1429. `${i === 0 ? `var ${RuntimeGlobals.exports} = ` : ""}${
  1430. RuntimeGlobals.require
  1431. }(${moduleIdExpr});`
  1432. );
  1433. } else {
  1434. if (i === 0) buf2.push(`var ${RuntimeGlobals.exports} = {};`);
  1435. const needThisAsExports = entryRuntimeRequirements.has(
  1436. RuntimeGlobals.thisAsExports
  1437. );
  1438. /** @type {string[]} */
  1439. const args = [];
  1440. if (
  1441. requireScopeUsed ||
  1442. entryRuntimeRequirements.has(RuntimeGlobals.exports)
  1443. ) {
  1444. const exportsArg = i === 0 ? RuntimeGlobals.exports : "{}";
  1445. args.push("0", exportsArg);
  1446. if (requireScopeUsed) {
  1447. args.push(RuntimeGlobals.require);
  1448. }
  1449. }
  1450. buf2.push(
  1451. Template.asString(
  1452. (() => {
  1453. if (needThisAsExports) {
  1454. const comma = args.length ? "," : "";
  1455. return `__webpack_modules__[${moduleIdExpr}].call(${RuntimeGlobals.exports}${comma}${args.join(",")});`;
  1456. }
  1457. return `__webpack_modules__[${moduleIdExpr}](${args.join(",")});`;
  1458. })()
  1459. )
  1460. );
  1461. }
  1462. }
  1463. if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
  1464. buf2.push(
  1465. `${RuntimeGlobals.exports} = ${RuntimeGlobals.onChunksLoaded}(${RuntimeGlobals.exports});`
  1466. );
  1467. }
  1468. if (
  1469. runtimeRequirements.has(RuntimeGlobals.startup) ||
  1470. (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) &&
  1471. runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter))
  1472. ) {
  1473. result.allowInlineStartup = false;
  1474. buf.push("// the startup function");
  1475. buf.push(
  1476. `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction("", [
  1477. ...buf2,
  1478. `return ${RuntimeGlobals.exports};`
  1479. ])};`
  1480. );
  1481. buf.push("");
  1482. startup.push("// run startup");
  1483. startup.push(
  1484. `var ${RuntimeGlobals.exports} = ${RuntimeGlobals.startup}();`
  1485. );
  1486. } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
  1487. buf.push("// the startup function");
  1488. buf.push(
  1489. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
  1490. );
  1491. beforeStartup.push("// run runtime startup");
  1492. beforeStartup.push(`${RuntimeGlobals.startup}();`);
  1493. startup.push("// startup");
  1494. startup.push(Template.asString(buf2));
  1495. } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)) {
  1496. buf.push("// the startup function");
  1497. buf.push(
  1498. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
  1499. );
  1500. startup.push("// startup");
  1501. startup.push(Template.asString(buf2));
  1502. afterStartup.push("// run runtime startup");
  1503. afterStartup.push(`${RuntimeGlobals.startup}();`);
  1504. } else {
  1505. startup.push("// startup");
  1506. startup.push(Template.asString(buf2));
  1507. }
  1508. } else if (
  1509. runtimeRequirements.has(RuntimeGlobals.startup) ||
  1510. runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
  1511. runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
  1512. ) {
  1513. buf.push(
  1514. "// the startup function",
  1515. "// It's empty as no entry modules are in this chunk",
  1516. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`,
  1517. ""
  1518. );
  1519. }
  1520. } else if (
  1521. runtimeRequirements.has(RuntimeGlobals.startup) ||
  1522. runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
  1523. runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
  1524. ) {
  1525. result.allowInlineStartup = false;
  1526. buf.push(
  1527. "// the startup function",
  1528. "// It's empty as some runtime module handles the default behavior",
  1529. `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
  1530. );
  1531. startup.push("// run startup");
  1532. startup.push(
  1533. `var ${RuntimeGlobals.exports} = ${RuntimeGlobals.startup}();`
  1534. );
  1535. }
  1536. return result;
  1537. }
  1538. /**
  1539. * Renders the generated source of the require function.
  1540. * @param {RenderBootstrapContext} renderContext options object
  1541. * @param {CompilationHooks} hooks hooks
  1542. * @returns {string} the generated source of the require function
  1543. */
  1544. renderRequire(renderContext, hooks) {
  1545. const {
  1546. chunk,
  1547. chunkGraph,
  1548. runtimeTemplate: { outputOptions }
  1549. } = renderContext;
  1550. const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
  1551. /**
  1552. * Renders missing module error.
  1553. * @param {string} condition guard expression
  1554. * @returns {string[]} source
  1555. */
  1556. const renderMissingModuleError = (condition) =>
  1557. outputOptions.pathinfo
  1558. ? [
  1559. `if (${condition}) {`,
  1560. Template.indent([
  1561. "delete __webpack_module_cache__[moduleId];",
  1562. 'var e = new Error("Cannot find module \'" + moduleId + "\'");',
  1563. "e.code = 'MODULE_NOT_FOUND';",
  1564. "throw e;"
  1565. ]),
  1566. "}"
  1567. ]
  1568. : [];
  1569. const moduleExecution = runtimeRequirements.has(
  1570. RuntimeGlobals.interceptModuleExecution
  1571. )
  1572. ? Template.asString([
  1573. `var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: ${RuntimeGlobals.require} };`,
  1574. `${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
  1575. ...renderMissingModuleError("!execOptions.factory"),
  1576. "module = execOptions.module;",
  1577. "execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
  1578. ])
  1579. : runtimeRequirements.has(RuntimeGlobals.thisAsExports)
  1580. ? Template.asString([
  1581. ...renderMissingModuleError("!(moduleId in __webpack_modules__)"),
  1582. `__webpack_modules__[moduleId].call(module.exports, module, module.exports, ${RuntimeGlobals.require});`
  1583. ])
  1584. : Template.asString([
  1585. ...renderMissingModuleError("!(moduleId in __webpack_modules__)"),
  1586. `__webpack_modules__[moduleId](module, module.exports, ${RuntimeGlobals.require});`
  1587. ]);
  1588. const needModuleId = runtimeRequirements.has(RuntimeGlobals.moduleId);
  1589. const needModuleLoaded = runtimeRequirements.has(
  1590. RuntimeGlobals.moduleLoaded
  1591. );
  1592. const needModuleDefer = runtimeRequirements.has(
  1593. RuntimeGlobals.makeDeferredNamespaceObject
  1594. );
  1595. const content = Template.asString([
  1596. "// Check if module is in cache",
  1597. "var cachedModule = __webpack_module_cache__[moduleId];",
  1598. "if (cachedModule !== undefined) {",
  1599. outputOptions.strictModuleErrorHandling
  1600. ? Template.indent([
  1601. "if (cachedModule.error !== undefined) throw cachedModule.error;",
  1602. "return cachedModule.exports;"
  1603. ])
  1604. : Template.indent("return cachedModule.exports;"),
  1605. "}",
  1606. "// Create a new module (and put it into the cache)",
  1607. "var module = __webpack_module_cache__[moduleId] = {",
  1608. Template.indent([
  1609. needModuleId ? "id: moduleId," : "// no module.id needed",
  1610. needModuleLoaded ? "loaded: false," : "// no module.loaded needed",
  1611. needModuleDefer
  1612. ? "exports: __webpack_module_deferred_exports__[moduleId] || {}"
  1613. : "exports: {}"
  1614. ]),
  1615. "};",
  1616. "",
  1617. outputOptions.strictModuleExceptionHandling
  1618. ? Template.asString([
  1619. "// Execute the module function",
  1620. "var threw = true;",
  1621. "try {",
  1622. Template.indent([
  1623. moduleExecution,
  1624. "threw = false;",
  1625. ...(needModuleDefer
  1626. ? ["delete __webpack_module_deferred_exports__[moduleId];"]
  1627. : [])
  1628. ]),
  1629. "} finally {",
  1630. Template.indent([
  1631. "if(threw) delete __webpack_module_cache__[moduleId];"
  1632. ]),
  1633. "}"
  1634. ])
  1635. : outputOptions.strictModuleErrorHandling
  1636. ? Template.asString([
  1637. "// Execute the module function",
  1638. "try {",
  1639. Template.indent(
  1640. needModuleDefer
  1641. ? [
  1642. moduleExecution,
  1643. "delete __webpack_module_deferred_exports__[moduleId];"
  1644. ]
  1645. : moduleExecution
  1646. ),
  1647. "} catch(e) {",
  1648. Template.indent(["module.error = e;", "throw e;"]),
  1649. "}"
  1650. ])
  1651. : Template.asString([
  1652. "// Execute the module function",
  1653. moduleExecution,
  1654. ...(needModuleDefer
  1655. ? ["delete __webpack_module_deferred_exports__[moduleId];"]
  1656. : [])
  1657. ]),
  1658. needModuleLoaded
  1659. ? Template.asString([
  1660. "",
  1661. "// Flag the module as loaded",
  1662. `${RuntimeGlobals.moduleLoaded} = true;`,
  1663. ""
  1664. ])
  1665. : "",
  1666. "// Return the exports of the module",
  1667. "return module.exports;"
  1668. ]);
  1669. return tryRunOrWebpackError(
  1670. () => hooks.renderRequire.call(content, renderContext),
  1671. "JavascriptModulesPlugin.getCompilationHooks().renderRequire"
  1672. );
  1673. }
  1674. /**
  1675. * Get renamed inline module.
  1676. * @param {Compilation} compilation compilation
  1677. * @param {Module[]} allModules allModules
  1678. * @param {MainRenderContext} renderContext renderContext
  1679. * @param {Set<Module>} inlinedModules inlinedModules
  1680. * @param {ChunkRenderContext} chunkRenderContext chunkRenderContext
  1681. * @param {CompilationHooks} hooks hooks
  1682. * @param {boolean | undefined} allStrict allStrict
  1683. * @param {boolean} hasChunkModules hasChunkModules
  1684. * @returns {Map<Module, Source> | false} renamed inlined modules
  1685. */
  1686. _getRenamedInlineModule(
  1687. compilation,
  1688. allModules,
  1689. renderContext,
  1690. inlinedModules,
  1691. chunkRenderContext,
  1692. hooks,
  1693. allStrict,
  1694. hasChunkModules
  1695. ) {
  1696. const innerStrict =
  1697. !allStrict &&
  1698. allModules.every((m) => /** @type {BuildInfo} */ (m.buildInfo).strict);
  1699. const isMultipleEntries = inlinedModules.size > 1;
  1700. const singleEntryWithModules = inlinedModules.size === 1 && hasChunkModules;
  1701. // TODO:
  1702. // This step is before the IIFE reason calculation. Ideally, it should only be executed when this function can optimize the
  1703. // IIFE reason. Otherwise, it should directly return false. There are four reasons now, we have skipped two already, the left
  1704. // one is 'it uses a non-standard name for the exports'.
  1705. if (isMultipleEntries || innerStrict || !singleEntryWithModules) {
  1706. return false;
  1707. }
  1708. /** @type {Map<Module, Source>} */
  1709. const renamedInlinedModules = new Map();
  1710. const { runtimeTemplate } = renderContext;
  1711. /** @typedef {{ source: Source, module: Module, ast: Program, variables: Set<Variable>, through: Set<Reference>, usedInNonInlined: Set<Variable>, moduleScope: Scope }} Info */
  1712. /** @type {Map<Module, Info>} */
  1713. const inlinedModulesToInfo = new Map();
  1714. /** @type {Set<string>} */
  1715. const nonInlinedModuleThroughIdentifiers = new Set();
  1716. for (const m of allModules) {
  1717. const isInlinedModule = inlinedModules && inlinedModules.has(m);
  1718. const moduleSource = this.renderModule(
  1719. m,
  1720. {
  1721. ...chunkRenderContext,
  1722. factory: !isInlinedModule,
  1723. inlinedInIIFE: false
  1724. },
  1725. hooks
  1726. );
  1727. if (!moduleSource) continue;
  1728. const code = /** @type {string} */ (moduleSource.source());
  1729. const { ast } = JavascriptParser._parse(
  1730. code,
  1731. {
  1732. sourceType: "auto",
  1733. ranges: true
  1734. },
  1735. JavascriptParser._getModuleParseFunction(compilation, m)
  1736. );
  1737. const scopeManager = eslintScope.analyze(ast, {
  1738. ecmaVersion: 6,
  1739. sourceType: "module",
  1740. optimistic: true,
  1741. ignoreEval: true
  1742. });
  1743. const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
  1744. if (inlinedModules && inlinedModules.has(m)) {
  1745. const moduleScope = globalScope.childScopes[0];
  1746. inlinedModulesToInfo.set(m, {
  1747. source: moduleSource,
  1748. ast,
  1749. module: m,
  1750. variables: new Set(moduleScope.variables),
  1751. through: new Set(moduleScope.through),
  1752. usedInNonInlined: new Set(),
  1753. moduleScope
  1754. });
  1755. } else {
  1756. for (const ref of globalScope.through) {
  1757. nonInlinedModuleThroughIdentifiers.add(ref.identifier.name);
  1758. }
  1759. }
  1760. }
  1761. for (const [, { variables, usedInNonInlined }] of inlinedModulesToInfo) {
  1762. for (const variable of variables) {
  1763. if (
  1764. nonInlinedModuleThroughIdentifiers.has(variable.name) ||
  1765. RESERVED_NAMES.has(variable.name)
  1766. ) {
  1767. usedInNonInlined.add(variable);
  1768. }
  1769. }
  1770. }
  1771. for (const [m, moduleInfo] of inlinedModulesToInfo) {
  1772. const { ast, source: _source, usedInNonInlined } = moduleInfo;
  1773. const source = new ReplaceSource(_source);
  1774. if (usedInNonInlined.size === 0) {
  1775. renamedInlinedModules.set(m, source);
  1776. continue;
  1777. }
  1778. const info = /** @type {Info} */ (inlinedModulesToInfo.get(m));
  1779. const allUsedNames = new Set(
  1780. Array.from(info.through, (v) => v.identifier.name)
  1781. );
  1782. for (const variable of usedInNonInlined) {
  1783. allUsedNames.add(variable.name);
  1784. }
  1785. for (const variable of info.variables) {
  1786. /** @type {UsedNamesInScopeInfo} */
  1787. const usedNamesInScopeInfo = new Map();
  1788. /** @type {ScopeSet} */
  1789. const ignoredScopes = new Set();
  1790. const name = variable.name;
  1791. const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
  1792. usedNamesInScopeInfo,
  1793. info.module.identifier(),
  1794. name
  1795. );
  1796. if (allUsedNames.has(name) || usedNames.has(name)) {
  1797. const references = getAllReferences(variable);
  1798. const allIdentifiers = new Set([
  1799. ...references.map((r) => r.identifier),
  1800. ...variable.identifiers
  1801. ]);
  1802. for (const ref of references) {
  1803. addScopeSymbols(
  1804. ref.from,
  1805. usedNames,
  1806. alreadyCheckedScopes,
  1807. ignoredScopes
  1808. );
  1809. }
  1810. const newName = findNewName(
  1811. variable.name,
  1812. allUsedNames,
  1813. usedNames,
  1814. m.readableIdentifier(runtimeTemplate.requestShortener)
  1815. );
  1816. allUsedNames.add(newName);
  1817. for (const identifier of allIdentifiers) {
  1818. const r = /** @type {Range} */ (identifier.range);
  1819. const path = getPathInAst(ast, identifier);
  1820. if (path && path.length > 1) {
  1821. const maybeProperty =
  1822. path[1].type === "AssignmentPattern" && path[1].left === path[0]
  1823. ? path[2]
  1824. : path[1];
  1825. if (
  1826. maybeProperty.type === "Property" &&
  1827. maybeProperty.shorthand
  1828. ) {
  1829. source.insert(r[1], `: ${newName}`);
  1830. continue;
  1831. }
  1832. }
  1833. source.replace(r[0], r[1] - 1, newName);
  1834. }
  1835. }
  1836. allUsedNames.add(name);
  1837. }
  1838. renamedInlinedModules.set(m, source);
  1839. }
  1840. return renamedInlinedModules;
  1841. }
  1842. }
  1843. module.exports = JavascriptModulesPlugin;
  1844. module.exports.chunkHasJs = chunkHasJs;