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.
		
		
		
		
		
			
		
			
				
					
					
						
							145 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							145 lines
						
					
					
						
							4.9 KiB
						
					
					
				| 'use strict';
 | |
| var dP = require('./_object-dp').f;
 | |
| var create = require('./_object-create');
 | |
| var redefineAll = require('./_redefine-all');
 | |
| var ctx = require('./_ctx');
 | |
| var anInstance = require('./_an-instance');
 | |
| var forOf = require('./_for-of');
 | |
| var $iterDefine = require('./_iter-define');
 | |
| var step = require('./_iter-step');
 | |
| var setSpecies = require('./_set-species');
 | |
| var DESCRIPTORS = require('./_descriptors');
 | |
| var fastKey = require('./_meta').fastKey;
 | |
| var validate = require('./_validate-collection');
 | |
| var SIZE = DESCRIPTORS ? '_s' : 'size';
 | |
| 
 | |
| var getEntry = function (that, key) {
 | |
|   // fast case
 | |
|   var index = fastKey(key);
 | |
|   var entry;
 | |
|   if (index !== 'F') return that._i[index];
 | |
|   // frozen object case
 | |
|   for (entry = that._f; entry; entry = entry.n) {
 | |
|     if (entry.k == key) return entry;
 | |
|   }
 | |
| };
 | |
| 
 | |
| module.exports = {
 | |
|   getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {
 | |
|     var C = wrapper(function (that, iterable) {
 | |
|       anInstance(that, C, NAME, '_i');
 | |
|       that._t = NAME;         // collection type
 | |
|       that._i = create(null); // index
 | |
|       that._f = undefined;    // first entry
 | |
|       that._l = undefined;    // last entry
 | |
|       that[SIZE] = 0;         // size
 | |
|       if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
 | |
|     });
 | |
|     redefineAll(C.prototype, {
 | |
|       // 23.1.3.1 Map.prototype.clear()
 | |
|       // 23.2.3.2 Set.prototype.clear()
 | |
|       clear: function clear() {
 | |
|         for (var that = validate(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {
 | |
|           entry.r = true;
 | |
|           if (entry.p) entry.p = entry.p.n = undefined;
 | |
|           delete data[entry.i];
 | |
|         }
 | |
|         that._f = that._l = undefined;
 | |
|         that[SIZE] = 0;
 | |
|       },
 | |
|       // 23.1.3.3 Map.prototype.delete(key)
 | |
|       // 23.2.3.4 Set.prototype.delete(value)
 | |
|       'delete': function (key) {
 | |
|         var that = validate(this, NAME);
 | |
|         var entry = getEntry(that, key);
 | |
|         if (entry) {
 | |
|           var next = entry.n;
 | |
|           var prev = entry.p;
 | |
|           delete that._i[entry.i];
 | |
|           entry.r = true;
 | |
|           if (prev) prev.n = next;
 | |
|           if (next) next.p = prev;
 | |
|           if (that._f == entry) that._f = next;
 | |
|           if (that._l == entry) that._l = prev;
 | |
|           that[SIZE]--;
 | |
|         } return !!entry;
 | |
|       },
 | |
|       // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
 | |
|       // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
 | |
|       forEach: function forEach(callbackfn /* , that = undefined */) {
 | |
|         validate(this, NAME);
 | |
|         var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);
 | |
|         var entry;
 | |
|         while (entry = entry ? entry.n : this._f) {
 | |
|           f(entry.v, entry.k, this);
 | |
|           // revert to the last existing entry
 | |
|           while (entry && entry.r) entry = entry.p;
 | |
|         }
 | |
|       },
 | |
|       // 23.1.3.7 Map.prototype.has(key)
 | |
|       // 23.2.3.7 Set.prototype.has(value)
 | |
|       has: function has(key) {
 | |
|         return !!getEntry(validate(this, NAME), key);
 | |
|       }
 | |
|     });
 | |
|     if (DESCRIPTORS) dP(C.prototype, 'size', {
 | |
|       get: function () {
 | |
|         return validate(this, NAME)[SIZE];
 | |
|       }
 | |
|     });
 | |
|     return C;
 | |
|   },
 | |
|   def: function (that, key, value) {
 | |
|     var entry = getEntry(that, key);
 | |
|     var prev, index;
 | |
|     // change existing entry
 | |
|     if (entry) {
 | |
|       entry.v = value;
 | |
|     // create new entry
 | |
|     } else {
 | |
|       that._l = entry = {
 | |
|         i: index = fastKey(key, true), // <- index
 | |
|         k: key,                        // <- key
 | |
|         v: value,                      // <- value
 | |
|         p: prev = that._l,             // <- previous entry
 | |
|         n: undefined,                  // <- next entry
 | |
|         r: false                       // <- removed
 | |
|       };
 | |
|       if (!that._f) that._f = entry;
 | |
|       if (prev) prev.n = entry;
 | |
|       that[SIZE]++;
 | |
|       // add to index
 | |
|       if (index !== 'F') that._i[index] = entry;
 | |
|     } return that;
 | |
|   },
 | |
|   getEntry: getEntry,
 | |
|   setStrong: function (C, NAME, IS_MAP) {
 | |
|     // add .keys, .values, .entries, [@@iterator]
 | |
|     // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
 | |
|     $iterDefine(C, NAME, function (iterated, kind) {
 | |
|       this._t = validate(iterated, NAME); // target
 | |
|       this._k = kind;                     // kind
 | |
|       this._l = undefined;                // previous
 | |
|     }, function () {
 | |
|       var that = this;
 | |
|       var kind = that._k;
 | |
|       var entry = that._l;
 | |
|       // revert to the last existing entry
 | |
|       while (entry && entry.r) entry = entry.p;
 | |
|       // get next entry
 | |
|       if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {
 | |
|         // or finish the iteration
 | |
|         that._t = undefined;
 | |
|         return step(1);
 | |
|       }
 | |
|       // return step by kind
 | |
|       if (kind == 'keys') return step(0, entry.k);
 | |
|       if (kind == 'values') return step(0, entry.v);
 | |
|       return step(0, [entry.k, entry.v]);
 | |
|     }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
 | |
| 
 | |
|     // add [@@species], 23.1.2.2, 23.2.2.2
 | |
|     setSpecies(NAME);
 | |
|   }
 | |
| };
 |