diff --git a/libraries/stdlib/js/src/kotlin/collections/HashMap.kt b/libraries/stdlib/js/src/kotlin/collections/HashMap.kt index f52be877fc9..90ef925072d 100644 --- a/libraries/stdlib/js/src/kotlin/collections/HashMap.kt +++ b/libraries/stdlib/js/src/kotlin/collections/HashMap.kt @@ -56,7 +56,7 @@ public actual open class HashMap : AbstractMutableMap, MutableMap : InternalMap { - private var backingMap: dynamic = createJsMap() - override var size: Int = 0 - private set - - override fun put(key: K, value: V): V? { - val hashCode = hash(key) - val chainOrEntry = getChainOrEntryOrNull(hashCode) - if (chainOrEntry == null) { - // This is a new chain, put it to the map. - backingMap[hashCode] = SimpleEntry(key, value) - } else { - if (chainOrEntry !is Array<*>) { - // It is an entry - val entry: SimpleEntry = chainOrEntry - if (entry.key == key) { - return entry.setValue(value) - } else { - backingMap[hashCode] = arrayOf(entry, SimpleEntry(key, value)) - size++ - return null - } - } else { - // Chain already exists, perhaps key also exists. - val chain: Array> = chainOrEntry - val entry = chain.findEntryInChain(key) - if (entry != null) { - return entry.setValue(value) - } - chain.asDynamic().push(SimpleEntry(key, value)) - } - } - size++ -// structureChanged(host) - return null - } - - override fun remove(key: K): V? { - val hashCode = hash(key) - val chainOrEntry = getChainOrEntryOrNull(hashCode) ?: return null - if (chainOrEntry !is Array<*>) { - val entry: MutableEntry = chainOrEntry - if (entry.key == key) { - jsDeleteProperty(backingMap, hashCode) - size-- - return entry.value - } else { - return null - } - } else { - val chain: Array> = chainOrEntry - for (index in chain.indices) { - val entry = chain[index] - if (key == entry.key) { - if (chain.size == 1) { - chain.asDynamic().length = 0 - // remove the whole array - jsDeleteProperty(backingMap, hashCode) - } else { - // splice out the entry we're removing - chain.asDynamic().splice(index, 1) - } - size-- -// structureChanged(host) - return entry.value - } - } - } - return null - } - - override fun clear() { - backingMap = createJsMap() - size = 0 - } - - override fun contains(key: K): Boolean = getEntry(key) != null - - override fun get(key: K): V? = getEntry(key)?.value - - private fun getEntry(key: K): MutableEntry? { - val chainOrEntry = getChainOrEntryOrNull(hash(key)) ?: return null - if (chainOrEntry !is Array<*>) { - val entry: MutableEntry = chainOrEntry - if (entry.key == key) { - return entry - } else { - return null - } - } else { - val chain: Array> = chainOrEntry - return chain.findEntryInChain(key) - } - } - - private fun Array>.findEntryInChain(key: K): MutableEntry? = - firstOrNull { entry -> entry.key == key } - - override fun iterator(): MutableIterator> { - - return object : MutableIterator> { - var state = -1 // -1 not ready, 0 - ready, 1 - done - - val keys: Array = js("Object").keys(backingMap) - var keyIndex = -1 - - var chainOrEntry: dynamic = null - var isChain = false - var itemIndex = -1 - var lastEntry: MutableEntry? = null - - private fun computeNext(): Int { - if (chainOrEntry != null && isChain) { - val chainSize: Int = chainOrEntry.unsafeCast>>().size - if (++itemIndex < chainSize) - return 0 - } - - if (++keyIndex < keys.size) { - chainOrEntry = backingMap[keys[keyIndex]] - isChain = chainOrEntry is Array<*> - itemIndex = 0 - return 0 - } else { - chainOrEntry = null - return 1 - } - } - - override fun hasNext(): Boolean { - if (state == -1) - state = computeNext() - return state == 0 - } - - override fun next(): MutableEntry { - if (!hasNext()) throw NoSuchElementException() - val lastEntry = if (isChain) { - chainOrEntry.unsafeCast>>()[itemIndex] - } else { - chainOrEntry.unsafeCast>() - } - this.lastEntry = lastEntry - state = -1 - return lastEntry - } - - override fun remove() { - checkNotNull(lastEntry) - this@InternalHashCodeMap.remove(lastEntry!!.key) - lastEntry = null - // the chain being iterated just got modified by InternalHashCodeMap.remove - itemIndex-- - } - } - } - - private fun getChainOrEntryOrNull(hashCode: Int): dynamic { - val chainOrEntry = backingMap[hashCode] - return if (chainOrEntry === undefined) null else chainOrEntry - } - - private fun hash(key: K) = key?.hashCode() ?: 0 -}