ConcatenatedModule.js 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const eslintScope = require("eslint-scope");
  7. const Referencer = require("eslint-scope/lib/referencer");
  8. const { SyncBailHook } = require("tapable");
  9. const {
  10. CachedSource,
  11. ConcatSource,
  12. ReplaceSource
  13. } = require("webpack-sources");
  14. const ConcatenationScope = require("../ConcatenationScope");
  15. const { UsageState } = require("../ExportsInfo");
  16. const Module = require("../Module");
  17. const {
  18. JAVASCRIPT_TYPE,
  19. JAVASCRIPT_TYPES
  20. } = require("../ModuleSourceTypeConstants");
  21. const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants");
  22. const RuntimeGlobals = require("../RuntimeGlobals");
  23. const Template = require("../Template");
  24. const { DEFAULTS } = require("../config/defaults");
  25. const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
  26. const { ImportPhaseUtils } = require("../dependencies/ImportPhase");
  27. const JavascriptParser = require("../javascript/JavascriptParser");
  28. const {
  29. getMakeDeferredNamespaceModeFromExportsType,
  30. getOptimizedDeferredModule
  31. } = require("../runtime/MakeDeferredNamespaceObjectRuntime");
  32. const { equals } = require("../util/ArrayHelpers");
  33. const LazySet = require("../util/LazySet");
  34. const { concatComparators } = require("../util/comparators");
  35. const {
  36. RESERVED_NAMES,
  37. addScopeSymbols,
  38. findNewName,
  39. getAllReferences,
  40. getPathInAst,
  41. getUsedNamesInScopeInfo
  42. } = require("../util/concatenate");
  43. const createHash = require("../util/createHash");
  44. const { makePathsRelative } = require("../util/identifier");
  45. const makeSerializable = require("../util/makeSerializable");
  46. const { propertyAccess, propertyName } = require("../util/property");
  47. const {
  48. filterRuntime,
  49. intersectRuntime,
  50. mergeRuntimeCondition,
  51. mergeRuntimeConditionNonFalse,
  52. runtimeConditionToString,
  53. subtractRuntimeCondition
  54. } = require("../util/runtime");
  55. /** @typedef {import("eslint-scope").Reference} Reference */
  56. /** @typedef {import("eslint-scope").Scope} Scope */
  57. /** @typedef {import("eslint-scope").Variable} Variable */
  58. /** @typedef {import("webpack-sources").Source} Source */
  59. /** @typedef {import("../config/defaults").WebpackOptionsNormalizedWithDefaults} WebpackOptions */
  60. /** @typedef {import("../ChunkGraph")} ChunkGraph */
  61. /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
  62. /** @typedef {import("../Compilation")} Compilation */
  63. /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
  64. /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
  65. /** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
  66. /** @typedef {import("../Module").BuildCallback} BuildCallback */
  67. /** @typedef {import("../Module").BuildInfo} BuildInfo */
  68. /** @typedef {import("../Module").FileSystemDependencies} FileSystemDependencies */
  69. /** @typedef {import("../Module").BuildMeta} BuildMeta */
  70. /** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
  71. /** @typedef {import("../Module").CodeGenerationResultData} CodeGenerationResultData */
  72. /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
  73. /** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
  74. /** @typedef {import("../Module").LibIdent} LibIdent */
  75. /** @typedef {import("../Module").NameForCondition} NameForCondition */
  76. /** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
  77. /** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
  78. /** @typedef {import("../Module").SourceTypes} SourceTypes */
  79. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  80. /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
  81. /** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
  82. /** @typedef {import("../RequestShortener")} RequestShortener */
  83. /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
  84. /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
  85. /** @typedef {import("../javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
  86. /** @typedef {import("../javascript/JavascriptParser").Program} Program */
  87. /** @typedef {import("../javascript/JavascriptParser").Range} Range */
  88. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  89. /** @typedef {import("../util/Hash")} Hash */
  90. /** @typedef {import("../util/Hash").HashFunction} HashFunction */
  91. /** @typedef {import("../util/concatenate").UsedNames} UsedNames */
  92. /** @typedef {import("../util/concatenate").ScopeInfo} ScopeInfo */
  93. /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
  94. /** @typedef {import("../util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */
  95. /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
  96. /**
  97. * @template T
  98. * @typedef {import("../InitFragment")<T>} InitFragment
  99. */
  100. /**
  101. * @template T
  102. * @typedef {import("../util/comparators").Comparator<T>} Comparator
  103. */
  104. // fix eslint-scope to support class properties correctly
  105. // cspell:word Referencer
  106. const ReferencerClass = Referencer;
  107. if (!ReferencerClass.prototype.PropertyDefinition) {
  108. ReferencerClass.prototype.PropertyDefinition =
  109. ReferencerClass.prototype.Property;
  110. }
  111. /** @typedef {RawBinding | SymbolBinding} Binding */
  112. /** @typedef {string[]} ExportName */
  113. /**
  114. * @typedef {object} RawBinding
  115. * @property {ModuleInfo} info
  116. * @property {string} rawName
  117. * @property {string=} comment
  118. * @property {ExportName} ids
  119. * @property {ExportName} exportName
  120. */
  121. /**
  122. * @typedef {object} SymbolBinding
  123. * @property {ConcatenatedModuleInfo} info
  124. * @property {string} name
  125. * @property {string=} comment
  126. * @property {ExportName} ids
  127. * @property {ExportName} exportName
  128. */
  129. /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo} ModuleInfo */
  130. /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo} ModuleInfoOrReference */
  131. /** @typedef {Map<string, string>} ExportMap */
  132. /**
  133. * @typedef {object} ConcatenatedModuleInfo
  134. * @property {"concatenated"} type
  135. * @property {Module} module
  136. * @property {number} index
  137. * @property {Program | undefined} ast
  138. * @property {Source | undefined} internalSource
  139. * @property {ReplaceSource | undefined} source
  140. * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
  141. * @property {ReadOnlyRuntimeRequirements | undefined} runtimeRequirements
  142. * @property {Scope | undefined} globalScope
  143. * @property {Scope | undefined} moduleScope
  144. * @property {Map<string, string>} internalNames
  145. * @property {ExportMap | undefined} exportMap
  146. * @property {ExportMap | undefined} rawExportMap
  147. * @property {string=} namespaceExportSymbol
  148. * @property {string | undefined} namespaceObjectName
  149. * @property {ConcatenationScope | undefined} concatenationScope
  150. * @property {boolean} interopNamespaceObjectUsed "default-with-named" namespace
  151. * @property {string | undefined} interopNamespaceObjectName "default-with-named" namespace
  152. * @property {boolean} interopNamespaceObject2Used "default-only" namespace
  153. * @property {string | undefined} interopNamespaceObject2Name "default-only" namespace
  154. * @property {boolean} interopDefaultAccessUsed runtime namespace object that detects "__esModule"
  155. * @property {string | undefined} interopDefaultAccessName runtime namespace object that detects "__esModule"
  156. */
  157. /**
  158. * @typedef {object} ExternalModuleInfo
  159. * @property {"external"} type
  160. * @property {Module} module
  161. * @property {RuntimeSpec | boolean} runtimeCondition
  162. * @property {NonDeferAccess} nonDeferAccess
  163. * @property {number} index
  164. * @property {string | undefined} name module.exports / harmony namespace object
  165. * @property {string | undefined} deferredName deferred module.exports / harmony namespace object
  166. * @property {boolean} deferred the module is deferred at least once
  167. * @property {boolean} deferredNamespaceObjectUsed deferred namespace object that being used in a not-analyzable way so it must be materialized
  168. * @property {string | undefined} deferredNamespaceObjectName deferred namespace object that being used in a not-analyzable way so it must be materialized
  169. * @property {boolean} interopNamespaceObjectUsed "default-with-named" namespace
  170. * @property {string | undefined} interopNamespaceObjectName "default-with-named" namespace
  171. * @property {boolean} interopNamespaceObject2Used "default-only" namespace
  172. * @property {string | undefined} interopNamespaceObject2Name "default-only" namespace
  173. * @property {boolean} interopDefaultAccessUsed runtime namespace object that detects "__esModule"
  174. * @property {string | undefined} interopDefaultAccessName runtime namespace object that detects "__esModule"
  175. */
  176. /**
  177. * @typedef {object} ReferenceToModuleInfo
  178. * @property {"reference"} type
  179. * @property {RuntimeSpec | boolean} runtimeCondition
  180. * @property {NonDeferAccess} nonDeferAccess
  181. * @property {ModuleInfo} target
  182. */
  183. /**
  184. * @template T
  185. * @param {string} property property
  186. * @param {(a: T[keyof T], b: T[keyof T]) => 0 | 1 | -1} comparator comparator
  187. * @returns {Comparator<T>} comparator
  188. */
  189. const createComparator = (property, comparator) => (a, b) =>
  190. comparator(
  191. a[/** @type {keyof T} */ (property)],
  192. b[/** @type {keyof T} */ (property)]
  193. );
  194. /**
  195. * @param {number} a a
  196. * @param {number} b b
  197. * @returns {0 | 1 | -1} result
  198. */
  199. const compareNumbers = (a, b) => {
  200. if (Number.isNaN(a)) {
  201. if (!Number.isNaN(b)) {
  202. return 1;
  203. }
  204. } else {
  205. if (Number.isNaN(b)) {
  206. return -1;
  207. }
  208. if (a !== b) {
  209. return a < b ? -1 : 1;
  210. }
  211. }
  212. return 0;
  213. };
  214. const bySourceOrder = createComparator("sourceOrder", compareNumbers);
  215. const byRangeStart = createComparator("rangeStart", compareNumbers);
  216. /**
  217. * @param {Iterable<string>} iterable iterable object
  218. * @returns {string} joined iterable object
  219. */
  220. const joinIterableWithComma = (iterable) => {
  221. // This is more performant than Array.from().join(", ")
  222. // as it doesn't create an array
  223. let str = "";
  224. let first = true;
  225. for (const item of iterable) {
  226. if (first) {
  227. first = false;
  228. } else {
  229. str += ", ";
  230. }
  231. str += item;
  232. }
  233. return str;
  234. };
  235. /** @typedef {boolean} NonDeferAccess */
  236. /**
  237. * @param {NonDeferAccess} a a
  238. * @param {NonDeferAccess} b b
  239. * @returns {NonDeferAccess} merged
  240. */
  241. const mergeNonDeferAccess = (a, b) => a || b;
  242. /**
  243. * @param {NonDeferAccess} a first
  244. * @param {NonDeferAccess} b second
  245. * @returns {NonDeferAccess} first - second
  246. */
  247. const subtractNonDeferAccess = (a, b) => a && !b;
  248. /**
  249. * @typedef {object} ConcatenationEntry
  250. * @property {"concatenated" | "external"} type
  251. * @property {Module} module
  252. * @property {RuntimeSpec | boolean} runtimeCondition
  253. * @property {NonDeferAccess} nonDeferAccess
  254. */
  255. /** @typedef {Set<ConcatenatedModuleInfo>} NeededNamespaceObjects */
  256. /** @typedef {Map<Module, ModuleInfo>} ModuleToInfoMap */
  257. /**
  258. * @param {ModuleGraph} moduleGraph the module graph
  259. * @param {ModuleInfo} info module info
  260. * @param {ExportName} exportName exportName
  261. * @param {ModuleToInfoMap} moduleToInfoMap moduleToInfoMap
  262. * @param {RuntimeSpec} runtime for which runtime
  263. * @param {RequestShortener} requestShortener the request shortener
  264. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  265. * @param {NeededNamespaceObjects} neededNamespaceObjects modules for which a namespace object should be generated
  266. * @param {boolean} asCall asCall
  267. * @param {boolean} depDeferred the dependency is deferred
  268. * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
  269. * @param {boolean | undefined} asiSafe asiSafe
  270. * @param {Set<ExportInfo>} alreadyVisited alreadyVisited
  271. * @returns {Binding} the final variable
  272. */
  273. const getFinalBinding = (
  274. moduleGraph,
  275. info,
  276. exportName,
  277. moduleToInfoMap,
  278. runtime,
  279. requestShortener,
  280. runtimeTemplate,
  281. neededNamespaceObjects,
  282. asCall,
  283. depDeferred,
  284. strictHarmonyModule,
  285. asiSafe,
  286. alreadyVisited = new Set()
  287. ) => {
  288. const exportsType = info.module.getExportsType(
  289. moduleGraph,
  290. strictHarmonyModule
  291. );
  292. const moduleDeferred =
  293. info.type === "external" &&
  294. info.deferred &&
  295. !(/** @type {BuildMeta} */ (info.module.buildMeta).async);
  296. const deferred = depDeferred && moduleDeferred;
  297. if (exportName.length === 0) {
  298. switch (exportsType) {
  299. case "default-only":
  300. if (deferred) info.deferredNamespaceObjectUsed = true;
  301. else info.interopNamespaceObject2Used = true;
  302. return {
  303. info,
  304. rawName: /** @type {string} */ (
  305. deferred
  306. ? info.deferredNamespaceObjectName
  307. : info.interopNamespaceObject2Name
  308. ),
  309. ids: exportName,
  310. exportName
  311. };
  312. case "default-with-named":
  313. if (deferred) info.deferredNamespaceObjectUsed = true;
  314. else info.interopNamespaceObjectUsed = true;
  315. return {
  316. info,
  317. rawName: /** @type {string} */ (
  318. deferred
  319. ? info.deferredNamespaceObjectName
  320. : info.interopNamespaceObjectName
  321. ),
  322. ids: exportName,
  323. exportName
  324. };
  325. case "namespace":
  326. case "dynamic":
  327. break;
  328. default:
  329. throw new Error(`Unexpected exportsType ${exportsType}`);
  330. }
  331. } else {
  332. switch (exportsType) {
  333. case "namespace":
  334. break;
  335. case "default-with-named":
  336. switch (exportName[0]) {
  337. case "default":
  338. exportName = exportName.slice(1);
  339. break;
  340. case "__esModule":
  341. return {
  342. info,
  343. rawName: "/* __esModule */true",
  344. ids: exportName.slice(1),
  345. exportName
  346. };
  347. }
  348. break;
  349. case "default-only": {
  350. const exportId = exportName[0];
  351. if (exportId === "__esModule") {
  352. return {
  353. info,
  354. rawName: "/* __esModule */true",
  355. ids: exportName.slice(1),
  356. exportName
  357. };
  358. }
  359. exportName = exportName.slice(1);
  360. if (exportId !== "default") {
  361. return {
  362. info,
  363. rawName:
  364. "/* non-default import from default-exporting module */undefined",
  365. ids: exportName,
  366. exportName
  367. };
  368. }
  369. break;
  370. }
  371. case "dynamic":
  372. switch (exportName[0]) {
  373. case "default": {
  374. exportName = exportName.slice(1);
  375. if (deferred) {
  376. return {
  377. info,
  378. rawName: `${info.deferredName}.a`,
  379. ids: exportName,
  380. exportName
  381. };
  382. }
  383. if (moduleDeferred) {
  384. return {
  385. info,
  386. rawName: /** @type {string} */ (info.name),
  387. ids: exportName,
  388. exportName
  389. };
  390. }
  391. info.interopDefaultAccessUsed = true;
  392. const defaultExport = asCall
  393. ? `${info.interopDefaultAccessName}()`
  394. : asiSafe
  395. ? `(${info.interopDefaultAccessName}())`
  396. : asiSafe === false
  397. ? `;(${info.interopDefaultAccessName}())`
  398. : `${info.interopDefaultAccessName}.a`;
  399. return {
  400. info,
  401. rawName: defaultExport,
  402. ids: exportName,
  403. exportName
  404. };
  405. }
  406. case "__esModule":
  407. return {
  408. info,
  409. rawName: "/* __esModule */true",
  410. ids: exportName.slice(1),
  411. exportName
  412. };
  413. }
  414. break;
  415. default:
  416. throw new Error(`Unexpected exportsType ${exportsType}`);
  417. }
  418. }
  419. if (exportName.length === 0) {
  420. switch (info.type) {
  421. case "concatenated":
  422. neededNamespaceObjects.add(info);
  423. return {
  424. info,
  425. rawName:
  426. /** @type {NonNullable<ConcatenatedModuleInfo["namespaceObjectName"]>} */
  427. (info.namespaceObjectName),
  428. ids: exportName,
  429. exportName
  430. };
  431. case "external":
  432. if (deferred) {
  433. info.deferredNamespaceObjectUsed = true;
  434. return {
  435. info,
  436. rawName: /** @type {string} */ (info.deferredNamespaceObjectName),
  437. ids: exportName,
  438. exportName
  439. };
  440. }
  441. return {
  442. info,
  443. rawName:
  444. /** @type {NonNullable<ExternalModuleInfo["name"]>} */
  445. (info.name),
  446. ids: exportName,
  447. exportName
  448. };
  449. }
  450. }
  451. const exportsInfo = moduleGraph.getExportsInfo(info.module);
  452. const exportInfo = exportsInfo.getExportInfo(exportName[0]);
  453. if (alreadyVisited.has(exportInfo)) {
  454. return {
  455. info,
  456. rawName: "/* circular reexport */ Object(function x() { x() }())",
  457. ids: [],
  458. exportName
  459. };
  460. }
  461. alreadyVisited.add(exportInfo);
  462. switch (info.type) {
  463. case "concatenated": {
  464. const exportId = exportName[0];
  465. if (exportInfo.provided === false) {
  466. // It's not provided, but it could be on the prototype
  467. neededNamespaceObjects.add(info);
  468. return {
  469. info,
  470. rawName: /** @type {string} */ (info.namespaceObjectName),
  471. ids: exportName,
  472. exportName
  473. };
  474. }
  475. const directExport = info.exportMap && info.exportMap.get(exportId);
  476. if (directExport) {
  477. const usedName = /** @type {ExportName} */ (
  478. exportsInfo.getUsedName(exportName, runtime)
  479. );
  480. if (!usedName) {
  481. return {
  482. info,
  483. rawName: "/* unused export */ undefined",
  484. ids: exportName.slice(1),
  485. exportName
  486. };
  487. }
  488. return {
  489. info,
  490. name: directExport,
  491. ids: usedName.slice(1),
  492. exportName
  493. };
  494. }
  495. const rawExport = info.rawExportMap && info.rawExportMap.get(exportId);
  496. if (rawExport) {
  497. return {
  498. info,
  499. rawName: rawExport,
  500. ids: exportName.slice(1),
  501. exportName
  502. };
  503. }
  504. const reexport = exportInfo.findTarget(moduleGraph, (module) =>
  505. moduleToInfoMap.has(module)
  506. );
  507. if (reexport === false) {
  508. throw new Error(
  509. `Target module of reexport from '${info.module.readableIdentifier(
  510. requestShortener
  511. )}' is not part of the concatenation (export '${exportId}')\nModules in the concatenation:\n${Array.from(
  512. moduleToInfoMap,
  513. ([m, info]) =>
  514. ` * ${info.type} ${m.readableIdentifier(requestShortener)}`
  515. ).join("\n")}`
  516. );
  517. }
  518. if (reexport) {
  519. const refInfo = moduleToInfoMap.get(reexport.module);
  520. return getFinalBinding(
  521. moduleGraph,
  522. /** @type {ModuleInfo} */ (refInfo),
  523. reexport.export
  524. ? [...reexport.export, ...exportName.slice(1)]
  525. : exportName.slice(1),
  526. moduleToInfoMap,
  527. runtime,
  528. requestShortener,
  529. runtimeTemplate,
  530. neededNamespaceObjects,
  531. asCall,
  532. reexport.deferred,
  533. /** @type {BuildMeta} */
  534. (info.module.buildMeta).strictHarmonyModule,
  535. asiSafe,
  536. alreadyVisited
  537. );
  538. }
  539. if (info.namespaceExportSymbol) {
  540. const usedName = /** @type {ExportName} */ (
  541. exportsInfo.getUsedName(exportName, runtime)
  542. );
  543. return {
  544. info,
  545. rawName: /** @type {string} */ (info.namespaceObjectName),
  546. ids: usedName,
  547. exportName
  548. };
  549. }
  550. throw new Error(
  551. `Cannot get final name for export '${exportName.join(
  552. "."
  553. )}' of ${info.module.readableIdentifier(requestShortener)}`
  554. );
  555. }
  556. case "external": {
  557. const used = /** @type {ExportName} */ (
  558. exportsInfo.getUsedName(exportName, runtime)
  559. );
  560. if (!used) {
  561. return {
  562. info,
  563. rawName: "/* unused export */ undefined",
  564. ids: exportName.slice(1),
  565. exportName
  566. };
  567. }
  568. const comment = equals(used, exportName)
  569. ? ""
  570. : Template.toNormalComment(`${exportName.join(".")}`);
  571. return {
  572. info,
  573. rawName:
  574. (deferred ? info.deferredName : info.name) +
  575. (deferred ? ".a" : "") +
  576. comment,
  577. ids: used,
  578. exportName
  579. };
  580. }
  581. }
  582. };
  583. /**
  584. * @param {ModuleGraph} moduleGraph the module graph
  585. * @param {ModuleInfo} info module info
  586. * @param {ExportName} exportName exportName
  587. * @param {ModuleToInfoMap} moduleToInfoMap moduleToInfoMap
  588. * @param {RuntimeSpec} runtime for which runtime
  589. * @param {RequestShortener} requestShortener the request shortener
  590. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  591. * @param {NeededNamespaceObjects} neededNamespaceObjects modules for which a namespace object should be generated
  592. * @param {boolean} asCall asCall
  593. * @param {boolean} depDeferred the dependency is deferred
  594. * @param {boolean | undefined} callContext callContext
  595. * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
  596. * @param {boolean | undefined} asiSafe asiSafe
  597. * @returns {string} the final name
  598. */
  599. const getFinalName = (
  600. moduleGraph,
  601. info,
  602. exportName,
  603. moduleToInfoMap,
  604. runtime,
  605. requestShortener,
  606. runtimeTemplate,
  607. neededNamespaceObjects,
  608. asCall,
  609. depDeferred,
  610. callContext,
  611. strictHarmonyModule,
  612. asiSafe
  613. ) => {
  614. const binding = getFinalBinding(
  615. moduleGraph,
  616. info,
  617. exportName,
  618. moduleToInfoMap,
  619. runtime,
  620. requestShortener,
  621. runtimeTemplate,
  622. neededNamespaceObjects,
  623. asCall,
  624. depDeferred,
  625. strictHarmonyModule,
  626. asiSafe
  627. );
  628. {
  629. const { ids, comment } = binding;
  630. /** @type {string} */
  631. let reference;
  632. /** @type {boolean} */
  633. let isPropertyAccess;
  634. if ("rawName" in binding) {
  635. reference = `${binding.rawName}${comment || ""}${propertyAccess(ids)}`;
  636. isPropertyAccess = ids.length > 0;
  637. } else {
  638. const { info, name: exportId } = binding;
  639. const name = info.internalNames.get(exportId);
  640. if (!name) {
  641. throw new Error(
  642. `The export "${exportId}" in "${info.module.readableIdentifier(
  643. requestShortener
  644. )}" has no internal name (existing names: ${
  645. Array.from(
  646. info.internalNames,
  647. ([name, symbol]) => `${name}: ${symbol}`
  648. ).join(", ") || "none"
  649. })`
  650. );
  651. }
  652. reference = `${name}${comment || ""}${propertyAccess(ids)}`;
  653. isPropertyAccess = ids.length > 1;
  654. }
  655. if (isPropertyAccess && asCall && callContext === false) {
  656. return asiSafe
  657. ? `(0,${reference})`
  658. : asiSafe === false
  659. ? `;(0,${reference})`
  660. : `/*#__PURE__*/Object(${reference})`;
  661. }
  662. return reference;
  663. }
  664. };
  665. /**
  666. * @typedef {object} ConcatenateModuleHooks
  667. * @property {SyncBailHook<[ConcatenatedModule, RuntimeSpec[], string, Record<string, string>], boolean>} onDemandExportsGeneration
  668. * @property {SyncBailHook<[Partial<ConcatenatedModuleInfo>, ConcatenatedModuleInfo], boolean | void>} concatenatedModuleInfo
  669. */
  670. /** @typedef {BuildInfo["topLevelDeclarations"]} TopLevelDeclarations */
  671. /** @type {WeakMap<Compilation, ConcatenateModuleHooks>} */
  672. const compilationHooksMap = new WeakMap();
  673. class ConcatenatedModule extends Module {
  674. /**
  675. * @param {Module} rootModule the root module of the concatenation
  676. * @param {Set<Module>} modules all modules in the concatenation (including the root module)
  677. * @param {RuntimeSpec} runtime the runtime
  678. * @param {Compilation} compilation the compilation
  679. * @param {AssociatedObjectForCache=} associatedObjectForCache object for caching
  680. * @param {HashFunction=} hashFunction hash function to use
  681. * @returns {ConcatenatedModule} the module
  682. */
  683. static create(
  684. rootModule,
  685. modules,
  686. runtime,
  687. compilation,
  688. associatedObjectForCache,
  689. hashFunction = DEFAULTS.HASH_FUNCTION
  690. ) {
  691. const identifier = ConcatenatedModule._createIdentifier(
  692. rootModule,
  693. modules,
  694. associatedObjectForCache,
  695. hashFunction
  696. );
  697. return new ConcatenatedModule({
  698. identifier,
  699. rootModule,
  700. modules,
  701. runtime,
  702. compilation
  703. });
  704. }
  705. /**
  706. * @param {Compilation} compilation the compilation
  707. * @returns {ConcatenateModuleHooks} the attached hooks
  708. */
  709. static getCompilationHooks(compilation) {
  710. let hooks = compilationHooksMap.get(compilation);
  711. if (hooks === undefined) {
  712. hooks = {
  713. onDemandExportsGeneration: new SyncBailHook([
  714. "module",
  715. "runtimes",
  716. "exportsFinalName",
  717. "exportsSource"
  718. ]),
  719. concatenatedModuleInfo: new SyncBailHook([
  720. "updatedInfo",
  721. "concatenatedModuleInfo"
  722. ])
  723. };
  724. compilationHooksMap.set(compilation, hooks);
  725. }
  726. return hooks;
  727. }
  728. /**
  729. * @param {object} options options
  730. * @param {string} options.identifier the identifier of the module
  731. * @param {Module} options.rootModule the root module of the concatenation
  732. * @param {RuntimeSpec} options.runtime the selected runtime
  733. * @param {Set<Module>} options.modules all concatenated modules
  734. * @param {Compilation} options.compilation the compilation
  735. */
  736. constructor({ identifier, rootModule, modules, runtime, compilation }) {
  737. super(JAVASCRIPT_MODULE_TYPE_ESM, null, rootModule && rootModule.layer);
  738. // Info from Factory
  739. /** @type {string} */
  740. this._identifier = identifier;
  741. /** @type {Module} */
  742. this.rootModule = rootModule;
  743. /** @type {Set<Module>} */
  744. this._modules = modules;
  745. this._runtime = runtime;
  746. this.factoryMeta = rootModule && rootModule.factoryMeta;
  747. /** @type {Compilation} */
  748. this.compilation = compilation;
  749. }
  750. /**
  751. * Assuming this module is in the cache. Update the (cached) module with
  752. * the fresh module from the factory. Usually updates internal references
  753. * and properties.
  754. * @param {Module} module fresh module
  755. * @returns {void}
  756. */
  757. updateCacheModule(module) {
  758. throw new Error("Must not be called");
  759. }
  760. /**
  761. * Returns the source types this module can generate.
  762. * @returns {SourceTypes} types available (do not mutate)
  763. */
  764. getSourceTypes() {
  765. return JAVASCRIPT_TYPES;
  766. }
  767. get modules() {
  768. return [...this._modules];
  769. }
  770. /**
  771. * Returns the unique identifier used to reference this module.
  772. * @returns {string} a unique identifier of the module
  773. */
  774. identifier() {
  775. return this._identifier;
  776. }
  777. /**
  778. * Returns a human-readable identifier for this module.
  779. * @param {RequestShortener} requestShortener the request shortener
  780. * @returns {string} a user readable identifier of the module
  781. */
  782. readableIdentifier(requestShortener) {
  783. return `${this.rootModule.readableIdentifier(
  784. requestShortener
  785. )} + ${this._modules.size - 1} modules`;
  786. }
  787. /**
  788. * Gets the library identifier.
  789. * @param {LibIdentOptions} options options
  790. * @returns {LibIdent | null} an identifier for library inclusion
  791. */
  792. libIdent(options) {
  793. return this.rootModule.libIdent(options);
  794. }
  795. /**
  796. * Returns the path used when matching this module against rule conditions.
  797. * @returns {NameForCondition | null} absolute path which should be used for condition matching (usually the resource path)
  798. */
  799. nameForCondition() {
  800. return this.rootModule.nameForCondition();
  801. }
  802. /**
  803. * Gets side effects connection state.
  804. * @param {ModuleGraph} moduleGraph the module graph
  805. * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
  806. */
  807. getSideEffectsConnectionState(moduleGraph) {
  808. return this.rootModule.getSideEffectsConnectionState(moduleGraph);
  809. }
  810. /**
  811. * Builds the module using the provided compilation context.
  812. * @param {WebpackOptions} options webpack options
  813. * @param {Compilation} compilation the compilation
  814. * @param {ResolverWithOptions} resolver the resolver
  815. * @param {InputFileSystem} fs the file system
  816. * @param {BuildCallback} callback callback function
  817. * @returns {void}
  818. */
  819. build(options, compilation, resolver, fs, callback) {
  820. const { rootModule } = this;
  821. const { moduleArgument, exportsArgument } =
  822. /** @type {BuildInfo} */
  823. (rootModule.buildInfo);
  824. /** @type {BuildInfo} */
  825. this.buildInfo = {
  826. strict: true,
  827. cacheable: true,
  828. moduleArgument,
  829. exportsArgument,
  830. fileDependencies: new LazySet(),
  831. contextDependencies: new LazySet(),
  832. missingDependencies: new LazySet(),
  833. topLevelDeclarations: new Set(),
  834. assets: undefined
  835. };
  836. this.buildMeta = rootModule.buildMeta;
  837. this.clearDependenciesAndBlocks();
  838. this.clearWarningsAndErrors();
  839. for (const m of this._modules) {
  840. // populate cacheable
  841. if (!(/** @type {BuildInfo} */ (m.buildInfo).cacheable)) {
  842. this.buildInfo.cacheable = false;
  843. }
  844. // populate dependencies
  845. for (const d of m.dependencies.filter(
  846. (dep) =>
  847. !(dep instanceof HarmonyImportDependency) ||
  848. !this._modules.has(
  849. /** @type {Module} */
  850. (compilation.moduleGraph.getModule(dep))
  851. )
  852. )) {
  853. this.dependencies.push(d);
  854. }
  855. // populate blocks
  856. for (const d of m.blocks) {
  857. this.blocks.push(d);
  858. }
  859. // populate warnings
  860. const warnings = m.getWarnings();
  861. if (warnings !== undefined) {
  862. for (const warning of warnings) {
  863. this.addWarning(warning);
  864. }
  865. }
  866. // populate errors
  867. const errors = m.getErrors();
  868. if (errors !== undefined) {
  869. for (const error of errors) {
  870. this.addError(error);
  871. }
  872. }
  873. const { assets, assetsInfo, topLevelDeclarations, needCreateRequire } =
  874. /** @type {BuildInfo} */ (m.buildInfo);
  875. const buildInfo = this.buildInfo;
  876. // populate topLevelDeclarations
  877. if (topLevelDeclarations) {
  878. const topLevelDeclarations = buildInfo.topLevelDeclarations;
  879. if (topLevelDeclarations !== undefined) {
  880. for (const decl of topLevelDeclarations) {
  881. topLevelDeclarations.add(decl);
  882. }
  883. }
  884. } else {
  885. buildInfo.topLevelDeclarations = undefined;
  886. }
  887. // populate needCreateRequire
  888. if (needCreateRequire) {
  889. this.buildInfo.needCreateRequire = true;
  890. }
  891. // populate assets
  892. if (assets) {
  893. if (buildInfo.assets === undefined) {
  894. buildInfo.assets = Object.create(null);
  895. }
  896. Object.assign(
  897. /** @type {NonNullable<BuildInfo["assets"]>} */
  898. (buildInfo.assets),
  899. assets
  900. );
  901. }
  902. if (assetsInfo) {
  903. if (buildInfo.assetsInfo === undefined) {
  904. buildInfo.assetsInfo = new Map();
  905. }
  906. for (const [key, value] of assetsInfo) {
  907. buildInfo.assetsInfo.set(key, value);
  908. }
  909. }
  910. }
  911. callback();
  912. }
  913. /**
  914. * Returns the estimated size for the requested source type.
  915. * @param {string=} type the source type for which the size should be estimated
  916. * @returns {number} the estimated size of the module (must be non-zero)
  917. */
  918. size(type) {
  919. // Guess size from embedded modules
  920. let size = 0;
  921. for (const module of this._modules) {
  922. size += module.size(type);
  923. }
  924. return size;
  925. }
  926. /**
  927. * @private
  928. * @param {Module} rootModule the root of the concatenation
  929. * @param {Set<Module>} modulesSet a set of modules which should be concatenated
  930. * @param {RuntimeSpec} runtime for this runtime
  931. * @param {ModuleGraph} moduleGraph the module graph
  932. * @returns {ConcatenationEntry[]} concatenation list
  933. */
  934. _createConcatenationList(rootModule, modulesSet, runtime, moduleGraph) {
  935. /** @type {ConcatenationEntry[]} */
  936. const list = [];
  937. /** @type {Map<Module, { runtimeCondition: RuntimeSpec | true, nonDeferAccess: NonDeferAccess }>} */
  938. const existingEntries = new Map();
  939. /**
  940. * @param {Module} module a module
  941. * @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true, nonDeferAccess: NonDeferAccess }>} imported modules in order
  942. */
  943. const getConcatenatedImports = (module) => {
  944. const connections = [...moduleGraph.getOutgoingConnections(module)];
  945. if (module === rootModule) {
  946. for (const c of moduleGraph.getOutgoingConnections(this)) {
  947. connections.push(c);
  948. }
  949. }
  950. /**
  951. * @type {{ connection: ModuleGraphConnection, sourceOrder: number, rangeStart: number | undefined, defer?: boolean }[]}
  952. */
  953. const references = connections
  954. .filter((connection) => {
  955. if (!(connection.dependency instanceof HarmonyImportDependency)) {
  956. return false;
  957. }
  958. if (
  959. !Module.getSourceBasicTypes(connection.module).has(JAVASCRIPT_TYPE)
  960. ) {
  961. return false;
  962. }
  963. return (
  964. connection &&
  965. connection.resolvedOriginModule === module &&
  966. connection.module &&
  967. connection.isTargetActive(runtime)
  968. );
  969. })
  970. .map((connection) => {
  971. const dep =
  972. /** @type {HarmonyImportDependency} */
  973. (connection.dependency);
  974. return {
  975. connection,
  976. sourceOrder: /** @type {number} */ (dep.sourceOrder),
  977. rangeStart: dep.range && dep.range[0],
  978. defer: ImportPhaseUtils.isDefer(dep.phase)
  979. };
  980. });
  981. /**
  982. * bySourceOrder
  983. * @example
  984. * import a from "a"; // sourceOrder=1
  985. * import b from "b"; // sourceOrder=2
  986. *
  987. * byRangeStart
  988. * @example
  989. * import {a, b} from "a"; // sourceOrder=1
  990. * a.a(); // first range
  991. * b.b(); // second range
  992. *
  993. * If there is no reexport, we have the same source.
  994. * If there is reexport, but module has side effects, this will lead to reexport module only.
  995. * If there is side-effects-free reexport, we can get simple deterministic result with range start comparison.
  996. */
  997. references.sort(concatComparators(bySourceOrder, byRangeStart));
  998. /** @type {Map<Module, { connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true, nonDeferAccess: NonDeferAccess }>} */
  999. const referencesMap = new Map();
  1000. for (const { connection, defer } of references) {
  1001. const runtimeCondition = filterRuntime(runtime, (r) =>
  1002. connection.isTargetActive(r)
  1003. );
  1004. if (runtimeCondition === false) continue;
  1005. const nonDeferAccess = !defer;
  1006. const module = connection.module;
  1007. const entry = referencesMap.get(module);
  1008. if (entry === undefined) {
  1009. referencesMap.set(module, {
  1010. connection,
  1011. runtimeCondition,
  1012. nonDeferAccess
  1013. });
  1014. continue;
  1015. }
  1016. entry.runtimeCondition = mergeRuntimeConditionNonFalse(
  1017. entry.runtimeCondition,
  1018. runtimeCondition,
  1019. runtime
  1020. );
  1021. entry.nonDeferAccess = mergeNonDeferAccess(
  1022. entry.nonDeferAccess,
  1023. nonDeferAccess
  1024. );
  1025. }
  1026. return referencesMap.values();
  1027. };
  1028. /**
  1029. * @param {ModuleGraphConnection} connection graph connection
  1030. * @param {RuntimeSpec | true} runtimeCondition runtime condition
  1031. * @param {NonDeferAccess} nonDeferAccess non-defer access
  1032. * @returns {void}
  1033. */
  1034. const enterModule = (connection, runtimeCondition, nonDeferAccess) => {
  1035. const module = connection.module;
  1036. if (!module) return;
  1037. const existingEntry = existingEntries.get(module);
  1038. if (
  1039. existingEntry &&
  1040. existingEntry.runtimeCondition === true &&
  1041. existingEntry.nonDeferAccess === true
  1042. ) {
  1043. return;
  1044. }
  1045. if (modulesSet.has(module)) {
  1046. existingEntries.set(module, {
  1047. runtimeCondition: true,
  1048. nonDeferAccess: true
  1049. });
  1050. if (runtimeCondition !== true) {
  1051. throw new Error(
  1052. `Cannot runtime-conditional concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}, ${runtimeConditionToString(
  1053. runtimeCondition
  1054. )}). This should not happen.`
  1055. );
  1056. }
  1057. if (nonDeferAccess !== true) {
  1058. throw new Error(
  1059. `Cannot deferred concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}. This should not happen.`
  1060. );
  1061. }
  1062. const imports = getConcatenatedImports(module);
  1063. for (const {
  1064. connection,
  1065. runtimeCondition,
  1066. nonDeferAccess
  1067. } of imports) {
  1068. enterModule(connection, runtimeCondition, nonDeferAccess);
  1069. }
  1070. list.push({
  1071. type: "concatenated",
  1072. module: connection.module,
  1073. runtimeCondition,
  1074. nonDeferAccess
  1075. });
  1076. } else {
  1077. /** @type {RuntimeSpec | boolean} */
  1078. let reducedRuntimeCondition;
  1079. /** @type {NonDeferAccess} */
  1080. let reducedNonDeferAccess;
  1081. if (existingEntry !== undefined) {
  1082. reducedRuntimeCondition = subtractRuntimeCondition(
  1083. runtimeCondition,
  1084. existingEntry.runtimeCondition,
  1085. runtime
  1086. );
  1087. reducedNonDeferAccess = subtractNonDeferAccess(
  1088. nonDeferAccess,
  1089. existingEntry.nonDeferAccess
  1090. );
  1091. if (
  1092. reducedRuntimeCondition === false &&
  1093. reducedNonDeferAccess === false
  1094. ) {
  1095. return;
  1096. }
  1097. if (reducedRuntimeCondition !== false) {
  1098. existingEntry.runtimeCondition = mergeRuntimeConditionNonFalse(
  1099. existingEntry.runtimeCondition,
  1100. reducedRuntimeCondition,
  1101. runtime
  1102. );
  1103. }
  1104. if (reducedNonDeferAccess !== false) {
  1105. existingEntry.nonDeferAccess = mergeNonDeferAccess(
  1106. existingEntry.nonDeferAccess,
  1107. reducedNonDeferAccess
  1108. );
  1109. }
  1110. } else {
  1111. reducedRuntimeCondition = runtimeCondition;
  1112. reducedNonDeferAccess = nonDeferAccess;
  1113. existingEntries.set(connection.module, {
  1114. runtimeCondition,
  1115. nonDeferAccess
  1116. });
  1117. }
  1118. if (list.length > 0) {
  1119. const lastItem = list[list.length - 1];
  1120. if (
  1121. lastItem.type === "external" &&
  1122. lastItem.module === connection.module
  1123. ) {
  1124. lastItem.runtimeCondition = mergeRuntimeCondition(
  1125. lastItem.runtimeCondition,
  1126. reducedRuntimeCondition,
  1127. runtime
  1128. );
  1129. lastItem.nonDeferAccess = mergeNonDeferAccess(
  1130. lastItem.nonDeferAccess,
  1131. reducedNonDeferAccess
  1132. );
  1133. return;
  1134. }
  1135. }
  1136. list.push({
  1137. type: "external",
  1138. get module() {
  1139. // We need to use a getter here, because the module in the dependency
  1140. // could be replaced by some other process (i. e. also replaced with a
  1141. // concatenated module)
  1142. return connection.module;
  1143. },
  1144. runtimeCondition: reducedRuntimeCondition,
  1145. nonDeferAccess: reducedNonDeferAccess
  1146. });
  1147. }
  1148. };
  1149. existingEntries.set(rootModule, {
  1150. runtimeCondition: true,
  1151. nonDeferAccess: true
  1152. });
  1153. const imports = getConcatenatedImports(rootModule);
  1154. for (const { connection, runtimeCondition, nonDeferAccess } of imports) {
  1155. enterModule(connection, runtimeCondition, nonDeferAccess);
  1156. }
  1157. list.push({
  1158. type: "concatenated",
  1159. module: rootModule,
  1160. runtimeCondition: true,
  1161. nonDeferAccess: true
  1162. });
  1163. return list;
  1164. }
  1165. /**
  1166. * @param {Module} rootModule the root module of the concatenation
  1167. * @param {Set<Module>} modules all modules in the concatenation (including the root module)
  1168. * @param {AssociatedObjectForCache=} associatedObjectForCache object for caching
  1169. * @param {HashFunction=} hashFunction hash function to use
  1170. * @returns {string} the identifier
  1171. */
  1172. static _createIdentifier(
  1173. rootModule,
  1174. modules,
  1175. associatedObjectForCache,
  1176. hashFunction = DEFAULTS.HASH_FUNCTION
  1177. ) {
  1178. const cachedMakePathsRelative = makePathsRelative.bindContextCache(
  1179. /** @type {string} */ (rootModule.context),
  1180. associatedObjectForCache
  1181. );
  1182. /** @type {string[]} */
  1183. const identifiers = [];
  1184. for (const module of modules) {
  1185. identifiers.push(cachedMakePathsRelative(module.identifier()));
  1186. }
  1187. identifiers.sort();
  1188. const hash = createHash(hashFunction);
  1189. hash.update(identifiers.join(" "));
  1190. return `${rootModule.identifier()}|${hash.digest("hex")}`;
  1191. }
  1192. /**
  1193. * Adds the provided file dependencies to the module.
  1194. * @param {FileSystemDependencies} fileDependencies set where file dependencies are added to
  1195. * @param {FileSystemDependencies} contextDependencies set where context dependencies are added to
  1196. * @param {FileSystemDependencies} missingDependencies set where missing dependencies are added to
  1197. * @param {FileSystemDependencies} buildDependencies set where build dependencies are added to
  1198. */
  1199. addCacheDependencies(
  1200. fileDependencies,
  1201. contextDependencies,
  1202. missingDependencies,
  1203. buildDependencies
  1204. ) {
  1205. for (const module of this._modules) {
  1206. module.addCacheDependencies(
  1207. fileDependencies,
  1208. contextDependencies,
  1209. missingDependencies,
  1210. buildDependencies
  1211. );
  1212. }
  1213. }
  1214. /**
  1215. * Generates code and runtime requirements for this module.
  1216. * @param {CodeGenerationContext} context context for code generation
  1217. * @returns {CodeGenerationResult} result
  1218. */
  1219. codeGeneration({
  1220. dependencyTemplates,
  1221. runtimeTemplate,
  1222. moduleGraph,
  1223. chunkGraph,
  1224. runtime: generationRuntime,
  1225. runtimes,
  1226. codeGenerationResults
  1227. }) {
  1228. const { concatenatedModuleInfo } = ConcatenatedModule.getCompilationHooks(
  1229. this.compilation
  1230. );
  1231. /** @type {RuntimeRequirements} */
  1232. const runtimeRequirements = new Set();
  1233. const runtime = intersectRuntime(generationRuntime, this._runtime);
  1234. const requestShortener = runtimeTemplate.requestShortener;
  1235. // Meta info for each module
  1236. const [modulesWithInfo, moduleToInfoMap] = this._getModulesWithInfo(
  1237. moduleGraph,
  1238. runtime
  1239. );
  1240. // Set with modules that need a generated namespace object
  1241. /** @type {NeededNamespaceObjects} */
  1242. const neededNamespaceObjects = new Set();
  1243. // List of all used names to avoid conflicts
  1244. const allUsedNames = new Set(RESERVED_NAMES);
  1245. // Generate source code and analyse scopes
  1246. // Prepare a ReplaceSource for the final source
  1247. for (const info of moduleToInfoMap.values()) {
  1248. this._analyseModule(
  1249. moduleToInfoMap,
  1250. info,
  1251. dependencyTemplates,
  1252. runtimeTemplate,
  1253. moduleGraph,
  1254. chunkGraph,
  1255. runtime,
  1256. runtimes,
  1257. /** @type {CodeGenerationResults} */
  1258. (codeGenerationResults),
  1259. allUsedNames
  1260. );
  1261. }
  1262. // Updated Top level declarations are created by renaming
  1263. /** @type {TopLevelDeclarations} */
  1264. const topLevelDeclarations = new Set();
  1265. // List of additional names in scope for module references
  1266. /** @type {Map<string, ScopeInfo>} */
  1267. const usedNamesInScopeInfo = new Map();
  1268. // Set of already checked scopes
  1269. /** @type {Set<Scope>} */
  1270. const ignoredScopes = new Set();
  1271. // get all global names
  1272. for (const info of modulesWithInfo) {
  1273. if (info.type === "concatenated") {
  1274. // ignore symbols from moduleScope
  1275. if (info.moduleScope) {
  1276. ignoredScopes.add(info.moduleScope);
  1277. }
  1278. // The super class expression in class scopes behaves weird
  1279. // We get ranges of all super class expressions to make
  1280. // renaming to work correctly
  1281. /** @typedef {{ range: Range, variables: Variable[] }} ClassInfo */
  1282. /** @type {WeakMap<Scope, ClassInfo[]>} */
  1283. const superClassCache = new WeakMap();
  1284. /**
  1285. * @param {Scope} scope scope
  1286. * @returns {ClassInfo[]} result
  1287. */
  1288. const getSuperClassExpressions = (scope) => {
  1289. const cacheEntry = superClassCache.get(scope);
  1290. if (cacheEntry !== undefined) return cacheEntry;
  1291. /** @type {ClassInfo[]} */
  1292. const superClassExpressions = [];
  1293. for (const childScope of scope.childScopes) {
  1294. if (childScope.type !== "class") continue;
  1295. const block = childScope.block;
  1296. if (
  1297. (block.type === "ClassDeclaration" ||
  1298. block.type === "ClassExpression") &&
  1299. block.superClass
  1300. ) {
  1301. superClassExpressions.push({
  1302. range: /** @type {Range} */ (block.superClass.range),
  1303. variables: childScope.variables
  1304. });
  1305. }
  1306. }
  1307. superClassCache.set(scope, superClassExpressions);
  1308. return superClassExpressions;
  1309. };
  1310. // add global symbols
  1311. if (info.globalScope) {
  1312. for (const reference of info.globalScope.through) {
  1313. const name = reference.identifier.name;
  1314. if (ConcatenationScope.isModuleReference(name)) {
  1315. const match = ConcatenationScope.matchModuleReference(name);
  1316. if (!match) continue;
  1317. const referencedInfo = modulesWithInfo[match.index];
  1318. if (referencedInfo.type === "reference") {
  1319. throw new Error("Module reference can't point to a reference");
  1320. }
  1321. const binding = getFinalBinding(
  1322. moduleGraph,
  1323. referencedInfo,
  1324. match.ids,
  1325. moduleToInfoMap,
  1326. runtime,
  1327. requestShortener,
  1328. runtimeTemplate,
  1329. neededNamespaceObjects,
  1330. false,
  1331. match.deferredImport,
  1332. /** @type {BuildMeta} */
  1333. (info.module.buildMeta).strictHarmonyModule,
  1334. true
  1335. );
  1336. if (!binding.ids) continue;
  1337. const { usedNames, alreadyCheckedScopes } =
  1338. getUsedNamesInScopeInfo(
  1339. usedNamesInScopeInfo,
  1340. binding.info.module.identifier(),
  1341. "name" in binding ? binding.name : ""
  1342. );
  1343. for (const expr of getSuperClassExpressions(reference.from)) {
  1344. if (
  1345. expr.range[0] <=
  1346. /** @type {Range} */ (reference.identifier.range)[0] &&
  1347. expr.range[1] >=
  1348. /** @type {Range} */ (reference.identifier.range)[1]
  1349. ) {
  1350. for (const variable of expr.variables) {
  1351. usedNames.add(variable.name);
  1352. }
  1353. }
  1354. }
  1355. addScopeSymbols(
  1356. reference.from,
  1357. usedNames,
  1358. alreadyCheckedScopes,
  1359. ignoredScopes
  1360. );
  1361. } else {
  1362. allUsedNames.add(name);
  1363. }
  1364. }
  1365. }
  1366. }
  1367. }
  1368. /**
  1369. * @param {string} name the name to find a new name for
  1370. * @param {ConcatenatedModuleInfo} info the info of the module
  1371. * @param {Reference[]} references the references to the name
  1372. * @returns {string | undefined} the new name or undefined if the name is not found
  1373. */
  1374. const _findNewName = (name, info, references) => {
  1375. const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
  1376. usedNamesInScopeInfo,
  1377. info.module.identifier(),
  1378. name
  1379. );
  1380. if (allUsedNames.has(name) || usedNames.has(name)) {
  1381. for (const ref of references) {
  1382. addScopeSymbols(
  1383. ref.from,
  1384. usedNames,
  1385. alreadyCheckedScopes,
  1386. ignoredScopes
  1387. );
  1388. }
  1389. const newName = findNewName(
  1390. name,
  1391. allUsedNames,
  1392. usedNames,
  1393. info.module.readableIdentifier(requestShortener)
  1394. );
  1395. allUsedNames.add(newName);
  1396. info.internalNames.set(name, newName);
  1397. topLevelDeclarations.add(newName);
  1398. return newName;
  1399. }
  1400. };
  1401. /**
  1402. * @param {string} name the name to find a new name for
  1403. * @param {ConcatenatedModuleInfo} info the info of the module
  1404. * @param {Reference[]} references the references to the name
  1405. * @returns {string | undefined} the new name or undefined if the name is not found
  1406. */
  1407. const _findNewNameForSpecifier = (name, info, references) => {
  1408. const { usedNames: moduleUsedNames, alreadyCheckedScopes } =
  1409. getUsedNamesInScopeInfo(
  1410. usedNamesInScopeInfo,
  1411. info.module.identifier(),
  1412. name
  1413. );
  1414. /** @type {UsedNames} */
  1415. const referencesUsedNames = new Set();
  1416. for (const ref of references) {
  1417. addScopeSymbols(
  1418. ref.from,
  1419. referencesUsedNames,
  1420. alreadyCheckedScopes,
  1421. ignoredScopes
  1422. );
  1423. }
  1424. if (moduleUsedNames.has(name) || referencesUsedNames.has(name)) {
  1425. const newName = findNewName(
  1426. name,
  1427. allUsedNames,
  1428. new Set([...moduleUsedNames, ...referencesUsedNames]),
  1429. info.module.readableIdentifier(requestShortener)
  1430. );
  1431. allUsedNames.add(newName);
  1432. topLevelDeclarations.add(newName);
  1433. return newName;
  1434. }
  1435. };
  1436. // generate names for symbols
  1437. for (const info of moduleToInfoMap.values()) {
  1438. const { usedNames: namespaceObjectUsedNames } = getUsedNamesInScopeInfo(
  1439. usedNamesInScopeInfo,
  1440. info.module.identifier(),
  1441. ""
  1442. );
  1443. switch (info.type) {
  1444. case "concatenated": {
  1445. const variables = /** @type {Scope} */ (info.moduleScope).variables;
  1446. for (const variable of variables) {
  1447. const name = variable.name;
  1448. const references = getAllReferences(variable);
  1449. const newName = _findNewName(name, info, references);
  1450. if (newName) {
  1451. const source = /** @type {ReplaceSource} */ (info.source);
  1452. const allIdentifiers = new Set([
  1453. ...references.map((r) => r.identifier),
  1454. ...variable.identifiers
  1455. ]);
  1456. for (const identifier of allIdentifiers) {
  1457. const r = /** @type {Range} */ (identifier.range);
  1458. const path = getPathInAst(
  1459. /** @type {NonNullable<ConcatenatedModuleInfo["ast"]>} */
  1460. (info.ast),
  1461. identifier
  1462. );
  1463. if (path && path.length > 1) {
  1464. const maybeProperty =
  1465. path[1].type === "AssignmentPattern" &&
  1466. path[1].left === path[0]
  1467. ? path[2]
  1468. : path[1];
  1469. if (
  1470. maybeProperty.type === "Property" &&
  1471. maybeProperty.shorthand
  1472. ) {
  1473. source.insert(r[1], `: ${newName}`);
  1474. continue;
  1475. }
  1476. }
  1477. source.replace(r[0], r[1] - 1, newName);
  1478. }
  1479. } else {
  1480. allUsedNames.add(name);
  1481. info.internalNames.set(name, name);
  1482. topLevelDeclarations.add(name);
  1483. }
  1484. }
  1485. /** @type {string} */
  1486. let namespaceObjectName;
  1487. if (info.namespaceExportSymbol) {
  1488. namespaceObjectName =
  1489. /** @type {string} */
  1490. (info.internalNames.get(info.namespaceExportSymbol));
  1491. } else {
  1492. namespaceObjectName = findNewName(
  1493. "namespaceObject",
  1494. allUsedNames,
  1495. namespaceObjectUsedNames,
  1496. info.module.readableIdentifier(requestShortener)
  1497. );
  1498. allUsedNames.add(namespaceObjectName);
  1499. }
  1500. info.namespaceObjectName = namespaceObjectName;
  1501. topLevelDeclarations.add(namespaceObjectName);
  1502. break;
  1503. }
  1504. case "external": {
  1505. const externalName = findNewName(
  1506. "",
  1507. allUsedNames,
  1508. namespaceObjectUsedNames,
  1509. info.module.readableIdentifier(requestShortener)
  1510. );
  1511. allUsedNames.add(externalName);
  1512. info.name = externalName;
  1513. topLevelDeclarations.add(externalName);
  1514. if (info.deferred) {
  1515. const externalName = findNewName(
  1516. "deferred",
  1517. allUsedNames,
  1518. namespaceObjectUsedNames,
  1519. info.module.readableIdentifier(requestShortener)
  1520. );
  1521. allUsedNames.add(externalName);
  1522. info.deferredName = externalName;
  1523. topLevelDeclarations.add(externalName);
  1524. const externalNameInterop = findNewName(
  1525. "deferredNamespaceObject",
  1526. allUsedNames,
  1527. namespaceObjectUsedNames,
  1528. info.module.readableIdentifier(requestShortener)
  1529. );
  1530. allUsedNames.add(externalNameInterop);
  1531. info.deferredNamespaceObjectName = externalNameInterop;
  1532. topLevelDeclarations.add(externalNameInterop);
  1533. }
  1534. break;
  1535. }
  1536. }
  1537. const buildMeta = /** @type {BuildMeta} */ (info.module.buildMeta);
  1538. if (buildMeta.exportsType !== "namespace") {
  1539. const externalNameInterop = findNewName(
  1540. "namespaceObject",
  1541. allUsedNames,
  1542. namespaceObjectUsedNames,
  1543. info.module.readableIdentifier(requestShortener)
  1544. );
  1545. allUsedNames.add(externalNameInterop);
  1546. info.interopNamespaceObjectName = externalNameInterop;
  1547. topLevelDeclarations.add(externalNameInterop);
  1548. }
  1549. if (
  1550. buildMeta.exportsType === "default" &&
  1551. buildMeta.defaultObject !== "redirect" &&
  1552. info.interopNamespaceObject2Used
  1553. ) {
  1554. const externalNameInterop = findNewName(
  1555. "namespaceObject2",
  1556. allUsedNames,
  1557. namespaceObjectUsedNames,
  1558. info.module.readableIdentifier(requestShortener)
  1559. );
  1560. allUsedNames.add(externalNameInterop);
  1561. info.interopNamespaceObject2Name = externalNameInterop;
  1562. topLevelDeclarations.add(externalNameInterop);
  1563. }
  1564. if (buildMeta.exportsType === "dynamic" || !buildMeta.exportsType) {
  1565. const externalNameInterop = findNewName(
  1566. "default",
  1567. allUsedNames,
  1568. namespaceObjectUsedNames,
  1569. info.module.readableIdentifier(requestShortener)
  1570. );
  1571. allUsedNames.add(externalNameInterop);
  1572. info.interopDefaultAccessName = externalNameInterop;
  1573. topLevelDeclarations.add(externalNameInterop);
  1574. }
  1575. }
  1576. // Find and replace references to modules
  1577. for (const info of moduleToInfoMap.values()) {
  1578. if (info.type === "concatenated") {
  1579. const globalScope = /** @type {Scope} */ (info.globalScope);
  1580. // group references by name
  1581. /** @type {Map<string, Reference[]>} */
  1582. const referencesByName = new Map();
  1583. for (const reference of globalScope.through) {
  1584. const name = reference.identifier.name;
  1585. if (!referencesByName.has(name)) {
  1586. referencesByName.set(name, []);
  1587. }
  1588. /** @type {Reference[]} */
  1589. (referencesByName.get(name)).push(reference);
  1590. }
  1591. for (const [name, references] of referencesByName) {
  1592. const match = ConcatenationScope.matchModuleReference(name);
  1593. if (match) {
  1594. const referencedInfo = modulesWithInfo[match.index];
  1595. if (referencedInfo.type === "reference") {
  1596. throw new Error("Module reference can't point to a reference");
  1597. }
  1598. const concatenationScope = /** @type {ConcatenatedModuleInfo} */ (
  1599. referencedInfo
  1600. ).concatenationScope;
  1601. const exportId = match.ids[0];
  1602. const specifier =
  1603. concatenationScope && concatenationScope.getRawExport(exportId);
  1604. if (specifier) {
  1605. const newName = _findNewNameForSpecifier(
  1606. specifier,
  1607. info,
  1608. references
  1609. );
  1610. const initFragmentChanged =
  1611. newName &&
  1612. concatenatedModuleInfo.call(
  1613. {
  1614. rawExportMap: new Map([
  1615. [exportId, /** @type {string} */ (newName)]
  1616. ])
  1617. },
  1618. /** @type {ConcatenatedModuleInfo} */ (referencedInfo)
  1619. );
  1620. if (initFragmentChanged) {
  1621. concatenationScope.setRawExportMap(exportId, newName);
  1622. }
  1623. }
  1624. const finalName = getFinalName(
  1625. moduleGraph,
  1626. referencedInfo,
  1627. match.ids,
  1628. moduleToInfoMap,
  1629. runtime,
  1630. requestShortener,
  1631. runtimeTemplate,
  1632. neededNamespaceObjects,
  1633. match.call,
  1634. match.deferredImport,
  1635. !match.directImport,
  1636. /** @type {BuildMeta} */
  1637. (info.module.buildMeta).strictHarmonyModule,
  1638. match.asiSafe
  1639. );
  1640. for (const reference of references) {
  1641. const r = /** @type {Range} */ (reference.identifier.range);
  1642. const source = /** @type {ReplaceSource} */ (info.source);
  1643. // range is extended by 2 chars to cover the appended "._"
  1644. source.replace(r[0], r[1] + 1, finalName);
  1645. }
  1646. }
  1647. }
  1648. }
  1649. }
  1650. // Map with all root exposed used exports
  1651. /** @type {Map<string, (requestShortener: RequestShortener) => string>} */
  1652. const exportsMap = new Map();
  1653. // Set with all root exposed unused exports
  1654. /** @type {Set<string>} */
  1655. const unusedExports = new Set();
  1656. const rootInfo =
  1657. /** @type {ConcatenatedModuleInfo} */
  1658. (moduleToInfoMap.get(this.rootModule));
  1659. const strictHarmonyModule =
  1660. /** @type {BuildMeta} */
  1661. (rootInfo.module.buildMeta).strictHarmonyModule;
  1662. const exportsInfo = moduleGraph.getExportsInfo(rootInfo.module);
  1663. /** @type {Record<string, string>} */
  1664. const exportsFinalName = {};
  1665. for (const exportInfo of exportsInfo.orderedExports) {
  1666. const name = exportInfo.name;
  1667. if (exportInfo.provided === false) continue;
  1668. const used = exportInfo.getUsedName(undefined, runtime);
  1669. if (!used) {
  1670. unusedExports.add(name);
  1671. continue;
  1672. }
  1673. exportsMap.set(used, (requestShortener) => {
  1674. try {
  1675. const finalName = getFinalName(
  1676. moduleGraph,
  1677. rootInfo,
  1678. [name],
  1679. moduleToInfoMap,
  1680. runtime,
  1681. requestShortener,
  1682. runtimeTemplate,
  1683. neededNamespaceObjects,
  1684. false,
  1685. false,
  1686. false,
  1687. strictHarmonyModule,
  1688. true
  1689. );
  1690. exportsFinalName[used] = finalName;
  1691. return `/* ${
  1692. exportInfo.isReexport() ? "reexport" : "binding"
  1693. } */ ${finalName}`;
  1694. } catch (err) {
  1695. /** @type {Error} */
  1696. (err).message +=
  1697. `\nwhile generating the root export '${name}' (used name: '${used}')`;
  1698. throw err;
  1699. }
  1700. });
  1701. }
  1702. const result = new ConcatSource();
  1703. // add harmony compatibility flag (must be first because of possible circular dependencies)
  1704. let shouldAddHarmonyFlag = false;
  1705. const rootExportsInfo = moduleGraph.getExportsInfo(this);
  1706. if (
  1707. rootExportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused ||
  1708. rootExportsInfo.getReadOnlyExportInfo("__esModule").getUsed(runtime) !==
  1709. UsageState.Unused
  1710. ) {
  1711. shouldAddHarmonyFlag = true;
  1712. }
  1713. // define exports
  1714. if (exportsMap.size > 0) {
  1715. /** @type {string[]} */
  1716. const definitions = [];
  1717. for (const [key, value] of exportsMap) {
  1718. definitions.push(
  1719. `\n ${propertyName(key)}: ${runtimeTemplate.returningFunction(
  1720. value(requestShortener)
  1721. )}`
  1722. );
  1723. }
  1724. runtimeRequirements.add(RuntimeGlobals.exports);
  1725. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1726. if (shouldAddHarmonyFlag) {
  1727. result.add("// ESM COMPAT FLAG\n");
  1728. result.add(
  1729. runtimeTemplate.defineEsModuleFlagStatement({
  1730. exportsArgument: this.exportsArgument,
  1731. runtimeRequirements
  1732. })
  1733. );
  1734. }
  1735. const exportsSource =
  1736. "\n// EXPORTS\n" +
  1737. `${RuntimeGlobals.definePropertyGetters}(${this.exportsArgument}, {${definitions.join(
  1738. ","
  1739. )}\n});\n`;
  1740. const { onDemandExportsGeneration } =
  1741. ConcatenatedModule.getCompilationHooks(this.compilation);
  1742. if (
  1743. !onDemandExportsGeneration.call(
  1744. this,
  1745. runtimes,
  1746. exportsSource,
  1747. exportsFinalName
  1748. )
  1749. ) {
  1750. result.add(exportsSource);
  1751. }
  1752. }
  1753. // list unused exports
  1754. if (unusedExports.size > 0) {
  1755. result.add(
  1756. `\n// UNUSED EXPORTS: ${joinIterableWithComma(unusedExports)}\n`
  1757. );
  1758. }
  1759. // generate namespace objects
  1760. /** @type {Map<ConcatenatedModuleInfo, string>} */
  1761. const namespaceObjectSources = new Map();
  1762. for (const info of neededNamespaceObjects) {
  1763. if (info.namespaceExportSymbol) continue;
  1764. /** @type {string[]} */
  1765. const nsObj = [];
  1766. const exportsInfo = moduleGraph.getExportsInfo(info.module);
  1767. for (const exportInfo of exportsInfo.orderedExports) {
  1768. if (exportInfo.provided === false) continue;
  1769. const usedName = exportInfo.getUsedName(undefined, runtime);
  1770. if (usedName) {
  1771. const finalName = getFinalName(
  1772. moduleGraph,
  1773. info,
  1774. [exportInfo.name],
  1775. moduleToInfoMap,
  1776. runtime,
  1777. requestShortener,
  1778. runtimeTemplate,
  1779. neededNamespaceObjects,
  1780. false,
  1781. false,
  1782. undefined,
  1783. /** @type {BuildMeta} */
  1784. (info.module.buildMeta).strictHarmonyModule,
  1785. true
  1786. );
  1787. nsObj.push(
  1788. `\n ${propertyName(usedName)}: ${runtimeTemplate.returningFunction(
  1789. finalName
  1790. )}`
  1791. );
  1792. }
  1793. }
  1794. const name = info.namespaceObjectName;
  1795. const defineGetters =
  1796. nsObj.length > 0
  1797. ? `${RuntimeGlobals.definePropertyGetters}(${name}, {${nsObj.join(
  1798. ","
  1799. )}\n});\n`
  1800. : "";
  1801. if (nsObj.length > 0) {
  1802. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1803. }
  1804. namespaceObjectSources.set(
  1805. info,
  1806. `
  1807. // NAMESPACE OBJECT: ${info.module.readableIdentifier(requestShortener)}
  1808. var ${name} = {};
  1809. ${RuntimeGlobals.makeNamespaceObject}(${name});
  1810. ${defineGetters}`
  1811. );
  1812. runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
  1813. }
  1814. // define required namespace objects (must be before evaluation modules)
  1815. for (const info of modulesWithInfo) {
  1816. if (info.type === "concatenated") {
  1817. const source = namespaceObjectSources.get(info);
  1818. if (!source) continue;
  1819. result.add(source);
  1820. }
  1821. if (info.type === "external" && info.deferred) {
  1822. const moduleId = JSON.stringify(chunkGraph.getModuleId(info.module));
  1823. const loader = getOptimizedDeferredModule(
  1824. moduleId,
  1825. info.module.getExportsType(
  1826. moduleGraph,
  1827. /** @type {BuildMeta} */
  1828. (this.rootModule.buildMeta).strictHarmonyModule
  1829. ),
  1830. // an async module will opt-out of the concat module optimization.
  1831. [],
  1832. runtimeRequirements
  1833. );
  1834. runtimeRequirements.add(RuntimeGlobals.require);
  1835. result.add(
  1836. `\n// DEFERRED EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\nvar ${info.deferredName} = ${loader};`
  1837. );
  1838. if (info.deferredNamespaceObjectUsed) {
  1839. runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
  1840. result.add(
  1841. `\nvar ${info.deferredNamespaceObjectName} = /*#__PURE__*/${
  1842. RuntimeGlobals.makeDeferredNamespaceObject
  1843. }(${JSON.stringify(
  1844. chunkGraph.getModuleId(info.module)
  1845. )}, ${getMakeDeferredNamespaceModeFromExportsType(
  1846. info.module.getExportsType(moduleGraph, strictHarmonyModule)
  1847. )});`
  1848. );
  1849. }
  1850. }
  1851. }
  1852. /** @type {InitFragment<ChunkRenderContext>[]} */
  1853. const chunkInitFragments = [];
  1854. // evaluate modules in order
  1855. for (const rawInfo of modulesWithInfo) {
  1856. /** @type {undefined | string} */
  1857. let name;
  1858. let isConditional = false;
  1859. const info = rawInfo.type === "reference" ? rawInfo.target : rawInfo;
  1860. switch (info.type) {
  1861. case "concatenated": {
  1862. result.add(
  1863. `\n;// ${info.module.readableIdentifier(requestShortener)}\n`
  1864. );
  1865. result.add(/** @type {ReplaceSource} */ (info.source));
  1866. if (info.chunkInitFragments) {
  1867. for (const f of info.chunkInitFragments) chunkInitFragments.push(f);
  1868. }
  1869. if (info.runtimeRequirements) {
  1870. for (const r of info.runtimeRequirements) {
  1871. runtimeRequirements.add(r);
  1872. }
  1873. }
  1874. name = info.namespaceObjectName;
  1875. break;
  1876. }
  1877. case "external": {
  1878. // deferred case is handled in the "const info of modulesWithInfo" loop above
  1879. if (!info.deferred) {
  1880. result.add(
  1881. `\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
  1882. requestShortener
  1883. )}\n`
  1884. );
  1885. runtimeRequirements.add(RuntimeGlobals.require);
  1886. const { runtimeCondition } =
  1887. /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */
  1888. (rawInfo);
  1889. const condition = runtimeTemplate.runtimeConditionExpression({
  1890. chunkGraph,
  1891. runtimeCondition,
  1892. runtime,
  1893. runtimeRequirements
  1894. });
  1895. if (condition !== "true") {
  1896. isConditional = true;
  1897. result.add(`if (${condition}) {\n`);
  1898. }
  1899. const moduleId = JSON.stringify(
  1900. chunkGraph.getModuleId(info.module)
  1901. );
  1902. result.add(`var ${info.name} = __webpack_require__(${moduleId});`);
  1903. name = info.name;
  1904. }
  1905. // If a module is deferred in other places, but used as non-deferred here,
  1906. // the module itself will be emitted as mod_deferred (in the case "external"),
  1907. // we need to emit an extra import declaration to evaluate it in order.
  1908. const { nonDeferAccess } =
  1909. /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */
  1910. (rawInfo);
  1911. if (info.deferred && nonDeferAccess) {
  1912. result.add(
  1913. `\n// non-deferred import to a deferred module (${info.module.readableIdentifier(requestShortener)})\nvar ${info.name} = ${info.deferredName}.a;`
  1914. );
  1915. }
  1916. break;
  1917. }
  1918. default:
  1919. // @ts-expect-error never is expected here
  1920. throw new Error(`Unsupported concatenation entry type ${info.type}`);
  1921. }
  1922. if (info.interopNamespaceObjectUsed) {
  1923. runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
  1924. result.add(
  1925. `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);`
  1926. );
  1927. }
  1928. if (info.interopNamespaceObject2Used) {
  1929. runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
  1930. result.add(
  1931. `\nvar ${info.interopNamespaceObject2Name} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});`
  1932. );
  1933. }
  1934. if (info.interopDefaultAccessUsed) {
  1935. runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
  1936. result.add(
  1937. `\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});`
  1938. );
  1939. }
  1940. if (isConditional) {
  1941. result.add("\n}");
  1942. }
  1943. }
  1944. /** @type {CodeGenerationResultData} */
  1945. const data = new Map();
  1946. if (chunkInitFragments.length > 0) {
  1947. data.set("chunkInitFragments", chunkInitFragments);
  1948. }
  1949. data.set("topLevelDeclarations", topLevelDeclarations);
  1950. /** @type {CodeGenerationResult} */
  1951. const resultEntry = {
  1952. sources: new Map([[JAVASCRIPT_TYPE, new CachedSource(result)]]),
  1953. data,
  1954. runtimeRequirements
  1955. };
  1956. return resultEntry;
  1957. }
  1958. /**
  1959. * @param {ModuleToInfoMap} modulesMap modulesMap
  1960. * @param {ModuleInfo} info info
  1961. * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
  1962. * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
  1963. * @param {ModuleGraph} moduleGraph moduleGraph
  1964. * @param {ChunkGraph} chunkGraph chunkGraph
  1965. * @param {RuntimeSpec} runtime runtime
  1966. * @param {RuntimeSpec[]} runtimes runtimes
  1967. * @param {CodeGenerationResults} codeGenerationResults codeGenerationResults
  1968. * @param {UsedNames} usedNames used names
  1969. */
  1970. _analyseModule(
  1971. modulesMap,
  1972. info,
  1973. dependencyTemplates,
  1974. runtimeTemplate,
  1975. moduleGraph,
  1976. chunkGraph,
  1977. runtime,
  1978. runtimes,
  1979. codeGenerationResults,
  1980. usedNames
  1981. ) {
  1982. if (info.type === "concatenated") {
  1983. const m = info.module;
  1984. try {
  1985. // Create a concatenation scope to track and capture information
  1986. const concatenationScope = new ConcatenationScope(
  1987. modulesMap,
  1988. info,
  1989. usedNames
  1990. );
  1991. // TODO cache codeGeneration results
  1992. const codeGenResult = m.codeGeneration({
  1993. dependencyTemplates,
  1994. runtimeTemplate,
  1995. moduleGraph,
  1996. chunkGraph,
  1997. runtime,
  1998. runtimes,
  1999. concatenationScope,
  2000. codeGenerationResults,
  2001. sourceTypes: JAVASCRIPT_TYPES
  2002. });
  2003. const source =
  2004. /** @type {Source} */
  2005. (codeGenResult.sources.get(JAVASCRIPT_TYPE));
  2006. const data = codeGenResult.data;
  2007. const chunkInitFragments = data && data.get("chunkInitFragments");
  2008. const code = source.source().toString();
  2009. /** @type {Program} */
  2010. let ast;
  2011. try {
  2012. ({ ast } = JavascriptParser._parse(
  2013. code,
  2014. {
  2015. sourceType: "module",
  2016. ranges: true
  2017. },
  2018. JavascriptParser._getModuleParseFunction(this.compilation, m)
  2019. ));
  2020. } catch (_err) {
  2021. const err =
  2022. /** @type {Error & { loc?: { line: number, column: number } }} */
  2023. (_err);
  2024. if (
  2025. err.loc &&
  2026. typeof err.loc === "object" &&
  2027. typeof err.loc.line === "number"
  2028. ) {
  2029. const lineNumber = err.loc.line;
  2030. const lines = code.split("\n");
  2031. err.message += `\n| ${lines
  2032. .slice(Math.max(0, lineNumber - 3), lineNumber + 2)
  2033. .join("\n| ")}`;
  2034. }
  2035. throw err;
  2036. }
  2037. const scopeManager = eslintScope.analyze(ast, {
  2038. ecmaVersion: 6,
  2039. sourceType: "module",
  2040. optimistic: true,
  2041. ignoreEval: true,
  2042. impliedStrict: true
  2043. });
  2044. const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
  2045. const moduleScope = globalScope.childScopes[0];
  2046. const resultSource = new ReplaceSource(source);
  2047. info.runtimeRequirements =
  2048. /** @type {ReadOnlyRuntimeRequirements} */
  2049. (codeGenResult.runtimeRequirements);
  2050. info.ast = ast;
  2051. info.internalSource = source;
  2052. info.source = resultSource;
  2053. info.chunkInitFragments = chunkInitFragments;
  2054. info.globalScope = globalScope;
  2055. info.moduleScope = moduleScope;
  2056. info.concatenationScope = concatenationScope;
  2057. } catch (err) {
  2058. /** @type {Error} */
  2059. (err).message +=
  2060. `\nwhile analyzing module ${m.identifier()} for concatenation`;
  2061. throw err;
  2062. }
  2063. }
  2064. }
  2065. /**
  2066. * @param {ModuleGraph} moduleGraph the module graph
  2067. * @param {RuntimeSpec} runtime the runtime
  2068. * @returns {[ModuleInfoOrReference[], ModuleToInfoMap]} module info items
  2069. */
  2070. _getModulesWithInfo(moduleGraph, runtime) {
  2071. const orderedConcatenationList = this._createConcatenationList(
  2072. this.rootModule,
  2073. this._modules,
  2074. runtime,
  2075. moduleGraph
  2076. );
  2077. /** @type {ModuleToInfoMap} */
  2078. const map = new Map();
  2079. const list = orderedConcatenationList.map((info, index) => {
  2080. let item = map.get(info.module);
  2081. if (item === undefined) {
  2082. switch (info.type) {
  2083. case "concatenated":
  2084. item = {
  2085. type: "concatenated",
  2086. module: info.module,
  2087. index,
  2088. ast: undefined,
  2089. internalSource: undefined,
  2090. runtimeRequirements: undefined,
  2091. source: undefined,
  2092. globalScope: undefined,
  2093. moduleScope: undefined,
  2094. internalNames: new Map(),
  2095. exportMap: undefined,
  2096. rawExportMap: undefined,
  2097. namespaceExportSymbol: undefined,
  2098. namespaceObjectName: undefined,
  2099. interopNamespaceObjectUsed: false,
  2100. interopNamespaceObjectName: undefined,
  2101. interopNamespaceObject2Used: false,
  2102. interopNamespaceObject2Name: undefined,
  2103. interopDefaultAccessUsed: false,
  2104. interopDefaultAccessName: undefined,
  2105. concatenationScope: undefined
  2106. };
  2107. break;
  2108. case "external":
  2109. item = {
  2110. type: "external",
  2111. module: info.module,
  2112. runtimeCondition: info.runtimeCondition,
  2113. nonDeferAccess: info.nonDeferAccess,
  2114. index,
  2115. name: undefined,
  2116. deferredName: undefined,
  2117. interopNamespaceObjectUsed: false,
  2118. interopNamespaceObjectName: undefined,
  2119. interopNamespaceObject2Used: false,
  2120. interopNamespaceObject2Name: undefined,
  2121. interopDefaultAccessUsed: false,
  2122. interopDefaultAccessName: undefined,
  2123. deferred: moduleGraph.isDeferred(info.module),
  2124. deferredNamespaceObjectName: undefined,
  2125. deferredNamespaceObjectUsed: false
  2126. };
  2127. break;
  2128. default:
  2129. throw new Error(
  2130. `Unsupported concatenation entry type ${info.type}`
  2131. );
  2132. }
  2133. map.set(
  2134. /** @type {ModuleInfo} */ (item).module,
  2135. /** @type {ModuleInfo} */ (item)
  2136. );
  2137. return /** @type {ModuleInfo} */ (item);
  2138. }
  2139. /** @type {ReferenceToModuleInfo} */
  2140. const ref = {
  2141. type: "reference",
  2142. runtimeCondition: info.runtimeCondition,
  2143. nonDeferAccess: info.nonDeferAccess,
  2144. target: item
  2145. };
  2146. return ref;
  2147. });
  2148. return [list, map];
  2149. }
  2150. /**
  2151. * Updates the hash with the data contributed by this instance.
  2152. * @param {Hash} hash the hash used to track dependencies
  2153. * @param {UpdateHashContext} context context
  2154. * @returns {void}
  2155. */
  2156. updateHash(hash, context) {
  2157. const { chunkGraph, runtime } = context;
  2158. for (const info of this._createConcatenationList(
  2159. this.rootModule,
  2160. this._modules,
  2161. intersectRuntime(runtime, this._runtime),
  2162. chunkGraph.moduleGraph
  2163. )) {
  2164. switch (info.type) {
  2165. case "concatenated":
  2166. info.module.updateHash(hash, context);
  2167. break;
  2168. case "external":
  2169. hash.update(`${chunkGraph.getModuleId(info.module)}`);
  2170. // TODO runtimeCondition
  2171. break;
  2172. }
  2173. }
  2174. super.updateHash(hash, context);
  2175. }
  2176. /**
  2177. * @param {ObjectDeserializerContext} context context
  2178. * @returns {ConcatenatedModule} ConcatenatedModule
  2179. */
  2180. static deserialize(context) {
  2181. const obj = new ConcatenatedModule({
  2182. identifier: /** @type {EXPECTED_ANY} */ (undefined),
  2183. rootModule: /** @type {EXPECTED_ANY} */ (undefined),
  2184. modules: /** @type {EXPECTED_ANY} */ (undefined),
  2185. runtime: undefined,
  2186. compilation: /** @type {EXPECTED_ANY} */ (undefined)
  2187. });
  2188. obj.deserialize(context);
  2189. return obj;
  2190. }
  2191. }
  2192. makeSerializable(ConcatenatedModule, "webpack/lib/optimize/ConcatenatedModule");
  2193. module.exports = ConcatenatedModule;