Files
airllm-fork-nodejs/node_modules/lifecycle-utils/dist/WeakValueMultiKeyMap.js
2026-02-05 15:27:49 +08:00

140 lines
4.0 KiB
JavaScript

import { MultiKeyMap } from "./MultiKeyMap.js";
/**
* A utility class that works like a `Map`,
* but accepts multiple values as the key for each value,
* and does not keep strong references to the values (allowing them to be garbage collected).
*
* When a value is garbage collected, it is automatically removed from the map.
*/
export class WeakValueMultiKeyMap {
/** @internal */ _map = new MultiKeyMap();
constructor(entries) {
if (entries != null) {
for (const [key, value] of entries)
this.set(key, value);
}
}
/**
* Add or update a value for a given key.
*
* Time complexity: O(1), given that the length of the key is constant.
*/
set(key, value) {
const currentWeakValue = this._map.get(key);
if (currentWeakValue != null) {
const currentValue = currentWeakValue.ref.deref();
if (currentValue != null)
currentWeakValue.tracker.unregister(currentValue);
}
const weakValue = {
ref: new WeakRef(value),
tracker: null // will be set below
};
weakValue.tracker = new FinalizationRegistry(this._finalize.bind(this, weakValue));
weakValue.tracker.register(value, key.slice());
this._map.set(key, weakValue);
return this;
}
/**
* Get a value for a given key.
*
* Time complexity: O(1), given that the length of the key is constant.
*/
get(key) {
const weakValue = this._map.get(key);
if (weakValue == null)
return undefined;
const value = weakValue.ref.deref();
/* c8 ignore start */
if (value == null) {
this._map.delete(key);
return undefined;
} /* c8 ignore stop */
return value;
}
/**
* Check if a value exists for a given key.
*
* Time complexity: O(1), given that the length of the key is constant.
*/
has(key) {
return this.get(key) != null;
}
/**
* Delete the value for a given key.
*
* Time complexity: O(1), given that the length of the key is constant.
*/
delete(key) {
const weakValue = this._map.get(key);
if (weakValue == null)
return false;
const value = weakValue.ref.deref();
if (value != null)
weakValue.tracker.unregister(value);
this._map.delete(key);
return true;
}
/**
* Clear all values from the map.
*/
clear() {
for (const [, weakValue] of this._map.entries()) {
const value = weakValue.ref.deref();
if (value != null)
weakValue.tracker.unregister(value);
}
this._map.clear();
}
/**
* Get the number of entries in the map.
*/
get size() {
return this._map.size;
}
/**
* Get an iterator for all entries in the map.
*/
*entries() {
for (const [key, weakValue] of this._map.entries()) {
const value = weakValue.ref.deref();
if (value != null)
yield [key, value];
}
}
/**
* Get an iterator for all keys in the map.
*/
*keys() {
for (const [key] of this.entries())
yield key;
}
/**
* Get an iterator for all values in the map.
*/
*values() {
for (const [, value] of this.entries())
yield value;
}
/**
* Call a function for each entry in the map.
*/
forEach(callbackfn, thisArg) {
for (const [key, value] of this.entries()) {
if (thisArg !== undefined)
callbackfn.call(thisArg, value, key, this);
else
callbackfn.call(this, value, key, this);
}
}
[Symbol.iterator]() {
return this.entries();
}
/** @internal */
_finalize(value, key) {
const weakValue = this._map.get(key);
if (weakValue === value)
this._map.delete(key);
}
}
//# sourceMappingURL=WeakValueMultiKeyMap.js.map