Skip to content

Commit

Permalink
default-weak-map: new structure
Browse files Browse the repository at this point in the history
  • Loading branch information
yoursunny committed Jun 17, 2020
1 parent 1c2f8ec commit 6618acd
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Full documentation for the library can be found [here](https://yomguithereal.git

* [BiMap](https://yomguithereal.github.io/mnemonist/bi-map)
* [DefaultMap](https://yomguithereal.github.io/mnemonist/default-map)
* [DefaultWeakMap](https://yomguithereal.github.io/mnemonist/default-weak-map)

---

Expand Down
2 changes: 1 addition & 1 deletion default-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/
function DefaultMap(factory) {
if (typeof factory !== 'function')
throw new Error('mnemonist/FuzzyMultiMap.constructor: expecting a function.');
throw new Error('mnemonist/DefaultMap.constructor: expecting a function.');

this.items = new Map();
this.factory = factory;
Expand Down
18 changes: 18 additions & 0 deletions default-weak-map.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Mnemonist DefaultWeakMap Typings
* ================================
*/
export default class DefaultWeakMap<K extends object, V> {

// Constructor
constructor(factory: (key: K) => V);

// Methods
clear(): void;
set(key: K, value: V): this;
delete(key: K): boolean;
has(key: K): boolean;
get(key: K): V;
peek(key: K): V | undefined;
inspect(): any;
}
108 changes: 108 additions & 0 deletions default-weak-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* Mnemonist DefaultWeakMap
* ========================
*
* JavaScript implementation of a default weak map that will return a constructed
* value any time one tries to access an non-existing key. It is similar to
* DefaultMap but uses ES6 WeakMap that only holds weak reference to keys.
*/

/**
* DefaultWeakMap.
*
* @constructor
*/
function DefaultWeakMap(factory) {
if (typeof factory !== 'function')
throw new Error('mnemonist/DefaultWeakMap.constructor: expecting a function.');

this.items = new WeakMap();
this.factory = factory;
}

/**
* Method used to clear the structure.
*
* @return {undefined}
*/
DefaultWeakMap.prototype.clear = function() {

// Properties
this.items = new WeakMap();
};

/**
* Method used to get the value set for given key. If the key does not exist,
* the value will be created using the provided factory.
*
* @param {any} key - Target key.
* @return {any}
*/
DefaultWeakMap.prototype.get = function(key) {
var value = this.items.get(key);

if (typeof value === 'undefined') {
value = this.factory(key);
this.items.set(key, value);
}

return value;
};

/**
* Method used to get the value set for given key. If the key does not exist,
* a value won't be created.
*
* @param {any} key - Target key.
* @return {any}
*/
DefaultWeakMap.prototype.peek = function(key) {
return this.items.get(key);
};

/**
* Method used to set a value for given key.
*
* @param {any} key - Target key.
* @param {any} value - Value.
* @return {DefaultMap}
*/
DefaultWeakMap.prototype.set = function(key, value) {
this.items.set(key, value);
return this;
};

/**
* Method used to test the existence of a key in the map.
*
* @param {any} key - Target key.
* @return {boolean}
*/
DefaultWeakMap.prototype.has = function(key) {
return this.items.has(key);
};

/**
* Method used to delete target key.
*
* @param {any} key - Target key.
* @return {boolean}
*/
DefaultWeakMap.prototype.delete = function(key) {
return this.items.delete(key);
};

/**
* Convenience known methods.
*/
DefaultWeakMap.prototype.inspect = function() {
return this.items;
};

if (typeof Symbol !== 'undefined')
DefaultWeakMap.prototype[Symbol.for('nodejs.util.inspect.custom')] = DefaultWeakMap.prototype.inspect;

/**
* Exporting.
*/
module.exports = DefaultWeakMap;
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export {default as BKTree} from './bk-tree';
export {default as BloomFilter} from './bloom-filter';
export {default as CircularBuffer} from './circular-buffer';
export {default as DefaultMap} from './default-map';
export {default as DefaultWeakMap} from './default-weak-map';
export {default as FixedDeque} from './fixed-deque';
export {default as FibonacciHeap, MinFibonacciHeap, MaxFibonacciHeap} from './fibonacci-heap';
export {default as FixedReverseHeap} from './fixed-reverse-heap';
Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = {
BKTree: require('./bk-tree.js'),
CircularBuffer: require('./circular-buffer.js'),
DefaultMap: require('./default-map.js'),
DefaultWeakMap: require('./default-weak-map.js'),
FixedDeque: require('./fixed-deque.js'),
StaticDisjointSet: require('./static-disjoint-set.js'),
FibonacciHeap: FibonacciHeap,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"globals": {
"Set": true,
"Map": true,
"WeakMap": true,
"Symbol": true,
"ArrayBuffer": true,
"Uint8Array": true,
Expand Down
60 changes: 60 additions & 0 deletions test/default-weak-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Mnemonist DefaultWeakMap Unit Tests
* ===================================
*/
var assert = require('assert'),
DefaultWeakMap = require('../default-weak-map.js');

var FACTORY = function() {
return [];
};

describe('DefaultWeakMap', function() {

it('should throw if passed factory is not a function.', function() {

assert.throws(function() {
new DefaultWeakMap(null);
}, /function/);
});

it('should be possible to set & get keys.', function() {
var map = new DefaultWeakMap(FACTORY);
const one = {}, two = {}, unknown = {};

map.get(one).push(1);
map.set(two, [2]);

assert.deepEqual(map.get(one), [1]);
assert.deepEqual(map.get(two), [2]);

assert.deepEqual(map.get(unknown), []);

map.clear();

assert.deepEqual(map.get(one), []);
});

it('should be possible to delete keys.', function() {
var map = new DefaultWeakMap(FACTORY);
const one = {};

map.set(one, 1);

assert.strictEqual(map.has(one), true);
assert.strictEqual(map.delete(one), true);
assert.strictEqual(map.has(one), false);
assert.strictEqual(map.delete(one), false);
});

it('should be possible to peek.', function() {
var map = new DefaultWeakMap(FACTORY);
const one = {}, two = {};

map.get(one).push(1);

assert.deepEqual(map.peek(one), [1]);
assert.strictEqual(map.peek(two), undefined);
assert.strictEqual(map.has(two), false);
});
});

0 comments on commit 6618acd

Please sign in to comment.