_collection-weak.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. 'use strict';
  2. var redefineAll = require('./_redefine-all');
  3. var getWeak = require('./_meta').getWeak;
  4. var anObject = require('./_an-object');
  5. var isObject = require('./_is-object');
  6. var anInstance = require('./_an-instance');
  7. var forOf = require('./_for-of');
  8. var createArrayMethod = require('./_array-methods');
  9. var $has = require('./_has');
  10. var validate = require('./_validate-collection');
  11. var arrayFind = createArrayMethod(5);
  12. var arrayFindIndex = createArrayMethod(6);
  13. var id = 0;
  14. // fallback for uncaught frozen keys
  15. var uncaughtFrozenStore = function (that) {
  16. return that._l || (that._l = new UncaughtFrozenStore());
  17. };
  18. var UncaughtFrozenStore = function () {
  19. this.a = [];
  20. };
  21. var findUncaughtFrozen = function (store, key) {
  22. return arrayFind(store.a, function (it) {
  23. return it[0] === key;
  24. });
  25. };
  26. UncaughtFrozenStore.prototype = {
  27. get: function (key) {
  28. var entry = findUncaughtFrozen(this, key);
  29. if (entry) return entry[1];
  30. },
  31. has: function (key) {
  32. return !!findUncaughtFrozen(this, key);
  33. },
  34. set: function (key, value) {
  35. var entry = findUncaughtFrozen(this, key);
  36. if (entry) entry[1] = value;
  37. else this.a.push([key, value]);
  38. },
  39. 'delete': function (key) {
  40. var index = arrayFindIndex(this.a, function (it) {
  41. return it[0] === key;
  42. });
  43. if (~index) this.a.splice(index, 1);
  44. return !!~index;
  45. }
  46. };
  47. module.exports = {
  48. getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {
  49. var C = wrapper(function (that, iterable) {
  50. anInstance(that, C, NAME, '_i');
  51. that._t = NAME; // collection type
  52. that._i = id++; // collection id
  53. that._l = undefined; // leak store for uncaught frozen objects
  54. if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
  55. });
  56. redefineAll(C.prototype, {
  57. // 23.3.3.2 WeakMap.prototype.delete(key)
  58. // 23.4.3.3 WeakSet.prototype.delete(value)
  59. 'delete': function (key) {
  60. if (!isObject(key)) return false;
  61. var data = getWeak(key);
  62. if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);
  63. return data && $has(data, this._i) && delete data[this._i];
  64. },
  65. // 23.3.3.4 WeakMap.prototype.has(key)
  66. // 23.4.3.4 WeakSet.prototype.has(value)
  67. has: function has(key) {
  68. if (!isObject(key)) return false;
  69. var data = getWeak(key);
  70. if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);
  71. return data && $has(data, this._i);
  72. }
  73. });
  74. return C;
  75. },
  76. def: function (that, key, value) {
  77. var data = getWeak(anObject(key), true);
  78. if (data === true) uncaughtFrozenStore(that).set(key, value);
  79. else data[that._i] = value;
  80. return that;
  81. },
  82. ufstore: uncaughtFrozenStore
  83. };