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.
		
		
		
		
			
				
					187 lines
				
				6.6 KiB
			
		
		
			
		
	
	
					187 lines
				
				6.6 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								var defineProperty = require('../internals/object-define-property').f;
							 | 
						||
| 
								 | 
							
								var create = require('../internals/object-create');
							 | 
						||
| 
								 | 
							
								var redefineAll = require('../internals/redefine-all');
							 | 
						||
| 
								 | 
							
								var bind = require('../internals/function-bind-context');
							 | 
						||
| 
								 | 
							
								var anInstance = require('../internals/an-instance');
							 | 
						||
| 
								 | 
							
								var iterate = require('../internals/iterate');
							 | 
						||
| 
								 | 
							
								var defineIterator = require('../internals/define-iterator');
							 | 
						||
| 
								 | 
							
								var setSpecies = require('../internals/set-species');
							 | 
						||
| 
								 | 
							
								var DESCRIPTORS = require('../internals/descriptors');
							 | 
						||
| 
								 | 
							
								var fastKey = require('../internals/internal-metadata').fastKey;
							 | 
						||
| 
								 | 
							
								var InternalStateModule = require('../internals/internal-state');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var setInternalState = InternalStateModule.set;
							 | 
						||
| 
								 | 
							
								var internalStateGetterFor = InternalStateModule.getterFor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								  getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
							 | 
						||
| 
								 | 
							
								    var C = wrapper(function (that, iterable) {
							 | 
						||
| 
								 | 
							
								      anInstance(that, C, CONSTRUCTOR_NAME);
							 | 
						||
| 
								 | 
							
								      setInternalState(that, {
							 | 
						||
| 
								 | 
							
								        type: CONSTRUCTOR_NAME,
							 | 
						||
| 
								 | 
							
								        index: create(null),
							 | 
						||
| 
								 | 
							
								        first: undefined,
							 | 
						||
| 
								 | 
							
								        last: undefined,
							 | 
						||
| 
								 | 
							
								        size: 0
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      if (!DESCRIPTORS) that.size = 0;
							 | 
						||
| 
								 | 
							
								      if (iterable != undefined) iterate(iterable, that[ADDER], that, IS_MAP);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var define = function (that, key, value) {
							 | 
						||
| 
								 | 
							
								      var state = getInternalState(that);
							 | 
						||
| 
								 | 
							
								      var entry = getEntry(that, key);
							 | 
						||
| 
								 | 
							
								      var previous, index;
							 | 
						||
| 
								 | 
							
								      // change existing entry
							 | 
						||
| 
								 | 
							
								      if (entry) {
							 | 
						||
| 
								 | 
							
								        entry.value = value;
							 | 
						||
| 
								 | 
							
								      // create new entry
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        state.last = entry = {
							 | 
						||
| 
								 | 
							
								          index: index = fastKey(key, true),
							 | 
						||
| 
								 | 
							
								          key: key,
							 | 
						||
| 
								 | 
							
								          value: value,
							 | 
						||
| 
								 | 
							
								          previous: previous = state.last,
							 | 
						||
| 
								 | 
							
								          next: undefined,
							 | 
						||
| 
								 | 
							
								          removed: false
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								        if (!state.first) state.first = entry;
							 | 
						||
| 
								 | 
							
								        if (previous) previous.next = entry;
							 | 
						||
| 
								 | 
							
								        if (DESCRIPTORS) state.size++;
							 | 
						||
| 
								 | 
							
								        else that.size++;
							 | 
						||
| 
								 | 
							
								        // add to index
							 | 
						||
| 
								 | 
							
								        if (index !== 'F') state.index[index] = entry;
							 | 
						||
| 
								 | 
							
								      } return that;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var getEntry = function (that, key) {
							 | 
						||
| 
								 | 
							
								      var state = getInternalState(that);
							 | 
						||
| 
								 | 
							
								      // fast case
							 | 
						||
| 
								 | 
							
								      var index = fastKey(key);
							 | 
						||
| 
								 | 
							
								      var entry;
							 | 
						||
| 
								 | 
							
								      if (index !== 'F') return state.index[index];
							 | 
						||
| 
								 | 
							
								      // frozen object case
							 | 
						||
| 
								 | 
							
								      for (entry = state.first; entry; entry = entry.next) {
							 | 
						||
| 
								 | 
							
								        if (entry.key == key) return entry;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    redefineAll(C.prototype, {
							 | 
						||
| 
								 | 
							
								      // 23.1.3.1 Map.prototype.clear()
							 | 
						||
| 
								 | 
							
								      // 23.2.3.2 Set.prototype.clear()
							 | 
						||
| 
								 | 
							
								      clear: function clear() {
							 | 
						||
| 
								 | 
							
								        var that = this;
							 | 
						||
| 
								 | 
							
								        var state = getInternalState(that);
							 | 
						||
| 
								 | 
							
								        var data = state.index;
							 | 
						||
| 
								 | 
							
								        var entry = state.first;
							 | 
						||
| 
								 | 
							
								        while (entry) {
							 | 
						||
| 
								 | 
							
								          entry.removed = true;
							 | 
						||
| 
								 | 
							
								          if (entry.previous) entry.previous = entry.previous.next = undefined;
							 | 
						||
| 
								 | 
							
								          delete data[entry.index];
							 | 
						||
| 
								 | 
							
								          entry = entry.next;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        state.first = state.last = undefined;
							 | 
						||
| 
								 | 
							
								        if (DESCRIPTORS) state.size = 0;
							 | 
						||
| 
								 | 
							
								        else that.size = 0;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      // 23.1.3.3 Map.prototype.delete(key)
							 | 
						||
| 
								 | 
							
								      // 23.2.3.4 Set.prototype.delete(value)
							 | 
						||
| 
								 | 
							
								      'delete': function (key) {
							 | 
						||
| 
								 | 
							
								        var that = this;
							 | 
						||
| 
								 | 
							
								        var state = getInternalState(that);
							 | 
						||
| 
								 | 
							
								        var entry = getEntry(that, key);
							 | 
						||
| 
								 | 
							
								        if (entry) {
							 | 
						||
| 
								 | 
							
								          var next = entry.next;
							 | 
						||
| 
								 | 
							
								          var prev = entry.previous;
							 | 
						||
| 
								 | 
							
								          delete state.index[entry.index];
							 | 
						||
| 
								 | 
							
								          entry.removed = true;
							 | 
						||
| 
								 | 
							
								          if (prev) prev.next = next;
							 | 
						||
| 
								 | 
							
								          if (next) next.previous = prev;
							 | 
						||
| 
								 | 
							
								          if (state.first == entry) state.first = next;
							 | 
						||
| 
								 | 
							
								          if (state.last == entry) state.last = prev;
							 | 
						||
| 
								 | 
							
								          if (DESCRIPTORS) state.size--;
							 | 
						||
| 
								 | 
							
								          else 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 */) {
							 | 
						||
| 
								 | 
							
								        var state = getInternalState(this);
							 | 
						||
| 
								 | 
							
								        var boundFunction = bind(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);
							 | 
						||
| 
								 | 
							
								        var entry;
							 | 
						||
| 
								 | 
							
								        while (entry = entry ? entry.next : state.first) {
							 | 
						||
| 
								 | 
							
								          boundFunction(entry.value, entry.key, this);
							 | 
						||
| 
								 | 
							
								          // revert to the last existing entry
							 | 
						||
| 
								 | 
							
								          while (entry && entry.removed) entry = entry.previous;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      // 23.1.3.7 Map.prototype.has(key)
							 | 
						||
| 
								 | 
							
								      // 23.2.3.7 Set.prototype.has(value)
							 | 
						||
| 
								 | 
							
								      has: function has(key) {
							 | 
						||
| 
								 | 
							
								        return !!getEntry(this, key);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    redefineAll(C.prototype, IS_MAP ? {
							 | 
						||
| 
								 | 
							
								      // 23.1.3.6 Map.prototype.get(key)
							 | 
						||
| 
								 | 
							
								      get: function get(key) {
							 | 
						||
| 
								 | 
							
								        var entry = getEntry(this, key);
							 | 
						||
| 
								 | 
							
								        return entry && entry.value;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      // 23.1.3.9 Map.prototype.set(key, value)
							 | 
						||
| 
								 | 
							
								      set: function set(key, value) {
							 | 
						||
| 
								 | 
							
								        return define(this, key === 0 ? 0 : key, value);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } : {
							 | 
						||
| 
								 | 
							
								      // 23.2.3.1 Set.prototype.add(value)
							 | 
						||
| 
								 | 
							
								      add: function add(value) {
							 | 
						||
| 
								 | 
							
								        return define(this, value = value === 0 ? 0 : value, value);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    if (DESCRIPTORS) defineProperty(C.prototype, 'size', {
							 | 
						||
| 
								 | 
							
								      get: function () {
							 | 
						||
| 
								 | 
							
								        return getInternalState(this).size;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    return C;
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								  setStrong: function (C, CONSTRUCTOR_NAME, IS_MAP) {
							 | 
						||
| 
								 | 
							
								    var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
							 | 
						||
| 
								 | 
							
								    var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
							 | 
						||
| 
								 | 
							
								    var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);
							 | 
						||
| 
								 | 
							
								    // 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
							 | 
						||
| 
								 | 
							
								    defineIterator(C, CONSTRUCTOR_NAME, function (iterated, kind) {
							 | 
						||
| 
								 | 
							
								      setInternalState(this, {
							 | 
						||
| 
								 | 
							
								        type: ITERATOR_NAME,
							 | 
						||
| 
								 | 
							
								        target: iterated,
							 | 
						||
| 
								 | 
							
								        state: getInternalCollectionState(iterated),
							 | 
						||
| 
								 | 
							
								        kind: kind,
							 | 
						||
| 
								 | 
							
								        last: undefined
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }, function () {
							 | 
						||
| 
								 | 
							
								      var state = getInternalIteratorState(this);
							 | 
						||
| 
								 | 
							
								      var kind = state.kind;
							 | 
						||
| 
								 | 
							
								      var entry = state.last;
							 | 
						||
| 
								 | 
							
								      // revert to the last existing entry
							 | 
						||
| 
								 | 
							
								      while (entry && entry.removed) entry = entry.previous;
							 | 
						||
| 
								 | 
							
								      // get next entry
							 | 
						||
| 
								 | 
							
								      if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
							 | 
						||
| 
								 | 
							
								        // or finish the iteration
							 | 
						||
| 
								 | 
							
								        state.target = undefined;
							 | 
						||
| 
								 | 
							
								        return { value: undefined, done: true };
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      // return step by kind
							 | 
						||
| 
								 | 
							
								      if (kind == 'keys') return { value: entry.key, done: false };
							 | 
						||
| 
								 | 
							
								      if (kind == 'values') return { value: entry.value, done: false };
							 | 
						||
| 
								 | 
							
								      return { value: [entry.key, entry.value], done: false };
							 | 
						||
| 
								 | 
							
								    }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // add [@@species], 23.1.2.2, 23.2.2.2
							 | 
						||
| 
								 | 
							
								    setSpecies(CONSTRUCTOR_NAME);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 |