ConcatenatedModule.js 57 KB

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