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.
		
		
		
		
		
			
		
			
				
					
					
						
							186 lines
						
					
					
						
							6.6 KiB
						
					
					
				
			
		
		
	
	
							186 lines
						
					
					
						
							6.6 KiB
						
					
					
				'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); | 
						|
  } | 
						|
};
 | 
						|
 |