You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.9 KiB
117 lines
3.9 KiB
'use strict'; |
|
|
|
var clear = require('es5-ext/object/clear') |
|
, setPrototypeOf = require('es5-ext/object/set-prototype-of') |
|
, validValue = require('es5-ext/object/valid-value') |
|
, callable = require('es5-ext/object/valid-callable') |
|
, d = require('d') |
|
, iterator = require('es6-iterator/valid-iterable') |
|
, forOf = require('es6-iterator/for-of') |
|
, isNative = require('../is-native-implemented') |
|
, MapPolyfill = require('../polyfill') |
|
, Iterator = require('../lib/primitive-iterator') |
|
|
|
, call = Function.prototype.call |
|
, create = Object.create, defineProperty = Object.defineProperty |
|
, defineProperties = Object.defineProperties, getPrototypeOf = Object.getPrototypeOf |
|
, hasOwnProperty = Object.prototype.hasOwnProperty |
|
, PrimitiveMap; |
|
|
|
module.exports = PrimitiveMap = function (/*iterable, serialize*/) { |
|
var iterable = arguments[0], serialize = arguments[1], self; |
|
if (!(this instanceof PrimitiveMap)) throw new TypeError('Constructor requires \'new\''); |
|
if (isNative && setPrototypeOf && (Map !== MapPolyfill)) { |
|
self = setPrototypeOf(new Map(), getPrototypeOf(this)); |
|
} else { |
|
self = this; |
|
} |
|
if (iterable != null) iterator(iterable); |
|
if (serialize !== undefined) { |
|
callable(serialize); |
|
defineProperty(self, '_serialize', d('', serialize)); |
|
} |
|
defineProperties(self, { |
|
__mapKeysData__: d('c', create(null)), |
|
__mapValuesData__: d('c', create(null)), |
|
__size__: d('w', 0) |
|
}); |
|
if (!iterable) return self; |
|
forOf(iterable, function (value) { |
|
var key = validValue(value)[0], sKey = self._serialize(key); |
|
if (sKey == null) throw new TypeError(key + " cannot be serialized"); |
|
value = value[1]; |
|
if (hasOwnProperty.call(self.__mapKeysData__, sKey)) { |
|
if (self.__mapValuesData__[sKey] === value) return; |
|
} else { |
|
++self.__size__; |
|
} |
|
self.__mapKeysData__[sKey] = key; |
|
self.__mapValuesData__[sKey] = value; |
|
}); |
|
return self; |
|
}; |
|
if (setPrototypeOf) setPrototypeOf(PrimitiveMap, MapPolyfill); |
|
|
|
PrimitiveMap.prototype = create(MapPolyfill.prototype, { |
|
constructor: d(PrimitiveMap), |
|
_serialize: d(function (value) { |
|
if (value && (typeof value.toString !== 'function')) return null; |
|
return String(value); |
|
}), |
|
clear: d(function () { |
|
if (!this.__size__) return; |
|
clear(this.__mapKeysData__); |
|
clear(this.__mapValuesData__); |
|
this.__size__ = 0; |
|
this.emit('_clear'); |
|
}), |
|
delete: d(function (key) { |
|
var sKey = this._serialize(key); |
|
if (sKey == null) return false; |
|
if (!hasOwnProperty.call(this.__mapKeysData__, sKey)) return false; |
|
delete this.__mapKeysData__[sKey]; |
|
delete this.__mapValuesData__[sKey]; |
|
--this.__size__; |
|
this.emit('_delete', sKey); |
|
return true; |
|
}), |
|
entries: d(function () { return new Iterator(this, 'key+value'); }), |
|
forEach: d(function (cb/*, thisArg*/) { |
|
var thisArg = arguments[1], iterator, result, sKey; |
|
callable(cb); |
|
iterator = this.entries(); |
|
result = iterator._next(); |
|
while (result !== undefined) { |
|
sKey = iterator.__list__[result]; |
|
call.call(cb, thisArg, this.__mapValuesData__[sKey], |
|
this.__mapKeysData__[sKey], this); |
|
result = iterator._next(); |
|
} |
|
}), |
|
get: d(function (key) { |
|
var sKey = this._serialize(key); |
|
if (sKey == null) return; |
|
return this.__mapValuesData__[sKey]; |
|
}), |
|
has: d(function (key) { |
|
var sKey = this._serialize(key); |
|
if (sKey == null) return false; |
|
return hasOwnProperty.call(this.__mapKeysData__, sKey); |
|
}), |
|
keys: d(function () { return new Iterator(this, 'key'); }), |
|
size: d.gs(function () { return this.__size__; }), |
|
set: d(function (key, value) { |
|
var sKey = this._serialize(key); |
|
if (sKey == null) throw new TypeError(key + " cannot be serialized"); |
|
if (hasOwnProperty.call(this.__mapKeysData__, sKey)) { |
|
if (this.__mapValuesData__[sKey] === value) return this; |
|
} else { |
|
++this.__size__; |
|
} |
|
this.__mapKeysData__[sKey] = key; |
|
this.__mapValuesData__[sKey] = value; |
|
this.emit('_add', sKey); |
|
return this; |
|
}), |
|
values: d(function () { return new Iterator(this, 'value'); }) |
|
});
|
|
|