提交学习笔记专用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1945 lines
56 KiB

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