• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2module.exports = ProtoList
3
4function setProto(obj, proto) {
5  if (typeof Object.setPrototypeOf === "function")
6    return Object.setPrototypeOf(obj, proto)
7  else
8    obj.__proto__ = proto
9}
10
11function ProtoList () {
12  this.list = []
13  var root = null
14  Object.defineProperty(this, 'root', {
15    get: function () { return root },
16    set: function (r) {
17      root = r
18      if (this.list.length) {
19        setProto(this.list[this.list.length - 1], r)
20      }
21    },
22    enumerable: true,
23    configurable: true
24  })
25}
26
27ProtoList.prototype =
28  { get length () { return this.list.length }
29  , get keys () {
30      var k = []
31      for (var i in this.list[0]) k.push(i)
32      return k
33    }
34  , get snapshot () {
35      var o = {}
36      this.keys.forEach(function (k) { o[k] = this.get(k) }, this)
37      return o
38    }
39  , get store () {
40      return this.list[0]
41    }
42  , push : function (obj) {
43      if (typeof obj !== "object") obj = {valueOf:obj}
44      if (this.list.length >= 1) {
45        setProto(this.list[this.list.length - 1], obj)
46      }
47      setProto(obj, this.root)
48      return this.list.push(obj)
49    }
50  , pop : function () {
51      if (this.list.length >= 2) {
52        setProto(this.list[this.list.length - 2], this.root)
53      }
54      return this.list.pop()
55    }
56  , unshift : function (obj) {
57      setProto(obj, this.list[0] || this.root)
58      return this.list.unshift(obj)
59    }
60  , shift : function () {
61      if (this.list.length === 1) {
62        setProto(this.list[0], this.root)
63      }
64      return this.list.shift()
65    }
66  , get : function (key) {
67      return this.list[0][key]
68    }
69  , set : function (key, val, save) {
70      if (!this.length) this.push({})
71      if (save && this.list[0].hasOwnProperty(key)) this.push({})
72      return this.list[0][key] = val
73    }
74  , forEach : function (fn, thisp) {
75      for (var key in this.list[0]) fn.call(thisp, key, this.list[0][key])
76    }
77  , slice : function () {
78      return this.list.slice.apply(this.list, arguments)
79    }
80  , splice : function () {
81      // handle injections
82      var ret = this.list.splice.apply(this.list, arguments)
83      for (var i = 0, l = this.list.length; i < l; i++) {
84        setProto(this.list[i], this.list[i + 1] || this.root)
85      }
86      return ret
87    }
88  }
89