Skip to content

Instantly share code, notes, and snippets.

@madbook
Created February 22, 2013 19:54
Show Gist options
  • Save madbook/5016099 to your computer and use it in GitHub Desktop.
Save madbook/5016099 to your computer and use it in GitHub Desktop.
my own implementation of the es6 map spec, written in coffeescript
toObject = (val) ->
if !val?
throw new TypeError()
return Object(val)
class MapIterator
next: ->
if !@__Map__? or !@__MapNextIndex__? or !@__MapIterationKind__?
return new TypeError('MapIterator not initialised')
if !@__Map__.__MapData__?
return new TypeError('Invalid Map object')
index = @__MapNextIndex__
entries = @__Map__.__MapData__
itemKind = @__MapIterationKind__
if index < entries.length
e = entries[index]
@__MapNextIndex__++
if e.key?
if itemKind == "key" then return e.key
if itemKind == "value" then return e.value
if itemKind == "key+value" then return [e.key, e.value]
return undefined # throw 'StopIteration' # need to do more than this?
# __iterator__: -> @
# __toStringTag__ : -> "Map Iterator"
IteratorComplete = (itr, value) ->
if value == undefined and itr.__MapNextIndex__ >= itr.__map__.__MapData__.length
return true
return false
CreateMapIterator = (map, kind) ->
map = toObject(map)
if !map.__MapData__ then throw new TypeError()
itr = new MapIterator()
itr.__Map__ = map
itr.__MapNextIndex__ = 0
itr.__MapIterationKind__ = kind
return itr
class Record
constructor: (@key, @value) ->
MapInitialisation = (obj, iterable) ->
if typeof obj != 'object'
throw new TypeError()
if obj.__MapData__?
throw new TypeError()
if !(Object.isExtensible(obj))
throw new TypeError()
if iterable?
iterable = toObject(iterable)
# iterable = @@iterable (wat?)
itr = obj.iterable()
adder = obj.set
if !(adder instanceof Function)
throw new TypeError()
obj.__MapData__ = []
if !iterable?
return obj
while true
next = itr.next()
if IteratorComplete(itr, next)
return obj
k = next["0"]
v = next["1"]
status = adder.call(obj, k, v)
class Map
constructor: (iterable) ->
status = MapInitialisation(@, iterable)
clear: ->
if !@__MapData__
throw new TypeError()
@__MapData__ = []
return undefined
delete: (key) ->
if !@__MapData__
throw new TypeError()
for p in @__MapData__
if p.key == key
p.key = undefined
p.value = undefined
# splice entry object out of list
return true
return false
forEach: (callbackfn, thisArg=undefined) ->
if !callbackfn? then return
if !@__MapData__ then throw new TypeError()
if !(callbackfn instanceof Function) then throw new TypeError()
for e in @__MapData__
if e.key?
callbackfn.call(thisArg, e.value, e.key, @)
return undefined
get: (key) ->
if !@__MapData__ then throw new TypeError()
for p in @__MapData__
if p.key == key
return p.value
return undefined
has: (key) ->
if !@__MapData__ then throw new TypeError()
for p in @__MapData__
if p.key == key
return true
return false
items: ->
CreateMapIterator(@, "key+value")
keys: ->
CreateMapIterator(@, "key")
set: (key, value) ->
if !@__MapData__ then throw new TypeError()
for p in @__MapData__
if p.key == key
p.value = value
return undefined
@__MapData__.push( new Record(key, value) )
return undefined
values: ->
CreateMapIterator(@, "value")
Object.defineProperty(Map::, 'size', {
get: ->
if !@__MapData__ then throw new TypeError()
count = 0
for p in @__MapData__
if p.key?
count++
return count
})
# __iterator__: ::items
# __toStringTag__: "Map"
window.Map = Map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment