Skip to content

Commit

Permalink
feat: add size property (#10)
Browse files Browse the repository at this point in the history
closes #1
  • Loading branch information
lsndr authored Aug 11, 2023
1 parent 656319c commit cb22cd6
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ map.get('key');

## API

#### size: number

Returns the number of values in the `WeakFlyweightSet` object.

> :warning: Number of values is not precise due to nature of `FinalizationRegistry` object.
#### set(any, object): this

The `set()` method adds or updates an element with a specified key and an object to a `WeakIdentityMap` object.
Expand Down
11 changes: 11 additions & 0 deletions src/weak-identity-map.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
export class WeakIdentityMap<K, V extends object> {
#size: number;
#map: Map<K, WeakRef<V>>;
#registry: FinalizationRegistry<{ key: K; ref: WeakRef<V> }>;

constructor() {
this.#size = 0;
this.#map = new Map();
this.#registry = new FinalizationRegistry((heldValue) => {
const ref = this.#map.get(heldValue.key);

if (ref === heldValue.ref) {
this.#size--;
this.#map.delete(heldValue.key);
}
});
Expand All @@ -25,11 +28,13 @@ export class WeakIdentityMap<K, V extends object> {
const oldValue = this.#map.get(key)?.deref();

if (typeof oldValue !== 'undefined') {
this.#size--;
this.#registry.unregister(oldValue);
}

const ref = new WeakRef<V>(value);

this.#size++;
this.#map.set(key, ref);
this.#registry.register(value, { key, ref });

Expand All @@ -40,6 +45,7 @@ export class WeakIdentityMap<K, V extends object> {
const value = this.#map.get(key)?.deref();

if (typeof value !== 'undefined') {
this.#size--;
this.#registry.unregister(value);
}

Expand All @@ -59,6 +65,7 @@ export class WeakIdentityMap<K, V extends object> {
}
}

this.#size = 0;
this.#map.clear();
}

Expand Down Expand Up @@ -132,4 +139,8 @@ export class WeakIdentityMap<K, V extends object> {
next,
};
}

get size() {
return this.#size;
}
}
11 changes: 11 additions & 0 deletions test/weak-identity-map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('WeakIdentityMap', () => {
map.set(1, entity);

expect(map.has(1)).toBeTruthy();
expect(map.size).toBe(1);
expect(typeof map.get(1) === 'object' && map.get(1) !== null).toBeTruthy();
expect(map.get(1)).toBe(entity);
});
Expand All @@ -25,6 +26,7 @@ describe('WeakIdentityMap', () => {
map.set(1, entity);
map.set(2, entity);

expect(map.size).toBe(2);
expect(map.has(1)).toBeTruthy();
expect(map.has(2)).toBeTruthy();
expect(Array.from(map.values()).length).toBe(2);
Expand All @@ -35,6 +37,9 @@ describe('WeakIdentityMap', () => {
gc();

try {
// TODO: figure out how to force calling FinalizationRegistry callback without mocking it
// expect(map.size).toBe(0);

expect(map.has(1)).toBeFalsy();
expect(map.has(2)).toBeFalsy();

Expand All @@ -60,6 +65,7 @@ describe('WeakIdentityMap', () => {
gc();

try {
expect(map.size).toBe(1);
expect(map.has(1)).toBeTruthy();
expect(map.get(1)).toBe(entity);

Expand All @@ -76,6 +82,7 @@ describe('WeakIdentityMap', () => {

expect(map.has(1)).toBeTruthy();
expect(map.delete(1)).toBeTruthy();
expect(map.size).toBe(0);
expect(map.has(1)).toBeFalsy();
});

Expand All @@ -90,6 +97,7 @@ describe('WeakIdentityMap', () => {

map.clear();

expect(map.size).toBe(0);
expect(map.has(1)).toBeFalsy();
expect(map.has(2)).toBeFalsy();
});
Expand All @@ -100,6 +108,7 @@ describe('WeakIdentityMap', () => {
map.set(1, entity);
map.set(2, entity);

expect(map.size).toBe(2);
expect(Array.from(map.keys()).sort()).toEqual([1, 2].sort());
});

Expand All @@ -112,6 +121,7 @@ describe('WeakIdentityMap', () => {

const values = Array.from(map.values()).sort();

expect(map.size).toBe(2);
expect(values.length).toBe(2);
expect(values[0]).toBe(entity1);
expect(values[1]).toBe(entity2);
Expand All @@ -126,6 +136,7 @@ describe('WeakIdentityMap', () => {

const entries = Array.from(map.entries()).sort();

expect(map.size).toBe(2);
expect(entries.length).toBe(2);
expect(entries).toEqual(
[
Expand Down

0 comments on commit cb22cd6

Please sign in to comment.