frail-map
Version:
FrailMap is an extension of WeakMap that supports primitive values using WeakRef.
121 lines (120 loc) • 3.58 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.FrailMap = void 0;
const StrongRef_js_1 = require("./StrongRef.js");
if (typeof WeakRef === "undefined") {
console.warn(`WeakRef is not available at this environment, falling back to simple object references.`);
}
/**
* Strong limbs with a weak grab, a WeakMap that supports scalars.
*
* `size` is not updated until a disposed object is accessed via one of
* these methods: `has`, `get`, `entries`, `forEach`, `keys` or `values`.
*/
class FrailMap extends Map {
constructor(entries) {
super();
if (entries) {
for (const [k, v] of entries) {
this.set(k, v);
}
}
}
/**
* Returns a specified element from the Map object. If the value that is
* associated to the provided key is an object, then you will get a reference
* to that object and any change made to that object will effectively modify
* it inside the Map.
*
* @returns Returns the element associated with the specified key. If no
* element is associated with the specified key or the value has been garbage
* collected, undefined is returned.
*/
get(key) {
const ref = super.get(key);
const val = ref?.deref();
if (val === undefined) {
this.delete(key);
return;
}
return val.data;
}
/**
* @returns boolean indicating whether an element with the specified key
* exists or not, updates size if value has been garbage collected.
*/
has(key) {
return super.has(key) && this.get(key) !== undefined;
}
/**
* Adds a new element with a specified key and value to the Map. If an element
* with the same key already exists, the element will be updated.
*
* A `strong` option can be provided to use a strong reference to act like a
* normal map.
*/
set(key, value, options) {
return super.set(key, (options?.strong || typeof WeakRef === "undefined"
? new StrongRef_js_1.StrongRef({ data: value })
: new WeakRef({ data: value })));
}
/**
* Executes a provided function once per each key/value pair in the Map, in
* insertion order.
*/
forEach(callbackfn, thisArg) {
super.forEach((container, k) => {
const ref = container.deref();
if (ref !== undefined) {
callbackfn.call(thisArg, ref.data, k, this);
}
else {
this.delete(k);
}
});
}
/**
* Returns an iterable of key, value pairs for every entry in the map.
*/
entries() {
const map = new Map();
this.forEach((v, k) => {
map.set(k, v);
});
return map.entries();
}
/**
* Returns an iterable of keys in the map
*/
keys() {
const keys = new Set();
this.forEach((_, k) => {
keys.add(k);
});
return keys.values();
}
/**
* Returns an iterable of values in the map
*/
values() {
const keys = new Set();
this.forEach((v) => {
keys.add(v);
});
return keys.values();
}
[Symbol.iterator]() {
return this.entries();
}
get [Symbol.toStringTag]() {
return "FrailMap";
}
toJSON() {
const json = {};
this.forEach((v, k) => {
json[k] = v;
});
return json;
}
}
exports.FrailMap = FrailMap;
;