UNPKG

24.6 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const util = require("util");
9const ExportsInfo = require("./ExportsInfo");
10const ModuleGraphConnection = require("./ModuleGraphConnection");
11const SortableSet = require("./util/SortableSet");
12const WeakTupleMap = require("./util/WeakTupleMap");
13
14/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
15/** @typedef {import("./Dependency")} Dependency */
16/** @typedef {import("./ExportsInfo").ExportInfo} ExportInfo */
17/** @typedef {import("./Module")} Module */
18/** @typedef {import("./ModuleProfile")} ModuleProfile */
19/** @typedef {import("./RequestShortener")} RequestShortener */
20/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
21
22/**
23 * @callback OptimizationBailoutFunction
24 * @param {RequestShortener} requestShortener
25 * @returns {string}
26 */
27
28const EMPTY_SET = new Set();
29
30/**
31 * @param {SortableSet<ModuleGraphConnection>} set input
32 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]>} mapped by origin module
33 */
34const getConnectionsByOriginModule = set => {
35 const map = new Map();
36 /** @type {Module | 0} */
37 let lastModule = 0;
38 /** @type {ModuleGraphConnection[]} */
39 let lastList = undefined;
40 for (const connection of set) {
41 const { originModule } = connection;
42 if (lastModule === originModule) {
43 lastList.push(connection);
44 } else {
45 lastModule = originModule;
46 const list = map.get(originModule);
47 if (list !== undefined) {
48 lastList = list;
49 list.push(connection);
50 } else {
51 const list = [connection];
52 lastList = list;
53 map.set(originModule, list);
54 }
55 }
56 }
57 return map;
58};
59
60/**
61 * @param {SortableSet<ModuleGraphConnection>} set input
62 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]>} mapped by module
63 */
64const getConnectionsByModule = set => {
65 const map = new Map();
66 /** @type {Module | 0} */
67 let lastModule = 0;
68 /** @type {ModuleGraphConnection[]} */
69 let lastList = undefined;
70 for (const connection of set) {
71 const { module } = connection;
72 if (lastModule === module) {
73 lastList.push(connection);
74 } else {
75 lastModule = module;
76 const list = map.get(module);
77 if (list !== undefined) {
78 lastList = list;
79 list.push(connection);
80 } else {
81 const list = [connection];
82 lastList = list;
83 map.set(module, list);
84 }
85 }
86 }
87 return map;
88};
89
90class ModuleGraphModule {
91 constructor() {
92 /** @type {SortableSet<ModuleGraphConnection>} */
93 this.incomingConnections = new SortableSet();
94 /** @type {SortableSet<ModuleGraphConnection> | undefined} */
95 this.outgoingConnections = undefined;
96 /** @type {Module | null} */
97 this.issuer = undefined;
98 /** @type {(string | OptimizationBailoutFunction)[]} */
99 this.optimizationBailout = [];
100 /** @type {ExportsInfo} */
101 this.exports = new ExportsInfo();
102 /** @type {number} */
103 this.preOrderIndex = null;
104 /** @type {number} */
105 this.postOrderIndex = null;
106 /** @type {number} */
107 this.depth = null;
108 /** @type {ModuleProfile} */
109 this.profile = undefined;
110 /** @type {boolean} */
111 this.async = false;
112 /** @type {ModuleGraphConnection[]} */
113 this._unassignedConnections = undefined;
114 }
115}
116
117class ModuleGraph {
118 constructor() {
119 /** @type {WeakMap<Dependency, ModuleGraphConnection>} */
120 this._dependencyMap = new WeakMap();
121 /** @type {Map<Module, ModuleGraphModule>} */
122 this._moduleMap = new Map();
123 /** @type {WeakMap<any, Object>} */
124 this._metaMap = new WeakMap();
125
126 /** @type {WeakTupleMap<any[], any>} */
127 this._cache = undefined;
128
129 /** @type {Map<Module, WeakTupleMap<any, any>>} */
130 this._moduleMemCaches = undefined;
131 }
132
133 /**
134 * @param {Module} module the module
135 * @returns {ModuleGraphModule} the internal module
136 */
137 _getModuleGraphModule(module) {
138 let mgm = this._moduleMap.get(module);
139 if (mgm === undefined) {
140 mgm = new ModuleGraphModule();
141 this._moduleMap.set(module, mgm);
142 }
143 return mgm;
144 }
145
146 /**
147 * @param {Dependency} dependency the dependency
148 * @param {DependenciesBlock} block parent block
149 * @param {Module} module parent module
150 * @param {number=} indexInBlock position in block
151 * @returns {void}
152 */
153 setParents(dependency, block, module, indexInBlock = -1) {
154 dependency._parentDependenciesBlockIndex = indexInBlock;
155 dependency._parentDependenciesBlock = block;
156 dependency._parentModule = module;
157 }
158
159 /**
160 * @param {Dependency} dependency the dependency
161 * @returns {Module} parent module
162 */
163 getParentModule(dependency) {
164 return dependency._parentModule;
165 }
166
167 /**
168 * @param {Dependency} dependency the dependency
169 * @returns {DependenciesBlock} parent block
170 */
171 getParentBlock(dependency) {
172 return dependency._parentDependenciesBlock;
173 }
174
175 /**
176 * @param {Dependency} dependency the dependency
177 * @returns {number} index
178 */
179 getParentBlockIndex(dependency) {
180 return dependency._parentDependenciesBlockIndex;
181 }
182
183 /**
184 * @param {Module} originModule the referencing module
185 * @param {Dependency} dependency the referencing dependency
186 * @param {Module} module the referenced module
187 * @returns {void}
188 */
189 setResolvedModule(originModule, dependency, module) {
190 const connection = new ModuleGraphConnection(
191 originModule,
192 dependency,
193 module,
194 undefined,
195 dependency.weak,
196 dependency.getCondition(this)
197 );
198 const connections = this._getModuleGraphModule(module).incomingConnections;
199 connections.add(connection);
200 if (originModule) {
201 const mgm = this._getModuleGraphModule(originModule);
202 if (mgm._unassignedConnections === undefined) {
203 mgm._unassignedConnections = [];
204 }
205 mgm._unassignedConnections.push(connection);
206 if (mgm.outgoingConnections === undefined) {
207 mgm.outgoingConnections = new SortableSet();
208 }
209 mgm.outgoingConnections.add(connection);
210 } else {
211 this._dependencyMap.set(dependency, connection);
212 }
213 }
214
215 /**
216 * @param {Dependency} dependency the referencing dependency
217 * @param {Module} module the referenced module
218 * @returns {void}
219 */
220 updateModule(dependency, module) {
221 const connection = this.getConnection(dependency);
222 if (connection.module === module) return;
223 const newConnection = connection.clone();
224 newConnection.module = module;
225 this._dependencyMap.set(dependency, newConnection);
226 connection.setActive(false);
227 const originMgm = this._getModuleGraphModule(connection.originModule);
228 originMgm.outgoingConnections.add(newConnection);
229 const targetMgm = this._getModuleGraphModule(module);
230 targetMgm.incomingConnections.add(newConnection);
231 }
232
233 /**
234 * @param {Dependency} dependency the referencing dependency
235 * @returns {void}
236 */
237 removeConnection(dependency) {
238 const connection = this.getConnection(dependency);
239 const targetMgm = this._getModuleGraphModule(connection.module);
240 targetMgm.incomingConnections.delete(connection);
241 const originMgm = this._getModuleGraphModule(connection.originModule);
242 originMgm.outgoingConnections.delete(connection);
243 this._dependencyMap.set(dependency, null);
244 }
245
246 /**
247 * @param {Dependency} dependency the referencing dependency
248 * @param {string} explanation an explanation
249 * @returns {void}
250 */
251 addExplanation(dependency, explanation) {
252 const connection = this.getConnection(dependency);
253 connection.addExplanation(explanation);
254 }
255
256 /**
257 * @param {Module} sourceModule the source module
258 * @param {Module} targetModule the target module
259 * @returns {void}
260 */
261 cloneModuleAttributes(sourceModule, targetModule) {
262 const oldMgm = this._getModuleGraphModule(sourceModule);
263 const newMgm = this._getModuleGraphModule(targetModule);
264 newMgm.postOrderIndex = oldMgm.postOrderIndex;
265 newMgm.preOrderIndex = oldMgm.preOrderIndex;
266 newMgm.depth = oldMgm.depth;
267 newMgm.exports = oldMgm.exports;
268 newMgm.async = oldMgm.async;
269 }
270
271 /**
272 * @param {Module} module the module
273 * @returns {void}
274 */
275 removeModuleAttributes(module) {
276 const mgm = this._getModuleGraphModule(module);
277 mgm.postOrderIndex = null;
278 mgm.preOrderIndex = null;
279 mgm.depth = null;
280 mgm.async = false;
281 }
282
283 /**
284 * @returns {void}
285 */
286 removeAllModuleAttributes() {
287 for (const mgm of this._moduleMap.values()) {
288 mgm.postOrderIndex = null;
289 mgm.preOrderIndex = null;
290 mgm.depth = null;
291 mgm.async = false;
292 }
293 }
294
295 /**
296 * @param {Module} oldModule the old referencing module
297 * @param {Module} newModule the new referencing module
298 * @param {function(ModuleGraphConnection): boolean} filterConnection filter predicate for replacement
299 * @returns {void}
300 */
301 moveModuleConnections(oldModule, newModule, filterConnection) {
302 if (oldModule === newModule) return;
303 const oldMgm = this._getModuleGraphModule(oldModule);
304 const newMgm = this._getModuleGraphModule(newModule);
305 // Outgoing connections
306 const oldConnections = oldMgm.outgoingConnections;
307 if (oldConnections !== undefined) {
308 if (newMgm.outgoingConnections === undefined) {
309 newMgm.outgoingConnections = new SortableSet();
310 }
311 const newConnections = newMgm.outgoingConnections;
312 for (const connection of oldConnections) {
313 if (filterConnection(connection)) {
314 connection.originModule = newModule;
315 newConnections.add(connection);
316 oldConnections.delete(connection);
317 }
318 }
319 }
320 // Incoming connections
321 const oldConnections2 = oldMgm.incomingConnections;
322 const newConnections2 = newMgm.incomingConnections;
323 for (const connection of oldConnections2) {
324 if (filterConnection(connection)) {
325 connection.module = newModule;
326 newConnections2.add(connection);
327 oldConnections2.delete(connection);
328 }
329 }
330 }
331
332 /**
333 * @param {Module} oldModule the old referencing module
334 * @param {Module} newModule the new referencing module
335 * @param {function(ModuleGraphConnection): boolean} filterConnection filter predicate for replacement
336 * @returns {void}
337 */
338 copyOutgoingModuleConnections(oldModule, newModule, filterConnection) {
339 if (oldModule === newModule) return;
340 const oldMgm = this._getModuleGraphModule(oldModule);
341 const newMgm = this._getModuleGraphModule(newModule);
342 // Outgoing connections
343 const oldConnections = oldMgm.outgoingConnections;
344 if (oldConnections !== undefined) {
345 if (newMgm.outgoingConnections === undefined) {
346 newMgm.outgoingConnections = new SortableSet();
347 }
348 const newConnections = newMgm.outgoingConnections;
349 for (const connection of oldConnections) {
350 if (filterConnection(connection)) {
351 const newConnection = connection.clone();
352 newConnection.originModule = newModule;
353 newConnections.add(newConnection);
354 if (newConnection.module !== undefined) {
355 const otherMgm = this._getModuleGraphModule(newConnection.module);
356 otherMgm.incomingConnections.add(newConnection);
357 }
358 }
359 }
360 }
361 }
362
363 /**
364 * @param {Module} module the referenced module
365 * @param {string} explanation an explanation why it's referenced
366 * @returns {void}
367 */
368 addExtraReason(module, explanation) {
369 const connections = this._getModuleGraphModule(module).incomingConnections;
370 connections.add(new ModuleGraphConnection(null, null, module, explanation));
371 }
372
373 /**
374 * @param {Dependency} dependency the dependency to look for a referenced module
375 * @returns {Module} the referenced module
376 */
377 getResolvedModule(dependency) {
378 const connection = this.getConnection(dependency);
379 return connection !== undefined ? connection.resolvedModule : null;
380 }
381
382 /**
383 * @param {Dependency} dependency the dependency to look for a referenced module
384 * @returns {ModuleGraphConnection | undefined} the connection
385 */
386 getConnection(dependency) {
387 const connection = this._dependencyMap.get(dependency);
388 if (connection === undefined) {
389 const module = this.getParentModule(dependency);
390 if (module !== undefined) {
391 const mgm = this._getModuleGraphModule(module);
392 if (
393 mgm._unassignedConnections &&
394 mgm._unassignedConnections.length !== 0
395 ) {
396 let foundConnection;
397 for (const connection of mgm._unassignedConnections) {
398 this._dependencyMap.set(connection.dependency, connection);
399 if (connection.dependency === dependency)
400 foundConnection = connection;
401 }
402 mgm._unassignedConnections.length = 0;
403 if (foundConnection !== undefined) {
404 return foundConnection;
405 }
406 }
407 }
408 this._dependencyMap.set(dependency, null);
409 return undefined;
410 }
411 return connection === null ? undefined : connection;
412 }
413
414 /**
415 * @param {Dependency} dependency the dependency to look for a referenced module
416 * @returns {Module} the referenced module
417 */
418 getModule(dependency) {
419 const connection = this.getConnection(dependency);
420 return connection !== undefined ? connection.module : null;
421 }
422
423 /**
424 * @param {Dependency} dependency the dependency to look for a referencing module
425 * @returns {Module} the referencing module
426 */
427 getOrigin(dependency) {
428 const connection = this.getConnection(dependency);
429 return connection !== undefined ? connection.originModule : null;
430 }
431
432 /**
433 * @param {Dependency} dependency the dependency to look for a referencing module
434 * @returns {Module} the original referencing module
435 */
436 getResolvedOrigin(dependency) {
437 const connection = this.getConnection(dependency);
438 return connection !== undefined ? connection.resolvedOriginModule : null;
439 }
440
441 /**
442 * @param {Module} module the module
443 * @returns {Iterable<ModuleGraphConnection>} reasons why a module is included
444 */
445 getIncomingConnections(module) {
446 const connections = this._getModuleGraphModule(module).incomingConnections;
447 return connections;
448 }
449
450 /**
451 * @param {Module} module the module
452 * @returns {Iterable<ModuleGraphConnection>} list of outgoing connections
453 */
454 getOutgoingConnections(module) {
455 const connections = this._getModuleGraphModule(module).outgoingConnections;
456 return connections === undefined ? EMPTY_SET : connections;
457 }
458
459 /**
460 * @param {Module} module the module
461 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]>} reasons why a module is included, in a map by source module
462 */
463 getIncomingConnectionsByOriginModule(module) {
464 const connections = this._getModuleGraphModule(module).incomingConnections;
465 return connections.getFromUnorderedCache(getConnectionsByOriginModule);
466 }
467
468 /**
469 * @param {Module} module the module
470 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]> | undefined} connections to modules, in a map by module
471 */
472 getOutgoingConnectionsByModule(module) {
473 const connections = this._getModuleGraphModule(module).outgoingConnections;
474 return connections === undefined
475 ? undefined
476 : connections.getFromUnorderedCache(getConnectionsByModule);
477 }
478
479 /**
480 * @param {Module} module the module
481 * @returns {ModuleProfile | null} the module profile
482 */
483 getProfile(module) {
484 const mgm = this._getModuleGraphModule(module);
485 return mgm.profile;
486 }
487
488 /**
489 * @param {Module} module the module
490 * @param {ModuleProfile | null} profile the module profile
491 * @returns {void}
492 */
493 setProfile(module, profile) {
494 const mgm = this._getModuleGraphModule(module);
495 mgm.profile = profile;
496 }
497
498 /**
499 * @param {Module} module the module
500 * @returns {Module | null} the issuer module
501 */
502 getIssuer(module) {
503 const mgm = this._getModuleGraphModule(module);
504 return mgm.issuer;
505 }
506
507 /**
508 * @param {Module} module the module
509 * @param {Module | null} issuer the issuer module
510 * @returns {void}
511 */
512 setIssuer(module, issuer) {
513 const mgm = this._getModuleGraphModule(module);
514 mgm.issuer = issuer;
515 }
516
517 /**
518 * @param {Module} module the module
519 * @param {Module | null} issuer the issuer module
520 * @returns {void}
521 */
522 setIssuerIfUnset(module, issuer) {
523 const mgm = this._getModuleGraphModule(module);
524 if (mgm.issuer === undefined) mgm.issuer = issuer;
525 }
526
527 /**
528 * @param {Module} module the module
529 * @returns {(string | OptimizationBailoutFunction)[]} optimization bailouts
530 */
531 getOptimizationBailout(module) {
532 const mgm = this._getModuleGraphModule(module);
533 return mgm.optimizationBailout;
534 }
535
536 /**
537 * @param {Module} module the module
538 * @returns {true | string[] | null} the provided exports
539 */
540 getProvidedExports(module) {
541 const mgm = this._getModuleGraphModule(module);
542 return mgm.exports.getProvidedExports();
543 }
544
545 /**
546 * @param {Module} module the module
547 * @param {string | string[]} exportName a name of an export
548 * @returns {boolean | null} true, if the export is provided by the module.
549 * null, if it's unknown.
550 * false, if it's not provided.
551 */
552 isExportProvided(module, exportName) {
553 const mgm = this._getModuleGraphModule(module);
554 const result = mgm.exports.isExportProvided(exportName);
555 return result === undefined ? null : result;
556 }
557
558 /**
559 * @param {Module} module the module
560 * @returns {ExportsInfo} info about the exports
561 */
562 getExportsInfo(module) {
563 const mgm = this._getModuleGraphModule(module);
564 return mgm.exports;
565 }
566
567 /**
568 * @param {Module} module the module
569 * @param {string} exportName the export
570 * @returns {ExportInfo} info about the export
571 */
572 getExportInfo(module, exportName) {
573 const mgm = this._getModuleGraphModule(module);
574 return mgm.exports.getExportInfo(exportName);
575 }
576
577 /**
578 * @param {Module} module the module
579 * @param {string} exportName the export
580 * @returns {ExportInfo} info about the export (do not modify)
581 */
582 getReadOnlyExportInfo(module, exportName) {
583 const mgm = this._getModuleGraphModule(module);
584 return mgm.exports.getReadOnlyExportInfo(exportName);
585 }
586
587 /**
588 * @param {Module} module the module
589 * @param {RuntimeSpec} runtime the runtime
590 * @returns {false | true | SortableSet<string> | null} the used exports
591 * false: module is not used at all.
592 * true: the module namespace/object export is used.
593 * SortableSet<string>: these export names are used.
594 * empty SortableSet<string>: module is used but no export.
595 * null: unknown, worst case should be assumed.
596 */
597 getUsedExports(module, runtime) {
598 const mgm = this._getModuleGraphModule(module);
599 return mgm.exports.getUsedExports(runtime);
600 }
601
602 /**
603 * @param {Module} module the module
604 * @returns {number} the index of the module
605 */
606 getPreOrderIndex(module) {
607 const mgm = this._getModuleGraphModule(module);
608 return mgm.preOrderIndex;
609 }
610
611 /**
612 * @param {Module} module the module
613 * @returns {number} the index of the module
614 */
615 getPostOrderIndex(module) {
616 const mgm = this._getModuleGraphModule(module);
617 return mgm.postOrderIndex;
618 }
619
620 /**
621 * @param {Module} module the module
622 * @param {number} index the index of the module
623 * @returns {void}
624 */
625 setPreOrderIndex(module, index) {
626 const mgm = this._getModuleGraphModule(module);
627 mgm.preOrderIndex = index;
628 }
629
630 /**
631 * @param {Module} module the module
632 * @param {number} index the index of the module
633 * @returns {boolean} true, if the index was set
634 */
635 setPreOrderIndexIfUnset(module, index) {
636 const mgm = this._getModuleGraphModule(module);
637 if (mgm.preOrderIndex === null) {
638 mgm.preOrderIndex = index;
639 return true;
640 }
641 return false;
642 }
643
644 /**
645 * @param {Module} module the module
646 * @param {number} index the index of the module
647 * @returns {void}
648 */
649 setPostOrderIndex(module, index) {
650 const mgm = this._getModuleGraphModule(module);
651 mgm.postOrderIndex = index;
652 }
653
654 /**
655 * @param {Module} module the module
656 * @param {number} index the index of the module
657 * @returns {boolean} true, if the index was set
658 */
659 setPostOrderIndexIfUnset(module, index) {
660 const mgm = this._getModuleGraphModule(module);
661 if (mgm.postOrderIndex === null) {
662 mgm.postOrderIndex = index;
663 return true;
664 }
665 return false;
666 }
667
668 /**
669 * @param {Module} module the module
670 * @returns {number} the depth of the module
671 */
672 getDepth(module) {
673 const mgm = this._getModuleGraphModule(module);
674 return mgm.depth;
675 }
676
677 /**
678 * @param {Module} module the module
679 * @param {number} depth the depth of the module
680 * @returns {void}
681 */
682 setDepth(module, depth) {
683 const mgm = this._getModuleGraphModule(module);
684 mgm.depth = depth;
685 }
686
687 /**
688 * @param {Module} module the module
689 * @param {number} depth the depth of the module
690 * @returns {boolean} true, if the depth was set
691 */
692 setDepthIfLower(module, depth) {
693 const mgm = this._getModuleGraphModule(module);
694 if (mgm.depth === null || mgm.depth > depth) {
695 mgm.depth = depth;
696 return true;
697 }
698 return false;
699 }
700
701 /**
702 * @param {Module} module the module
703 * @returns {boolean} true, if the module is async
704 */
705 isAsync(module) {
706 const mgm = this._getModuleGraphModule(module);
707 return mgm.async;
708 }
709
710 /**
711 * @param {Module} module the module
712 * @returns {void}
713 */
714 setAsync(module) {
715 const mgm = this._getModuleGraphModule(module);
716 mgm.async = true;
717 }
718
719 /**
720 * @param {any} thing any thing
721 * @returns {Object} metadata
722 */
723 getMeta(thing) {
724 let meta = this._metaMap.get(thing);
725 if (meta === undefined) {
726 meta = Object.create(null);
727 this._metaMap.set(thing, meta);
728 }
729 return meta;
730 }
731
732 /**
733 * @param {any} thing any thing
734 * @returns {Object} metadata
735 */
736 getMetaIfExisting(thing) {
737 return this._metaMap.get(thing);
738 }
739
740 /**
741 * @param {string=} cacheStage a persistent stage name for caching
742 */
743 freeze(cacheStage) {
744 this._cache = new WeakTupleMap();
745 this._cacheStage = cacheStage;
746 }
747
748 unfreeze() {
749 this._cache = undefined;
750 this._cacheStage = undefined;
751 }
752
753 /**
754 * @template {any[]} T
755 * @template V
756 * @param {(moduleGraph: ModuleGraph, ...args: T) => V} fn computer
757 * @param {T} args arguments
758 * @returns {V} computed value or cached
759 */
760 cached(fn, ...args) {
761 if (this._cache === undefined) return fn(this, ...args);
762 return this._cache.provide(fn, ...args, () => fn(this, ...args));
763 }
764
765 /**
766 * @param {Map<Module, WeakTupleMap<any, any>>} moduleMemCaches mem caches for modules for better caching
767 */
768 setModuleMemCaches(moduleMemCaches) {
769 this._moduleMemCaches = moduleMemCaches;
770 }
771
772 /**
773 * @param {Dependency} dependency dependency
774 * @param {...any} args arguments, last argument is a function called with moduleGraph, dependency, ...args
775 * @returns {any} computed value or cached
776 */
777 dependencyCacheProvide(dependency, ...args) {
778 /** @type {(moduleGraph: ModuleGraph, dependency: Dependency, ...args: any[]) => any} */
779 const fn = args.pop();
780 if (this._moduleMemCaches && this._cacheStage) {
781 const memCache = this._moduleMemCaches.get(
782 this.getParentModule(dependency)
783 );
784 if (memCache !== undefined) {
785 return memCache.provide(dependency, this._cacheStage, ...args, () =>
786 fn(this, dependency, ...args)
787 );
788 }
789 }
790 if (this._cache === undefined) return fn(this, dependency, ...args);
791 return this._cache.provide(dependency, ...args, () =>
792 fn(this, dependency, ...args)
793 );
794 }
795
796 // TODO remove in webpack 6
797 /**
798 * @param {Module} module the module
799 * @param {string} deprecateMessage message for the deprecation message
800 * @param {string} deprecationCode code for the deprecation
801 * @returns {ModuleGraph} the module graph
802 */
803 static getModuleGraphForModule(module, deprecateMessage, deprecationCode) {
804 const fn = deprecateMap.get(deprecateMessage);
805 if (fn) return fn(module);
806 const newFn = util.deprecate(
807 /**
808 * @param {Module} module the module
809 * @returns {ModuleGraph} the module graph
810 */
811 module => {
812 const moduleGraph = moduleGraphForModuleMap.get(module);
813 if (!moduleGraph)
814 throw new Error(
815 deprecateMessage +
816 "There was no ModuleGraph assigned to the Module for backward-compat (Use the new API)"
817 );
818 return moduleGraph;
819 },
820 deprecateMessage + ": Use new ModuleGraph API",
821 deprecationCode
822 );
823 deprecateMap.set(deprecateMessage, newFn);
824 return newFn(module);
825 }
826
827 // TODO remove in webpack 6
828 /**
829 * @param {Module} module the module
830 * @param {ModuleGraph} moduleGraph the module graph
831 * @returns {void}
832 */
833 static setModuleGraphForModule(module, moduleGraph) {
834 moduleGraphForModuleMap.set(module, moduleGraph);
835 }
836
837 // TODO remove in webpack 6
838 /**
839 * @param {Module} module the module
840 * @returns {void}
841 */
842 static clearModuleGraphForModule(module) {
843 moduleGraphForModuleMap.delete(module);
844 }
845}
846
847// TODO remove in webpack 6
848/** @type {WeakMap<Module, ModuleGraph>} */
849const moduleGraphForModuleMap = new WeakMap();
850
851// TODO remove in webpack 6
852/** @type {Map<string, (module: Module) => ModuleGraph>} */
853const deprecateMap = new Map();
854
855module.exports = ModuleGraph;
856module.exports.ModuleGraphConnection = ModuleGraphConnection;