JavascriptModulesPlugin.js 59 KB

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