| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const SortableSet = require("./SortableSet"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {import("../Compilation")} Compilation */ | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | /** @typedef {import("../Entrypoint").EntryOptions} EntryOptions */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {string | SortableSet<string> | undefined} RuntimeSpec */ | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | /** @typedef {RuntimeSpec | boolean} RuntimeCondition */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {Compilation} compilation the compilation | 
					
						
							|  |  |  |  * @param {string} name name of the entry | 
					
						
							|  |  |  |  * @param {EntryOptions=} options optionally already received entry options | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  |  * @returns {RuntimeSpec} runtime | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const getEntryRuntime = (compilation, name, options) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	let dependOn; | 
					
						
							|  |  |  | 	let runtime; | 
					
						
							|  |  |  | 	if (options) { | 
					
						
							|  |  |  | 		({ dependOn, runtime } = options); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		const entry = compilation.entries.get(name); | 
					
						
							|  |  |  | 		if (!entry) return name; | 
					
						
							|  |  |  | 		({ dependOn, runtime } = entry.options); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 	if (dependOn) { | 
					
						
							|  |  |  | 		/** @type {RuntimeSpec} */ | 
					
						
							| 
									
										
										
										
											2024-07-31 06:15:03 +08:00
										 |  |  | 		let result; | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 		const queue = new Set(dependOn); | 
					
						
							|  |  |  | 		for (const name of queue) { | 
					
						
							|  |  |  | 			const dep = compilation.entries.get(name); | 
					
						
							|  |  |  | 			if (!dep) continue; | 
					
						
							|  |  |  | 			const { dependOn, runtime } = dep.options; | 
					
						
							|  |  |  | 			if (dependOn) { | 
					
						
							|  |  |  | 				for (const name of dependOn) { | 
					
						
							|  |  |  | 					queue.add(name); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				result = mergeRuntimeOwned(result, runtime || name); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-15 03:08:14 +08:00
										 |  |  | 		return result || name; | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	return runtime || name; | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime runtime | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  |  * @param {(runtime: string | undefined) => void} fn functor | 
					
						
							| 
									
										
										
										
											2021-01-25 00:14:13 +08:00
										 |  |  |  * @param {boolean} deterministicOrder enforce a deterministic order | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  |  * @returns {void} | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-02-07 17:01:44 +08:00
										 |  |  | const forEachRuntime = (runtime, fn, deterministicOrder = false) => { | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 	if (runtime === undefined) { | 
					
						
							|  |  |  | 		fn(undefined); | 
					
						
							|  |  |  | 	} else if (typeof runtime === "string") { | 
					
						
							|  |  |  | 		fn(runtime); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2021-01-25 00:14:13 +08:00
										 |  |  | 		if (deterministicOrder) runtime.sort(); | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 		for (const r of runtime) { | 
					
						
							|  |  |  | 			fn(r); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  * @param {SortableSet<T>} set set | 
					
						
							|  |  |  |  * @returns {string} runtime key | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const getRuntimesKey = (set) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	set.sort(); | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | 	return [...set].join("\n"); | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime runtime(s) | 
					
						
							|  |  |  |  * @returns {string} key of runtimes | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const getRuntimeKey = (runtime) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	if (runtime === undefined) return "*"; | 
					
						
							|  |  |  | 	if (typeof runtime === "string") return runtime; | 
					
						
							|  |  |  | 	return runtime.getFromUnorderedCache(getRuntimesKey); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 06:19:39 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {string} key key of runtimes | 
					
						
							|  |  |  |  * @returns {RuntimeSpec} runtime(s) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const keyToRuntime = (key) => { | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 	if (key === "*") return; | 
					
						
							| 
									
										
										
										
											2020-09-04 06:19:39 +08:00
										 |  |  | 	const items = key.split("\n"); | 
					
						
							|  |  |  | 	if (items.length === 1) return items[0]; | 
					
						
							|  |  |  | 	return new SortableSet(items); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  * @param {SortableSet<T>} set set | 
					
						
							|  |  |  |  * @returns {string} runtime string | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const getRuntimesString = (set) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	set.sort(); | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | 	return [...set].join("+"); | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime runtime(s) | 
					
						
							|  |  |  |  * @returns {string} readable version | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const runtimeToString = (runtime) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	if (runtime === undefined) return "*"; | 
					
						
							|  |  |  | 	if (typeof runtime === "string") return runtime; | 
					
						
							|  |  |  | 	return runtime.getFromUnorderedCache(getRuntimesString); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeCondition} runtimeCondition runtime condition | 
					
						
							|  |  |  |  * @returns {string} readable version | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const runtimeConditionToString = (runtimeCondition) => { | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | 	if (runtimeCondition === true) return "true"; | 
					
						
							|  |  |  | 	if (runtimeCondition === false) return "false"; | 
					
						
							|  |  |  | 	return runtimeToString(runtimeCondition); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} a first | 
					
						
							|  |  |  |  * @param {RuntimeSpec} b second | 
					
						
							|  |  |  |  * @returns {boolean} true, when they are equal | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | const runtimeEqual = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	if (a === b) { | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} else if ( | 
					
						
							|  |  |  | 		a === undefined || | 
					
						
							|  |  |  | 		b === undefined || | 
					
						
							|  |  |  | 		typeof a === "string" || | 
					
						
							|  |  |  | 		typeof b === "string" | 
					
						
							|  |  |  | 	) { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} else if (a.size !== b.size) { | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	a.sort(); | 
					
						
							|  |  |  | 	b.sort(); | 
					
						
							|  |  |  | 	const aIt = a[Symbol.iterator](); | 
					
						
							|  |  |  | 	const bIt = b[Symbol.iterator](); | 
					
						
							|  |  |  | 	for (;;) { | 
					
						
							|  |  |  | 		const aV = aIt.next(); | 
					
						
							|  |  |  | 		if (aV.done) return true; | 
					
						
							|  |  |  | 		const bV = bIt.next(); | 
					
						
							|  |  |  | 		if (aV.value !== bV.value) return false; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} a first | 
					
						
							|  |  |  |  * @param {RuntimeSpec} b second | 
					
						
							|  |  |  |  * @returns {-1|0|1} compare | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const compareRuntime = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	if (a === b) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} else if (a === undefined) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} else if (b === undefined) { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	const aKey = getRuntimeKey(a); | 
					
						
							|  |  |  | 	const bKey = getRuntimeKey(b); | 
					
						
							|  |  |  | 	if (aKey < bKey) return -1; | 
					
						
							|  |  |  | 	if (aKey > bKey) return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} a first | 
					
						
							|  |  |  |  * @param {RuntimeSpec} b second | 
					
						
							|  |  |  |  * @returns {RuntimeSpec} merged | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | const mergeRuntime = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	if (a === undefined) { | 
					
						
							|  |  |  | 		return b; | 
					
						
							|  |  |  | 	} else if (b === undefined) { | 
					
						
							|  |  |  | 		return a; | 
					
						
							|  |  |  | 	} else if (a === b) { | 
					
						
							|  |  |  | 		return a; | 
					
						
							|  |  |  | 	} else if (typeof a === "string") { | 
					
						
							|  |  |  | 		if (typeof b === "string") { | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 			const set = new SortableSet(); | 
					
						
							|  |  |  | 			set.add(a); | 
					
						
							|  |  |  | 			set.add(b); | 
					
						
							|  |  |  | 			return set; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 		} else if (b.has(a)) { | 
					
						
							|  |  |  | 			return b; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		const set = new SortableSet(b); | 
					
						
							|  |  |  | 		set.add(a); | 
					
						
							|  |  |  | 		return set; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof b === "string") { | 
					
						
							|  |  |  | 		if (a.has(b)) return a; | 
					
						
							|  |  |  | 		const set = new SortableSet(a); | 
					
						
							|  |  |  | 		set.add(b); | 
					
						
							|  |  |  | 		return set; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	const set = new SortableSet(a); | 
					
						
							|  |  |  | 	for (const item of b) set.add(item); | 
					
						
							|  |  |  | 	if (set.size === a.size) return a; | 
					
						
							|  |  |  | 	return set; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeCondition} a first | 
					
						
							|  |  |  |  * @param {RuntimeCondition} b second | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime full runtime | 
					
						
							|  |  |  |  * @returns {RuntimeCondition} result | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const mergeRuntimeCondition = (a, b, runtime) => { | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | 	if (a === false) return b; | 
					
						
							|  |  |  | 	if (b === false) return a; | 
					
						
							|  |  |  | 	if (a === true || b === true) return true; | 
					
						
							|  |  |  | 	const merged = mergeRuntime(a, b); | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 	if (merged === undefined) return; | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | 	if (typeof merged === "string") { | 
					
						
							|  |  |  | 		if (typeof runtime === "string" && merged === runtime) return true; | 
					
						
							|  |  |  | 		return merged; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof runtime === "string" || runtime === undefined) return merged; | 
					
						
							|  |  |  | 	if (merged.size === runtime.size) return true; | 
					
						
							|  |  |  | 	return merged; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec | true} a first | 
					
						
							|  |  |  |  * @param {RuntimeSpec | true} b second | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime full runtime | 
					
						
							|  |  |  |  * @returns {RuntimeSpec | true} result | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const mergeRuntimeConditionNonFalse = (a, b, runtime) => { | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | 	if (a === true || b === true) return true; | 
					
						
							|  |  |  | 	const merged = mergeRuntime(a, b); | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 	if (merged === undefined) return; | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | 	if (typeof merged === "string") { | 
					
						
							|  |  |  | 		if (typeof runtime === "string" && merged === runtime) return true; | 
					
						
							|  |  |  | 		return merged; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof runtime === "string" || runtime === undefined) return merged; | 
					
						
							|  |  |  | 	if (merged.size === runtime.size) return true; | 
					
						
							|  |  |  | 	return merged; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} a first (may be modified) | 
					
						
							|  |  |  |  * @param {RuntimeSpec} b second | 
					
						
							|  |  |  |  * @returns {RuntimeSpec} merged | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const mergeRuntimeOwned = (a, b) => { | 
					
						
							|  |  |  | 	if (b === undefined) { | 
					
						
							|  |  |  | 		return a; | 
					
						
							|  |  |  | 	} else if (a === b) { | 
					
						
							|  |  |  | 		return a; | 
					
						
							|  |  |  | 	} else if (a === undefined) { | 
					
						
							|  |  |  | 		if (typeof b === "string") { | 
					
						
							| 
									
										
										
										
											2021-02-03 03:26:52 +08:00
										 |  |  | 			return b; | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		return new SortableSet(b); | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 	} else if (typeof a === "string") { | 
					
						
							|  |  |  | 		if (typeof b === "string") { | 
					
						
							|  |  |  | 			const set = new SortableSet(); | 
					
						
							|  |  |  | 			set.add(a); | 
					
						
							|  |  |  | 			set.add(b); | 
					
						
							|  |  |  | 			return set; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		const set = new SortableSet(b); | 
					
						
							|  |  |  | 		set.add(a); | 
					
						
							|  |  |  | 		return set; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof b === "string") { | 
					
						
							|  |  |  | 		a.add(b); | 
					
						
							|  |  |  | 		return a; | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	for (const item of b) a.add(item); | 
					
						
							|  |  |  | 	return a; | 
					
						
							| 
									
										
										
										
											2020-07-30 17:18:09 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} a first | 
					
						
							|  |  |  |  * @param {RuntimeSpec} b second | 
					
						
							|  |  |  |  * @returns {RuntimeSpec} merged | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const intersectRuntime = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	if (a === undefined) { | 
					
						
							|  |  |  | 		return b; | 
					
						
							|  |  |  | 	} else if (b === undefined) { | 
					
						
							|  |  |  | 		return a; | 
					
						
							|  |  |  | 	} else if (a === b) { | 
					
						
							|  |  |  | 		return a; | 
					
						
							|  |  |  | 	} else if (typeof a === "string") { | 
					
						
							|  |  |  | 		if (typeof b === "string") { | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 		} else if (b.has(a)) { | 
					
						
							|  |  |  | 			return a; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof b === "string") { | 
					
						
							|  |  |  | 		if (a.has(b)) return b; | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	const set = new SortableSet(); | 
					
						
							|  |  |  | 	for (const item of b) { | 
					
						
							|  |  |  | 		if (a.has(item)) set.add(item); | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 	if (set.size === 0) return; | 
					
						
							| 
									
										
										
										
											2024-07-31 13:38:50 +08:00
										 |  |  | 	if (set.size === 1) { | 
					
						
							|  |  |  | 		const [item] = set; | 
					
						
							|  |  |  | 		return item; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	return set; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} a first | 
					
						
							|  |  |  |  * @param {RuntimeSpec} b second | 
					
						
							|  |  |  |  * @returns {RuntimeSpec} result | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const subtractRuntime = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 	if (a === undefined) { | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 	} else if (b === undefined) { | 
					
						
							|  |  |  | 		return a; | 
					
						
							|  |  |  | 	} else if (a === b) { | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 	} else if (typeof a === "string") { | 
					
						
							|  |  |  | 		if (typeof b === "string") { | 
					
						
							| 
									
										
										
										
											2021-04-07 21:50:28 +08:00
										 |  |  | 			return a; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 		} else if (b.has(a)) { | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		return a; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof b === "string") { | 
					
						
							|  |  |  | 		if (!a.has(b)) return a; | 
					
						
							|  |  |  | 		if (a.size === 2) { | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 			for (const item of a) { | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 				if (item !== b) return item; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		const set = new SortableSet(a); | 
					
						
							|  |  |  | 		set.delete(b); | 
					
						
							|  |  |  | 		return set; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	const set = new SortableSet(); | 
					
						
							|  |  |  | 	for (const item of a) { | 
					
						
							|  |  |  | 		if (!b.has(item)) set.add(item); | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 	if (set.size === 0) return; | 
					
						
							| 
									
										
										
										
											2024-07-31 13:38:50 +08:00
										 |  |  | 	if (set.size === 1) { | 
					
						
							|  |  |  | 		const [item] = set; | 
					
						
							|  |  |  | 		return item; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 	return set; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeCondition} a first | 
					
						
							|  |  |  |  * @param {RuntimeCondition} b second | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime runtime | 
					
						
							|  |  |  |  * @returns {RuntimeCondition} result | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const subtractRuntimeCondition = (a, b, runtime) => { | 
					
						
							| 
									
										
										
										
											2020-10-30 00:53:56 +08:00
										 |  |  | 	if (b === true) return false; | 
					
						
							|  |  |  | 	if (b === false) return a; | 
					
						
							|  |  |  | 	if (a === false) return false; | 
					
						
							|  |  |  | 	const result = subtractRuntime(a === true ? runtime : a, b); | 
					
						
							|  |  |  | 	return result === undefined ? false : result; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime runtime | 
					
						
							| 
									
										
										
										
											2025-03-12 09:56:14 +08:00
										 |  |  |  * @param {(runtime?: RuntimeSpec) => boolean} filter filter function | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  |  * @returns {boolean | RuntimeSpec} true/false if filter is constant for all runtimes, otherwise runtimes that are active | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const filterRuntime = (runtime, filter) => { | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 	if (runtime === undefined) return filter(); | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 	if (typeof runtime === "string") return filter(runtime); | 
					
						
							|  |  |  | 	let some = false; | 
					
						
							|  |  |  | 	let every = true; | 
					
						
							| 
									
										
										
										
											2024-07-31 06:15:03 +08:00
										 |  |  | 	let result; | 
					
						
							| 
									
										
										
										
											2020-10-23 20:52:23 +08:00
										 |  |  | 	for (const r of runtime) { | 
					
						
							|  |  |  | 		const v = filter(r); | 
					
						
							|  |  |  | 		if (v) { | 
					
						
							|  |  |  | 			some = true; | 
					
						
							|  |  |  | 			result = mergeRuntimeOwned(result, r); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			every = false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!some) return false; | 
					
						
							|  |  |  | 	if (every) return true; | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  * @typedef {Map<string, T>} RuntimeSpecMapInnerMap | 
					
						
							| 
									
										
										
										
											2024-06-11 20:32:02 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  |  * @template [R=T] | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | class RuntimeSpecMap { | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 	 * @param {RuntimeSpecMap<T, R>=} clone copy form this | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	constructor(clone) { | 
					
						
							| 
									
										
										
										
											2025-04-17 06:54:48 +08:00
										 |  |  | 		/** @type {0 | 1 | 2} */ | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		this._mode = clone ? clone._mode : 0; // 0 = empty, 1 = single entry, 2 = map
 | 
					
						
							|  |  |  | 		/** @type {RuntimeSpec} */ | 
					
						
							|  |  |  | 		this._singleRuntime = clone ? clone._singleRuntime : undefined; | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 		/** @type {R | undefined} */ | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		this._singleValue = clone ? clone._singleValue : undefined; | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 		/** @type {RuntimeSpecMapInnerMap<R> | undefined} */ | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		this._map = clone && clone._map ? new Map(clone._map) : undefined; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtimes | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 	 * @returns {R | undefined} value | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	get(runtime) { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 				return; | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 			case 1: | 
					
						
							|  |  |  | 				return runtimeEqual(this._singleRuntime, runtime) | 
					
						
							|  |  |  | 					? this._singleValue | 
					
						
							|  |  |  | 					: undefined; | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).get( | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 					getRuntimeKey(runtime) | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtimes | 
					
						
							|  |  |  | 	 * @returns {boolean} true, when the runtime is stored | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	has(runtime) { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 			case 1: | 
					
						
							|  |  |  | 				return runtimeEqual(this._singleRuntime, runtime); | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).has( | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 					getRuntimeKey(runtime) | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtimes | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 	 * @param {R} value the value | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	set(runtime, value) { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				this._mode = 1; | 
					
						
							|  |  |  | 				this._singleRuntime = runtime; | 
					
						
							|  |  |  | 				this._singleValue = value; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case 1: | 
					
						
							|  |  |  | 				if (runtimeEqual(this._singleRuntime, runtime)) { | 
					
						
							|  |  |  | 					this._singleValue = value; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				this._mode = 2; | 
					
						
							|  |  |  | 				this._map = new Map(); | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				this._map.set( | 
					
						
							|  |  |  | 					getRuntimeKey(this._singleRuntime), | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 					/** @type {R} */ (this._singleValue) | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 				this._singleRuntime = undefined; | 
					
						
							|  |  |  | 				this._singleValue = undefined; | 
					
						
							|  |  |  | 			/* falls through */ | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				/** @type {RuntimeSpecMapInnerMap<R>} */ | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				(this._map).set(getRuntimeKey(runtime), value); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtimes | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 	 * @param {() => R} computer function to compute the value | 
					
						
							|  |  |  | 	 * @returns {R} the new value | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-01-25 00:14:13 +08:00
										 |  |  | 	provide(runtime, computer) { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				this._mode = 1; | 
					
						
							|  |  |  | 				this._singleRuntime = runtime; | 
					
						
							|  |  |  | 				return (this._singleValue = computer()); | 
					
						
							|  |  |  | 			case 1: { | 
					
						
							|  |  |  | 				if (runtimeEqual(this._singleRuntime, runtime)) { | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 					return /** @type {R} */ (this._singleValue); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				this._mode = 2; | 
					
						
							|  |  |  | 				this._map = new Map(); | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				this._map.set( | 
					
						
							|  |  |  | 					getRuntimeKey(this._singleRuntime), | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 					/** @type {R} */ | 
					
						
							|  |  |  | 					(this._singleValue) | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 				this._singleRuntime = undefined; | 
					
						
							|  |  |  | 				this._singleValue = undefined; | 
					
						
							|  |  |  | 				const newValue = computer(); | 
					
						
							|  |  |  | 				this._map.set(getRuntimeKey(runtime), newValue); | 
					
						
							|  |  |  | 				return newValue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			default: { | 
					
						
							|  |  |  | 				const key = getRuntimeKey(runtime); | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				const value = | 
					
						
							|  |  |  | 					/** @type {RuntimeSpecMapInnerMap<R>} */ | 
					
						
							|  |  |  | 					(this._map).get(key); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 				if (value !== undefined) return value; | 
					
						
							|  |  |  | 				const newValue = computer(); | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				/** @type {RuntimeSpecMapInnerMap<R>} */ | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				(this._map).set(key, newValue); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 				return newValue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-01-25 00:14:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-12 22:21:21 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtimes | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	delete(runtime) { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			case 1: | 
					
						
							|  |  |  | 				if (runtimeEqual(this._singleRuntime, runtime)) { | 
					
						
							|  |  |  | 					this._mode = 0; | 
					
						
							|  |  |  | 					this._singleRuntime = undefined; | 
					
						
							|  |  |  | 					this._singleValue = undefined; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				/** @type {RuntimeSpecMapInnerMap<R>} */ | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				(this._map).delete(getRuntimeKey(runtime)); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime the runtimes | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 	 * @param {(value: R | undefined) => R} fn function to update the value | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	update(runtime, fn) { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				throw new Error("runtime passed to update must exist"); | 
					
						
							|  |  |  | 			case 1: { | 
					
						
							|  |  |  | 				if (runtimeEqual(this._singleRuntime, runtime)) { | 
					
						
							|  |  |  | 					this._singleValue = fn(this._singleValue); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				const newValue = fn(undefined); | 
					
						
							|  |  |  | 				if (newValue !== undefined) { | 
					
						
							|  |  |  | 					this._mode = 2; | 
					
						
							|  |  |  | 					this._map = new Map(); | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 					this._map.set( | 
					
						
							|  |  |  | 						getRuntimeKey(this._singleRuntime), | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 						/** @type {R} */ | 
					
						
							|  |  |  | 						(this._singleValue) | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 					); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 					this._singleRuntime = undefined; | 
					
						
							|  |  |  | 					this._singleValue = undefined; | 
					
						
							|  |  |  | 					this._map.set(getRuntimeKey(runtime), newValue); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			default: { | 
					
						
							|  |  |  | 				const key = getRuntimeKey(runtime); | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				const oldValue = | 
					
						
							|  |  |  | 					/** @type {RuntimeSpecMapInnerMap<R>} */ | 
					
						
							|  |  |  | 					(this._map).get(key); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 				const newValue = fn(oldValue); | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 				if (newValue !== oldValue) { | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 					/** @type {RuntimeSpecMapInnerMap<R>} */ | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 					(this._map).set(key, newValue); | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	keys() { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				return []; | 
					
						
							|  |  |  | 			case 1: | 
					
						
							|  |  |  | 				return [this._singleRuntime]; | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 				return Array.from( | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 					/** @type {RuntimeSpecMapInnerMap<R>} */ | 
					
						
							| 
									
										
										
										
											2023-06-22 05:55:05 +08:00
										 |  |  | 					(this._map).keys(), | 
					
						
							|  |  |  | 					keyToRuntime | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 02:32:49 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 	 * @returns {IterableIterator<R>} values | 
					
						
							| 
									
										
										
										
											2024-09-11 02:32:49 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	values() { | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		switch (this._mode) { | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				return [][Symbol.iterator](); | 
					
						
							|  |  |  | 			case 1: | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				return [/** @type {R} */ (this._singleValue)][Symbol.iterator](); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 				return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).values(); | 
					
						
							| 
									
										
										
										
											2021-01-27 20:36:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get size() { | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 		if (/** @type {number} */ (this._mode) <= 1) { | 
					
						
							|  |  |  | 			return /** @type {number} */ (this._mode); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-07 21:09:05 +08:00
										 |  |  | 		return /** @type {RuntimeSpecMapInnerMap<R>} */ (this._map).size; | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RuntimeSpecSet { | 
					
						
							| 
									
										
										
										
											2023-06-12 22:21:21 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {Iterable<RuntimeSpec>=} iterable iterable | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	constructor(iterable) { | 
					
						
							|  |  |  | 		/** @type {Map<string, RuntimeSpec>} */ | 
					
						
							|  |  |  | 		this._map = new Map(); | 
					
						
							|  |  |  | 		if (iterable) { | 
					
						
							|  |  |  | 			for (const item of iterable) { | 
					
						
							|  |  |  | 				this.add(item); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-12 22:21:21 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime runtime | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	add(runtime) { | 
					
						
							|  |  |  | 		this._map.set(getRuntimeKey(runtime), runtime); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-12 22:21:21 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuntimeSpec} runtime runtime | 
					
						
							|  |  |  | 	 * @returns {boolean} true, when the runtime exists | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 	has(runtime) { | 
					
						
							|  |  |  | 		return this._map.has(getRuntimeKey(runtime)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 02:32:49 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @returns {IterableIterator<RuntimeSpec>} iterable iterator | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 	[Symbol.iterator]() { | 
					
						
							|  |  |  | 		return this._map.values(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get size() { | 
					
						
							|  |  |  | 		return this._map.size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | module.exports.RuntimeSpecMap = RuntimeSpecMap; | 
					
						
							| 
									
										
										
										
											2024-07-31 04:54:55 +08:00
										 |  |  | module.exports.RuntimeSpecSet = RuntimeSpecSet; | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | module.exports.compareRuntime = compareRuntime; | 
					
						
							|  |  |  | module.exports.filterRuntime = filterRuntime; | 
					
						
							|  |  |  | module.exports.forEachRuntime = forEachRuntime; | 
					
						
							|  |  |  | module.exports.getEntryRuntime = getEntryRuntime; | 
					
						
							|  |  |  | module.exports.getRuntimeKey = getRuntimeKey; | 
					
						
							|  |  |  | module.exports.intersectRuntime = intersectRuntime; | 
					
						
							|  |  |  | module.exports.keyToRuntime = keyToRuntime; | 
					
						
							|  |  |  | module.exports.mergeRuntime = mergeRuntime; | 
					
						
							|  |  |  | module.exports.mergeRuntimeCondition = mergeRuntimeCondition; | 
					
						
							|  |  |  | module.exports.mergeRuntimeConditionNonFalse = mergeRuntimeConditionNonFalse; | 
					
						
							|  |  |  | module.exports.mergeRuntimeOwned = mergeRuntimeOwned; | 
					
						
							|  |  |  | module.exports.runtimeConditionToString = runtimeConditionToString; | 
					
						
							|  |  |  | module.exports.runtimeEqual = runtimeEqual; | 
					
						
							|  |  |  | module.exports.runtimeToString = runtimeToString; | 
					
						
							|  |  |  | module.exports.subtractRuntime = subtractRuntime; | 
					
						
							|  |  |  | module.exports.subtractRuntimeCondition = subtractRuntimeCondition; |