
module.exports = ProtoList

function ProtoList () {
  this.list = []
  Object.defineProperty(this, "length",
    { get : function () { return this.list.length } })
}
ProtoList.prototype =
  { push : function (obj) {
      if (typeof obj !== "object") obj = {valueOf:obj}
      if (this.list.length >= 1) {
        this.list[this.list.length - 1].__proto__ = obj
      }
      obj.__proto__ = Object.prototype
      return this.list.push(obj)
    }
  , pop : function () {
      if (this.list.length >= 2) {
        this.list[this.list.length - 2].__proto__ = Object.prototype
      }
      return this.list.pop()
    }
  , unshift : function (obj) {
      obj.__proto__ = this.list[0] || Object.prototype
      return this.list.unshift(obj)
    }
  , shift : function () {
      if (this.list.length >= 1) {
        this.list[0].__proto__ = Object.prototype
      }
      return this.list.shift()
    }
  , get : function (key) {
      return this.list[0][key]
    }
  , set : function (key, val, save) {
      if (!this.length) this.push({})
      if (save && this.list[0].hasOwnProperty(key)) this.push({})
      return this.list[0][key] = val
    }
  , forEach : function (fn) {
      for (var key in this.list[0]) fn(key, this.list[0][key])
    }
  , slice : function () {
      return this.list.slice.apply(this.list, arguments)
    }
  }

if (module !== process.mainModule) return

var assert = require("assert")
  , sys = require("sys")

sys.debug("testing")
var p = new ProtoList
p.push({foo:"bar"})
p.push({})
p.set("foo", "baz")
assert.equal(p.get("foo"), "baz")

var p = new ProtoList
p.push({foo:"bar"})
p.set("foo", "baz")
assert.equal(p.get("foo"), "baz")
assert.equal(p.length, 1)
p.pop()
assert.equal(p.length, 0)
p.set("foo", "asdf")
assert.equal(p.length, 1)
assert.equal(p.get("foo"), "asdf")
p.push({bar:"baz"})
assert.equal(p.length, 2)
assert.equal(p.get("foo"), "asdf")
p.shift()
assert.equal(p.length, 1)
assert.equal(p.get("foo"), undefined)



sys.debug("ok")


module.exports = ProtoList

function ProtoList () {
  this.list = []
  Object.defineProperty(this, "length",
    { get : function () { return this.list.length } })
}
ProtoList.prototype =
  { push : function (obj) {
      if (typeof obj !== "object") obj = {valueOf:obj}
      if (this.list.length >= 1) {
        this.list[this.list.length - 1].__proto__ = obj
      }
      obj.__proto__ = Object.prototype
      return this.list.push(obj)
    }
  , pop : function () {
      if (this.list.length >= 2) {
        this.list[this.list.length - 2].__proto__ = Object.prototype
      }
      return this.list.pop()
    }
  , unshift : function (obj) {
      obj.__proto__ = this.list[0] || Object.prototype
      return this.list.unshift(obj)
    }
  , shift : function () {
      if (this.list.length >= 1) {
        this.list[0].__proto__ = Object.prototype
      }
      return this.list.shift()
    }
  , get : function (key) {
      return this.list[0][key]
    }
  , set : function (key, val, save) {
      if (!this.length) this.push({})
      if (save && this.list[0].hasOwnProperty(key)) this.push({})
      return this.list[0][key] = val
    }
  , forEach : function (fn, thisp) {
      for (var key in this.list[0]) fn.call(thisp, key, this.list[0][key])
    }
  , slice : function () {
      return this.list.slice.apply(this.list, arguments)
    }
  }

if (module !== process.mainModule) return

var assert = require("assert")
  , sys = require("sys")

sys.debug("testing")
var p = new ProtoList
p.push({foo:"bar"})
p.push({})
p.set("foo", "baz")
assert.equal(p.get("foo"), "baz")

var p = new ProtoList
p.push({foo:"bar"})
p.set("foo", "baz")
assert.equal(p.get("foo"), "baz")
assert.equal(p.length, 1)
p.pop()
assert.equal(p.length, 0)
p.set("foo", "asdf")
assert.equal(p.length, 1)
assert.equal(p.get("foo"), "asdf")
p.push({bar:"baz"})
assert.equal(p.length, 2)
assert.equal(p.get("foo"), "asdf")
p.shift()
assert.equal(p.length, 1)
assert.equal(p.get("foo"), undefined)



sys.debug("ok")

Handle this-context setting in forEach