| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {import("./Dependency")} Dependency */ | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | /** @typedef {import("./Dependency").GetConditionFn} GetConditionFn */ | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | /** @typedef {import("./Module")} Module */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */ | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-10-07 15:10:29 +08:00
										 |  |  |  * Module itself is not connected, but transitive modules are connected transitively. | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | const TRANSITIVE_ONLY = Symbol("transitive only"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-10-07 15:10:29 +08:00
										 |  |  |  * While determining the active state, this flag is used to signal a circular connection. | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | const CIRCULAR_CONNECTION = Symbol("circular connection"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {boolean | typeof TRANSITIVE_ONLY | typeof CIRCULAR_CONNECTION} ConnectionState */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {ConnectionState} a first | 
					
						
							|  |  |  |  * @param {ConnectionState} b second | 
					
						
							|  |  |  |  * @returns {ConnectionState} merged | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const addConnectionStates = (a, b) => { | 
					
						
							|  |  |  | 	if (a === true || b === true) return true; | 
					
						
							|  |  |  | 	if (a === false) return b; | 
					
						
							|  |  |  | 	if (b === false) return a; | 
					
						
							|  |  |  | 	if (a === TRANSITIVE_ONLY) return b; | 
					
						
							|  |  |  | 	if (b === TRANSITIVE_ONLY) return a; | 
					
						
							|  |  |  | 	return a; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {ConnectionState} a first | 
					
						
							|  |  |  |  * @param {ConnectionState} b second | 
					
						
							|  |  |  |  * @returns {ConnectionState} intersected | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const intersectConnectionStates = (a, b) => { | 
					
						
							|  |  |  | 	if (a === false || b === false) return false; | 
					
						
							|  |  |  | 	if (a === true) return b; | 
					
						
							|  |  |  | 	if (b === true) return a; | 
					
						
							|  |  |  | 	if (a === CIRCULAR_CONNECTION) return b; | 
					
						
							|  |  |  | 	if (b === CIRCULAR_CONNECTION) return a; | 
					
						
							|  |  |  | 	return a; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | class ModuleGraphConnection { | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2021-02-23 17:59:59 +08:00
										 |  |  | 	 * @param {Module|null} originModule the referencing module | 
					
						
							|  |  |  | 	 * @param {Dependency|null} dependency the referencing dependency | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 	 * @param {Module} module the referenced module | 
					
						
							|  |  |  | 	 * @param {string=} explanation some extra detail | 
					
						
							| 
									
										
										
										
											2019-10-29 18:04:50 +08:00
										 |  |  | 	 * @param {boolean=} weak the reference is weak | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	 * @param {false | null | GetConditionFn | undefined} condition condition for the connection | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 	constructor( | 
					
						
							|  |  |  | 		originModule, | 
					
						
							|  |  |  | 		dependency, | 
					
						
							|  |  |  | 		module, | 
					
						
							|  |  |  | 		explanation, | 
					
						
							|  |  |  | 		weak = false, | 
					
						
							|  |  |  | 		condition = undefined | 
					
						
							|  |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 		this.originModule = originModule; | 
					
						
							| 
									
										
										
										
											2018-08-07 20:20:53 +08:00
										 |  |  | 		this.resolvedOriginModule = originModule; | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 		this.dependency = dependency; | 
					
						
							|  |  |  | 		this.resolvedModule = module; | 
					
						
							|  |  |  | 		this.module = module; | 
					
						
							| 
									
										
										
										
											2019-10-29 18:04:50 +08:00
										 |  |  | 		this.weak = weak; | 
					
						
							| 
									
										
										
										
											2024-07-31 11:11:11 +08:00
										 |  |  | 		this.conditional = Boolean(condition); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:32:09 +08:00
										 |  |  | 		this._active = condition !== false; | 
					
						
							|  |  |  | 		this.condition = condition || undefined; | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 		/** @type {Set<string> | undefined} */ | 
					
						
							| 
									
										
										
										
											2019-11-08 19:22:00 +08:00
										 |  |  | 		this.explanations = undefined; | 
					
						
							| 
									
										
										
										
											2018-11-07 21:03:25 +08:00
										 |  |  | 		if (explanation) { | 
					
						
							| 
									
										
										
										
											2019-11-08 19:22:00 +08:00
										 |  |  | 			this.explanations = new Set(); | 
					
						
							| 
									
										
										
										
											2018-11-07 21:03:25 +08:00
										 |  |  | 			this.explanations.add(explanation); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 16:07:04 +08:00
										 |  |  | 	clone() { | 
					
						
							|  |  |  | 		const clone = new ModuleGraphConnection( | 
					
						
							|  |  |  | 			this.resolvedOriginModule, | 
					
						
							|  |  |  | 			this.dependency, | 
					
						
							|  |  |  | 			this.resolvedModule, | 
					
						
							|  |  |  | 			undefined, | 
					
						
							|  |  |  | 			this.weak, | 
					
						
							|  |  |  | 			this.condition | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		clone.originModule = this.originModule; | 
					
						
							|  |  |  | 		clone.module = this.module; | 
					
						
							|  |  |  | 		clone.conditional = this.conditional; | 
					
						
							|  |  |  | 		clone._active = this._active; | 
					
						
							|  |  |  | 		if (this.explanations) clone.explanations = new Set(this.explanations); | 
					
						
							|  |  |  | 		return clone; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  | 	 * @param {GetConditionFn} condition condition for the connection | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	addCondition(condition) { | 
					
						
							|  |  |  | 		if (this.conditional) { | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 			const old = | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  | 				/** @type {GetConditionFn} */ | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 				(this.condition); | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  | 			/** @type {GetConditionFn} */ | 
					
						
							|  |  |  | 			(this.condition) = (c, r) => | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 				intersectConnectionStates(old(c, r), condition(c, r)); | 
					
						
							| 
									
										
										
										
											2019-10-30 16:34:39 +08:00
										 |  |  | 		} else if (this._active) { | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 			this.conditional = true; | 
					
						
							|  |  |  | 			this.condition = condition; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 21:03:25 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {string} explanation the explanation to add | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 	addExplanation(explanation) { | 
					
						
							| 
									
										
										
										
											2019-11-08 19:22:00 +08:00
										 |  |  | 		if (this.explanations === undefined) { | 
					
						
							|  |  |  | 			this.explanations = new Set(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 		this.explanations.add(explanation); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get explanation() { | 
					
						
							| 
									
										
										
										
											2019-11-08 19:22:00 +08:00
										 |  |  | 		if (this.explanations === undefined) return ""; | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | 		return [...this.explanations].join(" "); | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtime | 
					
						
							|  |  |  | 	 * @returns {boolean} true, if the connection is active | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	isActive(runtime) { | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 		if (!this.conditional) return this._active; | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return ( | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  | 			/** @type {GetConditionFn} */ (this.condition)(this, runtime) !== false | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 		); | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-07 15:10:29 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtime | 
					
						
							|  |  |  | 	 * @returns {boolean} true, if the connection is active | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	isTargetActive(runtime) { | 
					
						
							|  |  |  | 		if (!this.conditional) return this._active; | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 		return ( | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  | 			/** @type {GetConditionFn} */ (this.condition)(this, runtime) === true | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 		); | 
					
						
							| 
									
										
										
										
											2020-10-07 15:10:29 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtime | 
					
						
							|  |  |  | 	 * @returns {ConnectionState} true: fully active, false: inactive, TRANSITIVE: direct module inactive, but transitive connection maybe active | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	getActiveState(runtime) { | 
					
						
							| 
									
										
										
										
											2019-10-30 16:34:39 +08:00
										 |  |  | 		if (!this.conditional) return this._active; | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  | 		return /** @type {GetConditionFn} */ (this.condition)(this, runtime); | 
					
						
							| 
									
										
										
										
											2019-10-30 04:37:59 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-30 16:34:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {boolean} value active or not | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	setActive(value) { | 
					
						
							| 
									
										
										
										
											2019-10-30 16:34:39 +08:00
										 |  |  | 		this.conditional = false; | 
					
						
							|  |  |  | 		this._active = value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-31 09:37:24 +08:00
										 |  |  | 	// TODO webpack 5 remove
 | 
					
						
							|  |  |  | 	get active() { | 
					
						
							|  |  |  | 		throw new Error("Use getActiveState instead"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	set active(value) { | 
					
						
							|  |  |  | 		throw new Error("Use setActive instead"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | /** @typedef {typeof TRANSITIVE_ONLY} TRANSITIVE_ONLY */ | 
					
						
							|  |  |  | /** @typedef {typeof CIRCULAR_CONNECTION} CIRCULAR_CONNECTION */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | module.exports = ModuleGraphConnection; | 
					
						
							| 
									
										
										
										
											2021-05-11 15:31:46 +08:00
										 |  |  | module.exports.CIRCULAR_CONNECTION = /** @type {typeof CIRCULAR_CONNECTION} */ ( | 
					
						
							|  |  |  | 	CIRCULAR_CONNECTION | 
					
						
							|  |  |  | ); | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | module.exports.TRANSITIVE_ONLY = /** @type {typeof TRANSITIVE_ONLY} */ ( | 
					
						
							|  |  |  | 	TRANSITIVE_ONLY | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | module.exports.addConnectionStates = addConnectionStates; |