114 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var hasOwnProperty = Object.prototype.hasOwnProperty
 | 
						|
 | 
						|
module.exports = PseudoMap
 | 
						|
 | 
						|
function PseudoMap (set) {
 | 
						|
  if (!(this instanceof PseudoMap)) // whyyyyyyy
 | 
						|
    throw new TypeError("Constructor PseudoMap requires 'new'")
 | 
						|
 | 
						|
  this.clear()
 | 
						|
 | 
						|
  if (set) {
 | 
						|
    if ((set instanceof PseudoMap) ||
 | 
						|
        (typeof Map === 'function' && set instanceof Map))
 | 
						|
      set.forEach(function (value, key) {
 | 
						|
        this.set(key, value)
 | 
						|
      }, this)
 | 
						|
    else if (Array.isArray(set))
 | 
						|
      set.forEach(function (kv) {
 | 
						|
        this.set(kv[0], kv[1])
 | 
						|
      }, this)
 | 
						|
    else
 | 
						|
      throw new TypeError('invalid argument')
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
PseudoMap.prototype.forEach = function (fn, thisp) {
 | 
						|
  thisp = thisp || this
 | 
						|
  Object.keys(this._data).forEach(function (k) {
 | 
						|
    if (k !== 'size')
 | 
						|
      fn.call(thisp, this._data[k].value, this._data[k].key)
 | 
						|
  }, this)
 | 
						|
}
 | 
						|
 | 
						|
PseudoMap.prototype.has = function (k) {
 | 
						|
  return !!find(this._data, k)
 | 
						|
}
 | 
						|
 | 
						|
PseudoMap.prototype.get = function (k) {
 | 
						|
  var res = find(this._data, k)
 | 
						|
  return res && res.value
 | 
						|
}
 | 
						|
 | 
						|
PseudoMap.prototype.set = function (k, v) {
 | 
						|
  set(this._data, k, v)
 | 
						|
}
 | 
						|
 | 
						|
PseudoMap.prototype.delete = function (k) {
 | 
						|
  var res = find(this._data, k)
 | 
						|
  if (res) {
 | 
						|
    delete this._data[res._index]
 | 
						|
    this._data.size--
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
PseudoMap.prototype.clear = function () {
 | 
						|
  var data = Object.create(null)
 | 
						|
  data.size = 0
 | 
						|
 | 
						|
  Object.defineProperty(this, '_data', {
 | 
						|
    value: data,
 | 
						|
    enumerable: false,
 | 
						|
    configurable: true,
 | 
						|
    writable: false
 | 
						|
  })
 | 
						|
}
 | 
						|
 | 
						|
Object.defineProperty(PseudoMap.prototype, 'size', {
 | 
						|
  get: function () {
 | 
						|
    return this._data.size
 | 
						|
  },
 | 
						|
  set: function (n) {},
 | 
						|
  enumerable: true,
 | 
						|
  configurable: true
 | 
						|
})
 | 
						|
 | 
						|
PseudoMap.prototype.values =
 | 
						|
PseudoMap.prototype.keys =
 | 
						|
PseudoMap.prototype.entries = function () {
 | 
						|
  throw new Error('iterators are not implemented in this version')
 | 
						|
}
 | 
						|
 | 
						|
// Either identical, or both NaN
 | 
						|
function same (a, b) {
 | 
						|
  return a === b || a !== a && b !== b
 | 
						|
}
 | 
						|
 | 
						|
function Entry (k, v, i) {
 | 
						|
  this.key = k
 | 
						|
  this.value = v
 | 
						|
  this._index = i
 | 
						|
}
 | 
						|
 | 
						|
function find (data, k) {
 | 
						|
  for (var i = 0, s = '_' + k, key = s;
 | 
						|
       hasOwnProperty.call(data, key);
 | 
						|
       key = s + i++) {
 | 
						|
    if (same(data[key].key, k))
 | 
						|
      return data[key]
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function set (data, k, v) {
 | 
						|
  for (var i = 0, s = '_' + k, key = s;
 | 
						|
       hasOwnProperty.call(data, key);
 | 
						|
       key = s + i++) {
 | 
						|
    if (same(data[key].key, k)) {
 | 
						|
      data[key].value = v
 | 
						|
      return
 | 
						|
    }
 | 
						|
  }
 | 
						|
  data.size++
 | 
						|
  data[key] = new Entry(k, v, key)
 | 
						|
}
 |