collection-weak.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. 'use strict';
  2. var redefineAll = require('../internals/redefine-all');
  3. var getWeakData = require('../internals/internal-metadata').getWeakData;
  4. var anObject = require('../internals/an-object');
  5. var isObject = require('../internals/is-object');
  6. var anInstance = require('../internals/an-instance');
  7. var iterate = require('../internals/iterate');
  8. var ArrayIterationModule = require('../internals/array-iteration');
  9. var $has = require('../internals/has');
  10. var InternalStateModule = require('../internals/internal-state');
  11. var setInternalState = InternalStateModule.set;
  12. var internalStateGetterFor = InternalStateModule.getterFor;
  13. var find = ArrayIterationModule.find;
  14. var findIndex = ArrayIterationModule.findIndex;
  15. var id = 0;
  16. // fallback for uncaught frozen keys
  17. var uncaughtFrozenStore = function (store) {
  18. return store.frozen || (store.frozen = new UncaughtFrozenStore());
  19. };
  20. var UncaughtFrozenStore = function () {
  21. this.entries = [];
  22. };
  23. var findUncaughtFrozen = function (store, key) {
  24. return find(store.entries, function (it) {
  25. return it[0] === key;
  26. });
  27. };
  28. UncaughtFrozenStore.prototype = {
  29. get: function (key) {
  30. var entry = findUncaughtFrozen(this, key);
  31. if (entry) return entry[1];
  32. },
  33. has: function (key) {
  34. return !!findUncaughtFrozen(this, key);
  35. },
  36. set: function (key, value) {
  37. var entry = findUncaughtFrozen(this, key);
  38. if (entry) entry[1] = value;
  39. else this.entries.push([key, value]);
  40. },
  41. 'delete': function (key) {
  42. var index = findIndex(this.entries, function (it) {
  43. return it[0] === key;
  44. });
  45. if (~index) this.entries.splice(index, 1);
  46. return !!~index;
  47. }
  48. };
  49. module.exports = {
  50. getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
  51. var C = wrapper(function (that, iterable) {
  52. anInstance(that, C, CONSTRUCTOR_NAME);
  53. setInternalState(that, {
  54. type: CONSTRUCTOR_NAME,
  55. id: id++,
  56. frozen: undefined
  57. });
  58. if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
  59. });
  60. var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
  61. var define = function (that, key, value) {
  62. var state = getInternalState(that);
  63. var data = getWeakData(anObject(key), true);
  64. if (data === true) uncaughtFrozenStore(state).set(key, value);
  65. else data[state.id] = value;
  66. return that;
  67. };
  68. redefineAll(C.prototype, {
  69. // `{ WeakMap, WeakSet }.prototype.delete(key)` methods
  70. // https://tc39.es/ecma262/#sec-weakmap.prototype.delete
  71. // https://tc39.es/ecma262/#sec-weakset.prototype.delete
  72. 'delete': function (key) {
  73. var state = getInternalState(this);
  74. if (!isObject(key)) return false;
  75. var data = getWeakData(key);
  76. if (data === true) return uncaughtFrozenStore(state)['delete'](key);
  77. return data && $has(data, state.id) && delete data[state.id];
  78. },
  79. // `{ WeakMap, WeakSet }.prototype.has(key)` methods
  80. // https://tc39.es/ecma262/#sec-weakmap.prototype.has
  81. // https://tc39.es/ecma262/#sec-weakset.prototype.has
  82. has: function has(key) {
  83. var state = getInternalState(this);
  84. if (!isObject(key)) return false;
  85. var data = getWeakData(key);
  86. if (data === true) return uncaughtFrozenStore(state).has(key);
  87. return data && $has(data, state.id);
  88. }
  89. });
  90. redefineAll(C.prototype, IS_MAP ? {
  91. // `WeakMap.prototype.get(key)` method
  92. // https://tc39.es/ecma262/#sec-weakmap.prototype.get
  93. get: function get(key) {
  94. var state = getInternalState(this);
  95. if (isObject(key)) {
  96. var data = getWeakData(key);
  97. if (data === true) return uncaughtFrozenStore(state).get(key);
  98. return data ? data[state.id] : undefined;
  99. }
  100. },
  101. // `WeakMap.prototype.set(key, value)` method
  102. // https://tc39.es/ecma262/#sec-weakmap.prototype.set
  103. set: function set(key, value) {
  104. return define(this, key, value);
  105. }
  106. } : {
  107. // `WeakSet.prototype.add(value)` method
  108. // https://tc39.es/ecma262/#sec-weakset.prototype.add
  109. add: function add(value) {
  110. return define(this, value, true);
  111. }
  112. });
  113. return C;
  114. }
  115. };