Best JavaScript code snippet using wpt
ChunkGraph.js
Source:ChunkGraph.js
1/*2 MIT License http://www.opensource.org/licenses/mit-license.php3 Author Tobias Koppers @sokra4*/5"use strict";6const util = require("util");7const Entrypoint = require("./Entrypoint");8const ModuleGraphConnection = require("./ModuleGraphConnection");9const { first } = require("./util/SetHelpers");10const SortableSet = require("./util/SortableSet");11const {12 compareModulesById,13 compareIterables,14 compareModulesByIdentifier,15 concatComparators,16 compareSelect,17 compareIds18} = require("./util/comparators");19const createHash = require("./util/createHash");20const findGraphRoots = require("./util/findGraphRoots");21const {22 RuntimeSpecMap,23 RuntimeSpecSet,24 runtimeToString,25 mergeRuntime,26 forEachRuntime27} = require("./util/runtime");28/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */29/** @typedef {import("./Chunk")} Chunk */30/** @typedef {import("./ChunkGroup")} ChunkGroup */31/** @typedef {import("./Module")} Module */32/** @typedef {import("./ModuleGraph")} ModuleGraph */33/** @typedef {import("./RuntimeModule")} RuntimeModule */34/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */35/** @type {ReadonlySet<string>} */36const EMPTY_SET = new Set();37const ZERO_BIG_INT = BigInt(0);38const compareModuleIterables = compareIterables(compareModulesByIdentifier);39/** @typedef {(c: Chunk, chunkGraph: ChunkGraph) => boolean} ChunkFilterPredicate */40/** @typedef {(m: Module) => boolean} ModuleFilterPredicate */41/**42 * @typedef {Object} ChunkSizeOptions43 * @property {number=} chunkOverhead constant overhead for a chunk44 * @property {number=} entryChunkMultiplicator multiplicator for initial chunks45 */46class ModuleHashInfo {47 constructor(hash, renderedHash) {48 this.hash = hash;49 this.renderedHash = renderedHash;50 }51}52/** @template T @typedef {(set: SortableSet<T>) => T[]} SetToArrayFunction<T> */53/**54 * @template T55 * @param {SortableSet<T>} set the set56 * @returns {T[]} set as array57 */58const getArray = set => {59 return Array.from(set);60};61/**62 * @param {SortableSet<Chunk>} chunks the chunks63 * @returns {RuntimeSpecSet} runtimes64 */65const getModuleRuntimes = chunks => {66 const runtimes = new RuntimeSpecSet();67 for (const chunk of chunks) {68 runtimes.add(chunk.runtime);69 }70 return runtimes;71};72/**73 * @param {SortableSet<Module>} set the set74 * @returns {Map<string, SortableSet<Module>>} modules by source type75 */76const modulesBySourceType = set => {77 /** @type {Map<string, SortableSet<Module>>} */78 const map = new Map();79 for (const module of set) {80 for (const sourceType of module.getSourceTypes()) {81 let innerSet = map.get(sourceType);82 if (innerSet === undefined) {83 innerSet = new SortableSet();84 map.set(sourceType, innerSet);85 }86 innerSet.add(module);87 }88 }89 for (const [key, innerSet] of map) {90 // When all modules have the source type, we reuse the original SortableSet91 // to benefit from the shared cache (especially for sorting)92 if (innerSet.size === set.size) {93 map.set(key, set);94 }95 }96 return map;97};98/** @type {WeakMap<Function, any>} */99const createOrderedArrayFunctionMap = new WeakMap();100/**101 * @template T102 * @param {function(T, T): -1|0|1} comparator comparator function103 * @returns {SetToArrayFunction<T>} set as ordered array104 */105const createOrderedArrayFunction = comparator => {106 /** @type {SetToArrayFunction<T>} */107 let fn = createOrderedArrayFunctionMap.get(comparator);108 if (fn !== undefined) return fn;109 fn = set => {110 set.sortWith(comparator);111 return Array.from(set);112 };113 createOrderedArrayFunctionMap.set(comparator, fn);114 return fn;115};116/**117 * @param {Iterable<Module>} modules the modules to get the count/size of118 * @returns {number} the size of the modules119 */120const getModulesSize = modules => {121 let size = 0;122 for (const module of modules) {123 for (const type of module.getSourceTypes()) {124 size += module.size(type);125 }126 }127 return size;128};129/**130 * @param {Iterable<Module>} modules the sortable Set to get the size of131 * @returns {Record<string, number>} the sizes of the modules132 */133const getModulesSizes = modules => {134 let sizes = Object.create(null);135 for (const module of modules) {136 for (const type of module.getSourceTypes()) {137 sizes[type] = (sizes[type] || 0) + module.size(type);138 }139 }140 return sizes;141};142/**143 * @param {Chunk} a chunk144 * @param {Chunk} b chunk145 * @returns {boolean} true, if a is always a parent of b146 */147const isAvailableChunk = (a, b) => {148 const queue = new Set(b.groupsIterable);149 for (const chunkGroup of queue) {150 if (a.isInGroup(chunkGroup)) continue;151 if (chunkGroup.isInitial()) return false;152 for (const parent of chunkGroup.parentsIterable) {153 queue.add(parent);154 }155 }156 return true;157};158class ChunkGraphModule {159 constructor() {160 /** @type {SortableSet<Chunk>} */161 this.chunks = new SortableSet();162 /** @type {Set<Chunk> | undefined} */163 this.entryInChunks = undefined;164 /** @type {Set<Chunk> | undefined} */165 this.runtimeInChunks = undefined;166 /** @type {RuntimeSpecMap<ModuleHashInfo>} */167 this.hashes = undefined;168 /** @type {string | number} */169 this.id = null;170 /** @type {RuntimeSpecMap<Set<string>> | undefined} */171 this.runtimeRequirements = undefined;172 /** @type {RuntimeSpecMap<string>} */173 this.graphHashes = undefined;174 /** @type {RuntimeSpecMap<string>} */175 this.graphHashesWithConnections = undefined;176 }177}178class ChunkGraphChunk {179 constructor() {180 /** @type {SortableSet<Module>} */181 this.modules = new SortableSet();182 /** @type {Map<Module, Entrypoint>} */183 this.entryModules = new Map();184 /** @type {SortableSet<RuntimeModule>} */185 this.runtimeModules = new SortableSet();186 /** @type {Set<RuntimeModule> | undefined} */187 this.fullHashModules = undefined;188 /** @type {Set<string> | undefined} */189 this.runtimeRequirements = undefined;190 /** @type {Set<string>} */191 this.runtimeRequirementsInTree = new Set();192 }193}194class ChunkGraph {195 /**196 * @param {ModuleGraph} moduleGraph the module graph197 */198 constructor(moduleGraph) {199 /** @private @type {WeakMap<Module, ChunkGraphModule>} */200 this._modules = new WeakMap();201 /** @private @type {WeakMap<Chunk, ChunkGraphChunk>} */202 this._chunks = new WeakMap();203 /** @private @type {WeakMap<AsyncDependenciesBlock, ChunkGroup>} */204 this._blockChunkGroups = new WeakMap();205 /** @private @type {Map<string, string | number>} */206 this._runtimeIds = new Map();207 /** @type {ModuleGraph} */208 this.moduleGraph = moduleGraph;209 this._getGraphRoots = this._getGraphRoots.bind(this);210 // Caching211 this._cacheChunkGraphModuleKey1 = undefined;212 this._cacheChunkGraphModuleValue1 = undefined;213 this._cacheChunkGraphModuleKey2 = undefined;214 this._cacheChunkGraphModuleValue2 = undefined;215 this._cacheChunkGraphChunkKey1 = undefined;216 this._cacheChunkGraphChunkValue1 = undefined;217 this._cacheChunkGraphChunkKey2 = undefined;218 this._cacheChunkGraphChunkValue2 = undefined;219 }220 /**221 * @private222 * @param {Module} module the module223 * @returns {ChunkGraphModule} internal module224 */225 _getChunkGraphModule(module) {226 if (this._cacheChunkGraphModuleKey1 === module)227 return this._cacheChunkGraphModuleValue1;228 if (this._cacheChunkGraphModuleKey2 === module)229 return this._cacheChunkGraphModuleValue2;230 let cgm = this._modules.get(module);231 if (cgm === undefined) {232 cgm = new ChunkGraphModule();233 this._modules.set(module, cgm);234 }235 this._cacheChunkGraphModuleKey2 = this._cacheChunkGraphModuleKey1;236 this._cacheChunkGraphModuleValue2 = this._cacheChunkGraphModuleValue1;237 this._cacheChunkGraphModuleKey1 = module;238 this._cacheChunkGraphModuleValue1 = cgm;239 return cgm;240 }241 /**242 * @private243 * @param {Chunk} chunk the chunk244 * @returns {ChunkGraphChunk} internal chunk245 */246 _getChunkGraphChunk(chunk) {247 if (this._cacheChunkGraphChunkKey1 === chunk)248 return this._cacheChunkGraphChunkValue1;249 if (this._cacheChunkGraphChunkKey2 === chunk)250 return this._cacheChunkGraphChunkValue2;251 let cgc = this._chunks.get(chunk);252 if (cgc === undefined) {253 cgc = new ChunkGraphChunk();254 this._chunks.set(chunk, cgc);255 }256 this._cacheChunkGraphChunkKey2 = this._cacheChunkGraphChunkKey1;257 this._cacheChunkGraphChunkValue2 = this._cacheChunkGraphChunkValue1;258 this._cacheChunkGraphChunkKey1 = chunk;259 this._cacheChunkGraphChunkValue1 = cgc;260 return cgc;261 }262 /**263 * @param {SortableSet<Module>} set the sortable Set to get the roots of264 * @returns {Module[]} the graph roots265 */266 _getGraphRoots(set) {267 const { moduleGraph } = this;268 return Array.from(269 findGraphRoots(set, module => {270 /** @type {Set<Module>} */271 const set = new Set();272 const addDependencies = module => {273 for (const connection of moduleGraph.getOutgoingConnections(module)) {274 if (!connection.module) continue;275 const activeState = connection.getActiveState(undefined);276 if (activeState === false) continue;277 if (activeState === ModuleGraphConnection.TRANSITIVE_ONLY) {278 addDependencies(connection.module);279 continue;280 }281 set.add(connection.module);282 }283 };284 addDependencies(module);285 return set;286 })287 ).sort(compareModulesByIdentifier);288 }289 /**290 * @param {Chunk} chunk the new chunk291 * @param {Module} module the module292 * @returns {void}293 */294 connectChunkAndModule(chunk, module) {295 const cgm = this._getChunkGraphModule(module);296 const cgc = this._getChunkGraphChunk(chunk);297 cgm.chunks.add(chunk);298 cgc.modules.add(module);299 }300 /**301 * @param {Chunk} chunk the chunk302 * @param {Module} module the module303 * @returns {void}304 */305 disconnectChunkAndModule(chunk, module) {306 const cgm = this._getChunkGraphModule(module);307 const cgc = this._getChunkGraphChunk(chunk);308 cgc.modules.delete(module);309 cgm.chunks.delete(chunk);310 }311 /**312 * @param {Chunk} chunk the chunk which will be disconnected313 * @returns {void}314 */315 disconnectChunk(chunk) {316 const cgc = this._getChunkGraphChunk(chunk);317 for (const module of cgc.modules) {318 const cgm = this._getChunkGraphModule(module);319 cgm.chunks.delete(chunk);320 }321 cgc.modules.clear();322 chunk.disconnectFromGroups();323 ChunkGraph.clearChunkGraphForChunk(chunk);324 }325 /**326 * @param {Chunk} chunk the chunk327 * @param {Iterable<Module>} modules the modules328 * @returns {void}329 */330 attachModules(chunk, modules) {331 const cgc = this._getChunkGraphChunk(chunk);332 for (const module of modules) {333 cgc.modules.add(module);334 }335 }336 /**337 * @param {Chunk} chunk the chunk338 * @param {Iterable<RuntimeModule>} modules the runtime modules339 * @returns {void}340 */341 attachRuntimeModules(chunk, modules) {342 const cgc = this._getChunkGraphChunk(chunk);343 for (const module of modules) {344 cgc.runtimeModules.add(module);345 }346 }347 /**348 * @param {Chunk} chunk the chunk349 * @param {Iterable<RuntimeModule>} modules the modules that require a full hash350 * @returns {void}351 */352 attachFullHashModules(chunk, modules) {353 const cgc = this._getChunkGraphChunk(chunk);354 if (cgc.fullHashModules === undefined) cgc.fullHashModules = new Set();355 for (const module of modules) {356 cgc.fullHashModules.add(module);357 }358 }359 /**360 * @param {Module} oldModule the replaced module361 * @param {Module} newModule the replacing module362 * @returns {void}363 */364 replaceModule(oldModule, newModule) {365 const oldCgm = this._getChunkGraphModule(oldModule);366 const newCgm = this._getChunkGraphModule(newModule);367 for (const chunk of oldCgm.chunks) {368 const cgc = this._getChunkGraphChunk(chunk);369 cgc.modules.delete(oldModule);370 cgc.modules.add(newModule);371 newCgm.chunks.add(chunk);372 }373 oldCgm.chunks.clear();374 if (oldCgm.entryInChunks !== undefined) {375 if (newCgm.entryInChunks === undefined) {376 newCgm.entryInChunks = new Set();377 }378 for (const chunk of oldCgm.entryInChunks) {379 const cgc = this._getChunkGraphChunk(chunk);380 const old = cgc.entryModules.get(oldModule);381 /** @type {Map<Module, Entrypoint>} */382 const newEntryModules = new Map();383 for (const [m, cg] of cgc.entryModules) {384 if (m === oldModule) {385 newEntryModules.set(newModule, old);386 } else {387 newEntryModules.set(m, cg);388 }389 }390 cgc.entryModules = newEntryModules;391 newCgm.entryInChunks.add(chunk);392 }393 oldCgm.entryInChunks = undefined;394 }395 if (oldCgm.runtimeInChunks !== undefined) {396 if (newCgm.runtimeInChunks === undefined) {397 newCgm.runtimeInChunks = new Set();398 }399 for (const chunk of oldCgm.runtimeInChunks) {400 const cgc = this._getChunkGraphChunk(chunk);401 cgc.runtimeModules.delete(/** @type {RuntimeModule} */ (oldModule));402 cgc.runtimeModules.add(/** @type {RuntimeModule} */ (newModule));403 newCgm.runtimeInChunks.add(chunk);404 if (405 cgc.fullHashModules !== undefined &&406 cgc.fullHashModules.has(/** @type {RuntimeModule} */ (oldModule))407 ) {408 cgc.fullHashModules.delete(/** @type {RuntimeModule} */ (oldModule));409 cgc.fullHashModules.add(/** @type {RuntimeModule} */ (newModule));410 }411 }412 oldCgm.runtimeInChunks = undefined;413 }414 }415 /**416 * @param {Module} module the checked module417 * @param {Chunk} chunk the checked chunk418 * @returns {boolean} true, if the chunk contains the module419 */420 isModuleInChunk(module, chunk) {421 const cgc = this._getChunkGraphChunk(chunk);422 return cgc.modules.has(module);423 }424 /**425 * @param {Module} module the checked module426 * @param {ChunkGroup} chunkGroup the checked chunk group427 * @returns {boolean} true, if the chunk contains the module428 */429 isModuleInChunkGroup(module, chunkGroup) {430 for (const chunk of chunkGroup.chunks) {431 if (this.isModuleInChunk(module, chunk)) return true;432 }433 return false;434 }435 /**436 * @param {Module} module the checked module437 * @returns {boolean} true, if the module is entry of any chunk438 */439 isEntryModule(module) {440 const cgm = this._getChunkGraphModule(module);441 return cgm.entryInChunks !== undefined;442 }443 /**444 * @param {Module} module the module445 * @returns {Iterable<Chunk>} iterable of chunks (do not modify)446 */447 getModuleChunksIterable(module) {448 const cgm = this._getChunkGraphModule(module);449 return cgm.chunks;450 }451 /**452 * @param {Module} module the module453 * @param {function(Chunk, Chunk): -1|0|1} sortFn sort function454 * @returns {Iterable<Chunk>} iterable of chunks (do not modify)455 */456 getOrderedModuleChunksIterable(module, sortFn) {457 const cgm = this._getChunkGraphModule(module);458 cgm.chunks.sortWith(sortFn);459 return cgm.chunks;460 }461 /**462 * @param {Module} module the module463 * @returns {Chunk[]} array of chunks (cached, do not modify)464 */465 getModuleChunks(module) {466 const cgm = this._getChunkGraphModule(module);467 return cgm.chunks.getFromCache(getArray);468 }469 /**470 * @param {Module} module the module471 * @returns {number} the number of chunk which contain the module472 */473 getNumberOfModuleChunks(module) {474 const cgm = this._getChunkGraphModule(module);475 return cgm.chunks.size;476 }477 /**478 * @param {Module} module the module479 * @returns {RuntimeSpecSet} runtimes480 */481 getModuleRuntimes(module) {482 const cgm = this._getChunkGraphModule(module);483 return cgm.chunks.getFromUnorderedCache(getModuleRuntimes);484 }485 /**486 * @param {Chunk} chunk the chunk487 * @returns {number} the number of module which are contained in this chunk488 */489 getNumberOfChunkModules(chunk) {490 const cgc = this._getChunkGraphChunk(chunk);491 return cgc.modules.size;492 }493 /**494 * @param {Chunk} chunk the chunk495 * @returns {Iterable<Module>} return the modules for this chunk496 */497 getChunkModulesIterable(chunk) {498 const cgc = this._getChunkGraphChunk(chunk);499 return cgc.modules;500 }501 /**502 * @param {Chunk} chunk the chunk503 * @param {string} sourceType source type504 * @returns {Iterable<Module> | undefined} return the modules for this chunk505 */506 getChunkModulesIterableBySourceType(chunk, sourceType) {507 const cgc = this._getChunkGraphChunk(chunk);508 const modulesWithSourceType = cgc.modules509 .getFromUnorderedCache(modulesBySourceType)510 .get(sourceType);511 return modulesWithSourceType;512 }513 /**514 * @param {Chunk} chunk the chunk515 * @param {function(Module, Module): -1|0|1} comparator comparator function516 * @returns {Iterable<Module>} return the modules for this chunk517 */518 getOrderedChunkModulesIterable(chunk, comparator) {519 const cgc = this._getChunkGraphChunk(chunk);520 cgc.modules.sortWith(comparator);521 return cgc.modules;522 }523 /**524 * @param {Chunk} chunk the chunk525 * @param {string} sourceType source type526 * @param {function(Module, Module): -1|0|1} comparator comparator function527 * @returns {Iterable<Module> | undefined} return the modules for this chunk528 */529 getOrderedChunkModulesIterableBySourceType(chunk, sourceType, comparator) {530 const cgc = this._getChunkGraphChunk(chunk);531 const modulesWithSourceType = cgc.modules532 .getFromUnorderedCache(modulesBySourceType)533 .get(sourceType);534 if (modulesWithSourceType === undefined) return undefined;535 modulesWithSourceType.sortWith(comparator);536 return modulesWithSourceType;537 }538 /**539 * @param {Chunk} chunk the chunk540 * @returns {Module[]} return the modules for this chunk (cached, do not modify)541 */542 getChunkModules(chunk) {543 const cgc = this._getChunkGraphChunk(chunk);544 return cgc.modules.getFromUnorderedCache(getArray);545 }546 /**547 * @param {Chunk} chunk the chunk548 * @param {function(Module, Module): -1|0|1} comparator comparator function549 * @returns {Module[]} return the modules for this chunk (cached, do not modify)550 */551 getOrderedChunkModules(chunk, comparator) {552 const cgc = this._getChunkGraphChunk(chunk);553 const arrayFunction = createOrderedArrayFunction(comparator);554 return cgc.modules.getFromUnorderedCache(arrayFunction);555 }556 /**557 * @param {Chunk} chunk the chunk558 * @param {ModuleFilterPredicate} filterFn function used to filter modules559 * @param {boolean} includeAllChunks all chunks or only async chunks560 * @returns {Record<string|number, (string|number)[]>} chunk to module ids object561 */562 getChunkModuleIdMap(chunk, filterFn, includeAllChunks = false) {563 /** @type {Record<string|number, (string|number)[]>} */564 const chunkModuleIdMap = Object.create(null);565 for (const asyncChunk of includeAllChunks566 ? chunk.getAllReferencedChunks()567 : chunk.getAllAsyncChunks()) {568 /** @type {(string|number)[]} */569 let array;570 for (const module of this.getOrderedChunkModulesIterable(571 asyncChunk,572 compareModulesById(this)573 )) {574 if (filterFn(module)) {575 if (array === undefined) {576 array = [];577 chunkModuleIdMap[asyncChunk.id] = array;578 }579 const moduleId = this.getModuleId(module);580 array.push(moduleId);581 }582 }583 }584 return chunkModuleIdMap;585 }586 /**587 * @param {Chunk} chunk the chunk588 * @param {ModuleFilterPredicate} filterFn function used to filter modules589 * @param {number} hashLength length of the hash590 * @param {boolean} includeAllChunks all chunks or only async chunks591 * @returns {Record<string|number, Record<string|number, string>>} chunk to module id to module hash object592 */593 getChunkModuleRenderedHashMap(594 chunk,595 filterFn,596 hashLength = 0,597 includeAllChunks = false598 ) {599 /** @type {Record<string|number, Record<string|number, string>>} */600 const chunkModuleHashMap = Object.create(null);601 for (const asyncChunk of includeAllChunks602 ? chunk.getAllReferencedChunks()603 : chunk.getAllAsyncChunks()) {604 /** @type {Record<string|number, string>} */605 let idToHashMap;606 for (const module of this.getOrderedChunkModulesIterable(607 asyncChunk,608 compareModulesById(this)609 )) {610 if (filterFn(module)) {611 if (idToHashMap === undefined) {612 idToHashMap = Object.create(null);613 chunkModuleHashMap[asyncChunk.id] = idToHashMap;614 }615 const moduleId = this.getModuleId(module);616 const hash = this.getRenderedModuleHash(module, asyncChunk.runtime);617 idToHashMap[moduleId] = hashLength ? hash.slice(0, hashLength) : hash;618 }619 }620 }621 return chunkModuleHashMap;622 }623 /**624 * @param {Chunk} chunk the chunk625 * @param {ChunkFilterPredicate} filterFn function used to filter chunks626 * @returns {Record<string|number, boolean>} chunk map627 */628 getChunkConditionMap(chunk, filterFn) {629 const map = Object.create(null);630 for (const c of chunk.getAllReferencedChunks()) {631 map[c.id] = filterFn(c, this);632 }633 return map;634 }635 /**636 * @param {Chunk} chunk the chunk637 * @param {ModuleFilterPredicate} filterFn predicate function used to filter modules638 * @param {ChunkFilterPredicate=} filterChunkFn predicate function used to filter chunks639 * @returns {boolean} return true if module exists in graph640 */641 hasModuleInGraph(chunk, filterFn, filterChunkFn) {642 const queue = new Set(chunk.groupsIterable);643 const chunksProcessed = new Set();644 for (const chunkGroup of queue) {645 for (const innerChunk of chunkGroup.chunks) {646 if (!chunksProcessed.has(innerChunk)) {647 chunksProcessed.add(innerChunk);648 if (!filterChunkFn || filterChunkFn(innerChunk, this)) {649 for (const module of this.getChunkModulesIterable(innerChunk)) {650 if (filterFn(module)) {651 return true;652 }653 }654 }655 }656 }657 for (const child of chunkGroup.childrenIterable) {658 queue.add(child);659 }660 }661 return false;662 }663 /**664 * @param {Chunk} chunkA first chunk665 * @param {Chunk} chunkB second chunk666 * @returns {-1|0|1} this is a comparator function like sort and returns -1, 0, or 1 based on sort order667 */668 compareChunks(chunkA, chunkB) {669 const cgcA = this._getChunkGraphChunk(chunkA);670 const cgcB = this._getChunkGraphChunk(chunkB);671 if (cgcA.modules.size > cgcB.modules.size) return -1;672 if (cgcA.modules.size < cgcB.modules.size) return 1;673 cgcA.modules.sortWith(compareModulesByIdentifier);674 cgcB.modules.sortWith(compareModulesByIdentifier);675 return compareModuleIterables(cgcA.modules, cgcB.modules);676 }677 /**678 * @param {Chunk} chunk the chunk679 * @returns {number} total size of all modules in the chunk680 */681 getChunkModulesSize(chunk) {682 const cgc = this._getChunkGraphChunk(chunk);683 return cgc.modules.getFromUnorderedCache(getModulesSize);684 }685 /**686 * @param {Chunk} chunk the chunk687 * @returns {Record<string, number>} total sizes of all modules in the chunk by source type688 */689 getChunkModulesSizes(chunk) {690 const cgc = this._getChunkGraphChunk(chunk);691 return cgc.modules.getFromUnorderedCache(getModulesSizes);692 }693 /**694 * @param {Chunk} chunk the chunk695 * @returns {Module[]} root modules of the chunks (ordered by identifier)696 */697 getChunkRootModules(chunk) {698 const cgc = this._getChunkGraphChunk(chunk);699 return cgc.modules.getFromUnorderedCache(this._getGraphRoots);700 }701 /**702 * @param {Chunk} chunk the chunk703 * @param {ChunkSizeOptions} options options object704 * @returns {number} total size of the chunk705 */706 getChunkSize(chunk, options = {}) {707 const cgc = this._getChunkGraphChunk(chunk);708 const modulesSize = cgc.modules.getFromUnorderedCache(getModulesSize);709 const chunkOverhead =710 typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;711 const entryChunkMultiplicator =712 typeof options.entryChunkMultiplicator === "number"713 ? options.entryChunkMultiplicator714 : 10;715 return (716 chunkOverhead +717 modulesSize * (chunk.canBeInitial() ? entryChunkMultiplicator : 1)718 );719 }720 /**721 * @param {Chunk} chunkA chunk722 * @param {Chunk} chunkB chunk723 * @param {ChunkSizeOptions} options options object724 * @returns {number} total size of the chunk or false if chunks can't be integrated725 */726 getIntegratedChunksSize(chunkA, chunkB, options = {}) {727 const cgcA = this._getChunkGraphChunk(chunkA);728 const cgcB = this._getChunkGraphChunk(chunkB);729 const allModules = new Set(cgcA.modules);730 for (const m of cgcB.modules) allModules.add(m);731 let modulesSize = getModulesSize(allModules);732 const chunkOverhead =733 typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;734 const entryChunkMultiplicator =735 typeof options.entryChunkMultiplicator === "number"736 ? options.entryChunkMultiplicator737 : 10;738 return (739 chunkOverhead +740 modulesSize *741 (chunkA.canBeInitial() || chunkB.canBeInitial()742 ? entryChunkMultiplicator743 : 1)744 );745 }746 /**747 * @param {Chunk} chunkA chunk748 * @param {Chunk} chunkB chunk749 * @returns {boolean} true, if chunks could be integrated750 */751 canChunksBeIntegrated(chunkA, chunkB) {752 if (chunkA.preventIntegration || chunkB.preventIntegration) {753 return false;754 }755 const hasRuntimeA = chunkA.hasRuntime();756 const hasRuntimeB = chunkB.hasRuntime();757 if (hasRuntimeA !== hasRuntimeB) {758 if (hasRuntimeA) {759 return isAvailableChunk(chunkA, chunkB);760 } else if (hasRuntimeB) {761 return isAvailableChunk(chunkB, chunkA);762 } else {763 return false;764 }765 }766 if (767 this.getNumberOfEntryModules(chunkA) > 0 ||768 this.getNumberOfEntryModules(chunkB) > 0769 ) {770 return false;771 }772 return true;773 }774 /**775 * @param {Chunk} chunkA the target chunk776 * @param {Chunk} chunkB the chunk to integrate777 * @returns {void}778 */779 integrateChunks(chunkA, chunkB) {780 // Decide for one name (deterministic)781 if (chunkA.name && chunkB.name) {782 if (783 this.getNumberOfEntryModules(chunkA) > 0 ===784 this.getNumberOfEntryModules(chunkB) > 0785 ) {786 // When both chunks have entry modules or none have one, use787 // shortest name788 if (chunkA.name.length !== chunkB.name.length) {789 chunkA.name =790 chunkA.name.length < chunkB.name.length ? chunkA.name : chunkB.name;791 } else {792 chunkA.name = chunkA.name < chunkB.name ? chunkA.name : chunkB.name;793 }794 } else if (this.getNumberOfEntryModules(chunkB) > 0) {795 // Pick the name of the chunk with the entry module796 chunkA.name = chunkB.name;797 }798 } else if (chunkB.name) {799 chunkA.name = chunkB.name;800 }801 // Merge id name hints802 for (const hint of chunkB.idNameHints) {803 chunkA.idNameHints.add(hint);804 }805 // Merge runtime806 chunkA.runtime = mergeRuntime(chunkA.runtime, chunkB.runtime);807 // getChunkModules is used here to create a clone, because disconnectChunkAndModule modifies808 for (const module of this.getChunkModules(chunkB)) {809 this.disconnectChunkAndModule(chunkB, module);810 this.connectChunkAndModule(chunkA, module);811 }812 for (const [module, chunkGroup] of Array.from(813 this.getChunkEntryModulesWithChunkGroupIterable(chunkB)814 )) {815 this.disconnectChunkAndEntryModule(chunkB, module);816 this.connectChunkAndEntryModule(chunkA, module, chunkGroup);817 }818 for (const chunkGroup of chunkB.groupsIterable) {819 chunkGroup.replaceChunk(chunkB, chunkA);820 chunkA.addGroup(chunkGroup);821 chunkB.removeGroup(chunkGroup);822 }823 ChunkGraph.clearChunkGraphForChunk(chunkB);824 }825 /**826 * @param {Module} module the checked module827 * @param {Chunk} chunk the checked chunk828 * @returns {boolean} true, if the chunk contains the module as entry829 */830 isEntryModuleInChunk(module, chunk) {831 const cgc = this._getChunkGraphChunk(chunk);832 return cgc.entryModules.has(module);833 }834 /**835 * @param {Chunk} chunk the new chunk836 * @param {Module} module the entry module837 * @param {Entrypoint=} entrypoint the chunk group which must be loaded before the module is executed838 * @returns {void}839 */840 connectChunkAndEntryModule(chunk, module, entrypoint) {841 const cgm = this._getChunkGraphModule(module);842 const cgc = this._getChunkGraphChunk(chunk);843 if (cgm.entryInChunks === undefined) {844 cgm.entryInChunks = new Set();845 }846 cgm.entryInChunks.add(chunk);847 cgc.entryModules.set(module, entrypoint);848 }849 /**850 * @param {Chunk} chunk the new chunk851 * @param {RuntimeModule} module the runtime module852 * @returns {void}853 */854 connectChunkAndRuntimeModule(chunk, module) {855 const cgm = this._getChunkGraphModule(module);856 const cgc = this._getChunkGraphChunk(chunk);857 if (cgm.runtimeInChunks === undefined) {858 cgm.runtimeInChunks = new Set();859 }860 cgm.runtimeInChunks.add(chunk);861 cgc.runtimeModules.add(module);862 }863 /**864 * @param {Chunk} chunk the new chunk865 * @param {RuntimeModule} module the module that require a full hash866 * @returns {void}867 */868 addFullHashModuleToChunk(chunk, module) {869 const cgc = this._getChunkGraphChunk(chunk);870 if (cgc.fullHashModules === undefined) cgc.fullHashModules = new Set();871 cgc.fullHashModules.add(module);872 }873 /**874 * @param {Chunk} chunk the new chunk875 * @param {Module} module the entry module876 * @returns {void}877 */878 disconnectChunkAndEntryModule(chunk, module) {879 const cgm = this._getChunkGraphModule(module);880 const cgc = this._getChunkGraphChunk(chunk);881 cgm.entryInChunks.delete(chunk);882 if (cgm.entryInChunks.size === 0) {883 cgm.entryInChunks = undefined;884 }885 cgc.entryModules.delete(module);886 }887 /**888 * @param {Chunk} chunk the new chunk889 * @param {RuntimeModule} module the runtime module890 * @returns {void}891 */892 disconnectChunkAndRuntimeModule(chunk, module) {893 const cgm = this._getChunkGraphModule(module);894 const cgc = this._getChunkGraphChunk(chunk);895 cgm.runtimeInChunks.delete(chunk);896 if (cgm.runtimeInChunks.size === 0) {897 cgm.runtimeInChunks = undefined;898 }899 cgc.runtimeModules.delete(module);900 }901 /**902 * @param {Module} module the entry module, it will no longer be entry903 * @returns {void}904 */905 disconnectEntryModule(module) {906 const cgm = this._getChunkGraphModule(module);907 for (const chunk of cgm.entryInChunks) {908 const cgc = this._getChunkGraphChunk(chunk);909 cgc.entryModules.delete(module);910 }911 cgm.entryInChunks = undefined;912 }913 /**914 * @param {Chunk} chunk the chunk, for which all entries will be removed915 * @returns {void}916 */917 disconnectEntries(chunk) {918 const cgc = this._getChunkGraphChunk(chunk);919 for (const module of cgc.entryModules.keys()) {920 const cgm = this._getChunkGraphModule(module);921 cgm.entryInChunks.delete(chunk);922 if (cgm.entryInChunks.size === 0) {923 cgm.entryInChunks = undefined;924 }925 }926 cgc.entryModules.clear();927 }928 /**929 * @param {Chunk} chunk the chunk930 * @returns {number} the amount of entry modules in chunk931 */932 getNumberOfEntryModules(chunk) {933 const cgc = this._getChunkGraphChunk(chunk);934 return cgc.entryModules.size;935 }936 /**937 * @param {Chunk} chunk the chunk938 * @returns {number} the amount of entry modules in chunk939 */940 getNumberOfRuntimeModules(chunk) {941 const cgc = this._getChunkGraphChunk(chunk);942 return cgc.runtimeModules.size;943 }944 /**945 * @param {Chunk} chunk the chunk946 * @returns {Iterable<Module>} iterable of modules (do not modify)947 */948 getChunkEntryModulesIterable(chunk) {949 const cgc = this._getChunkGraphChunk(chunk);950 return cgc.entryModules.keys();951 }952 /**953 * @param {Chunk} chunk the chunk954 * @returns {Iterable<Chunk>} iterable of chunks955 */956 getChunkEntryDependentChunksIterable(chunk) {957 /** @type {Set<Chunk>} */958 const set = new Set();959 for (const chunkGroup of chunk.groupsIterable) {960 if (chunkGroup instanceof Entrypoint) {961 const entrypointChunk = chunkGroup.getEntrypointChunk();962 const cgc = this._getChunkGraphChunk(entrypointChunk);963 for (const chunkGroup of cgc.entryModules.values()) {964 for (const c of chunkGroup.chunks) {965 if (c !== chunk && c !== entrypointChunk && !c.hasRuntime()) {966 set.add(c);967 }968 }969 }970 }971 }972 return set;973 }974 /**975 * @param {Chunk} chunk the chunk976 * @returns {boolean} true, when it has dependent chunks977 */978 hasChunkEntryDependentChunks(chunk) {979 const cgc = this._getChunkGraphChunk(chunk);980 for (const chunkGroup of cgc.entryModules.values()) {981 for (const c of chunkGroup.chunks) {982 if (c !== chunk) {983 return true;984 }985 }986 }987 return false;988 }989 /**990 * @param {Chunk} chunk the chunk991 * @returns {Iterable<RuntimeModule>} iterable of modules (do not modify)992 */993 getChunkRuntimeModulesIterable(chunk) {994 const cgc = this._getChunkGraphChunk(chunk);995 return cgc.runtimeModules;996 }997 /**998 * @param {Chunk} chunk the chunk999 * @returns {RuntimeModule[]} array of modules in order of execution1000 */1001 getChunkRuntimeModulesInOrder(chunk) {1002 const cgc = this._getChunkGraphChunk(chunk);1003 const array = Array.from(cgc.runtimeModules);1004 array.sort(1005 concatComparators(1006 compareSelect(1007 /**1008 * @param {RuntimeModule} r runtime module1009 * @returns {number=} stage1010 */1011 r => r.stage,1012 compareIds1013 ),1014 compareModulesByIdentifier1015 )1016 );1017 return array;1018 }1019 /**1020 * @param {Chunk} chunk the chunk1021 * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify)1022 */1023 getChunkFullHashModulesIterable(chunk) {1024 const cgc = this._getChunkGraphChunk(chunk);1025 return cgc.fullHashModules;1026 }1027 /**1028 * @param {Chunk} chunk the chunk1029 * @returns {ReadonlySet<RuntimeModule> | undefined} set of modules (do not modify)1030 */1031 getChunkFullHashModulesSet(chunk) {1032 const cgc = this._getChunkGraphChunk(chunk);1033 return cgc.fullHashModules;1034 }1035 /** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */1036 /**1037 * @param {Chunk} chunk the chunk1038 * @returns {Iterable<EntryModuleWithChunkGroup>} iterable of modules (do not modify)1039 */1040 getChunkEntryModulesWithChunkGroupIterable(chunk) {1041 const cgc = this._getChunkGraphChunk(chunk);1042 return cgc.entryModules;1043 }1044 /**1045 * @param {AsyncDependenciesBlock} depBlock the async block1046 * @returns {ChunkGroup} the chunk group1047 */1048 getBlockChunkGroup(depBlock) {1049 return this._blockChunkGroups.get(depBlock);1050 }1051 /**1052 * @param {AsyncDependenciesBlock} depBlock the async block1053 * @param {ChunkGroup} chunkGroup the chunk group1054 * @returns {void}1055 */1056 connectBlockAndChunkGroup(depBlock, chunkGroup) {1057 this._blockChunkGroups.set(depBlock, chunkGroup);1058 chunkGroup.addBlock(depBlock);1059 }1060 /**1061 * @param {ChunkGroup} chunkGroup the chunk group1062 * @returns {void}1063 */1064 disconnectChunkGroup(chunkGroup) {1065 for (const block of chunkGroup.blocksIterable) {1066 this._blockChunkGroups.delete(block);1067 }1068 // TODO refactor by moving blocks list into ChunkGraph1069 chunkGroup._blocks.clear();1070 }1071 /**1072 * @param {Module} module the module1073 * @returns {string | number} the id of the module1074 */1075 getModuleId(module) {1076 const cgm = this._getChunkGraphModule(module);1077 return cgm.id;1078 }1079 /**1080 * @param {Module} module the module1081 * @param {string | number} id the id of the module1082 * @returns {void}1083 */1084 setModuleId(module, id) {1085 const cgm = this._getChunkGraphModule(module);1086 cgm.id = id;1087 }1088 /**1089 * @param {string} runtime runtime1090 * @returns {string | number} the id of the runtime1091 */1092 getRuntimeId(runtime) {1093 return this._runtimeIds.get(runtime);1094 }1095 /**1096 * @param {string} runtime runtime1097 * @param {string | number} id the id of the runtime1098 * @returns {void}1099 */1100 setRuntimeId(runtime, id) {1101 this._runtimeIds.set(runtime, id);1102 }1103 /**1104 * @template T1105 * @param {Module} module the module1106 * @param {RuntimeSpecMap<T>} hashes hashes data1107 * @param {RuntimeSpec} runtime the runtime1108 * @returns {T} hash1109 */1110 _getModuleHashInfo(module, hashes, runtime) {1111 if (!hashes) {1112 throw new Error(1113 `Module ${module.identifier()} has no hash info for runtime ${runtimeToString(1114 runtime1115 )} (hashes not set at all)`1116 );1117 } else if (runtime === undefined) {1118 const hashInfoItems = new Set(hashes.values());1119 if (hashInfoItems.size !== 1) {1120 throw new Error(1121 `No unique hash info entry for unspecified runtime for ${module.identifier()} (existing runtimes: ${Array.from(1122 hashes.keys(),1123 r => runtimeToString(r)1124 ).join(", ")}).1125Caller might not support runtime-dependent code generation (opt-out via optimization.usedExports: "global").`1126 );1127 }1128 return first(hashInfoItems);1129 } else {1130 const hashInfo = hashes.get(runtime);1131 if (!hashInfo) {1132 throw new Error(1133 `Module ${module.identifier()} has no hash info for runtime ${runtimeToString(1134 runtime1135 )} (available runtimes ${Array.from(1136 hashes.keys(),1137 runtimeToString1138 ).join(", ")})`1139 );1140 }1141 return hashInfo;1142 }1143 }1144 /**1145 * @param {Module} module the module1146 * @param {RuntimeSpec} runtime the runtime1147 * @returns {boolean} true, if the module has hashes for this runtime1148 */1149 hasModuleHashes(module, runtime) {1150 const cgm = this._getChunkGraphModule(module);1151 const hashes = cgm.hashes;1152 return hashes && hashes.has(runtime);1153 }1154 /**1155 * @param {Module} module the module1156 * @param {RuntimeSpec} runtime the runtime1157 * @returns {string} hash1158 */1159 getModuleHash(module, runtime) {1160 const cgm = this._getChunkGraphModule(module);1161 const hashes = cgm.hashes;1162 return this._getModuleHashInfo(module, hashes, runtime).hash;1163 }1164 /**1165 * @param {Module} module the module1166 * @param {RuntimeSpec} runtime the runtime1167 * @returns {string} hash1168 */1169 getRenderedModuleHash(module, runtime) {1170 const cgm = this._getChunkGraphModule(module);1171 const hashes = cgm.hashes;1172 return this._getModuleHashInfo(module, hashes, runtime).renderedHash;1173 }1174 /**1175 * @param {Module} module the module1176 * @param {RuntimeSpec} runtime the runtime1177 * @param {string} hash the full hash1178 * @param {string} renderedHash the shortened hash for rendering1179 * @returns {void}1180 */1181 setModuleHashes(module, runtime, hash, renderedHash) {1182 const cgm = this._getChunkGraphModule(module);1183 if (cgm.hashes === undefined) {1184 cgm.hashes = new RuntimeSpecMap();1185 }1186 cgm.hashes.set(runtime, new ModuleHashInfo(hash, renderedHash));1187 }1188 /**1189 * @param {Module} module the module1190 * @param {RuntimeSpec} runtime the runtime1191 * @param {Set<string>} items runtime requirements to be added (ownership of this Set is given to ChunkGraph)1192 * @returns {void}1193 */1194 addModuleRuntimeRequirements(module, runtime, items) {1195 const cgm = this._getChunkGraphModule(module);1196 const runtimeRequirementsMap = cgm.runtimeRequirements;1197 if (runtimeRequirementsMap === undefined) {1198 const map = new RuntimeSpecMap();1199 map.set(runtime, items);1200 cgm.runtimeRequirements = map;1201 return;1202 }1203 runtimeRequirementsMap.update(runtime, runtimeRequirements => {1204 if (runtimeRequirements === undefined) {1205 return items;1206 } else if (runtimeRequirements.size >= items.size) {1207 for (const item of items) runtimeRequirements.add(item);1208 return runtimeRequirements;1209 } else {1210 for (const item of runtimeRequirements) items.add(item);1211 return items;1212 }1213 });1214 }1215 /**1216 * @param {Chunk} chunk the chunk1217 * @param {Set<string>} items runtime requirements to be added (ownership of this Set is given to ChunkGraph)1218 * @returns {void}1219 */1220 addChunkRuntimeRequirements(chunk, items) {1221 const cgc = this._getChunkGraphChunk(chunk);1222 const runtimeRequirements = cgc.runtimeRequirements;1223 if (runtimeRequirements === undefined) {1224 cgc.runtimeRequirements = items;1225 } else if (runtimeRequirements.size >= items.size) {1226 for (const item of items) runtimeRequirements.add(item);1227 } else {1228 for (const item of runtimeRequirements) items.add(item);1229 cgc.runtimeRequirements = items;1230 }1231 }1232 /**1233 * @param {Chunk} chunk the chunk1234 * @param {Iterable<string>} items runtime requirements to be added1235 * @returns {void}1236 */1237 addTreeRuntimeRequirements(chunk, items) {1238 const cgc = this._getChunkGraphChunk(chunk);1239 const runtimeRequirements = cgc.runtimeRequirementsInTree;1240 for (const item of items) runtimeRequirements.add(item);1241 }1242 /**1243 * @param {Module} module the module1244 * @param {RuntimeSpec} runtime the runtime1245 * @returns {ReadonlySet<string>} runtime requirements1246 */1247 getModuleRuntimeRequirements(module, runtime) {1248 const cgm = this._getChunkGraphModule(module);1249 const runtimeRequirements =1250 cgm.runtimeRequirements && cgm.runtimeRequirements.get(runtime);1251 return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements;1252 }1253 /**1254 * @param {Chunk} chunk the chunk1255 * @returns {ReadonlySet<string>} runtime requirements1256 */1257 getChunkRuntimeRequirements(chunk) {1258 const cgc = this._getChunkGraphChunk(chunk);1259 const runtimeRequirements = cgc.runtimeRequirements;1260 return runtimeRequirements === undefined ? EMPTY_SET : runtimeRequirements;1261 }1262 /**1263 * @param {Module} module the module1264 * @param {RuntimeSpec} runtime the runtime1265 * @param {boolean} withConnections include connections1266 * @returns {string} hash1267 */1268 getModuleGraphHash(module, runtime, withConnections = true) {1269 const cgm = this._getChunkGraphModule(module);1270 return withConnections1271 ? this._getModuleGraphHashWithConnections(cgm, module, runtime)1272 : this._getModuleGraphHashBigInt(cgm, module, runtime).toString(16);1273 }1274 /**1275 * @param {Module} module the module1276 * @param {RuntimeSpec} runtime the runtime1277 * @param {boolean} withConnections include connections1278 * @returns {bigint} hash1279 */1280 getModuleGraphHashBigInt(module, runtime, withConnections = true) {1281 const cgm = this._getChunkGraphModule(module);1282 return withConnections1283 ? BigInt(1284 `0x${this._getModuleGraphHashWithConnections(cgm, module, runtime)}`1285 )1286 : this._getModuleGraphHashBigInt(cgm, module, runtime);1287 }1288 /**1289 * @param {ChunkGraphModule} cgm the ChunkGraphModule1290 * @param {Module} module the module1291 * @param {RuntimeSpec} runtime the runtime1292 * @returns {bigint} hash as big int1293 */1294 _getModuleGraphHashBigInt(cgm, module, runtime) {1295 if (cgm.graphHashes === undefined) {1296 cgm.graphHashes = new RuntimeSpecMap();1297 }1298 const graphHash = cgm.graphHashes.provide(runtime, () => {1299 const hash = createHash("md4");1300 hash.update(`${cgm.id}`);1301 hash.update(`${this.moduleGraph.isAsync(module)}`);1302 this.moduleGraph.getExportsInfo(module).updateHash(hash, runtime);1303 return BigInt(`0x${/** @type {string} */ (hash.digest("hex"))}`);1304 });1305 return graphHash;1306 }1307 /**1308 * @param {ChunkGraphModule} cgm the ChunkGraphModule1309 * @param {Module} module the module1310 * @param {RuntimeSpec} runtime the runtime1311 * @returns {string} hash1312 */1313 _getModuleGraphHashWithConnections(cgm, module, runtime) {1314 if (cgm.graphHashesWithConnections === undefined) {1315 cgm.graphHashesWithConnections = new RuntimeSpecMap();1316 }1317 const activeStateToString = state => {1318 if (state === false) return "F";1319 if (state === true) return "T";1320 if (state === ModuleGraphConnection.TRANSITIVE_ONLY) return "O";1321 throw new Error("Not implemented active state");1322 };1323 const strict = module.buildMeta && module.buildMeta.strictHarmonyModule;1324 return cgm.graphHashesWithConnections.provide(runtime, () => {1325 const graphHash = this._getModuleGraphHashBigInt(1326 cgm,1327 module,1328 runtime1329 ).toString(16);1330 const connections = this.moduleGraph.getOutgoingConnections(module);1331 /** @type {Set<Module>} */1332 const activeNamespaceModules = new Set();1333 /** @type {Map<string, Module | Set<Module>>} */1334 const connectedModules = new Map();1335 const processConnection = (connection, stateInfo) => {1336 const module = connection.module;1337 stateInfo += module.getExportsType(this.moduleGraph, strict);1338 // cspell:word Tnamespace1339 if (stateInfo === "Tnamespace") activeNamespaceModules.add(module);1340 else {1341 const oldModule = connectedModules.get(stateInfo);1342 if (oldModule === undefined) {1343 connectedModules.set(stateInfo, module);1344 } else if (oldModule instanceof Set) {1345 oldModule.add(module);1346 } else if (oldModule !== module) {1347 connectedModules.set(stateInfo, new Set([oldModule, module]));1348 }1349 }1350 };1351 if (runtime === undefined || typeof runtime === "string") {1352 for (const connection of connections) {1353 const state = connection.getActiveState(runtime);1354 if (state === false) continue;1355 processConnection(connection, state === true ? "T" : "O");1356 }1357 } else {1358 // cspell:word Tnamespace1359 for (const connection of connections) {1360 const states = new Set();1361 let stateInfo = "";1362 forEachRuntime(1363 runtime,1364 runtime => {1365 const state = connection.getActiveState(runtime);1366 states.add(state);1367 stateInfo += activeStateToString(state) + runtime;1368 },1369 true1370 );1371 if (states.size === 1) {1372 const state = first(states);1373 if (state === false) continue;1374 stateInfo = activeStateToString(state);1375 }1376 processConnection(connection, stateInfo);1377 }1378 }1379 // cspell:word Tnamespace1380 if (activeNamespaceModules.size === 0 && connectedModules.size === 0)1381 return graphHash;1382 const connectedModulesInOrder =1383 connectedModules.size > 11384 ? Array.from(connectedModules).sort(([a], [b]) => (a < b ? -1 : 1))1385 : connectedModules;1386 const hash = createHash("md4");1387 const addModuleToHash = module => {1388 hash.update(1389 this._getModuleGraphHashBigInt(1390 this._getChunkGraphModule(module),1391 module,1392 runtime1393 ).toString(16)1394 );1395 };1396 const addModulesToHash = modules => {1397 let xor = ZERO_BIG_INT;1398 for (const m of modules) {1399 xor =1400 xor ^1401 this._getModuleGraphHashBigInt(1402 this._getChunkGraphModule(m),1403 m,1404 runtime1405 );1406 }1407 hash.update(xor.toString(16));1408 };1409 if (activeNamespaceModules.size === 1)1410 addModuleToHash(activeNamespaceModules.values().next().value);1411 else if (activeNamespaceModules.size > 1)1412 addModulesToHash(activeNamespaceModules);1413 for (const [stateInfo, modules] of connectedModulesInOrder) {1414 hash.update(stateInfo);1415 if (modules instanceof Set) {1416 addModulesToHash(modules);1417 } else {1418 addModuleToHash(modules);1419 }1420 }1421 hash.update(graphHash);1422 return /** @type {string} */ (hash.digest("hex"));1423 });1424 }1425 /**1426 * @param {Chunk} chunk the chunk1427 * @returns {ReadonlySet<string>} runtime requirements1428 */1429 getTreeRuntimeRequirements(chunk) {1430 const cgc = this._getChunkGraphChunk(chunk);1431 return cgc.runtimeRequirementsInTree;1432 }1433 // TODO remove in webpack 61434 /**1435 * @param {Module} module the module1436 * @param {string} deprecateMessage message for the deprecation message1437 * @param {string} deprecationCode code for the deprecation1438 * @returns {ChunkGraph} the chunk graph1439 */1440 static getChunkGraphForModule(module, deprecateMessage, deprecationCode) {1441 const fn = deprecateGetChunkGraphForModuleMap.get(deprecateMessage);1442 if (fn) return fn(module);1443 const newFn = util.deprecate(1444 /**1445 * @param {Module} module the module1446 * @returns {ChunkGraph} the chunk graph1447 */1448 module => {1449 const chunkGraph = chunkGraphForModuleMap.get(module);1450 if (!chunkGraph)1451 throw new Error(1452 deprecateMessage +1453 ": There was no ChunkGraph assigned to the Module for backward-compat (Use the new API)"1454 );1455 return chunkGraph;1456 },1457 deprecateMessage + ": Use new ChunkGraph API",1458 deprecationCode1459 );1460 deprecateGetChunkGraphForModuleMap.set(deprecateMessage, newFn);1461 return newFn(module);1462 }1463 // TODO remove in webpack 61464 /**1465 * @param {Module} module the module1466 * @param {ChunkGraph} chunkGraph the chunk graph1467 * @returns {void}1468 */1469 static setChunkGraphForModule(module, chunkGraph) {1470 chunkGraphForModuleMap.set(module, chunkGraph);1471 }1472 // TODO remove in webpack 61473 /**1474 * @param {Module} module the module1475 * @returns {void}1476 */1477 static clearChunkGraphForModule(module) {1478 chunkGraphForModuleMap.delete(module);1479 }1480 // TODO remove in webpack 61481 /**1482 * @param {Chunk} chunk the chunk1483 * @param {string} deprecateMessage message for the deprecation message1484 * @param {string} deprecationCode code for the deprecation1485 * @returns {ChunkGraph} the chunk graph1486 */1487 static getChunkGraphForChunk(chunk, deprecateMessage, deprecationCode) {1488 const fn = deprecateGetChunkGraphForChunkMap.get(deprecateMessage);1489 if (fn) return fn(chunk);1490 const newFn = util.deprecate(1491 /**1492 * @param {Chunk} chunk the chunk1493 * @returns {ChunkGraph} the chunk graph1494 */1495 chunk => {1496 const chunkGraph = chunkGraphForChunkMap.get(chunk);1497 if (!chunkGraph)1498 throw new Error(1499 deprecateMessage +1500 "There was no ChunkGraph assigned to the Chunk for backward-compat (Use the new API)"1501 );1502 return chunkGraph;1503 },1504 deprecateMessage + ": Use new ChunkGraph API",1505 deprecationCode1506 );1507 deprecateGetChunkGraphForChunkMap.set(deprecateMessage, newFn);1508 return newFn(chunk);1509 }1510 // TODO remove in webpack 61511 /**1512 * @param {Chunk} chunk the chunk1513 * @param {ChunkGraph} chunkGraph the chunk graph1514 * @returns {void}1515 */1516 static setChunkGraphForChunk(chunk, chunkGraph) {1517 chunkGraphForChunkMap.set(chunk, chunkGraph);1518 }1519 // TODO remove in webpack 61520 /**1521 * @param {Chunk} chunk the chunk1522 * @returns {void}1523 */1524 static clearChunkGraphForChunk(chunk) {1525 chunkGraphForChunkMap.delete(chunk);1526 }1527}1528// TODO remove in webpack 61529/** @type {WeakMap<Module, ChunkGraph>} */1530const chunkGraphForModuleMap = new WeakMap();1531// TODO remove in webpack 61532/** @type {WeakMap<Chunk, ChunkGraph>} */1533const chunkGraphForChunkMap = new WeakMap();1534// TODO remove in webpack 61535/** @type {Map<string, (module: Module) => ChunkGraph>} */1536const deprecateGetChunkGraphForModuleMap = new Map();1537// TODO remove in webpack 61538/** @type {Map<string, (chunk: Chunk) => ChunkGraph>} */1539const deprecateGetChunkGraphForChunkMap = new Map();...
Chunk.js
Source:Chunk.js
1/*2 MIT License http://www.opensource.org/licenses/mit-license.php3 Author Tobias Koppers @sokra4*/5"use strict";6const ChunkGraph = require("./ChunkGraph");7const Entrypoint = require("./Entrypoint");8const { intersect } = require("./util/SetHelpers");9const SortableSet = require("./util/SortableSet");10const StringXor = require("./util/StringXor");11const {12 compareModulesByIdentifier,13 compareChunkGroupsByIndex,14 compareModulesById15} = require("./util/comparators");16const { createArrayToSetDeprecationSet } = require("./util/deprecation");17const { mergeRuntime } = require("./util/runtime");18/** @typedef {import("webpack-sources").Source} Source */19/** @typedef {import("./ChunkGraph").ChunkFilterPredicate} ChunkFilterPredicate */20/** @typedef {import("./ChunkGraph").ChunkSizeOptions} ChunkSizeOptions */21/** @typedef {import("./ChunkGraph").ModuleFilterPredicate} ModuleFilterPredicate */22/** @typedef {import("./ChunkGroup")} ChunkGroup */23/** @typedef {import("./Compilation")} Compilation */24/** @typedef {import("./Compilation").AssetInfo} AssetInfo */25/** @typedef {import("./Compilation").PathData} PathData */26/** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */27/** @typedef {import("./Module")} Module */28/** @typedef {import("./ModuleGraph")} ModuleGraph */29/** @typedef {import("./util/Hash")} Hash */30/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */31const ChunkFilesSet = createArrayToSetDeprecationSet("chunk.files");32/**33 * @typedef {Object} WithId an object who has an id property *34 * @property {string | number} id the id of the object35 */36/**37 * @deprecated38 * @typedef {Object} ChunkMaps39 * @property {Record<string|number, string>} hash40 * @property {Record<string|number, Record<string, string>>} contentHash41 * @property {Record<string|number, string>} name42 */43/**44 * @deprecated45 * @typedef {Object} ChunkModuleMaps46 * @property {Record<string|number, (string|number)[]>} id47 * @property {Record<string|number, string>} hash48 */49let debugId = 1000;50/**51 * A Chunk is a unit of encapsulation for Modules.52 * Chunks are "rendered" into bundles that get emitted when the build completes.53 */54class Chunk {55 /**56 * @param {string=} name of chunk being created, is optional (for subclasses)57 * @param {boolean} backCompat enable backward-compatibility58 */59 constructor(name, backCompat = true) {60 /** @type {number | string | null} */61 this.id = null;62 /** @type {(number|string)[] | null} */63 this.ids = null;64 /** @type {number} */65 this.debugId = debugId++;66 /** @type {string} */67 this.name = name;68 /** @type {SortableSet<string>} */69 this.idNameHints = new SortableSet();70 /** @type {boolean} */71 this.preventIntegration = false;72 /** @type {(string | function(PathData, AssetInfo=): string)?} */73 this.filenameTemplate = undefined;74 /** @type {(string | function(PathData, AssetInfo=): string)?} */75 this.cssFilenameTemplate = undefined;76 /** @private @type {SortableSet<ChunkGroup>} */77 this._groups = new SortableSet(undefined, compareChunkGroupsByIndex);78 /** @type {RuntimeSpec} */79 this.runtime = undefined;80 /** @type {Set<string>} */81 this.files = backCompat ? new ChunkFilesSet() : new Set();82 /** @type {Set<string>} */83 this.auxiliaryFiles = new Set();84 /** @type {boolean} */85 this.rendered = false;86 /** @type {string=} */87 this.hash = undefined;88 /** @type {Record<string, string>} */89 this.contentHash = Object.create(null);90 /** @type {string=} */91 this.renderedHash = undefined;92 /** @type {string=} */93 this.chunkReason = undefined;94 /** @type {boolean} */95 this.extraAsync = false;96 }97 // TODO remove in webpack 698 // BACKWARD-COMPAT START99 get entryModule() {100 const entryModules = Array.from(101 ChunkGraph.getChunkGraphForChunk(102 this,103 "Chunk.entryModule",104 "DEP_WEBPACK_CHUNK_ENTRY_MODULE"105 ).getChunkEntryModulesIterable(this)106 );107 if (entryModules.length === 0) {108 return undefined;109 } else if (entryModules.length === 1) {110 return entryModules[0];111 } else {112 throw new Error(113 "Module.entryModule: Multiple entry modules are not supported by the deprecated API (Use the new ChunkGroup API)"114 );115 }116 }117 /**118 * @returns {boolean} true, if the chunk contains an entry module119 */120 hasEntryModule() {121 return (122 ChunkGraph.getChunkGraphForChunk(123 this,124 "Chunk.hasEntryModule",125 "DEP_WEBPACK_CHUNK_HAS_ENTRY_MODULE"126 ).getNumberOfEntryModules(this) > 0127 );128 }129 /**130 * @param {Module} module the module131 * @returns {boolean} true, if the chunk could be added132 */133 addModule(module) {134 const chunkGraph = ChunkGraph.getChunkGraphForChunk(135 this,136 "Chunk.addModule",137 "DEP_WEBPACK_CHUNK_ADD_MODULE"138 );139 if (chunkGraph.isModuleInChunk(module, this)) return false;140 chunkGraph.connectChunkAndModule(this, module);141 return true;142 }143 /**144 * @param {Module} module the module145 * @returns {void}146 */147 removeModule(module) {148 ChunkGraph.getChunkGraphForChunk(149 this,150 "Chunk.removeModule",151 "DEP_WEBPACK_CHUNK_REMOVE_MODULE"152 ).disconnectChunkAndModule(this, module);153 }154 /**155 * @returns {number} the number of module which are contained in this chunk156 */157 getNumberOfModules() {158 return ChunkGraph.getChunkGraphForChunk(159 this,160 "Chunk.getNumberOfModules",161 "DEP_WEBPACK_CHUNK_GET_NUMBER_OF_MODULES"162 ).getNumberOfChunkModules(this);163 }164 get modulesIterable() {165 const chunkGraph = ChunkGraph.getChunkGraphForChunk(166 this,167 "Chunk.modulesIterable",168 "DEP_WEBPACK_CHUNK_MODULES_ITERABLE"169 );170 return chunkGraph.getOrderedChunkModulesIterable(171 this,172 compareModulesByIdentifier173 );174 }175 /**176 * @param {Chunk} otherChunk the chunk to compare with177 * @returns {-1|0|1} the comparison result178 */179 compareTo(otherChunk) {180 const chunkGraph = ChunkGraph.getChunkGraphForChunk(181 this,182 "Chunk.compareTo",183 "DEP_WEBPACK_CHUNK_COMPARE_TO"184 );185 return chunkGraph.compareChunks(this, otherChunk);186 }187 /**188 * @param {Module} module the module189 * @returns {boolean} true, if the chunk contains the module190 */191 containsModule(module) {192 return ChunkGraph.getChunkGraphForChunk(193 this,194 "Chunk.containsModule",195 "DEP_WEBPACK_CHUNK_CONTAINS_MODULE"196 ).isModuleInChunk(module, this);197 }198 /**199 * @returns {Module[]} the modules for this chunk200 */201 getModules() {202 return ChunkGraph.getChunkGraphForChunk(203 this,204 "Chunk.getModules",205 "DEP_WEBPACK_CHUNK_GET_MODULES"206 ).getChunkModules(this);207 }208 /**209 * @returns {void}210 */211 remove() {212 const chunkGraph = ChunkGraph.getChunkGraphForChunk(213 this,214 "Chunk.remove",215 "DEP_WEBPACK_CHUNK_REMOVE"216 );217 chunkGraph.disconnectChunk(this);218 this.disconnectFromGroups();219 }220 /**221 * @param {Module} module the module222 * @param {Chunk} otherChunk the target chunk223 * @returns {void}224 */225 moveModule(module, otherChunk) {226 const chunkGraph = ChunkGraph.getChunkGraphForChunk(227 this,228 "Chunk.moveModule",229 "DEP_WEBPACK_CHUNK_MOVE_MODULE"230 );231 chunkGraph.disconnectChunkAndModule(this, module);232 chunkGraph.connectChunkAndModule(otherChunk, module);233 }234 /**235 * @param {Chunk} otherChunk the other chunk236 * @returns {boolean} true, if the specified chunk has been integrated237 */238 integrate(otherChunk) {239 const chunkGraph = ChunkGraph.getChunkGraphForChunk(240 this,241 "Chunk.integrate",242 "DEP_WEBPACK_CHUNK_INTEGRATE"243 );244 if (chunkGraph.canChunksBeIntegrated(this, otherChunk)) {245 chunkGraph.integrateChunks(this, otherChunk);246 return true;247 } else {248 return false;249 }250 }251 /**252 * @param {Chunk} otherChunk the other chunk253 * @returns {boolean} true, if chunks could be integrated254 */255 canBeIntegrated(otherChunk) {256 const chunkGraph = ChunkGraph.getChunkGraphForChunk(257 this,258 "Chunk.canBeIntegrated",259 "DEP_WEBPACK_CHUNK_CAN_BE_INTEGRATED"260 );261 return chunkGraph.canChunksBeIntegrated(this, otherChunk);262 }263 /**264 * @returns {boolean} true, if this chunk contains no module265 */266 isEmpty() {267 const chunkGraph = ChunkGraph.getChunkGraphForChunk(268 this,269 "Chunk.isEmpty",270 "DEP_WEBPACK_CHUNK_IS_EMPTY"271 );272 return chunkGraph.getNumberOfChunkModules(this) === 0;273 }274 /**275 * @returns {number} total size of all modules in this chunk276 */277 modulesSize() {278 const chunkGraph = ChunkGraph.getChunkGraphForChunk(279 this,280 "Chunk.modulesSize",281 "DEP_WEBPACK_CHUNK_MODULES_SIZE"282 );283 return chunkGraph.getChunkModulesSize(this);284 }285 /**286 * @param {ChunkSizeOptions} options options object287 * @returns {number} total size of this chunk288 */289 size(options = {}) {290 const chunkGraph = ChunkGraph.getChunkGraphForChunk(291 this,292 "Chunk.size",293 "DEP_WEBPACK_CHUNK_SIZE"294 );295 return chunkGraph.getChunkSize(this, options);296 }297 /**298 * @param {Chunk} otherChunk the other chunk299 * @param {ChunkSizeOptions} options options object300 * @returns {number} total size of the chunk or false if the chunk can't be integrated301 */302 integratedSize(otherChunk, options) {303 const chunkGraph = ChunkGraph.getChunkGraphForChunk(304 this,305 "Chunk.integratedSize",306 "DEP_WEBPACK_CHUNK_INTEGRATED_SIZE"307 );308 return chunkGraph.getIntegratedChunksSize(this, otherChunk, options);309 }310 /**311 * @param {ModuleFilterPredicate} filterFn function used to filter modules312 * @returns {ChunkModuleMaps} module map information313 */314 getChunkModuleMaps(filterFn) {315 const chunkGraph = ChunkGraph.getChunkGraphForChunk(316 this,317 "Chunk.getChunkModuleMaps",318 "DEP_WEBPACK_CHUNK_GET_CHUNK_MODULE_MAPS"319 );320 /** @type {Record<string|number, (string|number)[]>} */321 const chunkModuleIdMap = Object.create(null);322 /** @type {Record<string|number, string>} */323 const chunkModuleHashMap = Object.create(null);324 for (const asyncChunk of this.getAllAsyncChunks()) {325 /** @type {(string|number)[]} */326 let array;327 for (const module of chunkGraph.getOrderedChunkModulesIterable(328 asyncChunk,329 compareModulesById(chunkGraph)330 )) {331 if (filterFn(module)) {332 if (array === undefined) {333 array = [];334 chunkModuleIdMap[asyncChunk.id] = array;335 }336 const moduleId = chunkGraph.getModuleId(module);337 array.push(moduleId);338 chunkModuleHashMap[moduleId] = chunkGraph.getRenderedModuleHash(339 module,340 undefined341 );342 }343 }344 }345 return {346 id: chunkModuleIdMap,347 hash: chunkModuleHashMap348 };349 }350 /**351 * @param {ModuleFilterPredicate} filterFn predicate function used to filter modules352 * @param {ChunkFilterPredicate=} filterChunkFn predicate function used to filter chunks353 * @returns {boolean} return true if module exists in graph354 */355 hasModuleInGraph(filterFn, filterChunkFn) {356 const chunkGraph = ChunkGraph.getChunkGraphForChunk(357 this,358 "Chunk.hasModuleInGraph",359 "DEP_WEBPACK_CHUNK_HAS_MODULE_IN_GRAPH"360 );361 return chunkGraph.hasModuleInGraph(this, filterFn, filterChunkFn);362 }363 /**364 * @deprecated365 * @param {boolean} realHash whether the full hash or the rendered hash is to be used366 * @returns {ChunkMaps} the chunk map information367 */368 getChunkMaps(realHash) {369 /** @type {Record<string|number, string>} */370 const chunkHashMap = Object.create(null);371 /** @type {Record<string|number, Record<string, string>>} */372 const chunkContentHashMap = Object.create(null);373 /** @type {Record<string|number, string>} */374 const chunkNameMap = Object.create(null);375 for (const chunk of this.getAllAsyncChunks()) {376 chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash;377 for (const key of Object.keys(chunk.contentHash)) {378 if (!chunkContentHashMap[key]) {379 chunkContentHashMap[key] = Object.create(null);380 }381 chunkContentHashMap[key][chunk.id] = chunk.contentHash[key];382 }383 if (chunk.name) {384 chunkNameMap[chunk.id] = chunk.name;385 }386 }387 return {388 hash: chunkHashMap,389 contentHash: chunkContentHashMap,390 name: chunkNameMap391 };392 }393 // BACKWARD-COMPAT END394 /**395 * @returns {boolean} whether or not the Chunk will have a runtime396 */397 hasRuntime() {398 for (const chunkGroup of this._groups) {399 if (400 chunkGroup instanceof Entrypoint &&401 chunkGroup.getRuntimeChunk() === this402 ) {403 return true;404 }405 }406 return false;407 }408 /**409 * @returns {boolean} whether or not this chunk can be an initial chunk410 */411 canBeInitial() {412 for (const chunkGroup of this._groups) {413 if (chunkGroup.isInitial()) return true;414 }415 return false;416 }417 /**418 * @returns {boolean} whether this chunk can only be an initial chunk419 */420 isOnlyInitial() {421 if (this._groups.size <= 0) return false;422 for (const chunkGroup of this._groups) {423 if (!chunkGroup.isInitial()) return false;424 }425 return true;426 }427 /**428 * @returns {EntryOptions | undefined} the entry options for this chunk429 */430 getEntryOptions() {431 for (const chunkGroup of this._groups) {432 if (chunkGroup instanceof Entrypoint) {433 return chunkGroup.options;434 }435 }436 return undefined;437 }438 /**439 * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being added440 * @returns {void}441 */442 addGroup(chunkGroup) {443 this._groups.add(chunkGroup);444 }445 /**446 * @param {ChunkGroup} chunkGroup the chunkGroup the chunk is being removed from447 * @returns {void}448 */449 removeGroup(chunkGroup) {450 this._groups.delete(chunkGroup);451 }452 /**453 * @param {ChunkGroup} chunkGroup the chunkGroup to check454 * @returns {boolean} returns true if chunk has chunkGroup reference and exists in chunkGroup455 */456 isInGroup(chunkGroup) {457 return this._groups.has(chunkGroup);458 }459 /**460 * @returns {number} the amount of groups that the said chunk is in461 */462 getNumberOfGroups() {463 return this._groups.size;464 }465 /**466 * @returns {Iterable<ChunkGroup>} the chunkGroups that the said chunk is referenced in467 */468 get groupsIterable() {469 this._groups.sort();470 return this._groups;471 }472 /**473 * @returns {void}474 */475 disconnectFromGroups() {476 for (const chunkGroup of this._groups) {477 chunkGroup.removeChunk(this);478 }479 }480 /**481 * @param {Chunk} newChunk the new chunk that will be split out of482 * @returns {void}483 */484 split(newChunk) {485 for (const chunkGroup of this._groups) {486 chunkGroup.insertChunk(newChunk, this);487 newChunk.addGroup(chunkGroup);488 }489 for (const idHint of this.idNameHints) {490 newChunk.idNameHints.add(idHint);491 }492 newChunk.runtime = mergeRuntime(newChunk.runtime, this.runtime);493 }494 /**495 * @param {Hash} hash hash (will be modified)496 * @param {ChunkGraph} chunkGraph the chunk graph497 * @returns {void}498 */499 updateHash(hash, chunkGraph) {500 hash.update(501 `${this.id} ${this.ids ? this.ids.join() : ""} ${this.name || ""} `502 );503 const xor = new StringXor();504 for (const m of chunkGraph.getChunkModulesIterable(this)) {505 xor.add(chunkGraph.getModuleHash(m, this.runtime));506 }507 xor.updateHash(hash);508 const entryModules =509 chunkGraph.getChunkEntryModulesWithChunkGroupIterable(this);510 for (const [m, chunkGroup] of entryModules) {511 hash.update(`entry${chunkGraph.getModuleId(m)}${chunkGroup.id}`);512 }513 }514 /**515 * @returns {Set<Chunk>} a set of all the async chunks516 */517 getAllAsyncChunks() {518 const queue = new Set();519 const chunks = new Set();520 const initialChunks = intersect(521 Array.from(this.groupsIterable, g => new Set(g.chunks))522 );523 const initialQueue = new Set(this.groupsIterable);524 for (const chunkGroup of initialQueue) {525 for (const child of chunkGroup.childrenIterable) {526 if (child instanceof Entrypoint) {527 initialQueue.add(child);528 } else {529 queue.add(child);530 }531 }532 }533 for (const chunkGroup of queue) {534 for (const chunk of chunkGroup.chunks) {535 if (!initialChunks.has(chunk)) {536 chunks.add(chunk);537 }538 }539 for (const child of chunkGroup.childrenIterable) {540 queue.add(child);541 }542 }543 return chunks;544 }545 /**546 * @returns {Set<Chunk>} a set of all the initial chunks (including itself)547 */548 getAllInitialChunks() {549 const chunks = new Set();550 const queue = new Set(this.groupsIterable);551 for (const group of queue) {552 if (group.isInitial()) {553 for (const c of group.chunks) chunks.add(c);554 for (const g of group.childrenIterable) queue.add(g);555 }556 }557 return chunks;558 }559 /**560 * @returns {Set<Chunk>} a set of all the referenced chunks (including itself)561 */562 getAllReferencedChunks() {563 const queue = new Set(this.groupsIterable);564 const chunks = new Set();565 for (const chunkGroup of queue) {566 for (const chunk of chunkGroup.chunks) {567 chunks.add(chunk);568 }569 for (const child of chunkGroup.childrenIterable) {570 queue.add(child);571 }572 }573 return chunks;574 }575 /**576 * @returns {Set<Entrypoint>} a set of all the referenced entrypoints577 */578 getAllReferencedAsyncEntrypoints() {579 const queue = new Set(this.groupsIterable);580 const entrypoints = new Set();581 for (const chunkGroup of queue) {582 for (const entrypoint of chunkGroup.asyncEntrypointsIterable) {583 entrypoints.add(entrypoint);584 }585 for (const child of chunkGroup.childrenIterable) {586 queue.add(child);587 }588 }589 return entrypoints;590 }591 /**592 * @returns {boolean} true, if the chunk references async chunks593 */594 hasAsyncChunks() {595 const queue = new Set();596 const initialChunks = intersect(597 Array.from(this.groupsIterable, g => new Set(g.chunks))598 );599 for (const chunkGroup of this.groupsIterable) {600 for (const child of chunkGroup.childrenIterable) {601 queue.add(child);602 }603 }604 for (const chunkGroup of queue) {605 for (const chunk of chunkGroup.chunks) {606 if (!initialChunks.has(chunk)) {607 return true;608 }609 }610 for (const child of chunkGroup.childrenIterable) {611 queue.add(child);612 }613 }614 return false;615 }616 /**617 * @param {ChunkGraph} chunkGraph the chunk graph618 * @param {ChunkFilterPredicate=} filterFn function used to filter chunks619 * @returns {Record<string, (string | number)[]>} a record object of names to lists of child ids(?)620 */621 getChildIdsByOrders(chunkGraph, filterFn) {622 /** @type {Map<string, {order: number, group: ChunkGroup}[]>} */623 const lists = new Map();624 for (const group of this.groupsIterable) {625 if (group.chunks[group.chunks.length - 1] === this) {626 for (const childGroup of group.childrenIterable) {627 for (const key of Object.keys(childGroup.options)) {628 if (key.endsWith("Order")) {629 const name = key.slice(0, key.length - "Order".length);630 let list = lists.get(name);631 if (list === undefined) {632 list = [];633 lists.set(name, list);634 }635 list.push({636 order: childGroup.options[key],637 group: childGroup638 });639 }640 }641 }642 }643 }644 /** @type {Record<string, (string | number)[]>} */645 const result = Object.create(null);646 for (const [name, list] of lists) {647 list.sort((a, b) => {648 const cmp = b.order - a.order;649 if (cmp !== 0) return cmp;650 return a.group.compareTo(chunkGraph, b.group);651 });652 /** @type {Set<string | number>} */653 const chunkIdSet = new Set();654 for (const item of list) {655 for (const chunk of item.group.chunks) {656 if (filterFn && !filterFn(chunk, chunkGraph)) continue;657 chunkIdSet.add(chunk.id);658 }659 }660 if (chunkIdSet.size > 0) {661 result[name] = Array.from(chunkIdSet);662 }663 }664 return result;665 }666 /**667 * @param {ChunkGraph} chunkGraph the chunk graph668 * @param {string} type option name669 * @returns {{ onChunks: Chunk[], chunks: Set<Chunk> }[]} referenced chunks for a specific type670 */671 getChildrenOfTypeInOrder(chunkGraph, type) {672 const list = [];673 for (const group of this.groupsIterable) {674 for (const childGroup of group.childrenIterable) {675 const order = childGroup.options[type];676 if (order === undefined) continue;677 list.push({678 order,679 group,680 childGroup681 });682 }683 }684 if (list.length === 0) return undefined;685 list.sort((a, b) => {686 const cmp = b.order - a.order;687 if (cmp !== 0) return cmp;688 return a.group.compareTo(chunkGraph, b.group);689 });690 const result = [];691 let lastEntry;692 for (const { group, childGroup } of list) {693 if (lastEntry && lastEntry.onChunks === group.chunks) {694 for (const chunk of childGroup.chunks) {695 lastEntry.chunks.add(chunk);696 }697 } else {698 result.push(699 (lastEntry = {700 onChunks: group.chunks,701 chunks: new Set(childGroup.chunks)702 })703 );704 }705 }706 return result;707 }708 /**709 * @param {ChunkGraph} chunkGraph the chunk graph710 * @param {boolean=} includeDirectChildren include direct children (by default only children of async children are included)711 * @param {ChunkFilterPredicate=} filterFn function used to filter chunks712 * @returns {Record<string|number, Record<string, (string | number)[]>>} a record object of names to lists of child ids(?) by chunk id713 */714 getChildIdsByOrdersMap(chunkGraph, includeDirectChildren, filterFn) {715 /** @type {Record<string|number, Record<string, (string | number)[]>>} */716 const chunkMaps = Object.create(null);717 /**718 * @param {Chunk} chunk a chunk719 * @returns {void}720 */721 const addChildIdsByOrdersToMap = chunk => {722 const data = chunk.getChildIdsByOrders(chunkGraph, filterFn);723 for (const key of Object.keys(data)) {724 let chunkMap = chunkMaps[key];725 if (chunkMap === undefined) {726 chunkMaps[key] = chunkMap = Object.create(null);727 }728 chunkMap[chunk.id] = data[key];729 }730 };731 if (includeDirectChildren) {732 /** @type {Set<Chunk>} */733 const chunks = new Set();734 for (const chunkGroup of this.groupsIterable) {735 for (const chunk of chunkGroup.chunks) {736 chunks.add(chunk);737 }738 }739 for (const chunk of chunks) {740 addChildIdsByOrdersToMap(chunk);741 }742 }743 for (const chunk of this.getAllAsyncChunks()) {744 addChildIdsByOrdersToMap(chunk);745 }746 return chunkMaps;747 }748}...
Using AI Code Generation
1var wpt = require('webpagetest');2var wpt = new WebPageTest('www.webpagetest.org');3var options = {4};5wpt.runTest(url, options, function(err, data) {6 if (err) return console.error(err);7 console.log('Test submitted to WebPageTest!');8 console.log('Navigate to %sresult/%s/ to see the test results.', wpt.apiURL, data.data.testId);9});
Using AI Code Generation
1const wptools = require('wptools');2const fs = require('fs');3const path = require('path');4const csv = require('csv-parser');5const csvWriter = require('csv-write-stream');6const writer = csvWriter({ sendHeaders: false });7const results = [];8const csvFilePath = path.join(__dirname, 'data.csv');9const csvOutputPath = path.join(__dirname, 'output.csv');10const csvOutputPath2 = path.join(__dirname, 'output2.csv');11const csvOutputPath3 = path.join(__dirname, 'output3.csv');12const csvOutputPath4 = path.join(__dirname, 'output4.csv');13const csvOutputPath5 = path.join(__dirname, 'output5.csv');14const csvOutputPath6 = path.join(__dirname, 'output6.csv');15const csvOutputPath7 = path.join(__dirname, 'output7.csv');16const csvOutputPath8 = path.join(__dirname, 'output8.csv');17const csvOutputPath9 = path.join(__dirname, 'output9.csv');18const csvOutputPath10 = path.join(__dirname, 'output10.csv');19const csvOutputPath11 = path.join(__dirname, 'output11.csv');20const csvOutputPath12 = path.join(__dirname, 'output12.csv');21const csvOutputPath13 = path.join(__dirname, 'output13.csv');22const csvOutputPath14 = path.join(__dirname, 'output14.csv');23const csvOutputPath15 = path.join(__dirname, 'output15.csv');24const csvOutputPath16 = path.join(__dirname, 'output16.csv');25const csvOutputPath17 = path.join(__dirname, 'output17.csv');26const csvOutputPath18 = path.join(__dirname, 'output18.csv');27const csvOutputPath19 = path.join(__dirname, 'output19.csv');28const csvOutputPath20 = path.join(__dirname, 'output20.csv');29const csvOutputPath21 = path.join(__dirname, 'output21.csv');30const csvOutputPath22 = path.join(__dirname, 'output22.csv');31const csvOutputPath23 = path.join(__dirname, 'output23.csv');32const csvOutputPath24 = path.join(__dirname, 'output24.csv');33const csvOutputPath25 = path.join(__dirname, 'output25.csv');34const csvOutputPath26 = path.join(__dirname, 'output26.csv');35const csvOutputPath27 = path.join(__dirname, '
Using AI Code Generation
1const wptools = require('wptools');2var fs = require('fs');3var input = fs.readFileSync('input.txt').toString().split("\n");4var output = fs.createWriteStream('output.txt');5var chunk_size = 1;6var chunks = [];7for (var i = 0; i < input.length; i += chunk_size) {8 chunks.push(input.slice(i, i + chunk_size));9}10chunks.forEach(function(chunk) {11 chunk.forEach(function(url) {12 wptools.page(url)13 .get()14 .then(function(response) {15 var data = response.data;16 console.log(data);17 output.write(data + '\n');18 })19 .catch(function(err) {20 console.log(err);21 });22 });23});24const wptools = require('wptools');25var fs = require('fs');26var input = fs.readFileSync('input.txt').toString().split("\n");27var output = fs.createWriteStream('output.txt');28var chunk_size = 1;29var chunks = [];30for (var i = 0; i < input.length; i += chunk_size) {31 chunks.push(input.slice(i, i + chunk_size));32}33chunks.forEach(async function(chunk) {34 chunk.forEach(async function(url) {35 var data = await wptools.page(url).get();36 console.log(data.data);37 output.write(data.data + '\n');38 });39});
Using AI Code Generation
1function chunkCallback(chunkData) {2 console.log(chunkData);3}4function doneCallback() {5 console.log('done');6}7function errorCallback(error) {8 console.log(error);9}10function statusCallback(status) {11 console.log(status);12}13function headerCallback(header) {14 console.log(header);15}16function debugCallback(debug) {17 console.log(debug);18}19function consoleCallback(consoleData) {20 console.log(consoleData);21}22function errorCallback(error) {23 console.log(error);24}25function doneCallback() {26 console.log('done');27}28function statusCallback(status) {29 console.log(status);30}31function headerCallback(header) {32 console.log(header);33}34function debugCallback(debug) {35 console.log(debug);36}37function consoleCallback(consoleData) {38 console.log(consoleData);39}40function errorCallback(error) {41 console.log(error);42}43function doneCallback() {44 console.log('done');45}46function statusCallback(status) {47 console.log(status);48}49function headerCallback(header) {50 console.log(header);51}52function debugCallback(debug) {53 console.log(debug);54}55function consoleCallback(consoleData) {56 console.log(consoleData);57}58function errorCallback(error) {
Using AI Code Generation
1var wptools = require('wptools');2wptools('Barack Obama').chunk('infobox').then(function(resp){3 console.log(resp);4});5{ type: 'infobox',6 wikitext: '{{Infobox President of the United States\n| name = Barack Obama\n| order = 44th\n| image = Barack Obama official portrait cropped.jpg\n| caption = Official portrait of Obama as President\n| vicepresident = Joe Biden\n| residence = [[White House|The White House]]\n| termstart = January 20, 2009\n| termend = January 20, 2017\n| predecessor = George W. Bush\n| successor = Joe Biden\n| birth_date = August 4, 1961 (age 55)\n| birth_place = [[Honolulu, Hawaii]], [[U.S.]]\n| death_date =\n| death_place =\n| spouse = Michelle Obama\n| party = [[Democratic Party (United States)|Democratic]]\n| vicepresident = Joe Biden\n| termstart = January 20, 2009\n| termend = January 20, 2017\n| predecessor = George W. Bush\n| successor = Joe Biden\n| birth_date = August 4, 1961 (age 55)\n| birth_place = [[Honolulu, Hawaii]], [[U.S.]]\n| death_date =\n| death_place =\n| spouse = Michelle Obama\n| party = [[Democratic Party (United States)|Democratic]]\n| vicepresident = Joe Biden\n| termstart = January 20, 2009\n| termend = January 20, 2017\n| predecessor = George W. Bush\n| successor = Joe Biden\n| birth_date = August 4, 1961 (age 55)\n| birth_place = [[Honolulu, Hawaii]], [[U.S.]]\n| death_date =\n| death_place =\n| spouse = Michelle Obama\n| party = [[Democratic Party (United States)|Democratic]]\n| vicepresident = Joe Biden\n| termstart = January 20, 2009\n| termend = January 20, 2017\n| predecessor = George W
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!