ChunkGraph.js 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const util = require("util");
  7. const Entrypoint = require("./Entrypoint");
  8. const ModuleGraphConnection = require("./ModuleGraphConnection");
  9. const { first } = require("./util/SetHelpers");
  10. const SortableSet = require("./util/SortableSet");
  11. const {
  12. compareModulesById,
  13. compareIterables,
  14. compareModulesByIdentifier,
  15. concatComparators,
  16. compareSelect,
  17. compareIds
  18. } = require("./util/comparators");
  19. const createHash = require("./util/createHash");
  20. const findGraphRoots = require("./util/findGraphRoots");
  21. const {
  22. RuntimeSpecMap,
  23. RuntimeSpecSet,
  24. runtimeToString,
  25. mergeRuntime,
  26. forEachRuntime
  27. } = require("./util/runtime");
  28. /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
  29. /** @typedef {import("./Chunk")} Chunk */
  30. /** @typedef {import("./Chunk").ChunkId} ChunkId */
  31. /** @typedef {import("./ChunkGroup")} ChunkGroup */
  32. /** @typedef {import("./Generator").SourceTypes} SourceTypes */
  33. /** @typedef {import("./Module")} Module */
  34. /** @typedef {import("./Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
  35. /** @typedef {import("./ModuleGraph")} ModuleGraph */
  36. /** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
  37. /** @typedef {import("./RuntimeModule")} RuntimeModule */
  38. /** @typedef {typeof import("./util/Hash")} Hash */
  39. /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
  40. /** @type {ReadonlySet<string>} */
  41. const EMPTY_SET = new Set();
  42. const ZERO_BIG_INT = BigInt(0);
  43. const compareModuleIterables = compareIterables(compareModulesByIdentifier);
  44. /** @typedef {(c: Chunk, chunkGraph: ChunkGraph) => boolean} ChunkFilterPredicate */
  45. /** @typedef {(m: Module) => boolean} ModuleFilterPredicate */
  46. /** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */
  47. /**
  48. * @typedef {object} ChunkSizeOptions
  49. * @property {number=} chunkOverhead constant overhead for a chunk
  50. * @property {number=} entryChunkMultiplicator multiplicator for initial chunks
  51. */
  52. class ModuleHashInfo {
  53. /**
  54. * @param {string} hash hash
  55. * @param {string} renderedHash rendered hash
  56. */
  57. constructor(hash, renderedHash) {
  58. this.hash = hash;
  59. this.renderedHash = renderedHash;
  60. }
  61. }
  62. /** @template T @typedef {(set: SortableSet<T>) => T[]} SetToArrayFunction<T> */
  63. /**
  64. * @template T
  65. * @param {SortableSet<T>} set the set
  66. * @returns {T[]} set as array
  67. */
  68. const getArray = set => Array.from(set);
  69. /**
  70. * @param {SortableSet<Chunk>} chunks the chunks
  71. * @returns {RuntimeSpecSet} runtimes
  72. */
  73. const getModuleRuntimes = chunks => {
  74. const runtimes = new RuntimeSpecSet();
  75. for (const chunk of chunks) {
  76. runtimes.add(chunk.runtime);
  77. }
  78. return runtimes;
  79. };
  80. /**
  81. * @param {WeakMap<Module, Set<string>> | undefined} sourceTypesByModule sourceTypesByModule
  82. * @returns {function (SortableSet<Module>): Map<string, SortableSet<Module>>} modules by source type
  83. */
  84. const modulesBySourceType = sourceTypesByModule => set => {
  85. /** @type {Map<string, SortableSet<Module>>} */
  86. const map = new Map();
  87. for (const module of set) {
  88. const sourceTypes =
  89. (sourceTypesByModule && sourceTypesByModule.get(module)) ||
  90. module.getSourceTypes();
  91. for (const sourceType of sourceTypes) {
  92. let innerSet = map.get(sourceType);
  93. if (innerSet === undefined) {
  94. innerSet = new SortableSet();
  95. map.set(sourceType, innerSet);
  96. }
  97. innerSet.add(module);
  98. }
  99. }
  100. for (const [key, innerSet] of map) {
  101. // When all modules have the source type, we reuse the original SortableSet
  102. // to benefit from the shared cache (especially for sorting)
  103. if (innerSet.size === set.size) {
  104. map.set(key, set);
  105. }
  106. }
  107. return map;
  108. };
  109. const defaultModulesBySourceType = modulesBySourceType(undefined);
  110. /**
  111. * @template T
  112. * @type {WeakMap<Function, any>}
  113. */
  114. const createOrderedArrayFunctionMap = new WeakMap();
  115. /**
  116. * @template T
  117. * @param {function(T, T): -1|0|1} comparator comparator function
  118. * @returns {SetToArrayFunction<T>} set as ordered array
  119. */
  120. const createOrderedArrayFunction = comparator => {
  121. /** @type {SetToArrayFunction<T>} */
  122. let fn = createOrderedArrayFunctionMap.get(comparator);
  123. if (fn !== undefined) return fn;
  124. fn = set => {
  125. set.sortWith(comparator);
  126. return Array.from(set);
  127. };
  128. createOrderedArrayFunctionMap.set(comparator, fn);
  129. return fn;
  130. };
  131. /**
  132. * @param {Iterable<Module>} modules the modules to get the count/size of
  133. * @returns {number} the size of the modules
  134. */
  135. const getModulesSize = modules => {
  136. let size = 0;
  137. for (const module of modules) {
  138. for (const type of module.getSourceTypes()) {
  139. size += module.size(type);
  140. }
  141. }
  142. return size;
  143. };
  144. /**
  145. * @param {Iterable<Module>} modules the sortable Set to get the size of
  146. * @returns {Record<string, number>} the sizes of the modules
  147. */
  148. const getModulesSizes = modules => {
  149. const sizes = Object.create(null);
  150. for (const module of modules) {
  151. for (const type of module.getSourceTypes()) {
  152. sizes[type] = (sizes[type] || 0) + module.size(type);
  153. }
  154. }
  155. return sizes;
  156. };
  157. /**
  158. * @param {Chunk} a chunk
  159. * @param {Chunk} b chunk
  160. * @returns {boolean} true, if a is always a parent of b
  161. */
  162. const isAvailableChunk = (a, b) => {
  163. const queue = new Set(b.groupsIterable);
  164. for (const chunkGroup of queue) {
  165. if (a.isInGroup(chunkGroup)) continue;
  166. if (chunkGroup.isInitial()) return false;
  167. for (const parent of chunkGroup.parentsIterable) {
  168. queue.add(parent);
  169. }
  170. }
  171. return true;
  172. };
  173. /** @typedef {Set<Chunk>} EntryInChunks */
  174. /** @typedef {Set<Chunk>} RuntimeInChunks */
  175. /** @typedef {string | number} ModuleId */
  176. class ChunkGraphModule {
  177. constructor() {
  178. /** @type {SortableSet<Chunk>} */
  179. this.chunks = new SortableSet();
  180. /** @type {EntryInChunks | undefined} */
  181. this.entryInChunks = undefined;
  182. /** @type {RuntimeInChunks | undefined} */
  183. this.runtimeInChunks = undefined;
  184. /** @type {RuntimeSpecMap<ModuleHashInfo> | undefined} */
  185. this.hashes = undefined;
  186. /** @type {ModuleId | null} */
  187. this.id = null;
  188. /** @type {RuntimeSpecMap<Set<string>> | undefined} */
  189. this.runtimeRequirements = undefined;
  190. /** @type {RuntimeSpecMap<string> | undefined} */
  191. this.graphHashes = undefined;
  192. /** @type {RuntimeSpecMap<string> | undefined} */
  193. this.graphHashesWithConnections = undefined;
  194. }
  195. }
  196. class ChunkGraphChunk {
  197. constructor() {
  198. /** @type {SortableSet<Module>} */
  199. this.modules = new SortableSet();
  200. /** @type {WeakMap<Module, Set<string>> | undefined} */
  201. this.sourceTypesByModule = undefined;
  202. /** @type {Map<Module, Entrypoint>} */
  203. this.entryModules = new Map();
  204. /** @type {SortableSet<RuntimeModule>} */
  205. this.runtimeModules = new SortableSet();
  206. /** @type {Set<RuntimeModule> | undefined} */
  207. this.fullHashModules = undefined;
  208. /** @type {Set<RuntimeModule> | undefined} */
  209. this.dependentHashModules = undefined;
  210. /** @type {Set<string> | undefined} */
  211. this.runtimeRequirements = undefined;
  212. /** @type {Set<string>} */
  213. this.runtimeRequirementsInTree = new Set();
  214. this._modulesBySourceType = defaultModulesBySourceType;
  215. }
  216. }
  217. class ChunkGraph {
  218. /**
  219. * @param {ModuleGraph} moduleGraph the module graph
  220. * @param {string | Hash} hashFunction the hash function to use
  221. */
  222. constructor(moduleGraph, hashFunction = "md4") {
  223. /**
  224. * @private
  225. * @type {WeakMap<Module, ChunkGraphModule>}
  226. */
  227. this._modules = new WeakMap();
  228. /**
  229. * @private
  230. * @type {WeakMap<Chunk, ChunkGraphChunk>}
  231. */
  232. this._chunks = new WeakMap();
  233. /**
  234. * @private
  235. * @type {WeakMap<AsyncDependenciesBlock, ChunkGroup>}
  236. */
  237. this._blockChunkGroups = new WeakMap();
  238. /**
  239. * @private
  240. * @type {Map<string, string | number>}
  241. */
  242. this._runtimeIds = new Map();
  243. /** @type {ModuleGraph} */
  244. this.moduleGraph = moduleGraph;
  245. this._hashFunction = hashFunction;
  246. this._getGraphRoots = this._getGraphRoots.bind(this);
  247. }
  248. /**
  249. * @private
  250. * @param {Module} module the module
  251. * @returns {ChunkGraphModule} internal module
  252. */
  253. _getChunkGraphModule(module) {
  254. let cgm = this._modules.get(module);
  255. if (cgm === undefined) {
  256. cgm = new ChunkGraphModule();
  257. this._modules.set(module, cgm);
  258. }
  259. return cgm;
  260. }
  261. /**
  262. * @private
  263. * @param {Chunk} chunk the chunk
  264. * @returns {ChunkGraphChunk} internal chunk
  265. */
  266. _getChunkGraphChunk(chunk) {
  267. let cgc = this._chunks.get(chunk);
  268. if (cgc === undefined) {
  269. cgc = new ChunkGraphChunk();
  270. this._chunks.set(chunk, cgc);
  271. }
  272. return cgc;
  273. }
  274. /**
  275. * @param {SortableSet<Module>} set the sortable Set to get the roots of
  276. * @returns {Module[]} the graph roots
  277. */
  278. _getGraphRoots(set) {
  279. const { moduleGraph } = this;
  280. return Array.from(
  281. findGraphRoots(set, module => {
  282. /** @type {Set<Module>} */
  283. const set = new Set();
  284. /**
  285. * @param {Module} module module
  286. */
  287. const addDependencies = module => {
  288. for (const connection of moduleGraph.getOutgoingConnections(module)) {
  289. if (!connection.module) continue;
  290. const activeState = connection.getActiveState(undefined);
  291. if (activeState === false) continue;
  292. if (activeState === ModuleGraphConnection.TRANSITIVE_ONLY) {
  293. addDependencies(connection.module);
  294. continue;
  295. }
  296. set.add(connection.module);
  297. }
  298. };
  299. addDependencies(module);
  300. return set;
  301. })
  302. ).sort(compareModulesByIdentifier);
  303. }
  304. /**
  305. * @param {Chunk} chunk the new chunk
  306. * @param {Module} module the module
  307. * @returns {void}
  308. */
  309. connectChunkAndModule(chunk, module) {
  310. const cgm = this._getChunkGraphModule(module);
  311. const cgc = this._getChunkGraphChunk(chunk);
  312. cgm.chunks.add(chunk);
  313. cgc.modules.add(module);
  314. }
  315. /**
  316. * @param {Chunk} chunk the chunk
  317. * @param {Module} module the module
  318. * @returns {void}
  319. */
  320. disconnectChunkAndModule(chunk, module) {
  321. const cgm = this._getChunkGraphModule(module);
  322. const cgc = this._getChunkGraphChunk(chunk);
  323. cgc.modules.delete(module);
  324. // No need to invalidate cgc._modulesBySourceType because we modified cgc.modules anyway
  325. if (cgc.sourceTypesByModule) cgc.sourceTypesByModule.delete(module);
  326. cgm.chunks.delete(chunk);
  327. }
  328. /**
  329. * @param {Chunk} chunk the chunk which will be disconnected
  330. * @returns {void}
  331. */
  332. disconnectChunk(chunk) {
  333. const cgc = this._getChunkGraphChunk(chunk);
  334. for (const module of cgc.modules) {
  335. const cgm = this._getChunkGraphModule(module);
  336. cgm.chunks.delete(chunk);
  337. }
  338. cgc.modules.clear();
  339. chunk.disconnectFromGroups();
  340. ChunkGraph.clearChunkGraphForChunk(chunk);
  341. }
  342. /**
  343. * @param {Chunk} chunk the chunk
  344. * @param {Iterable<Module>} modules the modules
  345. * @returns {void}
  346. */
  347. attachModules(chunk, modules) {
  348. const cgc = this._getChunkGraphChunk(chunk);
  349. for (const module of modules) {
  350. cgc.modules.add(module);
  351. }
  352. }
  353. /**
  354. * @param {Chunk} chunk the chunk
  355. * @param {Iterable<RuntimeModule>} modules the runtime modules
  356. * @returns {void}
  357. */
  358. attachRuntimeModules(chunk, modules) {
  359. const cgc = this._getChunkGraphChunk(chunk);
  360. for (const module of modules) {
  361. cgc.runtimeModules.add(module);
  362. }
  363. }
  364. /**
  365. * @param {Chunk} chunk the chunk
  366. * @param {Iterable<RuntimeModule>} modules the modules that require a full hash
  367. * @returns {void}
  368. */
  369. attachFullHashModules(chunk, modules) {
  370. const cgc = this._getChunkGraphChunk(chunk);
  371. if (cgc.fullHashModules === undefined) cgc.fullHashModules = new Set();
  372. for (const module of modules) {
  373. cgc.fullHashModules.add(module);
  374. }
  375. }
  376. /**
  377. * @param {Chunk} chunk the chunk
  378. * @param {Iterable<RuntimeModule>} modules the modules that require a full hash
  379. * @returns {void}
  380. */
  381. attachDependentHashModules(chunk, modules) {
  382. const cgc = this._getChunkGraphChunk(chunk);
  383. if (cgc.dependentHashModules === undefined)
  384. cgc.dependentHashModules = new Set();
  385. for (const module of modules) {
  386. cgc.dependentHashModules.add(module);
  387. }
  388. }
  389. /**
  390. * @param {Module} oldModule the replaced module
  391. * @param {Module} newModule the replacing module
  392. * @returns {void}
  393. */
  394. replaceModule(oldModule, newModule) {
  395. const oldCgm = this._getChunkGraphModule(oldModule);
  396. const newCgm = this._getChunkGraphModule(newModule);
  397. for (const chunk of oldCgm.chunks) {
  398. const cgc = this._getChunkGraphChunk(chunk);
  399. cgc.modules.delete(oldModule);
  400. cgc.modules.add(newModule);
  401. newCgm.chunks.add(chunk);
  402. }
  403. oldCgm.chunks.clear();
  404. if (oldCgm.entryInChunks !== undefined) {
  405. if (newCgm.entryInChunks === undefined) {
  406. newCgm.entryInChunks = new Set();
  407. }
  408. for (const chunk of oldCgm.entryInChunks) {
  409. const cgc = this._getChunkGraphChunk(chunk);
  410. const old = /** @type {Entrypoint} */ (cgc.entryModules.get(oldModule));
  411. /** @type {Map<Module, Entrypoint>} */
  412. const newEntryModules = new Map();
  413. for (const [m, cg] of cgc.entryModules) {
  414. if (m === oldModule) {
  415. newEntryModules.set(newModule, old);
  416. } else {
  417. newEntryModules.set(m, cg);
  418. }
  419. }
  420. cgc.entryModules = newEntryModules;
  421. newCgm.entryInChunks.add(chunk);
  422. }
  423. oldCgm.entryInChunks = undefined;
  424. }
  425. if (oldCgm.runtimeInChunks !== undefined) {
  426. if (newCgm.runtimeInChunks === undefined) {
  427. newCgm.runtimeInChunks = new Set();
  428. }
  429. for (const chunk of oldCgm.runtimeInChunks) {
  430. const cgc = this._getChunkGraphChunk(chunk);
  431. cgc.runtimeModules.delete(/** @type {RuntimeModule} */ (oldModule));
  432. cgc.runtimeModules.add(/** @type {RuntimeModule} */ (newModule));
  433. newCgm.runtimeInChunks.add(chunk);
  434. if (
  435. cgc.fullHashModules !== undefined &&
  436. cgc.fullHashModules.has(/** @type {RuntimeModule} */ (oldModule))
  437. ) {
  438. cgc.fullHashModules.delete(/** @type {RuntimeModule} */ (oldModule));
  439. cgc.fullHashModules.add(/** @type {RuntimeModule} */ (newModule));
  440. }
  441. if (
  442. cgc.dependentHashModules !== undefined &&
  443. cgc.dependentHashModules.has(/** @type {RuntimeModule} */ (oldModule))
  444. ) {
  445. cgc.dependentHashModules.delete(
  446. /** @type {RuntimeModule} */ (oldModule)
  447. );
  448. cgc.dependentHashModules.add(
  449. /** @type {RuntimeModule} */ (newModule)
  450. );
  451. }
  452. }
  453. oldCgm.runtimeInChunks = undefined;
  454. }
  455. }
  456. /**
  457. * @param {Module} module the checked module
  458. * @param {Chunk} chunk the checked chunk
  459. * @returns {boolean} true, if the chunk contains the module
  460. */
  461. isModuleInChunk(module, chunk) {
  462. const cgc = this._getChunkGraphChunk(chunk);
  463. return cgc.modules.has(module);
  464. }
  465. /**
  466. * @param {Module} module the checked module
  467. * @param {ChunkGroup} chunkGroup the checked chunk group
  468. * @returns {boolean} true, if the chunk contains the module
  469. */
  470. isModuleInChunkGroup(module, chunkGroup) {
  471. for (const chunk of chunkGroup.chunks) {
  472. if (this.isModuleInChunk(module, chunk)) return true;
  473. }
  474. return false;
  475. }
  476. /**
  477. * @param {Module} module the checked module
  478. * @returns {boolean} true, if the module is entry of any chunk
  479. */
  480. isEntryModule(module) {
  481. const cgm = this._getChunkGraphModule(module);
  482. return cgm.entryInChunks !== undefined;
  483. }
  484. /**
  485. * @param {Module} module the module
  486. * @returns {Iterable<Chunk>} iterable of chunks (do not modify)
  487. */
  488. getModuleChunksIterable(module) {
  489. const cgm = this._getChunkGraphModule(module);
  490. return cgm.chunks;
  491. }
  492. /**
  493. * @param {Module} module the module
  494. * @param {function(Chunk, Chunk): -1|0|1} sortFn sort function
  495. * @returns {Iterable<Chunk>} iterable of chunks (do not modify)
  496. */
  497. getOrderedModuleChunksIterable(module, sortFn) {
  498. const cgm = this._getChunkGraphModule(module);
  499. cgm.chunks.sortWith(sortFn);
  500. return cgm.chunks;
  501. }
  502. /**
  503. * @param {Module} module the module
  504. * @returns {Chunk[]} array of chunks (cached, do not modify)
  505. */
  506. getModuleChunks(module) {
  507. const cgm = this._getChunkGraphModule(module);
  508. return cgm.chunks.getFromCache(getArray);
  509. }
  510. /**
  511. * @param {Module} module the module
  512. * @returns {number} the number of chunk which contain the module
  513. */
  514. getNumberOfModuleChunks(module) {
  515. const cgm = this._getChunkGraphModule(module);
  516. return cgm.chunks.size;
  517. }
  518. /**
  519. * @param {Module} module the module
  520. * @returns {RuntimeSpecSet} runtimes
  521. */
  522. getModuleRuntimes(module) {
  523. const cgm = this._getChunkGraphModule(module);
  524. return cgm.chunks.getFromUnorderedCache(getModuleRuntimes);
  525. }
  526. /**
  527. * @param {Chunk} chunk the chunk
  528. * @returns {number} the number of modules which are contained in this chunk
  529. */
  530. getNumberOfChunkModules(chunk) {
  531. const cgc = this._getChunkGraphChunk(chunk);
  532. return cgc.modules.size;
  533. }
  534. /**
  535. * @param {Chunk} chunk the chunk
  536. * @returns {number} the number of full hash modules which are contained in this chunk
  537. */
  538. getNumberOfChunkFullHashModules(chunk) {
  539. const cgc = this._getChunkGraphChunk(chunk);
  540. return cgc.fullHashModules === undefined ? 0 : cgc.fullHashModules.size;
  541. }
  542. /**
  543. * @param {Chunk} chunk the chunk
  544. * @returns {Iterable<Module>} return the modules for this chunk
  545. */
  546. getChunkModulesIterable(chunk) {
  547. const cgc = this._getChunkGraphChunk(chunk);
  548. return cgc.modules;
  549. }
  550. /**
  551. * @param {Chunk} chunk the chunk
  552. * @param {string} sourceType source type
  553. * @returns {Iterable<Module> | undefined} return the modules for this chunk
  554. */
  555. getChunkModulesIterableBySourceType(chunk, sourceType) {
  556. const cgc = this._getChunkGraphChunk(chunk);
  557. const modulesWithSourceType = cgc.modules
  558. .getFromUnorderedCache(cgc._modulesBySourceType)
  559. .get(sourceType);
  560. return modulesWithSourceType;
  561. }
  562. /**
  563. * @param {Chunk} chunk chunk
  564. * @param {Module} module chunk module
  565. * @param {Set<string>} sourceTypes source types
  566. */
  567. setChunkModuleSourceTypes(chunk, module, sourceTypes) {
  568. const cgc = this._getChunkGraphChunk(chunk);
  569. if (cgc.sourceTypesByModule === undefined) {
  570. cgc.sourceTypesByModule = new WeakMap();
  571. }
  572. cgc.sourceTypesByModule.set(module, sourceTypes);
  573. // Update cgc._modulesBySourceType to invalidate the cache
  574. cgc._modulesBySourceType = modulesBySourceType(cgc.sourceTypesByModule);
  575. }
  576. /**
  577. * @param {Chunk} chunk chunk
  578. * @param {Module} module chunk module
  579. * @returns {SourceTypes} source types
  580. */
  581. getChunkModuleSourceTypes(chunk, module) {
  582. const cgc = this._getChunkGraphChunk(chunk);
  583. if (cgc.sourceTypesByModule === undefined) {
  584. return module.getSourceTypes();
  585. }
  586. return cgc.sourceTypesByModule.get(module) || module.getSourceTypes();
  587. }
  588. /**
  589. * @param {Module} module module
  590. * @returns {SourceTypes} source types
  591. */
  592. getModuleSourceTypes(module) {
  593. return (
  594. this._getOverwrittenModuleSourceTypes(module) || module.getSourceTypes()
  595. );
  596. }
  597. /**
  598. * @param {Module} module module
  599. * @returns {Set<string> | undefined} source types
  600. */
  601. _getOverwrittenModuleSourceTypes(module) {
  602. let newSet = false;
  603. let sourceTypes;
  604. for (const chunk of this.getModuleChunksIterable(module)) {
  605. const cgc = this._getChunkGraphChunk(chunk);
  606. if (cgc.sourceTypesByModule === undefined) return;
  607. const st = cgc.sourceTypesByModule.get(module);
  608. if (st === undefined) return;
  609. if (!sourceTypes) {
  610. sourceTypes = st;
  611. continue;
  612. } else if (!newSet) {
  613. for (const type of st) {
  614. if (!newSet) {
  615. if (!sourceTypes.has(type)) {
  616. newSet = true;
  617. sourceTypes = new Set(sourceTypes);
  618. sourceTypes.add(type);
  619. }
  620. } else {
  621. sourceTypes.add(type);
  622. }
  623. }
  624. } else {
  625. for (const type of st) sourceTypes.add(type);
  626. }
  627. }
  628. return sourceTypes;
  629. }
  630. /**
  631. * @param {Chunk} chunk the chunk
  632. * @param {function(Module, Module): -1|0|1} comparator comparator function
  633. * @returns {Iterable<Module>} return the modules for this chunk
  634. */
  635. getOrderedChunkModulesIterable(chunk, comparator) {
  636. const cgc = this._getChunkGraphChunk(chunk);
  637. cgc.modules.sortWith(comparator);
  638. return cgc.modules;
  639. }
  640. /**
  641. * @param {Chunk} chunk the chunk
  642. * @param {string} sourceType source type
  643. * @param {function(Module, Module): -1|0|1} comparator comparator function
  644. * @returns {Iterable<Module> | undefined} return the modules for this chunk
  645. */
  646. getOrderedChunkModulesIterableBySourceType(chunk, sourceType, comparator) {
  647. const cgc = this._getChunkGraphChunk(chunk);
  648. const modulesWithSourceType = cgc.modules
  649. .getFromUnorderedCache(cgc._modulesBySourceType)
  650. .get(sourceType);
  651. if (modulesWithSourceType === undefined) return;
  652. modulesWithSourceType.sortWith(comparator);
  653. return modulesWithSourceType;
  654. }
  655. /**
  656. * @param {Chunk} chunk the chunk
  657. * @returns {Module[]} return the modules for this chunk (cached, do not modify)
  658. */
  659. getChunkModules(chunk) {
  660. const cgc = this._getChunkGraphChunk(chunk);
  661. return cgc.modules.getFromUnorderedCache(getArray);
  662. }
  663. /**
  664. * @param {Chunk} chunk the chunk
  665. * @param {function(Module, Module): -1|0|1} comparator comparator function
  666. * @returns {Module[]} return the modules for this chunk (cached, do not modify)
  667. */
  668. getOrderedChunkModules(chunk, comparator) {
  669. const cgc = this._getChunkGraphChunk(chunk);
  670. const arrayFunction = createOrderedArrayFunction(comparator);
  671. return cgc.modules.getFromUnorderedCache(arrayFunction);
  672. }
  673. /**
  674. * @param {Chunk} chunk the chunk
  675. * @param {ModuleFilterPredicate} filterFn function used to filter modules
  676. * @param {boolean} includeAllChunks all chunks or only async chunks
  677. * @returns {Record<string|number, (string|number)[]>} chunk to module ids object
  678. */
  679. getChunkModuleIdMap(chunk, filterFn, includeAllChunks = false) {
  680. /** @type {Record<string|number, (string|number)[]>} */
  681. const chunkModuleIdMap = Object.create(null);
  682. for (const asyncChunk of includeAllChunks
  683. ? chunk.getAllReferencedChunks()
  684. : chunk.getAllAsyncChunks()) {
  685. /** @type {(string | number)[] | undefined} */
  686. let array;
  687. for (const module of this.getOrderedChunkModulesIterable(
  688. asyncChunk,
  689. compareModulesById(this)
  690. )) {
  691. if (filterFn(module)) {
  692. if (array === undefined) {
  693. array = [];
  694. chunkModuleIdMap[/** @type {ChunkId} */ (asyncChunk.id)] = array;
  695. }
  696. const moduleId = /** @type {ModuleId} */ (this.getModuleId(module));
  697. array.push(moduleId);
  698. }
  699. }
  700. }
  701. return chunkModuleIdMap;
  702. }
  703. /**
  704. * @param {Chunk} chunk the chunk
  705. * @param {ModuleFilterPredicate} filterFn function used to filter modules
  706. * @param {number} hashLength length of the hash
  707. * @param {boolean} includeAllChunks all chunks or only async chunks
  708. * @returns {Record<string|number, Record<string|number, string>>} chunk to module id to module hash object
  709. */
  710. getChunkModuleRenderedHashMap(
  711. chunk,
  712. filterFn,
  713. hashLength = 0,
  714. includeAllChunks = false
  715. ) {
  716. /** @type {Record<ChunkId, Record<string|number, string>>} */
  717. const chunkModuleHashMap = Object.create(null);
  718. /** @typedef {Record<string|number, string>} IdToHashMap */
  719. for (const asyncChunk of includeAllChunks
  720. ? chunk.getAllReferencedChunks()
  721. : chunk.getAllAsyncChunks()) {
  722. /** @type {IdToHashMap | undefined} */
  723. let idToHashMap;
  724. for (const module of this.getOrderedChunkModulesIterable(
  725. asyncChunk,
  726. compareModulesById(this)
  727. )) {
  728. if (filterFn(module)) {
  729. if (idToHashMap === undefined) {
  730. idToHashMap = Object.create(null);
  731. chunkModuleHashMap[/** @type {ChunkId} */ (asyncChunk.id)] =
  732. /** @type {IdToHashMap} */ (idToHashMap);
  733. }
  734. const moduleId = this.getModuleId(module);
  735. const hash = this.getRenderedModuleHash(module, asyncChunk.runtime);
  736. /** @type {IdToHashMap} */
  737. (idToHashMap)[/** @type {ModuleId} */ (moduleId)] = hashLength
  738. ? hash.slice(0, hashLength)
  739. : hash;
  740. }
  741. }
  742. }
  743. return chunkModuleHashMap;
  744. }
  745. /**
  746. * @param {Chunk} chunk the chunk
  747. * @param {ChunkFilterPredicate} filterFn function used to filter chunks
  748. * @returns {Record<string|number, boolean>} chunk map
  749. */
  750. getChunkConditionMap(chunk, filterFn) {
  751. const map = Object.create(null);
  752. for (const c of chunk.getAllReferencedChunks()) {
  753. map[/** @type {ChunkId} */ (c.id)] = filterFn(c, this);
  754. }
  755. return map;
  756. }
  757. /**
  758. * @param {Chunk} chunk the chunk
  759. * @param {ModuleFilterPredicate} filterFn predicate function used to filter modules
  760. * @param {ChunkFilterPredicate=} filterChunkFn predicate function used to filter chunks
  761. * @returns {boolean} return true if module exists in graph
  762. */
  763. hasModuleInGraph(chunk, filterFn, filterChunkFn) {
  764. const queue = new Set(chunk.groupsIterable);
  765. const chunksProcessed = new Set();
  766. for (const chunkGroup of queue) {
  767. for (const innerChunk of chunkGroup.chunks) {
  768. if (!chunksProcessed.has(innerChunk)) {
  769. chunksProcessed.add(innerChunk);
  770. if (!filterChunkFn || filterChunkFn(innerChunk, this)) {
  771. for (const module of this.getChunkModulesIterable(innerChunk)) {
  772. if (filterFn(module)) {
  773. return true;
  774. }
  775. }
  776. }
  777. }
  778. }
  779. for (const child of chunkGroup.childrenIterable) {
  780. queue.add(child);
  781. }
  782. }
  783. return false;
  784. }
  785. /**
  786. * @param {Chunk} chunkA first chunk
  787. * @param {Chunk} chunkB second chunk
  788. * @returns {-1|0|1} this is a comparator function like sort and returns -1, 0, or 1 based on sort order
  789. */
  790. compareChunks(chunkA, chunkB) {
  791. const cgcA = this._getChunkGraphChunk(chunkA);
  792. const cgcB = this._getChunkGraphChunk(chunkB);
  793. if (cgcA.modules.size > cgcB.modules.size) return -1;
  794. if (cgcA.modules.size < cgcB.modules.size) return 1;
  795. cgcA.modules.sortWith(compareModulesByIdentifier);
  796. cgcB.modules.sortWith(compareModulesByIdentifier);
  797. return compareModuleIterables(cgcA.modules, cgcB.modules);
  798. }
  799. /**
  800. * @param {Chunk} chunk the chunk
  801. * @returns {number} total size of all modules in the chunk
  802. */
  803. getChunkModulesSize(chunk) {
  804. const cgc = this._getChunkGraphChunk(chunk);
  805. return cgc.modules.getFromUnorderedCache(getModulesSize);
  806. }
  807. /**
  808. * @param {Chunk} chunk the chunk
  809. * @returns {Record<string, number>} total sizes of all modules in the chunk by source type
  810. */
  811. getChunkModulesSizes(chunk) {
  812. const cgc = this._getChunkGraphChunk(chunk);
  813. return cgc.modules.getFromUnorderedCache(getModulesSizes);
  814. }
  815. /**
  816. * @param {Chunk} chunk the chunk
  817. * @returns {Module[]} root modules of the chunks (ordered by identifier)
  818. */
  819. getChunkRootModules(chunk) {
  820. const cgc = this._getChunkGraphChunk(chunk);
  821. return cgc.modules.getFromUnorderedCache(this._getGraphRoots);
  822. }
  823. /**
  824. * @param {Chunk} chunk the chunk
  825. * @param {ChunkSizeOptions} options options object
  826. * @returns {number} total size of the chunk
  827. */
  828. getChunkSize(chunk, options = {}) {
  829. const cgc = this._getChunkGraphChunk(chunk);
  830. const modulesSize = cgc.modules.getFromUnorderedCache(getModulesSize);
  831. const chunkOverhead =
  832. typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
  833. const entryChunkMultiplicator =
  834. typeof options.entryChunkMultiplicator === "number"
  835. ? options.entryChunkMultiplicator
  836. : 10;
  837. return (
  838. chunkOverhead +
  839. modulesSize * (chunk.canBeInitial() ? entryChunkMultiplicator : 1)
  840. );
  841. }
  842. /**
  843. * @param {Chunk} chunkA chunk
  844. * @param {Chunk} chunkB chunk
  845. * @param {ChunkSizeOptions} options options object
  846. * @returns {number} total size of the chunk or false if chunks can't be integrated
  847. */
  848. getIntegratedChunksSize(chunkA, chunkB, options = {}) {
  849. const cgcA = this._getChunkGraphChunk(chunkA);
  850. const cgcB = this._getChunkGraphChunk(chunkB);
  851. const allModules = new Set(cgcA.modules);
  852. for (const m of cgcB.modules) allModules.add(m);
  853. const modulesSize = getModulesSize(allModules);
  854. const chunkOverhead =
  855. typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
  856. const entryChunkMultiplicator =
  857. typeof options.entryChunkMultiplicator === "number"
  858. ? options.entryChunkMultiplicator
  859. : 10;
  860. return (
  861. chunkOverhead +
  862. modulesSize *
  863. (chunkA.canBeInitial() || chunkB.canBeInitial()
  864. ? entryChunkMultiplicator
  865. : 1)
  866. );
  867. }
  868. /**
  869. * @param {Chunk} chunkA chunk
  870. * @param {Chunk} chunkB chunk
  871. * @returns {boolean} true, if chunks could be integrated
  872. */
  873. canChunksBeIntegrated(chunkA, chunkB) {
  874. if (chunkA.preventIntegration || chunkB.preventIntegration) {
  875. return false;
  876. }
  877. const hasRuntimeA = chunkA.hasRuntime();
  878. const hasRuntimeB = chunkB.hasRuntime();
  879. if (hasRuntimeA !== hasRuntimeB) {
  880. if (hasRuntimeA) {
  881. return isAvailableChunk(chunkA, chunkB);
  882. } else if (hasRuntimeB) {
  883. return isAvailableChunk(chunkB, chunkA);
  884. }
  885. return false;
  886. }
  887. if (
  888. this.getNumberOfEntryModules(chunkA) > 0 ||
  889. this.getNumberOfEntryModules(chunkB) > 0
  890. ) {
  891. return false;
  892. }
  893. return true;
  894. }
  895. /**
  896. * @param {Chunk} chunkA the target chunk
  897. * @param {Chunk} chunkB the chunk to integrate
  898. * @returns {void}
  899. */
  900. integrateChunks(chunkA, chunkB) {
  901. // Decide for one name (deterministic)
  902. if (chunkA.name && chunkB.name) {
  903. if (
  904. this.getNumberOfEntryModules(chunkA) > 0 ===
  905. this.getNumberOfEntryModules(chunkB) > 0
  906. ) {
  907. // When both chunks have entry modules or none have one, use
  908. // shortest name
  909. if (chunkA.name.length !== chunkB.name.length) {
  910. chunkA.name =
  911. chunkA.name.length < chunkB.name.length ? chunkA.name : chunkB.name;
  912. } else {
  913. chunkA.name = chunkA.name < chunkB.name ? chunkA.name : chunkB.name;
  914. }
  915. } else if (this.getNumberOfEntryModules(chunkB) > 0) {
  916. // Pick the name of the chunk with the entry module
  917. chunkA.name = chunkB.name;
  918. }
  919. } else if (chunkB.name) {
  920. chunkA.name = chunkB.name;
  921. }
  922. // Merge id name hints
  923. for (const hint of chunkB.idNameHints) {
  924. chunkA.idNameHints.add(hint);
  925. }
  926. // Merge runtime
  927. chunkA.runtime = mergeRuntime(chunkA.runtime, chunkB.runtime);
  928. // getChunkModules is used here to create a clone, because disconnectChunkAndModule modifies
  929. for (const module of this.getChunkModules(chunkB)) {
  930. this.disconnectChunkAndModule(chunkB, module);
  931. this.connectChunkAndModule(chunkA, module);
  932. }
  933. for (const [module, chunkGroup] of Array.from(
  934. this.getChunkEntryModulesWithChunkGroupIterable(chunkB)
  935. )) {
  936. this.disconnectChunkAndEntryModule(chunkB, module);
  937. this.connectChunkAndEntryModule(
  938. chunkA,
  939. module,
  940. /** @type {Entrypoint} */
  941. (chunkGroup)
  942. );
  943. }
  944. for (const chunkGroup of chunkB.groupsIterable) {
  945. chunkGroup.replaceChunk(chunkB, chunkA);
  946. chunkA.addGroup(chunkGroup);
  947. chunkB.removeGroup(chunkGroup);
  948. }
  949. ChunkGraph.clearChunkGraphForChunk(chunkB);
  950. }
  951. /**
  952. * @param {Chunk} chunk the chunk to upgrade
  953. * @returns {void}
  954. */
  955. upgradeDependentToFullHashModules(chunk) {
  956. const cgc = this._getChunkGraphChunk(chunk);
  957. if (cgc.dependentHashModules === undefined) return;
  958. if (cgc.fullHashModules === undefined) {
  959. cgc.fullHashModules = cgc.dependentHashModules;
  960. } else {
  961. for (const m of cgc.dependentHashModules) {
  962. cgc.fullHashModules.add(m);
  963. }
  964. cgc.dependentHashModules = undefined;
  965. }
  966. }
  967. /**
  968. * @param {Module} module the checked module
  969. * @param {Chunk} chunk the checked chunk
  970. * @returns {boolean} true, if the chunk contains the module as entry
  971. */
  972. isEntryModuleInChunk(module, chunk) {
  973. const cgc = this._getChunkGraphChunk(chunk);
  974. return cgc.entryModules.has(module);
  975. }
  976. /**
  977. * @param {Chunk} chunk the new chunk
  978. * @param {Module} module the entry module
  979. * @param {Entrypoint} entrypoint the chunk group which must be loaded before the module is executed
  980. * @returns {void}
  981. */
  982. connectChunkAndEntryModule(chunk, module, entrypoint) {
  983. const cgm = this._getChunkGraphModule(module);
  984. const cgc = this._getChunkGraphChunk(chunk);
  985. if (cgm.entryInChunks === undefined) {
  986. cgm.entryInChunks = new Set();
  987. }
  988. cgm.entryInChunks.add(chunk);
  989. cgc.entryModules.set(module, entrypoint);
  990. }
  991. /**
  992. * @param {Chunk} chunk the new chunk
  993. * @param {RuntimeModule} module the runtime module
  994. * @returns {void}
  995. */
  996. connectChunkAndRuntimeModule(chunk, module) {
  997. const cgm = this._getChunkGraphModule(module);
  998. const cgc = this._getChunkGraphChunk(chunk);
  999. if (cgm.runtimeInChunks === undefined) {
  1000. cgm.runtimeInChunks = new Set();
  1001. }
  1002. cgm.runtimeInChunks.add(chunk);
  1003. cgc.runtimeModules.add(module);
  1004. }
  1005. /**
  1006. * @param {Chunk} chunk the new chunk
  1007. * @param {RuntimeModule} module the module that require a full hash
  1008. * @returns {void}
  1009. */
  1010. addFullHashModuleToChunk(chunk, module) {
  1011. const cgc = this._getChunkGraphChunk(chunk);
  1012. if (cgc.fullHashModules === undefined) cgc.fullHashModules = new Set();
  1013. cgc.fullHashModules.add(module);
  1014. }
  1015. /**
  1016. * @param {Chunk} chunk the new chunk
  1017. * @param {RuntimeModule} module the module that require a full hash
  1018. * @returns {void}
  1019. */
  1020. addDependentHashModuleToChunk(chunk, module) {
  1021. const cgc = this._getChunkGraphChunk(chunk);
  1022. if (cgc.dependentHashModules === undefined)
  1023. cgc.dependentHashModules = new Set();
  1024. cgc.dependentHashModules.add(module);
  1025. }
  1026. /**
  1027. * @param {Chunk} chunk the new chunk
  1028. * @param {Module} module the entry module
  1029. * @returns {void}
  1030. */
  1031. disconnectChunkAndEntryModule(chunk, module) {
  1032. const cgm = this._getChunkGraphModule(module);
  1033. const cgc = this._getChunkGraphChunk(chunk);
  1034. /** @type {EntryInChunks} */
  1035. (cgm.entryInChunks).delete(chunk);
  1036. if (/** @type {EntryInChunks} */ (cgm.entryInChunks).size === 0) {
  1037. cgm.entryInChunks = undefined;
  1038. }
  1039. cgc.entryModules.delete(module);
  1040. }
  1041. /**
  1042. * @param {Chunk} chunk the new chunk
  1043. * @param {RuntimeModule} module the runtime module
  1044. * @returns {void}
  1045. */
  1046. disconnectChunkAndRuntimeModule(chunk, module) {
  1047. const cgm = this._getChunkGraphModule(module);
  1048. const cgc = this._getChunkGraphChunk(chunk);
  1049. /** @type {RuntimeInChunks} */
  1050. (cgm.runtimeInChunks).delete(chunk);
  1051. if (/** @type {RuntimeInChunks} */ (cgm.runtimeInChunks).size === 0) {
  1052. cgm.runtimeInChunks = undefined;
  1053. }
  1054. cgc.runtimeModules.delete(module);
  1055. }
  1056. /**
  1057. * @param {Module} module the entry module, it will no longer be entry
  1058. * @returns {void}
  1059. */
  1060. disconnectEntryModule(module) {
  1061. const cgm = this._getChunkGraphModule(module);
  1062. for (const chunk of /** @type {EntryInChunks} */ (cgm.entryInChunks)) {
  1063. const cgc = this._getChunkGraphChunk(chunk);
  1064. cgc.entryModules.delete(module);
  1065. }
  1066. cgm.entryInChunks = undefined;
  1067. }
  1068. /**
  1069. * @param {Chunk} chunk the chunk, for which all entries will be removed
  1070. * @returns {void}
  1071. */
  1072. disconnectEntries(chunk) {
  1073. const cgc = this._getChunkGraphChunk(chunk);
  1074. for (const module of cgc.entryModules.keys()) {
  1075. const cgm = this._getChunkGraphModule(module);
  1076. /** @type {EntryInChunks} */
  1077. (cgm.entryInChunks).delete(chunk);
  1078. if (/** @type {EntryInChunks} */ (cgm.entryInChunks).size === 0) {
  1079. cgm.entryInChunks = undefined;
  1080. }
  1081. }
  1082. cgc.entryModules.clear();
  1083. }
  1084. /**
  1085. * @param {Chunk} chunk the chunk
  1086. * @returns {number} the amount of entry modules in chunk
  1087. */
  1088. getNumberOfEntryModules(chunk) {
  1089. const cgc = this._getChunkGraphChunk(chunk);
  1090. return cgc.entryModules.size;
  1091. }
  1092. /**
  1093. * @param {Chunk} chunk the chunk
  1094. * @returns {number} the amount of entry modules in chunk
  1095. */
  1096. getNumberOfRuntimeModules(chunk) {
  1097. const cgc = this._getChunkGraphChunk(chunk);
  1098. return cgc.runtimeModules.size;
  1099. }
  1100. /**
  1101. * @param {Chunk} chunk the chunk
  1102. * @returns {Iterable<Module>} iterable of modules (do not modify)
  1103. */
  1104. getChunkEntryModulesIterable(chunk) {
  1105. const cgc = this._getChunkGraphChunk(chunk);
  1106. return cgc.entryModules.keys();
  1107. }
  1108. /**
  1109. * @param {Chunk} chunk the chunk
  1110. * @returns {Iterable<Chunk>} iterable of chunks
  1111. */
  1112. getChunkEntryDependentChunksIterable(chunk) {
  1113. /** @type {Set<Chunk>} */
  1114. const set = new Set();
  1115. for (const chunkGroup of chunk.groupsIterable) {
  1116. if (chunkGroup instanceof Entrypoint) {
  1117. const entrypointChunk = chunkGroup.getEntrypointChunk();
  1118. const cgc = this._getChunkGraphChunk(entrypointChunk);
  1119. for (const chunkGroup of cgc.entryModules.values()) {
  1120. for (const c of chunkGroup.chunks) {
  1121. if (c !== chunk && c !== entrypointChunk && !c.hasRuntime()) {
  1122. set.add(c);
  1123. }
  1124. }
  1125. }
  1126. }
  1127. }
  1128. return set;
  1129. }
  1130. /**
  1131. * @param {Chunk} chunk the chunk
  1132. * @returns {boolean} true, when it has dependent chunks
  1133. */
  1134. hasChunkEntryDependentChunks(chunk) {
  1135. const cgc = this._getChunkGraphChunk(chunk);
  1136. for (const chunkGroup of cgc.entryModules.values()) {
  1137. for (const c of chunkGroup.chunks) {
  1138. if (c !== chunk) {
  1139. return true;
  1140. }
  1141. }
  1142. }
  1143. return false;
  1144. }
  1145. /**
  1146. * @param {Chunk} chunk the chunk
  1147. * @returns {Iterable<RuntimeModule>} iterable of modules (do not modify)
  1148. */
  1149. getChunkRuntimeModulesIterable(chunk) {
  1150. const cgc = this._getChunkGraphChunk(chunk);
  1151. return cgc.runtimeModules;
  1152. }
  1153. /**
  1154. * @param {Chunk} chunk the chunk
  1155. * @returns {RuntimeModule[]} array of modules in order of execution
  1156. */
  1157. getChunkRuntimeModulesInOrder(chunk) {
  1158. const cgc = this._getChunkGraphChunk(chunk);
  1159. const array = Array.from(cgc.runtimeModules);
  1160. array.sort(
  1161. concatComparators(
  1162. compareSelect(r => /** @type {RuntimeModule} */ (r).stage, compareIds),
  1163. compareModulesByIdentifier
  1164. )
  1165. );
  1166. return array;
  1167. }
  1168. /**
  1169. * @param {Chunk} chunk the chunk
  1170. * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify)
  1171. */
  1172. getChunkFullHashModulesIterable(chunk) {
  1173. const cgc = this._getChunkGraphChunk(chunk);
  1174. return cgc.fullHashModules;
  1175. }
  1176. /**
  1177. * @param {Chunk} chunk the chunk
  1178. * @returns {ReadonlySet<RuntimeModule> | undefined} set of modules (do not modify)
  1179. */
  1180. getChunkFullHashModulesSet(chunk) {
  1181. const cgc = this._getChunkGraphChunk(chunk);
  1182. return cgc.fullHashModules;
  1183. }
  1184. /**
  1185. * @param {Chunk} chunk the chunk
  1186. * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify)
  1187. */
  1188. getChunkDependentHashModulesIterable(chunk) {
  1189. const cgc = this._getChunkGraphChunk(chunk);
  1190. return cgc.dependentHashModules;
  1191. }
  1192. /**
  1193. * @param {Chunk} chunk the chunk
  1194. * @returns {Iterable<EntryModuleWithChunkGroup>} iterable of modules (do not modify)
  1195. */
  1196. getChunkEntryModulesWithChunkGroupIterable(chunk) {
  1197. const cgc = this._getChunkGraphChunk(chunk);
  1198. return cgc.entryModules;
  1199. }
  1200. /**
  1201. * @param {AsyncDependenciesBlock} depBlock the async block
  1202. * @returns {ChunkGroup | undefined} the chunk group
  1203. */
  1204. getBlockChunkGroup(depBlock) {
  1205. return this._blockChunkGroups.get(depBlock);
  1206. }
  1207. /**
  1208. * @param {AsyncDependenciesBlock} depBlock the async block
  1209. * @param {ChunkGroup} chunkGroup the chunk group
  1210. * @returns {void}
  1211. */
  1212. connectBlockAndChunkGroup(depBlock, chunkGroup) {
  1213. this._blockChunkGroups.set(depBlock, chunkGroup);
  1214. chunkGroup.addBlock(depBlock);
  1215. }
  1216. /**
  1217. * @param {ChunkGroup} chunkGroup the chunk group
  1218. * @returns {void}
  1219. */
  1220. disconnectChunkGroup(chunkGroup) {
  1221. for (const block of chunkGroup.blocksIterable) {
  1222. this._blockChunkGroups.delete(block);
  1223. }
  1224. // TODO refactor by moving blocks list into ChunkGraph
  1225. chunkGroup._blocks.clear();
  1226. }
  1227. /**
  1228. * @param {Module} module the module
  1229. * @returns {ModuleId | null} the id of the module
  1230. */
  1231. getModuleId(module) {
  1232. const cgm = this._getChunkGraphModule(module);
  1233. return cgm.id;
  1234. }
  1235. /**
  1236. * @param {Module} module the module
  1237. * @param {ModuleId} id the id of the module
  1238. * @returns {void}
  1239. */
  1240. setModuleId(module, id) {
  1241. const cgm = this._getChunkGraphModule(module);
  1242. cgm.id = id;
  1243. }
  1244. /**
  1245. * @param {string} runtime runtime
  1246. * @returns {string | number} the id of the runtime
  1247. */
  1248. getRuntimeId(runtime) {
  1249. return /** @type {string | number} */ (this._runtimeIds.get(runtime));
  1250. }
  1251. /**
  1252. * @param {string} runtime runtime
  1253. * @param {string | number} id the id of the runtime
  1254. * @returns {void}
  1255. */
  1256. setRuntimeId(runtime, id) {
  1257. this._runtimeIds.set(runtime, id);
  1258. }
  1259. /**
  1260. * @template T
  1261. * @param {Module} module the module
  1262. * @param {RuntimeSpecMap<T>} hashes hashes data
  1263. * @param {RuntimeSpec} runtime the runtime
  1264. * @returns {T} hash
  1265. */
  1266. _getModuleHashInfo(module, hashes, runtime) {
  1267. if (!hashes) {
  1268. throw new Error(
  1269. `Module ${module.identifier()} has no hash info for runtime ${runtimeToString(
  1270. runtime
  1271. )} (hashes not set at all)`
  1272. );
  1273. } else if (runtime === undefined) {
  1274. const hashInfoItems = new Set(hashes.values());
  1275. if (hashInfoItems.size !== 1) {
  1276. throw new Error(
  1277. `No unique hash info entry for unspecified runtime for ${module.identifier()} (existing runtimes: ${Array.from(
  1278. hashes.keys(),
  1279. r => runtimeToString(r)
  1280. ).join(", ")}).
  1281. Caller might not support runtime-dependent code generation (opt-out via optimization.usedExports: "global").`
  1282. );
  1283. }
  1284. return /** @type {T} */ (first(hashInfoItems));
  1285. } else {
  1286. const hashInfo = hashes.get(runtime);
  1287. if (!hashInfo) {
  1288. throw new Error(
  1289. `Module ${module.identifier()} has no hash info for runtime ${runtimeToString(
  1290. runtime
  1291. )} (available runtimes ${Array.from(
  1292. hashes.keys(),
  1293. runtimeToString
  1294. ).join(", ")})`
  1295. );
  1296. }
  1297. return hashInfo;
  1298. }
  1299. }
  1300. /**
  1301. * @param {Module} module the module
  1302. * @param {RuntimeSpec} runtime the runtime
  1303. * @returns {boolean} true, if the module has hashes for this runtime
  1304. */
  1305. hasModuleHashes(module, runtime) {
  1306. const cgm = this._getChunkGraphModule(module);
  1307. const hashes = /** @type {RuntimeSpecMap<ModuleHashInfo>} */ (cgm.hashes);
  1308. return hashes && hashes.has(runtime);
  1309. }
  1310. /**
  1311. * @param {Module} module the module
  1312. * @param {RuntimeSpec} runtime the runtime
  1313. * @returns {string} hash
  1314. */
  1315. getModuleHash(module, runtime) {
  1316. const cgm = this._getChunkGraphModule(module);
  1317. const hashes = /** @type {RuntimeSpecMap<ModuleHashInfo>} */ (cgm.hashes);
  1318. return this._getModuleHashInfo(module, hashes, runtime).hash;
  1319. }
  1320. /**
  1321. * @param {Module} module the module
  1322. * @param {RuntimeSpec} runtime the runtime
  1323. * @returns {string} hash
  1324. */
  1325. getRenderedModuleHash(module, runtime) {
  1326. const cgm = this._getChunkGraphModule(module);
  1327. const hashes = /** @type {RuntimeSpecMap<ModuleHashInfo>} */ (cgm.hashes);
  1328. return this._getModuleHashInfo(module, hashes, runtime).renderedHash;
  1329. }
  1330. /**
  1331. * @param {Module} module the module
  1332. * @param {RuntimeSpec} runtime the runtime
  1333. * @param {string} hash the full hash
  1334. * @param {string} renderedHash the shortened hash for rendering
  1335. * @returns {void}
  1336. */
  1337. setModuleHashes(module, runtime, hash, renderedHash) {
  1338. const cgm = this._getChunkGraphModule(module);
  1339. if (cgm.hashes === undefined) {
  1340. cgm.hashes = new RuntimeSpecMap();
  1341. }
  1342. cgm.hashes.set(runtime, new ModuleHashInfo(hash, renderedHash));
  1343. }
  1344. /**
  1345. * @param {Module} module the module
  1346. * @param {RuntimeSpec} runtime the runtime
  1347. * @param {Set<string>} items runtime requirements to be added (ownership of this Set is given to ChunkGraph when transferOwnership not false)
  1348. * @param {boolean} transferOwnership true: transfer ownership of the items object, false: items is immutable and shared and won't be modified
  1349. * @returns {void}
  1350. */
  1351. addModuleRuntimeRequirements(
  1352. module,
  1353. runtime,
  1354. items,
  1355. transferOwnership = true
  1356. ) {
  1357. const cgm = this._getChunkGraphModule(module);
  1358. const runtimeRequirementsMap = cgm.runtimeRequirements;
  1359. if (runtimeRequirementsMap === undefined) {
  1360. const map = new RuntimeSpecMap();
  1361. // TODO avoid cloning item and track ownership instead
  1362. map.set(runtime, transferOwnership ? items : new Set(items));
  1363. cgm.runtimeRequirements = map;
  1364. return;
  1365. }
  1366. runtimeRequirementsMap.update(runtime, runtimeRequirements => {
  1367. if (runtimeRequirements === undefined) {
  1368. return transferOwnership ? items : new Set(items);
  1369. } else if (!transferOwnership || runtimeRequirements.size >= items.size) {
  1370. for (const item of items) runtimeRequirements.add(item);
  1371. return runtimeRequirements;
  1372. }
  1373. for (const item of runtimeRequirements) items.add(item);
  1374. return items;
  1375. });
  1376. }
  1377. /**
  1378. * @param {Chunk} chunk the chunk
  1379. * @param {Set<string>} items runtime requirements to be added (ownership of this Set is given to ChunkGraph)
  1380. * @returns {void}
  1381. */
  1382. addChunkRuntimeRequirements(chunk, items) {
  1383. const cgc = this._getChunkGraphChunk(chunk);
  1384. const runtimeRequirements = cgc.runtimeRequirements;
  1385. if (runtimeRequirements === undefined) {
  1386. cgc.runtimeRequirements = items;
  1387. } else if (runtimeRequirements.size >= items.size) {
  1388. for (const item of items) runtimeRequirements.add(item);
  1389. } else {
  1390. for (const item of runtimeRequirements) items.add(item);
  1391. cgc.runtimeRequirements = items;
  1392. }
  1393. }
  1394. /**
  1395. * @param {Chunk} chunk the chunk
  1396. * @param {Iterable<string>} items runtime requirements to be added
  1397. * @returns {void}
  1398. */
  1399. addTreeRuntimeRequirements(chunk, items) {
  1400. const cgc = this._getChunkGraphChunk(chunk);
  1401. const runtimeRequirements = cgc.runtimeRequirementsInTree;
  1402. for (const item of items) runtimeRequirements.add(item);
  1403. }
  1404. /**
  1405. * @param {Module} module the module
  1406. * @param {RuntimeSpec} runtime the runtime
  1407. * @returns {ReadOnlyRuntimeRequirements} runtime requirements
  1408. */
  1409. getModuleRuntimeRequirements(module, runtime) {
  1410. const cgm = this._getChunkGraphModule(module);
  1411. const runtimeRequirements =
  1412. cgm.runtimeRequirements && cgm.runtimeRequirements.get(runtime);
  1413. return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements;
  1414. }
  1415. /**
  1416. * @param {Chunk} chunk the chunk
  1417. * @returns {ReadOnlyRuntimeRequirements} runtime requirements
  1418. */
  1419. getChunkRuntimeRequirements(chunk) {
  1420. const cgc = this._getChunkGraphChunk(chunk);
  1421. const runtimeRequirements = cgc.runtimeRequirements;
  1422. return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements;
  1423. }
  1424. /**
  1425. * @param {Module} module the module
  1426. * @param {RuntimeSpec} runtime the runtime
  1427. * @param {boolean} withConnections include connections
  1428. * @returns {string} hash
  1429. */
  1430. getModuleGraphHash(module, runtime, withConnections = true) {
  1431. const cgm = this._getChunkGraphModule(module);
  1432. return withConnections
  1433. ? this._getModuleGraphHashWithConnections(cgm, module, runtime)
  1434. : this._getModuleGraphHashBigInt(cgm, module, runtime).toString(16);
  1435. }
  1436. /**
  1437. * @param {Module} module the module
  1438. * @param {RuntimeSpec} runtime the runtime
  1439. * @param {boolean} withConnections include connections
  1440. * @returns {bigint} hash
  1441. */
  1442. getModuleGraphHashBigInt(module, runtime, withConnections = true) {
  1443. const cgm = this._getChunkGraphModule(module);
  1444. return withConnections
  1445. ? BigInt(
  1446. `0x${this._getModuleGraphHashWithConnections(cgm, module, runtime)}`
  1447. )
  1448. : this._getModuleGraphHashBigInt(cgm, module, runtime);
  1449. }
  1450. /**
  1451. * @param {ChunkGraphModule} cgm the ChunkGraphModule
  1452. * @param {Module} module the module
  1453. * @param {RuntimeSpec} runtime the runtime
  1454. * @returns {bigint} hash as big int
  1455. */
  1456. _getModuleGraphHashBigInt(cgm, module, runtime) {
  1457. if (cgm.graphHashes === undefined) {
  1458. cgm.graphHashes = new RuntimeSpecMap();
  1459. }
  1460. const graphHash = cgm.graphHashes.provide(runtime, () => {
  1461. const hash = createHash(this._hashFunction);
  1462. hash.update(`${cgm.id}${this.moduleGraph.isAsync(module)}`);
  1463. const sourceTypes = this._getOverwrittenModuleSourceTypes(module);
  1464. if (sourceTypes !== undefined) {
  1465. for (const type of sourceTypes) hash.update(type);
  1466. }
  1467. this.moduleGraph.getExportsInfo(module).updateHash(hash, runtime);
  1468. return BigInt(`0x${/** @type {string} */ (hash.digest("hex"))}`);
  1469. });
  1470. return graphHash;
  1471. }
  1472. /**
  1473. * @param {ChunkGraphModule} cgm the ChunkGraphModule
  1474. * @param {Module} module the module
  1475. * @param {RuntimeSpec} runtime the runtime
  1476. * @returns {string} hash
  1477. */
  1478. _getModuleGraphHashWithConnections(cgm, module, runtime) {
  1479. if (cgm.graphHashesWithConnections === undefined) {
  1480. cgm.graphHashesWithConnections = new RuntimeSpecMap();
  1481. }
  1482. /**
  1483. * @param {ConnectionState} state state
  1484. * @returns {"F" | "T" | "O"} result
  1485. */
  1486. const activeStateToString = state => {
  1487. if (state === false) return "F";
  1488. if (state === true) return "T";
  1489. if (state === ModuleGraphConnection.TRANSITIVE_ONLY) return "O";
  1490. throw new Error("Not implemented active state");
  1491. };
  1492. const strict = module.buildMeta && module.buildMeta.strictHarmonyModule;
  1493. return cgm.graphHashesWithConnections.provide(runtime, () => {
  1494. const graphHash = this._getModuleGraphHashBigInt(
  1495. cgm,
  1496. module,
  1497. runtime
  1498. ).toString(16);
  1499. const connections = this.moduleGraph.getOutgoingConnections(module);
  1500. /** @type {Set<Module>} */
  1501. const activeNamespaceModules = new Set();
  1502. /** @type {Map<string, Module | Set<Module>>} */
  1503. const connectedModules = new Map();
  1504. /**
  1505. * @param {ModuleGraphConnection} connection connection
  1506. * @param {string} stateInfo state info
  1507. */
  1508. const processConnection = (connection, stateInfo) => {
  1509. const module = connection.module;
  1510. stateInfo += module.getExportsType(this.moduleGraph, strict);
  1511. // cspell:word Tnamespace
  1512. if (stateInfo === "Tnamespace") activeNamespaceModules.add(module);
  1513. else {
  1514. const oldModule = connectedModules.get(stateInfo);
  1515. if (oldModule === undefined) {
  1516. connectedModules.set(stateInfo, module);
  1517. } else if (oldModule instanceof Set) {
  1518. oldModule.add(module);
  1519. } else if (oldModule !== module) {
  1520. connectedModules.set(stateInfo, new Set([oldModule, module]));
  1521. }
  1522. }
  1523. };
  1524. if (runtime === undefined || typeof runtime === "string") {
  1525. for (const connection of connections) {
  1526. const state = connection.getActiveState(runtime);
  1527. if (state === false) continue;
  1528. processConnection(connection, state === true ? "T" : "O");
  1529. }
  1530. } else {
  1531. // cspell:word Tnamespace
  1532. for (const connection of connections) {
  1533. const states = new Set();
  1534. let stateInfo = "";
  1535. forEachRuntime(
  1536. runtime,
  1537. runtime => {
  1538. const state = connection.getActiveState(runtime);
  1539. states.add(state);
  1540. stateInfo += activeStateToString(state) + runtime;
  1541. },
  1542. true
  1543. );
  1544. if (states.size === 1) {
  1545. const state = first(states);
  1546. if (state === false) continue;
  1547. stateInfo = activeStateToString(state);
  1548. }
  1549. processConnection(connection, stateInfo);
  1550. }
  1551. }
  1552. // cspell:word Tnamespace
  1553. if (activeNamespaceModules.size === 0 && connectedModules.size === 0)
  1554. return graphHash;
  1555. const connectedModulesInOrder =
  1556. connectedModules.size > 1
  1557. ? Array.from(connectedModules).sort(([a], [b]) => (a < b ? -1 : 1))
  1558. : connectedModules;
  1559. const hash = createHash(this._hashFunction);
  1560. /**
  1561. * @param {Module} module module
  1562. */
  1563. const addModuleToHash = module => {
  1564. hash.update(
  1565. this._getModuleGraphHashBigInt(
  1566. this._getChunkGraphModule(module),
  1567. module,
  1568. runtime
  1569. ).toString(16)
  1570. );
  1571. };
  1572. /**
  1573. * @param {Set<Module>} modules modules
  1574. */
  1575. const addModulesToHash = modules => {
  1576. let xor = ZERO_BIG_INT;
  1577. for (const m of modules) {
  1578. xor =
  1579. xor ^
  1580. this._getModuleGraphHashBigInt(
  1581. this._getChunkGraphModule(m),
  1582. m,
  1583. runtime
  1584. );
  1585. }
  1586. hash.update(xor.toString(16));
  1587. };
  1588. if (activeNamespaceModules.size === 1)
  1589. addModuleToHash(
  1590. /** @type {Module} */ (activeNamespaceModules.values().next().value)
  1591. );
  1592. else if (activeNamespaceModules.size > 1)
  1593. addModulesToHash(activeNamespaceModules);
  1594. for (const [stateInfo, modules] of connectedModulesInOrder) {
  1595. hash.update(stateInfo);
  1596. if (modules instanceof Set) {
  1597. addModulesToHash(modules);
  1598. } else {
  1599. addModuleToHash(modules);
  1600. }
  1601. }
  1602. hash.update(graphHash);
  1603. return /** @type {string} */ (hash.digest("hex"));
  1604. });
  1605. }
  1606. /**
  1607. * @param {Chunk} chunk the chunk
  1608. * @returns {ReadOnlyRuntimeRequirements} runtime requirements
  1609. */
  1610. getTreeRuntimeRequirements(chunk) {
  1611. const cgc = this._getChunkGraphChunk(chunk);
  1612. return cgc.runtimeRequirementsInTree;
  1613. }
  1614. // TODO remove in webpack 6
  1615. /**
  1616. * @param {Module} module the module
  1617. * @param {string} deprecateMessage message for the deprecation message
  1618. * @param {string} deprecationCode code for the deprecation
  1619. * @returns {ChunkGraph} the chunk graph
  1620. */
  1621. static getChunkGraphForModule(module, deprecateMessage, deprecationCode) {
  1622. const fn = deprecateGetChunkGraphForModuleMap.get(deprecateMessage);
  1623. if (fn) return fn(module);
  1624. const newFn = util.deprecate(
  1625. /**
  1626. * @param {Module} module the module
  1627. * @returns {ChunkGraph} the chunk graph
  1628. */
  1629. module => {
  1630. const chunkGraph = chunkGraphForModuleMap.get(module);
  1631. if (!chunkGraph)
  1632. throw new Error(
  1633. `${
  1634. deprecateMessage
  1635. }: There was no ChunkGraph assigned to the Module for backward-compat (Use the new API)`
  1636. );
  1637. return chunkGraph;
  1638. },
  1639. `${deprecateMessage}: Use new ChunkGraph API`,
  1640. deprecationCode
  1641. );
  1642. deprecateGetChunkGraphForModuleMap.set(deprecateMessage, newFn);
  1643. return newFn(module);
  1644. }
  1645. // TODO remove in webpack 6
  1646. /**
  1647. * @param {Module} module the module
  1648. * @param {ChunkGraph} chunkGraph the chunk graph
  1649. * @returns {void}
  1650. */
  1651. static setChunkGraphForModule(module, chunkGraph) {
  1652. chunkGraphForModuleMap.set(module, chunkGraph);
  1653. }
  1654. // TODO remove in webpack 6
  1655. /**
  1656. * @param {Module} module the module
  1657. * @returns {void}
  1658. */
  1659. static clearChunkGraphForModule(module) {
  1660. chunkGraphForModuleMap.delete(module);
  1661. }
  1662. // TODO remove in webpack 6
  1663. /**
  1664. * @param {Chunk} chunk the chunk
  1665. * @param {string} deprecateMessage message for the deprecation message
  1666. * @param {string} deprecationCode code for the deprecation
  1667. * @returns {ChunkGraph} the chunk graph
  1668. */
  1669. static getChunkGraphForChunk(chunk, deprecateMessage, deprecationCode) {
  1670. const fn = deprecateGetChunkGraphForChunkMap.get(deprecateMessage);
  1671. if (fn) return fn(chunk);
  1672. const newFn = util.deprecate(
  1673. /**
  1674. * @param {Chunk} chunk the chunk
  1675. * @returns {ChunkGraph} the chunk graph
  1676. */
  1677. chunk => {
  1678. const chunkGraph = chunkGraphForChunkMap.get(chunk);
  1679. if (!chunkGraph)
  1680. throw new Error(
  1681. `${
  1682. deprecateMessage
  1683. }There was no ChunkGraph assigned to the Chunk for backward-compat (Use the new API)`
  1684. );
  1685. return chunkGraph;
  1686. },
  1687. `${deprecateMessage}: Use new ChunkGraph API`,
  1688. deprecationCode
  1689. );
  1690. deprecateGetChunkGraphForChunkMap.set(deprecateMessage, newFn);
  1691. return newFn(chunk);
  1692. }
  1693. // TODO remove in webpack 6
  1694. /**
  1695. * @param {Chunk} chunk the chunk
  1696. * @param {ChunkGraph} chunkGraph the chunk graph
  1697. * @returns {void}
  1698. */
  1699. static setChunkGraphForChunk(chunk, chunkGraph) {
  1700. chunkGraphForChunkMap.set(chunk, chunkGraph);
  1701. }
  1702. // TODO remove in webpack 6
  1703. /**
  1704. * @param {Chunk} chunk the chunk
  1705. * @returns {void}
  1706. */
  1707. static clearChunkGraphForChunk(chunk) {
  1708. chunkGraphForChunkMap.delete(chunk);
  1709. }
  1710. }
  1711. // TODO remove in webpack 6
  1712. /** @type {WeakMap<Module, ChunkGraph>} */
  1713. const chunkGraphForModuleMap = new WeakMap();
  1714. // TODO remove in webpack 6
  1715. /** @type {WeakMap<Chunk, ChunkGraph>} */
  1716. const chunkGraphForChunkMap = new WeakMap();
  1717. // TODO remove in webpack 6
  1718. /** @type {Map<string, (module: Module) => ChunkGraph>} */
  1719. const deprecateGetChunkGraphForModuleMap = new Map();
  1720. // TODO remove in webpack 6
  1721. /** @type {Map<string, (chunk: Chunk) => ChunkGraph>} */
  1722. const deprecateGetChunkGraphForChunkMap = new Map();
  1723. module.exports = ChunkGraph;