const ion = null # don't depend on ion for this. # the uniqueCounter and getId have to be defined outside of the MapShim constructor. # otherwise some objects may end up with the same uniqueId if they are added to different Maps. let uniqueCounter = 0 const idName = "_Map_id_" const getId = (key) -> if not key? return String(key) if typeof key is 'string' or typeof key is 'number' or typeof key is 'boolean' return "_" + key let id = key[idName] if not id? # checking the definition shouldn't be necessary. # but nodejs has an object returning undefined # even though the definition says it has a value. let def = Object.getOwnPropertyDescriptor(key, idName) if def? id = def.value else id = ++uniqueCounter Object.defineProperty(key, idName, {value:id}) return id const MapShim(pairs) -> if pairs? throw new Error("Don't add items in the constructor, IE implementation of Set breaks this") let lookup = {} let keys = [] const methods = get: (key) -> lookup[getId(key)] set: (key, value) -> let id = getId(key) if not lookup.hasOwnProperty(id) keys.push(key) lookup[id] = value return value has: (key) -> let id = getId(key) return lookup.hasOwnProperty(id) delete: (key) -> let id = getId(key) keys.remove(key) delete lookup[id] clear: -> lookup = {} keys = [] forEach: (callback, thisArg) -> for key in keys let value = @get(key) callback.call(thisArg, value, key, @) for key, value of methods Object.defineProperty(@, key, {value}) # we will even replace Googles crap implementation of Map that doesn't yet have forEach if not global.Map?.prototype.forEach? if global.window console.warn('Shimming Map') global.Map = MapShim export const test = -> const Map = global.Map let map = new Map() map.set('a', 1) map.set('b', 2) assert Object.keys(map).length is 0 assert map.has('a') assert not map.has('c') assert map.get('a') is 1 assert map.get('b') is 2 assert map.get('c') is undefined let mykey1 = {} map.set(mykey1, "one") assert Object.keys(mykey1).length is 0 assert map.get(mykey1) is "one"