three
Version:
JavaScript 3D library
123 lines (82 loc) • 2.22 kB
JavaScript
/**
* Data structure for the renderer. It allows defining values
* with chained, hierarchical keys. Keys are meant to be
* objects since the module internally works with Weak Maps
* for performance reasons.
*
* @private
*/
class ChainMap {
/**
* Constructs a new Chain Map.
*/
constructor() {
/**
* A map of Weak Maps by their key length.
*
* @type {Object<number, WeakMap>}
*/
this.weakMaps = {};
}
/**
* Returns the Weak Map for the given keys.
*
* @param {Array<Object>} keys - List of keys.
* @return {WeakMap} The weak map.
*/
_getWeakMap( keys ) {
const length = keys.length;
let weakMap = this.weakMaps[ length ];
if ( weakMap === undefined ) {
weakMap = new WeakMap();
this.weakMaps[ length ] = weakMap;
}
return weakMap;
}
/**
* Returns the value for the given array of keys.
*
* @param {Array<Object>} keys - List of keys.
* @return {any} The value. Returns `undefined` if no value was found.
*/
get( keys ) {
let map = this._getWeakMap( keys );
for ( let i = 0; i < keys.length - 1; i ++ ) {
map = map.get( keys[ i ] );
if ( map === undefined ) return undefined;
}
return map.get( keys[ keys.length - 1 ] );
}
/**
* Sets the value for the given keys.
*
* @param {Array<Object>} keys - List of keys.
* @param {any} value - The value to set.
* @return {ChainMap} A reference to this Chain Map.
*/
set( keys, value ) {
let map = this._getWeakMap( keys );
for ( let i = 0; i < keys.length - 1; i ++ ) {
const key = keys[ i ];
if ( map.has( key ) === false ) map.set( key, new WeakMap() );
map = map.get( key );
}
map.set( keys[ keys.length - 1 ], value );
return this;
}
/**
* Deletes a value for the given keys.
*
* @param {Array<Object>} keys - The keys.
* @return {boolean} Returns `true` if the value has been removed successfully and `false` if the value has not be found.
*/
delete( keys ) {
let map = this._getWeakMap( keys );
for ( let i = 0; i < keys.length - 1; i ++ ) {
map = map.get( keys[ i ] );
if ( map === undefined ) return false;
}
return map.delete( keys[ keys.length - 1 ] );
}
}
export default ChainMap;