123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. 'use strict';
  2. var clear = require('es5-ext/object/clear')
  3. , setPrototypeOf = require('es5-ext/object/set-prototype-of')
  4. , validValue = require('es5-ext/object/valid-value')
  5. , callable = require('es5-ext/object/valid-callable')
  6. , d = require('d')
  7. , iterator = require('es6-iterator/valid-iterable')
  8. , forOf = require('es6-iterator/for-of')
  9. , isNative = require('../is-native-implemented')
  10. , MapPolyfill = require('../polyfill')
  11. , Iterator = require('../lib/primitive-iterator')
  12. , call = Function.prototype.call
  13. , create = Object.create, defineProperty = Object.defineProperty
  14. , defineProperties = Object.defineProperties, getPrototypeOf = Object.getPrototypeOf
  15. , hasOwnProperty = Object.prototype.hasOwnProperty
  16. , PrimitiveMap;
  17. module.exports = PrimitiveMap = function (/*iterable, serialize*/) {
  18. var iterable = arguments[0], serialize = arguments[1], self;
  19. if (!(this instanceof PrimitiveMap)) throw new TypeError('Constructor requires \'new\'');
  20. if (isNative && setPrototypeOf && (Map !== MapPolyfill)) {
  21. self = setPrototypeOf(new Map(), getPrototypeOf(this));
  22. } else {
  23. self = this;
  24. }
  25. if (iterable != null) iterator(iterable);
  26. if (serialize !== undefined) {
  27. callable(serialize);
  28. defineProperty(self, '_serialize', d('', serialize));
  29. }
  30. defineProperties(self, {
  31. __mapKeysData__: d('c', create(null)),
  32. __mapValuesData__: d('c', create(null)),
  33. __size__: d('w', 0)
  34. });
  35. if (!iterable) return self;
  36. forOf(iterable, function (value) {
  37. var key = validValue(value)[0], sKey = self._serialize(key);
  38. if (sKey == null) throw new TypeError(key + " cannot be serialized");
  39. value = value[1];
  40. if (hasOwnProperty.call(self.__mapKeysData__, sKey)) {
  41. if (self.__mapValuesData__[sKey] === value) return;
  42. } else {
  43. ++self.__size__;
  44. }
  45. self.__mapKeysData__[sKey] = key;
  46. self.__mapValuesData__[sKey] = value;
  47. });
  48. return self;
  49. };
  50. if (setPrototypeOf) setPrototypeOf(PrimitiveMap, MapPolyfill);
  51. PrimitiveMap.prototype = create(MapPolyfill.prototype, {
  52. constructor: d(PrimitiveMap),
  53. _serialize: d(function (value) {
  54. if (value && (typeof value.toString !== 'function')) return null;
  55. return String(value);
  56. }),
  57. clear: d(function () {
  58. if (!this.__size__) return;
  59. clear(this.__mapKeysData__);
  60. clear(this.__mapValuesData__);
  61. this.__size__ = 0;
  62. this.emit('_clear');
  63. }),
  64. delete: d(function (key) {
  65. var sKey = this._serialize(key);
  66. if (sKey == null) return false;
  67. if (!hasOwnProperty.call(this.__mapKeysData__, sKey)) return false;
  68. delete this.__mapKeysData__[sKey];
  69. delete this.__mapValuesData__[sKey];
  70. --this.__size__;
  71. this.emit('_delete', sKey);
  72. return true;
  73. }),
  74. entries: d(function () { return new Iterator(this, 'key+value'); }),
  75. forEach: d(function (cb/*, thisArg*/) {
  76. var thisArg = arguments[1], iterator, result, sKey;
  77. callable(cb);
  78. iterator = this.entries();
  79. result = iterator._next();
  80. while (result !== undefined) {
  81. sKey = iterator.__list__[result];
  82. call.call(cb, thisArg, this.__mapValuesData__[sKey],
  83. this.__mapKeysData__[sKey], this);
  84. result = iterator._next();
  85. }
  86. }),
  87. get: d(function (key) {
  88. var sKey = this._serialize(key);
  89. if (sKey == null) return;
  90. return this.__mapValuesData__[sKey];
  91. }),
  92. has: d(function (key) {
  93. var sKey = this._serialize(key);
  94. if (sKey == null) return false;
  95. return hasOwnProperty.call(this.__mapKeysData__, sKey);
  96. }),
  97. keys: d(function () { return new Iterator(this, 'key'); }),
  98. size: d.gs(function () { return this.__size__; }),
  99. set: d(function (key, value) {
  100. var sKey = this._serialize(key);
  101. if (sKey == null) throw new TypeError(key + " cannot be serialized");
  102. if (hasOwnProperty.call(this.__mapKeysData__, sKey)) {
  103. if (this.__mapValuesData__[sKey] === value) return this;
  104. } else {
  105. ++this.__size__;
  106. }
  107. this.__mapKeysData__[sKey] = key;
  108. this.__mapValuesData__[sKey] = value;
  109. this.emit('_add', sKey);
  110. return this;
  111. }),
  112. values: d(function () { return new Iterator(this, 'value'); })
  113. });