• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1var hasOwnProperty = Object.prototype.hasOwnProperty
2
3module.exports = PseudoMap
4
5function PseudoMap (set) {
6  if (!(this instanceof PseudoMap)) // whyyyyyyy
7    throw new TypeError("Constructor PseudoMap requires 'new'")
8
9  this.clear()
10
11  if (set) {
12    if ((set instanceof PseudoMap) ||
13        (typeof Map === 'function' && set instanceof Map))
14      set.forEach(function (value, key) {
15        this.set(key, value)
16      }, this)
17    else if (Array.isArray(set))
18      set.forEach(function (kv) {
19        this.set(kv[0], kv[1])
20      }, this)
21    else
22      throw new TypeError('invalid argument')
23  }
24}
25
26PseudoMap.prototype.forEach = function (fn, thisp) {
27  thisp = thisp || this
28  Object.keys(this._data).forEach(function (k) {
29    if (k !== 'size')
30      fn.call(thisp, this._data[k].value, this._data[k].key)
31  }, this)
32}
33
34PseudoMap.prototype.has = function (k) {
35  return !!find(this._data, k)
36}
37
38PseudoMap.prototype.get = function (k) {
39  var res = find(this._data, k)
40  return res && res.value
41}
42
43PseudoMap.prototype.set = function (k, v) {
44  set(this._data, k, v)
45}
46
47PseudoMap.prototype.delete = function (k) {
48  var res = find(this._data, k)
49  if (res) {
50    delete this._data[res._index]
51    this._data.size--
52  }
53}
54
55PseudoMap.prototype.clear = function () {
56  var data = Object.create(null)
57  data.size = 0
58
59  Object.defineProperty(this, '_data', {
60    value: data,
61    enumerable: false,
62    configurable: true,
63    writable: false
64  })
65}
66
67Object.defineProperty(PseudoMap.prototype, 'size', {
68  get: function () {
69    return this._data.size
70  },
71  set: function (n) {},
72  enumerable: true,
73  configurable: true
74})
75
76PseudoMap.prototype.values =
77PseudoMap.prototype.keys =
78PseudoMap.prototype.entries = function () {
79  throw new Error('iterators are not implemented in this version')
80}
81
82// Either identical, or both NaN
83function same (a, b) {
84  return a === b || a !== a && b !== b
85}
86
87function Entry (k, v, i) {
88  this.key = k
89  this.value = v
90  this._index = i
91}
92
93function find (data, k) {
94  for (var i = 0, s = '_' + k, key = s;
95       hasOwnProperty.call(data, key);
96       key = s + i++) {
97    if (same(data[key].key, k))
98      return data[key]
99  }
100}
101
102function set (data, k, v) {
103  for (var i = 0, s = '_' + k, key = s;
104       hasOwnProperty.call(data, key);
105       key = s + i++) {
106    if (same(data[key].key, k)) {
107      data[key].value = v
108      return
109    }
110  }
111  data.size++
112  data[key] = new Entry(k, v, key)
113}
114