| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  |  * @template {EXPECTED_ANY[]} T | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  |  * @template V | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  |  * @typedef {Map<EXPECTED_ANY, WeakTupleMap<T, V>>} M | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-04-04 21:38:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  |  * @template {EXPECTED_ANY[]} T | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  |  * @template V | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  |  * @typedef {WeakMap<EXPECTED_OBJECT, WeakTupleMap<T, V>>} W | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  |  * @param {EXPECTED_ANY} thing thing | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  |  * @returns {boolean} true if is weak | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | const isWeakKey = thing => typeof thing === "object" && thing !== null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  |  * @template {unknown[]} T | 
					
						
							|  |  |  |  * @typedef {T extends readonly (infer ElementType)[] ? ElementType : never} ArrayElement | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @template {EXPECTED_ANY[]} K | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  |  * @template V | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class WeakTupleMap { | 
					
						
							|  |  |  | 	constructor() { | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		/** @private */ | 
					
						
							|  |  |  | 		this.f = 0; | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @private | 
					
						
							| 
									
										
										
										
											2025-04-03 00:02:22 +08:00
										 |  |  | 		 * @type {V | undefined} | 
					
						
							| 
									
										
										
										
											2024-06-11 20:32:02 +08:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		this.v = undefined; | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @private | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		 * @type {M<K, V> | undefined} | 
					
						
							| 
									
										
										
										
											2024-06-11 20:32:02 +08:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		this.m = undefined; | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @private | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		 * @type {W<K, V> | undefined} | 
					
						
							| 
									
										
										
										
											2024-06-11 20:32:02 +08:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		this.w = undefined; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {[...K, V]} args tuple | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	set(...args) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		/** @type {WeakTupleMap<K, V>} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		let node = this; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		for (let i = 0; i < args.length - 1; i++) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			node = node._get(/** @type {ArrayElement<K>} */ (args[i])); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		node._setValue(/** @type {V} */ (args[args.length - 1])); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {K} args tuple | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	 * @returns {boolean} true, if the tuple is in the Set | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	has(...args) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		/** @type {WeakTupleMap<K, V> | undefined} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		let node = this; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		for (let i = 0; i < args.length; i++) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			node = node._peek(/** @type {ArrayElement<K>} */ (args[i])); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 			if (node === undefined) return false; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		return node._hasValue(); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {K} args tuple | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	 * @returns {V | undefined} the value | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	get(...args) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		/** @type {WeakTupleMap<K, V> | undefined} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		let node = this; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		for (let i = 0; i < args.length; i++) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			node = node._peek(/** @type {ArrayElement<K>} */ (args[i])); | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 			if (node === undefined) return; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		return node._getValue(); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {[...K, (...args: K) => V]} args tuple | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	 * @returns {V} the value | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	provide(...args) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		/** @type {WeakTupleMap<K, V>} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		let node = this; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		for (let i = 0; i < args.length - 1; i++) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			node = node._get(/** @type {ArrayElement<K>} */ (args[i])); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-04-03 00:02:22 +08:00
										 |  |  | 		if (node._hasValue()) return /** @type {V} */ (node._getValue()); | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		const fn = /** @type {(...args: K) => V} */ (args[args.length - 1]); | 
					
						
							|  |  |  | 		const newValue = fn(.../** @type {K} */ (args.slice(0, -1))); | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		node._setValue(newValue); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		return newValue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {K} args tuple | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	delete(...args) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		/** @type {WeakTupleMap<K, V> | undefined} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		let node = this; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 		for (let i = 0; i < args.length; i++) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			node = node._peek(/** @type {ArrayElement<K>} */ (args[i])); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 			if (node === undefined) return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		node._deleteValue(); | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	clear() { | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		this.f = 0; | 
					
						
							|  |  |  | 		this.v = undefined; | 
					
						
							|  |  |  | 		this.w = undefined; | 
					
						
							|  |  |  | 		this.m = undefined; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_getValue() { | 
					
						
							|  |  |  | 		return this.v; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_hasValue() { | 
					
						
							|  |  |  | 		return (this.f & 1) === 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-03 00:02:22 +08:00
										 |  |  | 	 * @param {V} v value | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	 * @private | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 	_setValue(v) { | 
					
						
							|  |  |  | 		this.f |= 1; | 
					
						
							|  |  |  | 		this.v = v; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_deleteValue() { | 
					
						
							|  |  |  | 		this.f &= 6; | 
					
						
							|  |  |  | 		this.v = undefined; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {ArrayElement<K>} thing thing | 
					
						
							|  |  |  | 	 * @returns {WeakTupleMap<K, V> | undefined} thing | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	 * @private | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 	_peek(thing) { | 
					
						
							|  |  |  | 		if (isWeakKey(thing)) { | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 			if ((this.f & 4) !== 4) return; | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			return /** @type {WeakMap<ArrayElement<K>, WeakTupleMap<K, V>>} */ ( | 
					
						
							|  |  |  | 				this.w | 
					
						
							|  |  |  | 			).get(thing); | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-08-02 02:36:27 +08:00
										 |  |  | 		if ((this.f & 2) !== 2) return; | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		return /** @type {Map<ArrayElement<K>, WeakTupleMap<K, V>>} */ (this.m).get( | 
					
						
							|  |  |  | 			thing | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @private | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {ArrayElement<K>} thing thing | 
					
						
							|  |  |  | 	 * @returns {WeakTupleMap<K, V>} value | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 	_get(thing) { | 
					
						
							|  |  |  | 		if (isWeakKey(thing)) { | 
					
						
							|  |  |  | 			if ((this.f & 4) !== 4) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 				/** @type {W<K, V>} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 				const newMap = new WeakMap(); | 
					
						
							|  |  |  | 				this.f |= 4; | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 				/** @type {WeakTupleMap<K, V>} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 				const newNode = new WeakTupleMap(); | 
					
						
							|  |  |  | 				(this.w = newMap).set(thing, newNode); | 
					
						
							|  |  |  | 				return newNode; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			const entry = /** @type {W<K, V>} */ (this.w).get(thing); | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 			if (entry !== undefined) { | 
					
						
							|  |  |  | 				return entry; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			/** @type {WeakTupleMap<K, V>} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 			const newNode = new WeakTupleMap(); | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			/** @type {W<K, V>} */ | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 			(this.w).set(thing, newNode); | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 			return newNode; | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if ((this.f & 2) !== 2) { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			/** @type {M<K, V>} */ | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 			const newMap = new Map(); | 
					
						
							|  |  |  | 			this.f |= 2; | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			/** @type {WeakTupleMap<K, V>} */ | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 			const newNode = new WeakTupleMap(); | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 			(this.m = newMap).set(thing, newNode); | 
					
						
							| 
									
										
										
										
											2021-09-27 22:31:42 +08:00
										 |  |  | 			return newNode; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		const entry = | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 			/** @type {M<K, V>} */ | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 			(this.m).get(thing); | 
					
						
							|  |  |  | 		if (entry !== undefined) { | 
					
						
							|  |  |  | 			return entry; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		/** @type {WeakTupleMap<K, V>} */ | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		const newNode = new WeakTupleMap(); | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 		/** @type {M<K, V>} */ | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 		(this.m).set(thing, newNode); | 
					
						
							|  |  |  | 		return newNode; | 
					
						
							| 
									
										
										
										
											2021-04-13 23:33:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = WeakTupleMap; |