ConcatenatedModule.js 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976
  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 { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants");
  18. const RuntimeGlobals = require("../RuntimeGlobals");
  19. const Template = require("../Template");
  20. const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
  21. const JavascriptParser = require("../javascript/JavascriptParser");
  22. const { equals } = require("../util/ArrayHelpers");
  23. const LazySet = require("../util/LazySet");
  24. const { concatComparators } = require("../util/comparators");
  25. const createHash = require("../util/createHash");
  26. const { makePathsRelative } = require("../util/identifier");
  27. const makeSerializable = require("../util/makeSerializable");
  28. const { getAllReferences, getPathInAst } = require("../util/mergeScope");
  29. const propertyAccess = require("../util/propertyAccess");
  30. const { propertyName } = require("../util/propertyName");
  31. const {
  32. filterRuntime,
  33. intersectRuntime,
  34. mergeRuntimeCondition,
  35. mergeRuntimeConditionNonFalse,
  36. runtimeConditionToString,
  37. subtractRuntimeCondition
  38. } = require("../util/runtime");
  39. /** @typedef {import("eslint-scope").Reference} Reference */
  40. /** @typedef {import("eslint-scope").Scope} Scope */
  41. /** @typedef {import("eslint-scope").Variable} Variable */
  42. /** @typedef {import("webpack-sources").Source} Source */
  43. /** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
  44. /** @typedef {import("../ChunkGraph")} ChunkGraph */
  45. /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
  46. /** @typedef {import("../Compilation")} Compilation */
  47. /** @typedef {import("../Dependency")} Dependency */
  48. /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
  49. /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
  50. /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
  51. /** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
  52. /** @typedef {import("../Module").BuildInfo} BuildInfo */
  53. /** @typedef {import("../Module").BuildMeta} BuildMeta */
  54. /** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
  55. /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
  56. /** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
  57. /** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
  58. /** @typedef {import("../Module").SourceTypes} SourceTypes */
  59. /** @typedef {import("../ModuleGraph")} ModuleGraph */
  60. /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
  61. /** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
  62. /** @typedef {import("../RequestShortener")} RequestShortener */
  63. /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
  64. /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
  65. /** @typedef {import("../WebpackError")} WebpackError */
  66. /** @typedef {import("../javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
  67. /** @typedef {import("../javascript/JavascriptParser").Program} Program */
  68. /** @typedef {import("../javascript/JavascriptParser").Range} Range */
  69. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  70. /** @typedef {import("../util/Hash")} Hash */
  71. /** @typedef {typeof import("../util/Hash")} HashConstructor */
  72. /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
  73. /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
  74. /**
  75. * @template T
  76. * @typedef {import("../InitFragment")<T>} InitFragment
  77. */
  78. /**
  79. * @template T
  80. * @typedef {import("../util/comparators").Comparator<T>} Comparator
  81. */
  82. // fix eslint-scope to support class properties correctly
  83. // cspell:word Referencer
  84. const ReferencerClass = /** @type {any} */ (Referencer);
  85. if (!ReferencerClass.prototype.PropertyDefinition) {
  86. ReferencerClass.prototype.PropertyDefinition =
  87. ReferencerClass.prototype.Property;
  88. }
  89. /**
  90. * @typedef {object} ReexportInfo
  91. * @property {Module} module
  92. * @property {string[]} export
  93. */
  94. /** @typedef {RawBinding | SymbolBinding} Binding */
  95. /**
  96. * @typedef {object} RawBinding
  97. * @property {ModuleInfo} info
  98. * @property {string} rawName
  99. * @property {string=} comment
  100. * @property {string[]} ids
  101. * @property {string[]} exportName
  102. */
  103. /**
  104. * @typedef {object} SymbolBinding
  105. * @property {ConcatenatedModuleInfo} info
  106. * @property {string} name
  107. * @property {string=} comment
  108. * @property {string[]} ids
  109. * @property {string[]} exportName
  110. */
  111. /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */
  112. /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo } ModuleInfoOrReference */
  113. /**
  114. * @typedef {object} ConcatenatedModuleInfo
  115. * @property {"concatenated"} type
  116. * @property {Module} module
  117. * @property {number} index
  118. * @property {Program | undefined} ast
  119. * @property {Source} internalSource
  120. * @property {ReplaceSource} source
  121. * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
  122. * @property {ReadOnlyRuntimeRequirements} runtimeRequirements
  123. * @property {Scope} globalScope
  124. * @property {Scope} moduleScope
  125. * @property {Map<string, string>} internalNames
  126. * @property {Map<string, string> | undefined} exportMap
  127. * @property {Map<string, string> | undefined} rawExportMap
  128. * @property {string=} namespaceExportSymbol
  129. * @property {string | undefined} namespaceObjectName
  130. * @property {boolean} interopNamespaceObjectUsed
  131. * @property {string | undefined} interopNamespaceObjectName
  132. * @property {boolean} interopNamespaceObject2Used
  133. * @property {string | undefined} interopNamespaceObject2Name
  134. * @property {boolean} interopDefaultAccessUsed
  135. * @property {string | undefined} interopDefaultAccessName
  136. */
  137. /**
  138. * @typedef {object} ExternalModuleInfo
  139. * @property {"external"} type
  140. * @property {Module} module
  141. * @property {RuntimeSpec | boolean} runtimeCondition
  142. * @property {number} index
  143. * @property {string} name
  144. * @property {boolean} interopNamespaceObjectUsed
  145. * @property {string} interopNamespaceObjectName
  146. * @property {boolean} interopNamespaceObject2Used
  147. * @property {string} interopNamespaceObject2Name
  148. * @property {boolean} interopDefaultAccessUsed
  149. * @property {string} interopDefaultAccessName
  150. */
  151. /**
  152. * @typedef {object} ReferenceToModuleInfo
  153. * @property {"reference"} type
  154. * @property {RuntimeSpec | boolean} runtimeCondition
  155. * @property {ConcatenatedModuleInfo | ExternalModuleInfo} target
  156. */
  157. /** @typedef {Set<string>} UsedNames */
  158. const RESERVED_NAMES = new Set(
  159. [
  160. // internal names (should always be renamed)
  161. ConcatenationScope.DEFAULT_EXPORT,
  162. ConcatenationScope.NAMESPACE_OBJECT_EXPORT,
  163. // keywords
  164. "abstract,arguments,async,await,boolean,break,byte,case,catch,char,class,const,continue",
  165. "debugger,default,delete,do,double,else,enum,eval,export,extends,false,final,finally,float",
  166. "for,function,goto,if,implements,import,in,instanceof,int,interface,let,long,native,new,null",
  167. "package,private,protected,public,return,short,static,super,switch,synchronized,this,throw",
  168. "throws,transient,true,try,typeof,var,void,volatile,while,with,yield",
  169. // commonjs/amd
  170. "module,__dirname,__filename,exports,require,define",
  171. // js globals
  172. "Array,Date,eval,function,hasOwnProperty,Infinity,isFinite,isNaN,isPrototypeOf,length,Math",
  173. "NaN,name,Number,Object,prototype,String,toString,undefined,valueOf",
  174. // browser globals
  175. "alert,all,anchor,anchors,area,assign,blur,button,checkbox,clearInterval,clearTimeout",
  176. "clientInformation,close,closed,confirm,constructor,crypto,decodeURI,decodeURIComponent",
  177. "defaultStatus,document,element,elements,embed,embeds,encodeURI,encodeURIComponent,escape",
  178. "event,fileUpload,focus,form,forms,frame,innerHeight,innerWidth,layer,layers,link,location",
  179. "mimeTypes,navigate,navigator,frames,frameRate,hidden,history,image,images,offscreenBuffering",
  180. "open,opener,option,outerHeight,outerWidth,packages,pageXOffset,pageYOffset,parent,parseFloat",
  181. "parseInt,password,pkcs11,plugin,prompt,propertyIsEnum,radio,reset,screenX,screenY,scroll",
  182. "secure,select,self,setInterval,setTimeout,status,submit,taint,text,textarea,top,unescape",
  183. "untaint,window",
  184. // window events
  185. "onblur,onclick,onerror,onfocus,onkeydown,onkeypress,onkeyup,onmouseover,onload,onmouseup,onmousedown,onsubmit"
  186. ]
  187. .join(",")
  188. .split(",")
  189. );
  190. const createComparator = (property, comparator) => (a, b) =>
  191. comparator(a[property], b[property]);
  192. /**
  193. * @param {number} a a
  194. * @param {number} b b
  195. * @returns {0 | 1 | -1} result
  196. */
  197. const compareNumbers = (a, b) => {
  198. if (isNaN(a)) {
  199. if (!isNaN(b)) {
  200. return 1;
  201. }
  202. } else {
  203. if (isNaN(b)) {
  204. return -1;
  205. }
  206. if (a !== b) {
  207. return a < b ? -1 : 1;
  208. }
  209. }
  210. return 0;
  211. };
  212. const bySourceOrder = createComparator("sourceOrder", compareNumbers);
  213. const byRangeStart = createComparator("rangeStart", compareNumbers);
  214. /**
  215. * @param {Iterable<string>} iterable iterable object
  216. * @returns {string} joined iterable object
  217. */
  218. const joinIterableWithComma = iterable => {
  219. // This is more performant than Array.from().join(", ")
  220. // as it doesn't create an array
  221. let str = "";
  222. let first = true;
  223. for (const item of iterable) {
  224. if (first) {
  225. first = false;
  226. } else {
  227. str += ", ";
  228. }
  229. str += item;
  230. }
  231. return str;
  232. };
  233. /**
  234. * @typedef {object} ConcatenationEntry
  235. * @property {"concatenated" | "external"} type
  236. * @property {Module} module
  237. * @property {RuntimeSpec | boolean} runtimeCondition
  238. */
  239. /**
  240. * @param {ModuleGraph} moduleGraph the module graph
  241. * @param {ModuleInfo} info module info
  242. * @param {string[]} exportName exportName
  243. * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap
  244. * @param {RuntimeSpec} runtime for which runtime
  245. * @param {RequestShortener} requestShortener the request shortener
  246. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  247. * @param {Set<ConcatenatedModuleInfo>} neededNamespaceObjects modules for which a namespace object should be generated
  248. * @param {boolean} asCall asCall
  249. * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
  250. * @param {boolean | undefined} asiSafe asiSafe
  251. * @param {Set<ExportInfo>} alreadyVisited alreadyVisited
  252. * @returns {Binding} the final variable
  253. */
  254. const getFinalBinding = (
  255. moduleGraph,
  256. info,
  257. exportName,
  258. moduleToInfoMap,
  259. runtime,
  260. requestShortener,
  261. runtimeTemplate,
  262. neededNamespaceObjects,
  263. asCall,
  264. strictHarmonyModule,
  265. asiSafe,
  266. alreadyVisited = new Set()
  267. ) => {
  268. const exportsType = info.module.getExportsType(
  269. moduleGraph,
  270. strictHarmonyModule
  271. );
  272. if (exportName.length === 0) {
  273. switch (exportsType) {
  274. case "default-only":
  275. info.interopNamespaceObject2Used = true;
  276. return {
  277. info,
  278. rawName: /** @type {string} */ (info.interopNamespaceObject2Name),
  279. ids: exportName,
  280. exportName
  281. };
  282. case "default-with-named":
  283. info.interopNamespaceObjectUsed = true;
  284. return {
  285. info,
  286. rawName: /** @type {string} */ (info.interopNamespaceObjectName),
  287. ids: exportName,
  288. exportName
  289. };
  290. case "namespace":
  291. case "dynamic":
  292. break;
  293. default:
  294. throw new Error(`Unexpected exportsType ${exportsType}`);
  295. }
  296. } else {
  297. switch (exportsType) {
  298. case "namespace":
  299. break;
  300. case "default-with-named":
  301. switch (exportName[0]) {
  302. case "default":
  303. exportName = exportName.slice(1);
  304. break;
  305. case "__esModule":
  306. return {
  307. info,
  308. rawName: "/* __esModule */true",
  309. ids: exportName.slice(1),
  310. exportName
  311. };
  312. }
  313. break;
  314. case "default-only": {
  315. const exportId = exportName[0];
  316. if (exportId === "__esModule") {
  317. return {
  318. info,
  319. rawName: "/* __esModule */true",
  320. ids: exportName.slice(1),
  321. exportName
  322. };
  323. }
  324. exportName = exportName.slice(1);
  325. if (exportId !== "default") {
  326. return {
  327. info,
  328. rawName:
  329. "/* non-default import from default-exporting module */undefined",
  330. ids: exportName,
  331. exportName
  332. };
  333. }
  334. break;
  335. }
  336. case "dynamic":
  337. switch (exportName[0]) {
  338. case "default": {
  339. exportName = exportName.slice(1);
  340. info.interopDefaultAccessUsed = true;
  341. const defaultExport = asCall
  342. ? `${info.interopDefaultAccessName}()`
  343. : asiSafe
  344. ? `(${info.interopDefaultAccessName}())`
  345. : asiSafe === false
  346. ? `;(${info.interopDefaultAccessName}())`
  347. : `${info.interopDefaultAccessName}.a`;
  348. return {
  349. info,
  350. rawName: defaultExport,
  351. ids: exportName,
  352. exportName
  353. };
  354. }
  355. case "__esModule":
  356. return {
  357. info,
  358. rawName: "/* __esModule */true",
  359. ids: exportName.slice(1),
  360. exportName
  361. };
  362. }
  363. break;
  364. default:
  365. throw new Error(`Unexpected exportsType ${exportsType}`);
  366. }
  367. }
  368. if (exportName.length === 0) {
  369. switch (info.type) {
  370. case "concatenated":
  371. neededNamespaceObjects.add(info);
  372. return {
  373. info,
  374. rawName: /** @type {string} */ (info.namespaceObjectName),
  375. ids: exportName,
  376. exportName
  377. };
  378. case "external":
  379. return { info, rawName: info.name, ids: exportName, exportName };
  380. }
  381. }
  382. const exportsInfo = moduleGraph.getExportsInfo(info.module);
  383. const exportInfo = exportsInfo.getExportInfo(exportName[0]);
  384. if (alreadyVisited.has(exportInfo)) {
  385. return {
  386. info,
  387. rawName: "/* circular reexport */ Object(function x() { x() }())",
  388. ids: [],
  389. exportName
  390. };
  391. }
  392. alreadyVisited.add(exportInfo);
  393. switch (info.type) {
  394. case "concatenated": {
  395. const exportId = exportName[0];
  396. if (exportInfo.provided === false) {
  397. // It's not provided, but it could be on the prototype
  398. neededNamespaceObjects.add(info);
  399. return {
  400. info,
  401. rawName: /** @type {string} */ (info.namespaceObjectName),
  402. ids: exportName,
  403. exportName
  404. };
  405. }
  406. const directExport = info.exportMap && info.exportMap.get(exportId);
  407. if (directExport) {
  408. const usedName = /** @type {string[]} */ (
  409. exportsInfo.getUsedName(exportName, runtime)
  410. );
  411. if (!usedName) {
  412. return {
  413. info,
  414. rawName: "/* unused export */ undefined",
  415. ids: exportName.slice(1),
  416. exportName
  417. };
  418. }
  419. return {
  420. info,
  421. name: directExport,
  422. ids: usedName.slice(1),
  423. exportName
  424. };
  425. }
  426. const rawExport = info.rawExportMap && info.rawExportMap.get(exportId);
  427. if (rawExport) {
  428. return {
  429. info,
  430. rawName: rawExport,
  431. ids: exportName.slice(1),
  432. exportName
  433. };
  434. }
  435. const reexport = exportInfo.findTarget(moduleGraph, module =>
  436. moduleToInfoMap.has(module)
  437. );
  438. if (reexport === false) {
  439. throw new Error(
  440. `Target module of reexport from '${info.module.readableIdentifier(
  441. requestShortener
  442. )}' is not part of the concatenation (export '${exportId}')\nModules in the concatenation:\n${Array.from(
  443. moduleToInfoMap,
  444. ([m, info]) =>
  445. ` * ${info.type} ${m.readableIdentifier(requestShortener)}`
  446. ).join("\n")}`
  447. );
  448. }
  449. if (reexport) {
  450. const refInfo = moduleToInfoMap.get(reexport.module);
  451. return getFinalBinding(
  452. moduleGraph,
  453. /** @type {ModuleInfo} */ (refInfo),
  454. reexport.export
  455. ? [...reexport.export, ...exportName.slice(1)]
  456. : exportName.slice(1),
  457. moduleToInfoMap,
  458. runtime,
  459. requestShortener,
  460. runtimeTemplate,
  461. neededNamespaceObjects,
  462. asCall,
  463. /** @type {BuildMeta} */
  464. (info.module.buildMeta).strictHarmonyModule,
  465. asiSafe,
  466. alreadyVisited
  467. );
  468. }
  469. if (info.namespaceExportSymbol) {
  470. const usedName = /** @type {string[]} */ (
  471. exportsInfo.getUsedName(exportName, runtime)
  472. );
  473. return {
  474. info,
  475. rawName: /** @type {string} */ (info.namespaceObjectName),
  476. ids: usedName,
  477. exportName
  478. };
  479. }
  480. throw new Error(
  481. `Cannot get final name for export '${exportName.join(
  482. "."
  483. )}' of ${info.module.readableIdentifier(requestShortener)}`
  484. );
  485. }
  486. case "external": {
  487. const used = /** @type {string[]} */ (
  488. exportsInfo.getUsedName(exportName, runtime)
  489. );
  490. if (!used) {
  491. return {
  492. info,
  493. rawName: "/* unused export */ undefined",
  494. ids: exportName.slice(1),
  495. exportName
  496. };
  497. }
  498. const comment = equals(used, exportName)
  499. ? ""
  500. : Template.toNormalComment(`${exportName.join(".")}`);
  501. return { info, rawName: info.name + comment, ids: used, exportName };
  502. }
  503. }
  504. };
  505. /**
  506. * @param {ModuleGraph} moduleGraph the module graph
  507. * @param {ModuleInfo} info module info
  508. * @param {string[]} exportName exportName
  509. * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap
  510. * @param {RuntimeSpec} runtime for which runtime
  511. * @param {RequestShortener} requestShortener the request shortener
  512. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  513. * @param {Set<ConcatenatedModuleInfo>} neededNamespaceObjects modules for which a namespace object should be generated
  514. * @param {boolean} asCall asCall
  515. * @param {boolean | undefined} callContext callContext
  516. * @param {boolean | undefined} strictHarmonyModule strictHarmonyModule
  517. * @param {boolean | undefined} asiSafe asiSafe
  518. * @returns {string} the final name
  519. */
  520. const getFinalName = (
  521. moduleGraph,
  522. info,
  523. exportName,
  524. moduleToInfoMap,
  525. runtime,
  526. requestShortener,
  527. runtimeTemplate,
  528. neededNamespaceObjects,
  529. asCall,
  530. callContext,
  531. strictHarmonyModule,
  532. asiSafe
  533. ) => {
  534. const binding = getFinalBinding(
  535. moduleGraph,
  536. info,
  537. exportName,
  538. moduleToInfoMap,
  539. runtime,
  540. requestShortener,
  541. runtimeTemplate,
  542. neededNamespaceObjects,
  543. asCall,
  544. strictHarmonyModule,
  545. asiSafe
  546. );
  547. {
  548. const { ids, comment } = binding;
  549. let reference;
  550. let isPropertyAccess;
  551. if ("rawName" in binding) {
  552. reference = `${binding.rawName}${comment || ""}${propertyAccess(ids)}`;
  553. isPropertyAccess = ids.length > 0;
  554. } else {
  555. const { info, name: exportId } = binding;
  556. const name = info.internalNames.get(exportId);
  557. if (!name) {
  558. throw new Error(
  559. `The export "${exportId}" in "${info.module.readableIdentifier(
  560. requestShortener
  561. )}" has no internal name (existing names: ${
  562. Array.from(
  563. info.internalNames,
  564. ([name, symbol]) => `${name}: ${symbol}`
  565. ).join(", ") || "none"
  566. })`
  567. );
  568. }
  569. reference = `${name}${comment || ""}${propertyAccess(ids)}`;
  570. isPropertyAccess = ids.length > 1;
  571. }
  572. if (isPropertyAccess && asCall && callContext === false) {
  573. return asiSafe
  574. ? `(0,${reference})`
  575. : asiSafe === false
  576. ? `;(0,${reference})`
  577. : `/*#__PURE__*/Object(${reference})`;
  578. }
  579. return reference;
  580. }
  581. };
  582. /**
  583. * @param {Scope | null} s scope
  584. * @param {UsedNames} nameSet name set
  585. * @param {TODO} scopeSet1 scope set 1
  586. * @param {TODO} scopeSet2 scope set 2
  587. */
  588. const addScopeSymbols = (s, nameSet, scopeSet1, scopeSet2) => {
  589. let scope = s;
  590. while (scope) {
  591. if (scopeSet1.has(scope)) break;
  592. if (scopeSet2.has(scope)) break;
  593. scopeSet1.add(scope);
  594. for (const variable of scope.variables) {
  595. nameSet.add(variable.name);
  596. }
  597. scope = scope.upper;
  598. }
  599. };
  600. const TYPES = new Set(["javascript"]);
  601. /**
  602. * @typedef {object} ConcatenateModuleHooks
  603. * @property {SyncBailHook<[Record<string, string>]>} exportsDefinitions
  604. */
  605. /** @type {WeakMap<Compilation, ConcatenateModuleHooks>} */
  606. const compilationHooksMap = new WeakMap();
  607. class ConcatenatedModule extends Module {
  608. /**
  609. * @param {Module} rootModule the root module of the concatenation
  610. * @param {Set<Module>} modules all modules in the concatenation (including the root module)
  611. * @param {RuntimeSpec} runtime the runtime
  612. * @param {Compilation} compilation the compilation
  613. * @param {object=} associatedObjectForCache object for caching
  614. * @param {string | HashConstructor=} hashFunction hash function to use
  615. * @returns {ConcatenatedModule} the module
  616. */
  617. static create(
  618. rootModule,
  619. modules,
  620. runtime,
  621. compilation,
  622. associatedObjectForCache,
  623. hashFunction = "md4"
  624. ) {
  625. const identifier = ConcatenatedModule._createIdentifier(
  626. rootModule,
  627. modules,
  628. associatedObjectForCache,
  629. hashFunction
  630. );
  631. return new ConcatenatedModule({
  632. identifier,
  633. rootModule,
  634. modules,
  635. runtime,
  636. compilation
  637. });
  638. }
  639. /**
  640. * @param {Compilation} compilation the compilation
  641. * @returns {ConcatenateModuleHooks} the attached hooks
  642. */
  643. static getCompilationHooks(compilation) {
  644. let hooks = compilationHooksMap.get(compilation);
  645. if (hooks === undefined) {
  646. hooks = {
  647. exportsDefinitions: new SyncBailHook(["definitions"])
  648. };
  649. compilationHooksMap.set(compilation, hooks);
  650. }
  651. return hooks;
  652. }
  653. /**
  654. * @param {object} options options
  655. * @param {string} options.identifier the identifier of the module
  656. * @param {Module=} options.rootModule the root module of the concatenation
  657. * @param {RuntimeSpec} options.runtime the selected runtime
  658. * @param {Set<Module>=} options.modules all concatenated modules
  659. * @param {Compilation} options.compilation the compilation
  660. */
  661. constructor({ identifier, rootModule, modules, runtime, compilation }) {
  662. super(JAVASCRIPT_MODULE_TYPE_ESM, null, rootModule && rootModule.layer);
  663. // Info from Factory
  664. /** @type {string} */
  665. this._identifier = identifier;
  666. /** @type {Module} */
  667. this.rootModule = rootModule;
  668. /** @type {Set<Module>} */
  669. this._modules = modules;
  670. this._runtime = runtime;
  671. this.factoryMeta = rootModule && rootModule.factoryMeta;
  672. /** @type {Compilation | undefined} */
  673. this.compilation = compilation;
  674. }
  675. /**
  676. * Assuming this module is in the cache. Update the (cached) module with
  677. * the fresh module from the factory. Usually updates internal references
  678. * and properties.
  679. * @param {Module} module fresh module
  680. * @returns {void}
  681. */
  682. updateCacheModule(module) {
  683. throw new Error("Must not be called");
  684. }
  685. /**
  686. * @returns {SourceTypes} types available (do not mutate)
  687. */
  688. getSourceTypes() {
  689. return TYPES;
  690. }
  691. get modules() {
  692. return Array.from(this._modules);
  693. }
  694. /**
  695. * @returns {string} a unique identifier of the module
  696. */
  697. identifier() {
  698. return this._identifier;
  699. }
  700. /**
  701. * @param {RequestShortener} requestShortener the request shortener
  702. * @returns {string} a user readable identifier of the module
  703. */
  704. readableIdentifier(requestShortener) {
  705. return (
  706. this.rootModule.readableIdentifier(requestShortener) +
  707. ` + ${this._modules.size - 1} modules`
  708. );
  709. }
  710. /**
  711. * @param {LibIdentOptions} options options
  712. * @returns {string | null} an identifier for library inclusion
  713. */
  714. libIdent(options) {
  715. return this.rootModule.libIdent(options);
  716. }
  717. /**
  718. * @returns {string | null} absolute path which should be used for condition matching (usually the resource path)
  719. */
  720. nameForCondition() {
  721. return this.rootModule.nameForCondition();
  722. }
  723. /**
  724. * @param {ModuleGraph} moduleGraph the module graph
  725. * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
  726. */
  727. getSideEffectsConnectionState(moduleGraph) {
  728. return this.rootModule.getSideEffectsConnectionState(moduleGraph);
  729. }
  730. /**
  731. * @param {WebpackOptions} options webpack options
  732. * @param {Compilation} compilation the compilation
  733. * @param {ResolverWithOptions} resolver the resolver
  734. * @param {InputFileSystem} fs the file system
  735. * @param {function(WebpackError=): void} callback callback function
  736. * @returns {void}
  737. */
  738. build(options, compilation, resolver, fs, callback) {
  739. const { rootModule } = this;
  740. const { moduleArgument, exportsArgument } =
  741. /** @type {BuildInfo} */
  742. (rootModule.buildInfo);
  743. this.buildInfo = {
  744. strict: true,
  745. cacheable: true,
  746. moduleArgument,
  747. exportsArgument,
  748. fileDependencies: new LazySet(),
  749. contextDependencies: new LazySet(),
  750. missingDependencies: new LazySet(),
  751. topLevelDeclarations: new Set(),
  752. assets: undefined
  753. };
  754. this.buildMeta = rootModule.buildMeta;
  755. this.clearDependenciesAndBlocks();
  756. this.clearWarningsAndErrors();
  757. for (const m of this._modules) {
  758. // populate cacheable
  759. if (!(/** @type {BuildInfo} */ (m.buildInfo).cacheable)) {
  760. this.buildInfo.cacheable = false;
  761. }
  762. // populate dependencies
  763. for (const d of m.dependencies.filter(
  764. dep =>
  765. !(dep instanceof HarmonyImportDependency) ||
  766. !this._modules.has(
  767. /** @type {Module} */ (compilation.moduleGraph.getModule(dep))
  768. )
  769. )) {
  770. this.dependencies.push(d);
  771. }
  772. // populate blocks
  773. for (const d of m.blocks) {
  774. this.blocks.push(d);
  775. }
  776. // populate warnings
  777. const warnings = m.getWarnings();
  778. if (warnings !== undefined) {
  779. for (const warning of warnings) {
  780. this.addWarning(warning);
  781. }
  782. }
  783. // populate errors
  784. const errors = m.getErrors();
  785. if (errors !== undefined) {
  786. for (const error of errors) {
  787. this.addError(error);
  788. }
  789. }
  790. const { assets, assetsInfo, topLevelDeclarations } =
  791. /** @type {BuildInfo} */ (m.buildInfo);
  792. // populate topLevelDeclarations
  793. if (topLevelDeclarations) {
  794. const topLevelDeclarations = this.buildInfo.topLevelDeclarations;
  795. if (topLevelDeclarations !== undefined) {
  796. for (const decl of topLevelDeclarations) {
  797. topLevelDeclarations.add(decl);
  798. }
  799. }
  800. } else {
  801. this.buildInfo.topLevelDeclarations = undefined;
  802. }
  803. // populate assets
  804. if (assets) {
  805. if (this.buildInfo.assets === undefined) {
  806. this.buildInfo.assets = Object.create(null);
  807. }
  808. Object.assign(/** @type {BuildInfo} */ (this.buildInfo).assets, assets);
  809. }
  810. if (assetsInfo) {
  811. if (this.buildInfo.assetsInfo === undefined) {
  812. this.buildInfo.assetsInfo = new Map();
  813. }
  814. for (const [key, value] of assetsInfo) {
  815. this.buildInfo.assetsInfo.set(key, value);
  816. }
  817. }
  818. }
  819. callback();
  820. }
  821. /**
  822. * @param {string=} type the source type for which the size should be estimated
  823. * @returns {number} the estimated size of the module (must be non-zero)
  824. */
  825. size(type) {
  826. // Guess size from embedded modules
  827. let size = 0;
  828. for (const module of this._modules) {
  829. size += module.size(type);
  830. }
  831. return size;
  832. }
  833. /**
  834. * @private
  835. * @param {Module} rootModule the root of the concatenation
  836. * @param {Set<Module>} modulesSet a set of modules which should be concatenated
  837. * @param {RuntimeSpec} runtime for this runtime
  838. * @param {ModuleGraph} moduleGraph the module graph
  839. * @returns {ConcatenationEntry[]} concatenation list
  840. */
  841. _createConcatenationList(rootModule, modulesSet, runtime, moduleGraph) {
  842. /** @type {ConcatenationEntry[]} */
  843. const list = [];
  844. /** @type {Map<Module, RuntimeSpec | true>} */
  845. const existingEntries = new Map();
  846. /**
  847. * @param {Module} module a module
  848. * @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} imported modules in order
  849. */
  850. const getConcatenatedImports = module => {
  851. let connections = Array.from(moduleGraph.getOutgoingConnections(module));
  852. if (module === rootModule) {
  853. for (const c of moduleGraph.getOutgoingConnections(this))
  854. connections.push(c);
  855. }
  856. /**
  857. * @type {Array<{ connection: ModuleGraphConnection, sourceOrder: number, rangeStart: number }>}
  858. */
  859. const references = connections
  860. .filter(connection => {
  861. if (!(connection.dependency instanceof HarmonyImportDependency))
  862. return false;
  863. return (
  864. connection &&
  865. connection.resolvedOriginModule === module &&
  866. connection.module &&
  867. connection.isTargetActive(runtime)
  868. );
  869. })
  870. .map(connection => {
  871. const dep = /** @type {HarmonyImportDependency} */ (
  872. connection.dependency
  873. );
  874. return {
  875. connection,
  876. sourceOrder: dep.sourceOrder,
  877. rangeStart: dep.range && dep.range[0]
  878. };
  879. });
  880. /**
  881. * bySourceOrder
  882. * @example
  883. * import a from "a"; // sourceOrder=1
  884. * import b from "b"; // sourceOrder=2
  885. *
  886. * byRangeStart
  887. * @example
  888. * import {a, b} from "a"; // sourceOrder=1
  889. * a.a(); // first range
  890. * b.b(); // second range
  891. *
  892. * If there is no reexport, we have the same source.
  893. * If there is reexport, but module has side effects, this will lead to reexport module only.
  894. * If there is side-effects-free reexport, we can get simple deterministic result with range start comparison.
  895. */
  896. references.sort(concatComparators(bySourceOrder, byRangeStart));
  897. /** @type {Map<Module, { connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} */
  898. const referencesMap = new Map();
  899. for (const { connection } of references) {
  900. const runtimeCondition = filterRuntime(runtime, r =>
  901. connection.isTargetActive(r)
  902. );
  903. if (runtimeCondition === false) continue;
  904. const module = connection.module;
  905. const entry = referencesMap.get(module);
  906. if (entry === undefined) {
  907. referencesMap.set(module, { connection, runtimeCondition });
  908. continue;
  909. }
  910. entry.runtimeCondition = mergeRuntimeConditionNonFalse(
  911. entry.runtimeCondition,
  912. runtimeCondition,
  913. runtime
  914. );
  915. }
  916. return referencesMap.values();
  917. };
  918. /**
  919. * @param {ModuleGraphConnection} connection graph connection
  920. * @param {RuntimeSpec | true} runtimeCondition runtime condition
  921. * @returns {void}
  922. */
  923. const enterModule = (connection, runtimeCondition) => {
  924. const module = connection.module;
  925. if (!module) return;
  926. const existingEntry = existingEntries.get(module);
  927. if (existingEntry === true) {
  928. return;
  929. }
  930. if (modulesSet.has(module)) {
  931. existingEntries.set(module, true);
  932. if (runtimeCondition !== true) {
  933. throw new Error(
  934. `Cannot runtime-conditional concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}, ${runtimeConditionToString(
  935. runtimeCondition
  936. )}). This should not happen.`
  937. );
  938. }
  939. const imports = getConcatenatedImports(module);
  940. for (const { connection, runtimeCondition } of imports)
  941. enterModule(connection, runtimeCondition);
  942. list.push({
  943. type: "concatenated",
  944. module: connection.module,
  945. runtimeCondition
  946. });
  947. } else {
  948. if (existingEntry !== undefined) {
  949. const reducedRuntimeCondition = subtractRuntimeCondition(
  950. runtimeCondition,
  951. existingEntry,
  952. runtime
  953. );
  954. if (reducedRuntimeCondition === false) return;
  955. runtimeCondition = reducedRuntimeCondition;
  956. existingEntries.set(
  957. connection.module,
  958. mergeRuntimeConditionNonFalse(
  959. existingEntry,
  960. runtimeCondition,
  961. runtime
  962. )
  963. );
  964. } else {
  965. existingEntries.set(connection.module, runtimeCondition);
  966. }
  967. if (list.length > 0) {
  968. const lastItem = list[list.length - 1];
  969. if (
  970. lastItem.type === "external" &&
  971. lastItem.module === connection.module
  972. ) {
  973. lastItem.runtimeCondition = mergeRuntimeCondition(
  974. lastItem.runtimeCondition,
  975. runtimeCondition,
  976. runtime
  977. );
  978. return;
  979. }
  980. }
  981. list.push({
  982. type: "external",
  983. get module() {
  984. // We need to use a getter here, because the module in the dependency
  985. // could be replaced by some other process (i. e. also replaced with a
  986. // concatenated module)
  987. return connection.module;
  988. },
  989. runtimeCondition
  990. });
  991. }
  992. };
  993. existingEntries.set(rootModule, true);
  994. const imports = getConcatenatedImports(rootModule);
  995. for (const { connection, runtimeCondition } of imports)
  996. enterModule(connection, runtimeCondition);
  997. list.push({
  998. type: "concatenated",
  999. module: rootModule,
  1000. runtimeCondition: true
  1001. });
  1002. return list;
  1003. }
  1004. /**
  1005. * @param {Module} rootModule the root module of the concatenation
  1006. * @param {Set<Module>} modules all modules in the concatenation (including the root module)
  1007. * @param {object=} associatedObjectForCache object for caching
  1008. * @param {string | HashConstructor=} hashFunction hash function to use
  1009. * @returns {string} the identifier
  1010. */
  1011. static _createIdentifier(
  1012. rootModule,
  1013. modules,
  1014. associatedObjectForCache,
  1015. hashFunction = "md4"
  1016. ) {
  1017. const cachedMakePathsRelative = makePathsRelative.bindContextCache(
  1018. /** @type {string} */ (rootModule.context),
  1019. associatedObjectForCache
  1020. );
  1021. let identifiers = [];
  1022. for (const module of modules) {
  1023. identifiers.push(cachedMakePathsRelative(module.identifier()));
  1024. }
  1025. identifiers.sort();
  1026. const hash = createHash(hashFunction);
  1027. hash.update(identifiers.join(" "));
  1028. return rootModule.identifier() + "|" + hash.digest("hex");
  1029. }
  1030. /**
  1031. * @param {LazySet<string>} fileDependencies set where file dependencies are added to
  1032. * @param {LazySet<string>} contextDependencies set where context dependencies are added to
  1033. * @param {LazySet<string>} missingDependencies set where missing dependencies are added to
  1034. * @param {LazySet<string>} buildDependencies set where build dependencies are added to
  1035. */
  1036. addCacheDependencies(
  1037. fileDependencies,
  1038. contextDependencies,
  1039. missingDependencies,
  1040. buildDependencies
  1041. ) {
  1042. for (const module of this._modules) {
  1043. module.addCacheDependencies(
  1044. fileDependencies,
  1045. contextDependencies,
  1046. missingDependencies,
  1047. buildDependencies
  1048. );
  1049. }
  1050. }
  1051. /**
  1052. * @param {CodeGenerationContext} context context for code generation
  1053. * @returns {CodeGenerationResult} result
  1054. */
  1055. codeGeneration({
  1056. dependencyTemplates,
  1057. runtimeTemplate,
  1058. moduleGraph,
  1059. chunkGraph,
  1060. runtime: generationRuntime,
  1061. codeGenerationResults
  1062. }) {
  1063. /** @type {Set<string>} */
  1064. const runtimeRequirements = new Set();
  1065. const runtime = intersectRuntime(generationRuntime, this._runtime);
  1066. const requestShortener = runtimeTemplate.requestShortener;
  1067. // Meta info for each module
  1068. const [modulesWithInfo, moduleToInfoMap] = this._getModulesWithInfo(
  1069. moduleGraph,
  1070. runtime
  1071. );
  1072. // Set with modules that need a generated namespace object
  1073. /** @type {Set<ConcatenatedModuleInfo>} */
  1074. const neededNamespaceObjects = new Set();
  1075. // Generate source code and analyse scopes
  1076. // Prepare a ReplaceSource for the final source
  1077. for (const info of moduleToInfoMap.values()) {
  1078. this._analyseModule(
  1079. moduleToInfoMap,
  1080. info,
  1081. dependencyTemplates,
  1082. runtimeTemplate,
  1083. moduleGraph,
  1084. chunkGraph,
  1085. runtime,
  1086. codeGenerationResults
  1087. );
  1088. }
  1089. // List of all used names to avoid conflicts
  1090. const allUsedNames = new Set(RESERVED_NAMES);
  1091. // Updated Top level declarations are created by renaming
  1092. const topLevelDeclarations = new Set();
  1093. // List of additional names in scope for module references
  1094. /** @type {Map<string, { usedNames: UsedNames, alreadyCheckedScopes: Set<TODO> }>} */
  1095. const usedNamesInScopeInfo = new Map();
  1096. /**
  1097. * @param {string} module module identifier
  1098. * @param {string} id export id
  1099. * @returns {{ usedNames: UsedNames, alreadyCheckedScopes: Set<TODO> }} info
  1100. */
  1101. const getUsedNamesInScopeInfo = (module, id) => {
  1102. const key = `${module}-${id}`;
  1103. let info = usedNamesInScopeInfo.get(key);
  1104. if (info === undefined) {
  1105. info = {
  1106. usedNames: new Set(),
  1107. alreadyCheckedScopes: new Set()
  1108. };
  1109. usedNamesInScopeInfo.set(key, info);
  1110. }
  1111. return info;
  1112. };
  1113. // Set of already checked scopes
  1114. const ignoredScopes = new Set();
  1115. // get all global names
  1116. for (const info of modulesWithInfo) {
  1117. if (info.type === "concatenated") {
  1118. // ignore symbols from moduleScope
  1119. if (info.moduleScope) {
  1120. ignoredScopes.add(info.moduleScope);
  1121. }
  1122. // The super class expression in class scopes behaves weird
  1123. // We get ranges of all super class expressions to make
  1124. // renaming to work correctly
  1125. const superClassCache = new WeakMap();
  1126. /**
  1127. * @param {Scope} scope scope
  1128. * @returns {TODO} result
  1129. */
  1130. const getSuperClassExpressions = scope => {
  1131. const cacheEntry = superClassCache.get(scope);
  1132. if (cacheEntry !== undefined) return cacheEntry;
  1133. const superClassExpressions = [];
  1134. for (const childScope of scope.childScopes) {
  1135. if (childScope.type !== "class") continue;
  1136. const block = childScope.block;
  1137. if (
  1138. (block.type === "ClassDeclaration" ||
  1139. block.type === "ClassExpression") &&
  1140. block.superClass
  1141. ) {
  1142. superClassExpressions.push({
  1143. range: block.superClass.range,
  1144. variables: childScope.variables
  1145. });
  1146. }
  1147. }
  1148. superClassCache.set(scope, superClassExpressions);
  1149. return superClassExpressions;
  1150. };
  1151. // add global symbols
  1152. if (info.globalScope) {
  1153. for (const reference of info.globalScope.through) {
  1154. const name = reference.identifier.name;
  1155. if (ConcatenationScope.isModuleReference(name)) {
  1156. const match = ConcatenationScope.matchModuleReference(name);
  1157. if (!match) continue;
  1158. const referencedInfo = modulesWithInfo[match.index];
  1159. if (referencedInfo.type === "reference")
  1160. throw new Error("Module reference can't point to a reference");
  1161. const binding = getFinalBinding(
  1162. moduleGraph,
  1163. referencedInfo,
  1164. match.ids,
  1165. moduleToInfoMap,
  1166. runtime,
  1167. requestShortener,
  1168. runtimeTemplate,
  1169. neededNamespaceObjects,
  1170. false,
  1171. /** @type {BuildMeta} */
  1172. (info.module.buildMeta).strictHarmonyModule,
  1173. true
  1174. );
  1175. if (!binding.ids) continue;
  1176. const { usedNames, alreadyCheckedScopes } =
  1177. getUsedNamesInScopeInfo(
  1178. binding.info.module.identifier(),
  1179. "name" in binding ? binding.name : ""
  1180. );
  1181. for (const expr of getSuperClassExpressions(reference.from)) {
  1182. if (
  1183. expr.range[0] <=
  1184. /** @type {Range} */ (reference.identifier.range)[0] &&
  1185. expr.range[1] >=
  1186. /** @type {Range} */ (reference.identifier.range)[1]
  1187. ) {
  1188. for (const variable of expr.variables) {
  1189. usedNames.add(variable.name);
  1190. }
  1191. }
  1192. }
  1193. addScopeSymbols(
  1194. reference.from,
  1195. usedNames,
  1196. alreadyCheckedScopes,
  1197. ignoredScopes
  1198. );
  1199. } else {
  1200. allUsedNames.add(name);
  1201. }
  1202. }
  1203. }
  1204. }
  1205. }
  1206. // generate names for symbols
  1207. for (const info of moduleToInfoMap.values()) {
  1208. const { usedNames: namespaceObjectUsedNames } = getUsedNamesInScopeInfo(
  1209. info.module.identifier(),
  1210. ""
  1211. );
  1212. switch (info.type) {
  1213. case "concatenated": {
  1214. for (const variable of info.moduleScope.variables) {
  1215. const name = variable.name;
  1216. const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
  1217. info.module.identifier(),
  1218. name
  1219. );
  1220. if (allUsedNames.has(name) || usedNames.has(name)) {
  1221. const references = getAllReferences(variable);
  1222. for (const ref of references) {
  1223. addScopeSymbols(
  1224. ref.from,
  1225. usedNames,
  1226. alreadyCheckedScopes,
  1227. ignoredScopes
  1228. );
  1229. }
  1230. const newName = this.findNewName(
  1231. name,
  1232. allUsedNames,
  1233. usedNames,
  1234. info.module.readableIdentifier(requestShortener)
  1235. );
  1236. allUsedNames.add(newName);
  1237. info.internalNames.set(name, newName);
  1238. topLevelDeclarations.add(newName);
  1239. const source = info.source;
  1240. const allIdentifiers = new Set(
  1241. references.map(r => r.identifier).concat(variable.identifiers)
  1242. );
  1243. for (const identifier of allIdentifiers) {
  1244. const r = /** @type {Range} */ (identifier.range);
  1245. const path = getPathInAst(info.ast, identifier);
  1246. if (path && path.length > 1) {
  1247. const maybeProperty =
  1248. path[1].type === "AssignmentPattern" &&
  1249. path[1].left === path[0]
  1250. ? path[2]
  1251. : path[1];
  1252. if (
  1253. maybeProperty.type === "Property" &&
  1254. maybeProperty.shorthand
  1255. ) {
  1256. source.insert(r[1], `: ${newName}`);
  1257. continue;
  1258. }
  1259. }
  1260. source.replace(r[0], r[1] - 1, newName);
  1261. }
  1262. } else {
  1263. allUsedNames.add(name);
  1264. info.internalNames.set(name, name);
  1265. topLevelDeclarations.add(name);
  1266. }
  1267. }
  1268. let namespaceObjectName;
  1269. if (info.namespaceExportSymbol) {
  1270. namespaceObjectName = info.internalNames.get(
  1271. info.namespaceExportSymbol
  1272. );
  1273. } else {
  1274. namespaceObjectName = this.findNewName(
  1275. "namespaceObject",
  1276. allUsedNames,
  1277. namespaceObjectUsedNames,
  1278. info.module.readableIdentifier(requestShortener)
  1279. );
  1280. allUsedNames.add(namespaceObjectName);
  1281. }
  1282. info.namespaceObjectName =
  1283. /** @type {string} */
  1284. (namespaceObjectName);
  1285. topLevelDeclarations.add(namespaceObjectName);
  1286. break;
  1287. }
  1288. case "external": {
  1289. const externalName = this.findNewName(
  1290. "",
  1291. allUsedNames,
  1292. namespaceObjectUsedNames,
  1293. info.module.readableIdentifier(requestShortener)
  1294. );
  1295. allUsedNames.add(externalName);
  1296. info.name = externalName;
  1297. topLevelDeclarations.add(externalName);
  1298. break;
  1299. }
  1300. }
  1301. const buildMeta = /** @type {BuildMeta} */ (info.module.buildMeta);
  1302. if (buildMeta.exportsType !== "namespace") {
  1303. const externalNameInterop = this.findNewName(
  1304. "namespaceObject",
  1305. allUsedNames,
  1306. namespaceObjectUsedNames,
  1307. info.module.readableIdentifier(requestShortener)
  1308. );
  1309. allUsedNames.add(externalNameInterop);
  1310. info.interopNamespaceObjectName = externalNameInterop;
  1311. topLevelDeclarations.add(externalNameInterop);
  1312. }
  1313. if (
  1314. buildMeta.exportsType === "default" &&
  1315. buildMeta.defaultObject !== "redirect"
  1316. ) {
  1317. const externalNameInterop = this.findNewName(
  1318. "namespaceObject2",
  1319. allUsedNames,
  1320. namespaceObjectUsedNames,
  1321. info.module.readableIdentifier(requestShortener)
  1322. );
  1323. allUsedNames.add(externalNameInterop);
  1324. info.interopNamespaceObject2Name = externalNameInterop;
  1325. topLevelDeclarations.add(externalNameInterop);
  1326. }
  1327. if (buildMeta.exportsType === "dynamic" || !buildMeta.exportsType) {
  1328. const externalNameInterop = this.findNewName(
  1329. "default",
  1330. allUsedNames,
  1331. namespaceObjectUsedNames,
  1332. info.module.readableIdentifier(requestShortener)
  1333. );
  1334. allUsedNames.add(externalNameInterop);
  1335. info.interopDefaultAccessName = externalNameInterop;
  1336. topLevelDeclarations.add(externalNameInterop);
  1337. }
  1338. }
  1339. // Find and replace references to modules
  1340. for (const info of moduleToInfoMap.values()) {
  1341. if (info.type === "concatenated") {
  1342. for (const reference of info.globalScope.through) {
  1343. const name = reference.identifier.name;
  1344. const match = ConcatenationScope.matchModuleReference(name);
  1345. if (match) {
  1346. const referencedInfo = modulesWithInfo[match.index];
  1347. if (referencedInfo.type === "reference")
  1348. throw new Error("Module reference can't point to a reference");
  1349. const finalName = getFinalName(
  1350. moduleGraph,
  1351. referencedInfo,
  1352. match.ids,
  1353. moduleToInfoMap,
  1354. runtime,
  1355. requestShortener,
  1356. runtimeTemplate,
  1357. neededNamespaceObjects,
  1358. match.call,
  1359. !match.directImport,
  1360. /** @type {BuildMeta} */
  1361. (info.module.buildMeta).strictHarmonyModule,
  1362. match.asiSafe
  1363. );
  1364. const r = /** @type {Range} */ (reference.identifier.range);
  1365. const source = info.source;
  1366. // range is extended by 2 chars to cover the appended "._"
  1367. source.replace(r[0], r[1] + 1, finalName);
  1368. }
  1369. }
  1370. }
  1371. }
  1372. // Map with all root exposed used exports
  1373. /** @type {Map<string, function(RequestShortener): string>} */
  1374. const exportsMap = new Map();
  1375. // Set with all root exposed unused exports
  1376. /** @type {Set<string>} */
  1377. const unusedExports = new Set();
  1378. const rootInfo = /** @type {ConcatenatedModuleInfo} */ (
  1379. moduleToInfoMap.get(this.rootModule)
  1380. );
  1381. const strictHarmonyModule =
  1382. /** @type {BuildMeta} */
  1383. (rootInfo.module.buildMeta).strictHarmonyModule;
  1384. const exportsInfo = moduleGraph.getExportsInfo(rootInfo.module);
  1385. /** @type {Record<string, string>} */
  1386. const exportsFinalName = {};
  1387. for (const exportInfo of exportsInfo.orderedExports) {
  1388. const name = exportInfo.name;
  1389. if (exportInfo.provided === false) continue;
  1390. const used = exportInfo.getUsedName(undefined, runtime);
  1391. if (!used) {
  1392. unusedExports.add(name);
  1393. continue;
  1394. }
  1395. exportsMap.set(used, requestShortener => {
  1396. try {
  1397. const finalName = getFinalName(
  1398. moduleGraph,
  1399. rootInfo,
  1400. [name],
  1401. moduleToInfoMap,
  1402. runtime,
  1403. requestShortener,
  1404. runtimeTemplate,
  1405. neededNamespaceObjects,
  1406. false,
  1407. false,
  1408. strictHarmonyModule,
  1409. true
  1410. );
  1411. exportsFinalName[used] = finalName;
  1412. return `/* ${
  1413. exportInfo.isReexport() ? "reexport" : "binding"
  1414. } */ ${finalName}`;
  1415. } catch (e) {
  1416. /** @type {Error} */
  1417. (e).message +=
  1418. `\nwhile generating the root export '${name}' (used name: '${used}')`;
  1419. throw e;
  1420. }
  1421. });
  1422. }
  1423. const result = new ConcatSource();
  1424. // add harmony compatibility flag (must be first because of possible circular dependencies)
  1425. let shouldAddHarmonyFlag = false;
  1426. if (
  1427. moduleGraph.getExportsInfo(this).otherExportsInfo.getUsed(runtime) !==
  1428. UsageState.Unused
  1429. ) {
  1430. shouldAddHarmonyFlag = true;
  1431. }
  1432. // define exports
  1433. if (exportsMap.size > 0) {
  1434. const { exportsDefinitions } = ConcatenatedModule.getCompilationHooks(
  1435. this.compilation
  1436. );
  1437. const definitions = [];
  1438. for (const [key, value] of exportsMap) {
  1439. definitions.push(
  1440. `\n ${propertyName(key)}: ${runtimeTemplate.returningFunction(
  1441. value(requestShortener)
  1442. )}`
  1443. );
  1444. }
  1445. const shouldSkipRenderDefinitions =
  1446. exportsDefinitions.call(exportsFinalName);
  1447. if (!shouldSkipRenderDefinitions) {
  1448. runtimeRequirements.add(RuntimeGlobals.exports);
  1449. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1450. if (shouldAddHarmonyFlag) {
  1451. result.add(`// ESM COMPAT FLAG\n`);
  1452. result.add(
  1453. runtimeTemplate.defineEsModuleFlagStatement({
  1454. exportsArgument: this.exportsArgument,
  1455. runtimeRequirements
  1456. })
  1457. );
  1458. }
  1459. result.add(`\n// EXPORTS\n`);
  1460. result.add(
  1461. `${RuntimeGlobals.definePropertyGetters}(${
  1462. this.exportsArgument
  1463. }, {${definitions.join(",")}\n});\n`
  1464. );
  1465. } else {
  1466. this.buildMeta.exportsFinalName = exportsFinalName;
  1467. }
  1468. }
  1469. // list unused exports
  1470. if (unusedExports.size > 0) {
  1471. result.add(
  1472. `\n// UNUSED EXPORTS: ${joinIterableWithComma(unusedExports)}\n`
  1473. );
  1474. }
  1475. // generate namespace objects
  1476. const namespaceObjectSources = new Map();
  1477. for (const info of neededNamespaceObjects) {
  1478. if (info.namespaceExportSymbol) continue;
  1479. const nsObj = [];
  1480. const exportsInfo = moduleGraph.getExportsInfo(info.module);
  1481. for (const exportInfo of exportsInfo.orderedExports) {
  1482. if (exportInfo.provided === false) continue;
  1483. const usedName = exportInfo.getUsedName(undefined, runtime);
  1484. if (usedName) {
  1485. const finalName = getFinalName(
  1486. moduleGraph,
  1487. info,
  1488. [exportInfo.name],
  1489. moduleToInfoMap,
  1490. runtime,
  1491. requestShortener,
  1492. runtimeTemplate,
  1493. neededNamespaceObjects,
  1494. false,
  1495. undefined,
  1496. /** @type {BuildMeta} */
  1497. (info.module.buildMeta).strictHarmonyModule,
  1498. true
  1499. );
  1500. nsObj.push(
  1501. `\n ${propertyName(usedName)}: ${runtimeTemplate.returningFunction(
  1502. finalName
  1503. )}`
  1504. );
  1505. }
  1506. }
  1507. const name = info.namespaceObjectName;
  1508. const defineGetters =
  1509. nsObj.length > 0
  1510. ? `${RuntimeGlobals.definePropertyGetters}(${name}, {${nsObj.join(
  1511. ","
  1512. )}\n});\n`
  1513. : "";
  1514. if (nsObj.length > 0)
  1515. runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
  1516. namespaceObjectSources.set(
  1517. info,
  1518. `
  1519. // NAMESPACE OBJECT: ${info.module.readableIdentifier(requestShortener)}
  1520. var ${name} = {};
  1521. ${RuntimeGlobals.makeNamespaceObject}(${name});
  1522. ${defineGetters}`
  1523. );
  1524. runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
  1525. }
  1526. // define required namespace objects (must be before evaluation modules)
  1527. for (const info of modulesWithInfo) {
  1528. if (info.type === "concatenated") {
  1529. const source = namespaceObjectSources.get(info);
  1530. if (!source) continue;
  1531. result.add(source);
  1532. }
  1533. }
  1534. const chunkInitFragments = [];
  1535. // evaluate modules in order
  1536. for (const rawInfo of modulesWithInfo) {
  1537. let name;
  1538. let isConditional = false;
  1539. const info = rawInfo.type === "reference" ? rawInfo.target : rawInfo;
  1540. switch (info.type) {
  1541. case "concatenated": {
  1542. result.add(
  1543. `\n;// CONCATENATED MODULE: ${info.module.readableIdentifier(
  1544. requestShortener
  1545. )}\n`
  1546. );
  1547. result.add(info.source);
  1548. if (info.chunkInitFragments) {
  1549. for (const f of info.chunkInitFragments) chunkInitFragments.push(f);
  1550. }
  1551. if (info.runtimeRequirements) {
  1552. for (const r of info.runtimeRequirements) {
  1553. runtimeRequirements.add(r);
  1554. }
  1555. }
  1556. name = info.namespaceObjectName;
  1557. break;
  1558. }
  1559. case "external": {
  1560. result.add(
  1561. `\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
  1562. requestShortener
  1563. )}\n`
  1564. );
  1565. runtimeRequirements.add(RuntimeGlobals.require);
  1566. const { runtimeCondition } =
  1567. /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */ (rawInfo);
  1568. const condition = runtimeTemplate.runtimeConditionExpression({
  1569. chunkGraph,
  1570. runtimeCondition,
  1571. runtime,
  1572. runtimeRequirements
  1573. });
  1574. if (condition !== "true") {
  1575. isConditional = true;
  1576. result.add(`if (${condition}) {\n`);
  1577. }
  1578. result.add(
  1579. `var ${info.name} = ${RuntimeGlobals.require}(${JSON.stringify(
  1580. chunkGraph.getModuleId(info.module)
  1581. )});`
  1582. );
  1583. name = info.name;
  1584. break;
  1585. }
  1586. default:
  1587. // @ts-expect-error never is expected here
  1588. throw new Error(`Unsupported concatenation entry type ${info.type}`);
  1589. }
  1590. if (info.interopNamespaceObjectUsed) {
  1591. runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
  1592. result.add(
  1593. `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);`
  1594. );
  1595. }
  1596. if (info.interopNamespaceObject2Used) {
  1597. runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
  1598. result.add(
  1599. `\nvar ${info.interopNamespaceObject2Name} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});`
  1600. );
  1601. }
  1602. if (info.interopDefaultAccessUsed) {
  1603. runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
  1604. result.add(
  1605. `\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});`
  1606. );
  1607. }
  1608. if (isConditional) {
  1609. result.add("\n}");
  1610. }
  1611. }
  1612. const data = new Map();
  1613. if (chunkInitFragments.length > 0)
  1614. data.set("chunkInitFragments", chunkInitFragments);
  1615. data.set("topLevelDeclarations", topLevelDeclarations);
  1616. /** @type {CodeGenerationResult} */
  1617. const resultEntry = {
  1618. sources: new Map([["javascript", new CachedSource(result)]]),
  1619. data,
  1620. runtimeRequirements
  1621. };
  1622. return resultEntry;
  1623. }
  1624. /**
  1625. * @param {Map<Module, ModuleInfo>} modulesMap modulesMap
  1626. * @param {ModuleInfo} info info
  1627. * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
  1628. * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
  1629. * @param {ModuleGraph} moduleGraph moduleGraph
  1630. * @param {ChunkGraph} chunkGraph chunkGraph
  1631. * @param {RuntimeSpec} runtime runtime
  1632. * @param {CodeGenerationResults} codeGenerationResults codeGenerationResults
  1633. */
  1634. _analyseModule(
  1635. modulesMap,
  1636. info,
  1637. dependencyTemplates,
  1638. runtimeTemplate,
  1639. moduleGraph,
  1640. chunkGraph,
  1641. runtime,
  1642. codeGenerationResults
  1643. ) {
  1644. if (info.type === "concatenated") {
  1645. const m = info.module;
  1646. try {
  1647. // Create a concatenation scope to track and capture information
  1648. const concatenationScope = new ConcatenationScope(modulesMap, info);
  1649. // TODO cache codeGeneration results
  1650. const codeGenResult = m.codeGeneration({
  1651. dependencyTemplates,
  1652. runtimeTemplate,
  1653. moduleGraph,
  1654. chunkGraph,
  1655. runtime,
  1656. concatenationScope,
  1657. codeGenerationResults,
  1658. sourceTypes: TYPES
  1659. });
  1660. const source = /** @type {Source} */ (
  1661. codeGenResult.sources.get("javascript")
  1662. );
  1663. const data = codeGenResult.data;
  1664. const chunkInitFragments = data && data.get("chunkInitFragments");
  1665. const code = source.source().toString();
  1666. let ast;
  1667. try {
  1668. ast = JavascriptParser._parse(code, {
  1669. sourceType: "module"
  1670. });
  1671. } catch (err) {
  1672. if (
  1673. err.loc &&
  1674. typeof err.loc === "object" &&
  1675. typeof err.loc.line === "number"
  1676. ) {
  1677. const lineNumber = err.loc.line;
  1678. const lines = code.split("\n");
  1679. err.message +=
  1680. "\n| " +
  1681. lines
  1682. .slice(Math.max(0, lineNumber - 3), lineNumber + 2)
  1683. .join("\n| ");
  1684. }
  1685. throw err;
  1686. }
  1687. const scopeManager = eslintScope.analyze(ast, {
  1688. ecmaVersion: 6,
  1689. sourceType: "module",
  1690. optimistic: true,
  1691. ignoreEval: true,
  1692. impliedStrict: true
  1693. });
  1694. const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
  1695. const moduleScope = globalScope.childScopes[0];
  1696. const resultSource = new ReplaceSource(source);
  1697. info.runtimeRequirements = codeGenResult.runtimeRequirements;
  1698. info.ast = ast;
  1699. info.internalSource = source;
  1700. info.source = resultSource;
  1701. info.chunkInitFragments = chunkInitFragments;
  1702. info.globalScope = globalScope;
  1703. info.moduleScope = moduleScope;
  1704. } catch (err) {
  1705. /** @type {Error} */
  1706. (err).message +=
  1707. `\nwhile analyzing module ${m.identifier()} for concatenation`;
  1708. throw err;
  1709. }
  1710. }
  1711. }
  1712. /**
  1713. * @param {ModuleGraph} moduleGraph the module graph
  1714. * @param {RuntimeSpec} runtime the runtime
  1715. * @returns {[ModuleInfoOrReference[], Map<Module, ModuleInfo>]} module info items
  1716. */
  1717. _getModulesWithInfo(moduleGraph, runtime) {
  1718. const orderedConcatenationList = this._createConcatenationList(
  1719. this.rootModule,
  1720. this._modules,
  1721. runtime,
  1722. moduleGraph
  1723. );
  1724. /** @type {Map<Module, ModuleInfo>} */
  1725. const map = new Map();
  1726. const list = orderedConcatenationList.map((info, index) => {
  1727. let item = map.get(info.module);
  1728. if (item === undefined) {
  1729. switch (info.type) {
  1730. case "concatenated":
  1731. item = {
  1732. type: "concatenated",
  1733. module: info.module,
  1734. index,
  1735. ast: undefined,
  1736. internalSource: undefined,
  1737. runtimeRequirements: undefined,
  1738. source: undefined,
  1739. globalScope: undefined,
  1740. moduleScope: undefined,
  1741. internalNames: new Map(),
  1742. exportMap: undefined,
  1743. rawExportMap: undefined,
  1744. namespaceExportSymbol: undefined,
  1745. namespaceObjectName: undefined,
  1746. interopNamespaceObjectUsed: false,
  1747. interopNamespaceObjectName: undefined,
  1748. interopNamespaceObject2Used: false,
  1749. interopNamespaceObject2Name: undefined,
  1750. interopDefaultAccessUsed: false,
  1751. interopDefaultAccessName: undefined
  1752. };
  1753. break;
  1754. case "external":
  1755. item = {
  1756. type: "external",
  1757. module: info.module,
  1758. runtimeCondition: info.runtimeCondition,
  1759. index,
  1760. name: undefined,
  1761. interopNamespaceObjectUsed: false,
  1762. interopNamespaceObjectName: undefined,
  1763. interopNamespaceObject2Used: false,
  1764. interopNamespaceObject2Name: undefined,
  1765. interopDefaultAccessUsed: false,
  1766. interopDefaultAccessName: undefined
  1767. };
  1768. break;
  1769. default:
  1770. throw new Error(
  1771. `Unsupported concatenation entry type ${info.type}`
  1772. );
  1773. }
  1774. map.set(
  1775. /** @type {ModuleInfo} */ (item).module,
  1776. /** @type {ModuleInfo} */ (item)
  1777. );
  1778. return item;
  1779. } else {
  1780. /** @type {ReferenceToModuleInfo} */
  1781. const ref = {
  1782. type: "reference",
  1783. runtimeCondition: info.runtimeCondition,
  1784. target: item
  1785. };
  1786. return ref;
  1787. }
  1788. });
  1789. return [list, map];
  1790. }
  1791. /**
  1792. * @param {string} oldName old name
  1793. * @param {UsedNames} usedNamed1 used named 1
  1794. * @param {UsedNames} usedNamed2 used named 2
  1795. * @param {string} extraInfo extra info
  1796. * @returns {string} found new name
  1797. */
  1798. findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
  1799. let name = oldName;
  1800. if (name === ConcatenationScope.DEFAULT_EXPORT) {
  1801. name = "";
  1802. }
  1803. if (name === ConcatenationScope.NAMESPACE_OBJECT_EXPORT) {
  1804. name = "namespaceObject";
  1805. }
  1806. // Remove uncool stuff
  1807. extraInfo = extraInfo.replace(
  1808. /\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g,
  1809. ""
  1810. );
  1811. const splittedInfo = extraInfo.split("/");
  1812. while (splittedInfo.length) {
  1813. name = splittedInfo.pop() + (name ? "_" + name : "");
  1814. const nameIdent = Template.toIdentifier(name);
  1815. if (
  1816. !usedNamed1.has(nameIdent) &&
  1817. (!usedNamed2 || !usedNamed2.has(nameIdent))
  1818. )
  1819. return nameIdent;
  1820. }
  1821. let i = 0;
  1822. let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
  1823. while (
  1824. usedNamed1.has(nameWithNumber) ||
  1825. (usedNamed2 && usedNamed2.has(nameWithNumber))
  1826. ) {
  1827. i++;
  1828. nameWithNumber = Template.toIdentifier(`${name}_${i}`);
  1829. }
  1830. return nameWithNumber;
  1831. }
  1832. /**
  1833. * @param {Hash} hash the hash used to track dependencies
  1834. * @param {UpdateHashContext} context context
  1835. * @returns {void}
  1836. */
  1837. updateHash(hash, context) {
  1838. const { chunkGraph, runtime } = context;
  1839. for (const info of this._createConcatenationList(
  1840. this.rootModule,
  1841. this._modules,
  1842. intersectRuntime(runtime, this._runtime),
  1843. chunkGraph.moduleGraph
  1844. )) {
  1845. switch (info.type) {
  1846. case "concatenated":
  1847. info.module.updateHash(hash, context);
  1848. break;
  1849. case "external":
  1850. hash.update(`${chunkGraph.getModuleId(info.module)}`);
  1851. // TODO runtimeCondition
  1852. break;
  1853. }
  1854. }
  1855. super.updateHash(hash, context);
  1856. }
  1857. /**
  1858. * @param {ObjectDeserializerContext} context context
  1859. * @returns {ConcatenatedModule} ConcatenatedModule
  1860. */
  1861. static deserialize(context) {
  1862. const obj = new ConcatenatedModule({
  1863. identifier: undefined,
  1864. rootModule: undefined,
  1865. modules: undefined,
  1866. runtime: undefined,
  1867. compilation: undefined
  1868. });
  1869. obj.deserialize(context);
  1870. return obj;
  1871. }
  1872. }
  1873. makeSerializable(ConcatenatedModule, "webpack/lib/optimize/ConcatenatedModule");
  1874. module.exports = ConcatenatedModule;