Last active
September 2, 2015 06:56
-
-
Save MattiasFestin/e5e92d5ae5e2b4bf89c3 to your computer and use it in GitHub Desktop.
WeakHashMap for ext.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ext.define('Ext.util.WeakHashMap', { | |
mixins: { | |
observable: 'Ext.util.Observable' | |
}, | |
generation: 0, | |
/** | |
* Creates new HashMap. | |
* @param {Object} config (optional) Config object. | |
* @param Array keys Private parameter used in cloneing | |
* @param Array values Private parameter used in cloneing | |
*/ | |
constructor: function(config, keys, values) { | |
config = config || {}; | |
var keyFn = config.keyFn; | |
this._keys = keys || []; | |
this._wm = new WeakMap(values || []); | |
this.initialConfig = config; | |
this.addEvents( | |
/** | |
* @event add | |
* Fires when a new item is added to the hash. | |
* @param {Ext.util.HashMap} this | |
* @param {String} key The key of the added item. | |
* @param {Object} value The value of the added item. | |
*/ | |
'add', | |
/** | |
* @event clear | |
* Fires when the hash is cleared. | |
* @param {Ext.util.HashMap} this | |
*/ | |
'clear', | |
/** | |
* @event remove | |
* Fires when an item is removed from the hash. | |
* @param {Ext.util.HashMap} this | |
* @param {String} key The key of the removed item. | |
* @param {Object} value The value of the removed item. | |
*/ | |
'remove', | |
/** | |
* @event replace | |
* Fires when an item is replaced in the hash. | |
* @param {Ext.util.HashMap} this | |
* @param {String} key The key of the replaced item. | |
* @param {Object} value The new value for the item. | |
* @param {Object} old The old value for the item. | |
*/ | |
'replace' | |
); | |
this.mixins.observable.constructor.call(this, config); | |
this.clear(true); | |
if (keyFn) { | |
this.getKey = keyFn; | |
} | |
}, | |
_removeDeadReferenses: function () { | |
this._keys.forEach(this.get, this); | |
}, | |
add: function (key, value) { | |
this.generation++; | |
var _key = [key]; | |
this._wm.set(_key, value); | |
this._keys.push(_key); | |
if (this.hasListeners.add) { | |
this.fireEvent('add', this, _key, value); | |
} | |
return value; | |
}, | |
clear: function (/* private */ initial) { | |
var self = this; | |
this._keys.forEach(function (k) { | |
self._wm.delete(k); | |
}); | |
this._keys = []; | |
this.generation = initial ? 0 : this.generation + 1; | |
if (initial !== true && this.hasListeners.clear) { | |
this.fireEvent('clear', this); | |
} | |
return this; | |
}, | |
clone: function () { | |
this._removeDeadReferenses(); | |
return new Ext.util.WeakHashMap(this.initialConfig, this.getKeys(), this.getValues()); | |
}, | |
contains: function (value) { | |
this._removeDeadReferenses(); | |
var self = this; | |
return this._keys.some(function (k) { | |
return self._wm.get(k) === value; | |
}); | |
}, | |
containsKey: function (key) { | |
this._removeDeadReferenses(); | |
return this._keys.some(function (k) { | |
return k[0] === key; | |
}); | |
}, | |
each: function (fn, scope) { | |
this._removeDeadReferenses(); | |
var self = this; | |
this._keys.forEach(function (k) { | |
fn.call(scope || self, k[0], self._wm.get(k), this._keys.length); | |
}); | |
}, | |
indexOf: function (key) { | |
var index = -1; | |
this._keys.some(function (k, i) { | |
if (k[0] === k) { | |
index = i; | |
return true; | |
} | |
}); | |
}, | |
get: function (key) { | |
var i = this.indexOf(key); | |
if (i > -1) { | |
if (this._wm.has(key)) { | |
return this._wm.get(key); | |
} else { | |
//Garbage collector has taken it from weakmap | |
//Remove it from _keys array | |
this._keys.splice(i, 1); | |
} | |
} | |
}, | |
getCount: function () { | |
this._removeDeadReferenses(); | |
return this._keys.length; | |
}, | |
getKey: function (value) { | |
this._removeDeadReferenses(); | |
var self = this; | |
return this._keys.filter(function (k) { | |
return self._wm.get(k) === value; | |
})[0][0]; | |
}, | |
getKeys: function () { | |
this._removeDeadReferenses(); | |
return this._keys.map(function (k) { | |
return k[0]; | |
});; | |
}, | |
getValues: function (value) { | |
this._removeDeadReferenses(); | |
var self = this; | |
return this._keys.map(function (k) { | |
return self._wm.get(k); | |
}); | |
}, | |
remove: function (value) { | |
this._removeDeadReferenses(); | |
var key = this.getKey(value), | |
k = this._keys[this.indexOf(key)], | |
i = this.indexOf(k), | |
exsists = k !== undefined && i > -1; | |
if (exsists) { | |
this._wm.delete(k); | |
this._keys.splice(i, 1); | |
} | |
if (this.hasListeners.remove) { | |
this.fireEvent('remove', this, key, value); | |
} | |
return exsists; | |
}, | |
removeAtKey: function (key) { | |
this._removeDeadReferenses(); | |
var i = this.indexOf(key), | |
k = this._keys[i], | |
exsists = key !== undefined && i > -1, | |
value = this._wm.get(k); | |
if (exsists) { | |
this._wm.delete(k); | |
this._keys.splice(i, 1); | |
} | |
if (this.hasListeners.remove) { | |
this.fireEvent('remove', this, key, value); | |
} | |
return exsists; | |
}, | |
replace: function (key) { | |
this._removeDeadReferenses(); | |
this.generation++; | |
var i = this.indexOf(key), | |
k = this._keys[i], | |
value = this._wm.get(k); | |
if (!this.containsKey(key)) { | |
this.add(key, value); | |
} | |
//[FIXME - Mattias 2015-09-02] - Is it dangeourus to give references to old values??? | |
var old = this._wm.get(key); | |
this._wm.set(key, value); | |
if (this.hasListeners.replace) { | |
this.fireEvent('replace', this, key, value, old); | |
} | |
return value; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment