$.collection-weak.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. 'use strict';
  2. var hide = require('./$.hide')
  3. , redefineAll = require('./$.redefine-all')
  4. , anObject = require('./$.an-object')
  5. , isObject = require('./$.is-object')
  6. , strictNew = require('./$.strict-new')
  7. , forOf = require('./$.for-of')
  8. , createArrayMethod = require('./$.array-methods')
  9. , $has = require('./$.has')
  10. , WEAK = require('./$.uid')('weak')
  11. , isExtensible = Object.isExtensible || isObject
  12. , arrayFind = createArrayMethod(5)
  13. , arrayFindIndex = createArrayMethod(6)
  14. , id = 0;
  15. // fallback for frozen keys
  16. var frozenStore = function(that){
  17. return that._l || (that._l = new FrozenStore);
  18. };
  19. var FrozenStore = function(){
  20. this.a = [];
  21. };
  22. var findFrozen = function(store, key){
  23. return arrayFind(store.a, function(it){
  24. return it[0] === key;
  25. });
  26. };
  27. FrozenStore.prototype = {
  28. get: function(key){
  29. var entry = findFrozen(this, key);
  30. if(entry)return entry[1];
  31. },
  32. has: function(key){
  33. return !!findFrozen(this, key);
  34. },
  35. set: function(key, value){
  36. var entry = findFrozen(this, key);
  37. if(entry)entry[1] = value;
  38. else this.a.push([key, value]);
  39. },
  40. 'delete': function(key){
  41. var index = arrayFindIndex(this.a, function(it){
  42. return it[0] === key;
  43. });
  44. if(~index)this.a.splice(index, 1);
  45. return !!~index;
  46. }
  47. };
  48. module.exports = {
  49. getConstructor: function(wrapper, NAME, IS_MAP, ADDER){
  50. var C = wrapper(function(that, iterable){
  51. strictNew(that, C, NAME);
  52. that._i = id++; // collection id
  53. that._l = undefined; // leak store for 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. if(!isExtensible(key))return frozenStore(this)['delete'](key);
  62. return $has(key, WEAK) && $has(key[WEAK], this._i) && delete key[WEAK][this._i];
  63. },
  64. // 23.3.3.4 WeakMap.prototype.has(key)
  65. // 23.4.3.4 WeakSet.prototype.has(value)
  66. has: function has(key){
  67. if(!isObject(key))return false;
  68. if(!isExtensible(key))return frozenStore(this).has(key);
  69. return $has(key, WEAK) && $has(key[WEAK], this._i);
  70. }
  71. });
  72. return C;
  73. },
  74. def: function(that, key, value){
  75. if(!isExtensible(anObject(key))){
  76. frozenStore(that).set(key, value);
  77. } else {
  78. $has(key, WEAK) || hide(key, WEAK, {});
  79. key[WEAK][that._i] = value;
  80. } return that;
  81. },
  82. frozenStore: frozenStore,
  83. WEAK: WEAK
  84. };