[K/JS] Support essential Kotlin collections (List, MutableList, Set, MutableSet, Map, MutableMap) for exporting into JS
^KT-34995 Fixed ^KT-44871 Fixed
This commit is contained in:
@@ -10111,6 +10111,11 @@ public open class ArrayList<E> : kotlin.collections.AbstractMutableList<E>, kotl
|
||||
|
||||
public open override fun addAll(elements: kotlin.collections.Collection<E>): kotlin.Boolean
|
||||
|
||||
@kotlin.js.ExperimentalJsExport
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public open override fun asJsArrayView(): kotlin.js.collections.JsArray<E>
|
||||
|
||||
public open override fun clear(): kotlin.Unit
|
||||
|
||||
public final fun ensureCapacity(minCapacity: kotlin.Int): kotlin.Unit
|
||||
@@ -10310,6 +10315,11 @@ public open class LinkedHashSet<E> : kotlin.collections.HashSet<E>, kotlin.colle
|
||||
public interface List<out E> : kotlin.collections.Collection<E> {
|
||||
public abstract override val size: kotlin.Int { get; }
|
||||
|
||||
@kotlin.js.ExperimentalJsExport
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public open fun asJsReadonlyArrayView(): kotlin.js.collections.JsReadonlyArray<E>
|
||||
|
||||
public abstract override operator fun contains(element: E): kotlin.Boolean
|
||||
|
||||
public abstract override fun containsAll(elements: kotlin.collections.Collection<E>): kotlin.Boolean
|
||||
@@ -10362,6 +10372,11 @@ public interface Map<K, out V> {
|
||||
|
||||
public abstract val values: kotlin.collections.Collection<V> { get; }
|
||||
|
||||
@kotlin.js.ExperimentalJsExport
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public open fun asJsReadonlyMapView(): kotlin.js.collections.JsReadonlyMap<K, V>
|
||||
|
||||
public abstract fun containsKey(key: K): kotlin.Boolean
|
||||
|
||||
public abstract fun containsValue(value: V): kotlin.Boolean
|
||||
@@ -10410,6 +10425,11 @@ public interface MutableList<E> : kotlin.collections.List<E>, kotlin.collections
|
||||
|
||||
public abstract override fun addAll(elements: kotlin.collections.Collection<E>): kotlin.Boolean
|
||||
|
||||
@kotlin.js.ExperimentalJsExport
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public open fun asJsArrayView(): kotlin.js.collections.JsArray<E>
|
||||
|
||||
public abstract override fun clear(): kotlin.Unit
|
||||
|
||||
public abstract override fun listIterator(): kotlin.collections.MutableListIterator<E>
|
||||
@@ -10448,6 +10468,11 @@ public interface MutableMap<K, V> : kotlin.collections.Map<K, V> {
|
||||
|
||||
public abstract override val values: kotlin.collections.MutableCollection<V> { get; }
|
||||
|
||||
@kotlin.js.ExperimentalJsExport
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public open fun asJsMapView(): kotlin.js.collections.JsMap<K, V>
|
||||
|
||||
public abstract fun clear(): kotlin.Unit
|
||||
|
||||
public abstract fun put(key: K, value: V): V?
|
||||
@@ -10466,6 +10491,11 @@ public interface MutableSet<E> : kotlin.collections.Set<E>, kotlin.collections.M
|
||||
|
||||
public abstract override fun addAll(elements: kotlin.collections.Collection<E>): kotlin.Boolean
|
||||
|
||||
@kotlin.js.ExperimentalJsExport
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public open fun asJsSetView(): kotlin.js.collections.JsSet<E>
|
||||
|
||||
public abstract override fun clear(): kotlin.Unit
|
||||
|
||||
public abstract override operator fun iterator(): kotlin.collections.MutableIterator<E>
|
||||
@@ -10483,6 +10513,11 @@ public interface RandomAccess {
|
||||
public interface Set<out E> : kotlin.collections.Collection<E> {
|
||||
public abstract override val size: kotlin.Int { get; }
|
||||
|
||||
@kotlin.js.ExperimentalJsExport
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public open fun asJsReadonlySetView(): kotlin.js.collections.JsReadonlySet<E>
|
||||
|
||||
public abstract override operator fun contains(element: E): kotlin.Boolean
|
||||
|
||||
public abstract override fun containsAll(elements: kotlin.collections.Collection<E>): kotlin.Boolean
|
||||
@@ -10498,4 +10533,4 @@ public abstract class ShortIterator : kotlin.collections.Iterator<kotlin.Short>
|
||||
public final override operator fun next(): kotlin.Short
|
||||
|
||||
public abstract fun nextShort(): kotlin.Short
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
@kotlin.js.JsName(name = "Array")
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
public open external class JsArray<E> : kotlin.js.collections.JsReadonlyArray<E> {
|
||||
public constructor JsArray<E>()
|
||||
}
|
||||
|
||||
@kotlin.js.JsName(name = "Map")
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
public open external class JsMap<K, V> : kotlin.js.collections.JsReadonlyMap<K, V> {
|
||||
public constructor JsMap<K, V>()
|
||||
}
|
||||
|
||||
@kotlin.js.JsName(name = "ReadonlyArray")
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
public external interface JsReadonlyArray<out E> {
|
||||
}
|
||||
|
||||
@kotlin.js.JsName(name = "ReadonlyMap")
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
public external interface JsReadonlyMap<K, out V> {
|
||||
}
|
||||
|
||||
@kotlin.js.JsName(name = "ReadonlySet")
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
public external interface JsReadonlySet<out E> {
|
||||
}
|
||||
|
||||
@kotlin.js.JsName(name = "Set")
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
@kotlin.js.ExperimentalJsCollectionsApi
|
||||
public open external class JsSet<E> : kotlin.js.collections.JsReadonlySet<E> {
|
||||
public constructor JsSet<E>()
|
||||
}
|
||||
@@ -201,6 +201,15 @@ public final annotation class EagerInitialization : kotlin.Annotation {
|
||||
public constructor EagerInitialization()
|
||||
}
|
||||
|
||||
@kotlin.RequiresOptIn(level = Level.WARNING)
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FUNCTION})
|
||||
@kotlin.annotation.MustBeDocumented
|
||||
@kotlin.SinceKotlin(version = "1.9")
|
||||
public final annotation class ExperimentalJsCollectionsApi : kotlin.Annotation {
|
||||
public constructor ExperimentalJsCollectionsApi()
|
||||
}
|
||||
|
||||
@kotlin.RequiresOptIn(level = Level.WARNING)
|
||||
@kotlin.annotation.MustBeDocumented
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
|
||||
@@ -130,4 +130,19 @@ public expect annotation class JsExport() {
|
||||
)
|
||||
@MustBeDocumented
|
||||
@SinceKotlin("1.9")
|
||||
public annotation class ExperimentalJsReflectionCreateInstance
|
||||
public annotation class ExperimentalJsReflectionCreateInstance
|
||||
|
||||
/**
|
||||
* This annotation marks the experimental JS-collections API that allows to manipulate with native JS-collections
|
||||
* The API can be removed completely in any further release.
|
||||
*
|
||||
* Any usage of a declaration annotated with `@ExperimentalJsCollectionsApi` should be accepted either by
|
||||
* annotating that usage with the [OptIn] annotation, e.g. `@OptIn(ExperimentalJsCollectionsApi::class)`,
|
||||
* or by using the compiler argument `-opt-in=kotlin.js.ExperimentalJsCollectionsApi`.
|
||||
*/
|
||||
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
|
||||
@MustBeDocumented
|
||||
@SinceKotlin("1.9")
|
||||
public annotation class ExperimentalJsCollectionsApi
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.js.collections.*
|
||||
|
||||
/**
|
||||
* Classes that inherit from this interface can be represented as a sequence of elements that can
|
||||
* be iterated over.
|
||||
@@ -146,8 +148,11 @@ public interface List<out E> : Collection<E> {
|
||||
// Query Operations
|
||||
|
||||
override val size: Int
|
||||
|
||||
override fun isEmpty(): Boolean
|
||||
|
||||
override fun contains(element: @UnsafeVariance E): Boolean
|
||||
|
||||
override fun iterator(): Iterator<E>
|
||||
|
||||
// Bulk Operations
|
||||
@@ -191,6 +196,15 @@ public interface List<out E> : Collection<E> {
|
||||
* Structural changes in the base list make the behavior of the view undefined.
|
||||
*/
|
||||
public fun subList(fromIndex: Int, toIndex: Int): List<E>
|
||||
|
||||
/**
|
||||
* Returns a view with the [JsReadonlyArray] methods to consume it in JavaScript as a regular readonly array.
|
||||
* Structural changes in the base list are synchronized with the view.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@ExperimentalJsCollectionsApi
|
||||
@SinceKotlin("1.9")
|
||||
public fun asJsReadonlyArrayView(): JsReadonlyArray<E> = createJsReadonlyArrayViewFrom(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +240,9 @@ public interface MutableList<E> : List<E>, MutableCollection<E> {
|
||||
public fun addAll(index: Int, elements: Collection<E>): Boolean
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean
|
||||
|
||||
override fun clear(): Unit
|
||||
|
||||
// Positional Access Operations
|
||||
@@ -256,6 +272,15 @@ public interface MutableList<E> : List<E>, MutableCollection<E> {
|
||||
|
||||
// View
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E>
|
||||
|
||||
/**
|
||||
* Returns a view with the [JsArray] methods to consume it in JavaScript as a regular array.
|
||||
* Structural changes in the base list are synchronized with the view, and vice verse.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@ExperimentalJsCollectionsApi
|
||||
@SinceKotlin("1.9")
|
||||
public fun asJsArrayView(): JsArray<E> = createJsArrayViewFrom(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,12 +293,24 @@ public interface Set<out E> : Collection<E> {
|
||||
// Query Operations
|
||||
|
||||
override val size: Int
|
||||
|
||||
override fun isEmpty(): Boolean
|
||||
|
||||
override fun contains(element: @UnsafeVariance E): Boolean
|
||||
|
||||
override fun iterator(): Iterator<E>
|
||||
|
||||
// Bulk Operations
|
||||
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
|
||||
|
||||
/**
|
||||
* Returns a view with the [JsReadonlySet] methods to consume it in JavaScript as a regular readonly Set.
|
||||
* Structural changes in the base set are synchronized with the view.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@ExperimentalJsCollectionsApi
|
||||
@SinceKotlin("1.9")
|
||||
public fun asJsReadonlySetView(): JsReadonlySet<E> = createJsReadonlySetViewFrom(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,9 +336,21 @@ public interface MutableSet<E> : Set<E>, MutableCollection<E> {
|
||||
// Bulk Modification Operations
|
||||
|
||||
override fun addAll(elements: Collection<E>): Boolean
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean
|
||||
|
||||
override fun clear(): Unit
|
||||
|
||||
/**
|
||||
* Returns a view with the [JsSet] methods to consume it in JavaScript as a regular Set.
|
||||
* Structural changes in the base set are synchronized with the view, and vice verse.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@ExperimentalJsCollectionsApi
|
||||
@SinceKotlin("1.9")
|
||||
public fun asJsSetView(): JsSet<E> = createJsSetViewFrom(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,6 +419,15 @@ public interface Map<K, out V> {
|
||||
*/
|
||||
public val value: V
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view with the [JsReadonlyMap] methods to consume it in JavaScript as a regular readonly Map.
|
||||
* Structural changes in the base map are synchronized with the view.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@ExperimentalJsCollectionsApi
|
||||
@SinceKotlin("1.9")
|
||||
public fun asJsReadonlyMapView(): JsReadonlyMap<K, V> = createJsReadonlyMapViewFrom(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,4 +490,13 @@ public interface MutableMap<K, V> : Map<K, V> {
|
||||
*/
|
||||
public fun setValue(newValue: V): V
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view with the [JsMap] methods to consume it in JavaScript as a regular Map.
|
||||
* Structural changes in the base map are synchronized with the view, and vice verse.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@ExperimentalJsCollectionsApi
|
||||
@SinceKotlin("1.9")
|
||||
public fun asJsMapView(): JsMap<K, V> = createJsMapViewFrom(this)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
@file:OptIn(ExperimentalJsCollectionsApi::class)
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.js.collections.*
|
||||
|
||||
private class JsArrayView<E> : JsArray<E>()
|
||||
|
||||
private fun UNSUPPORTED_OPERATION() {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
internal fun <E> createJsReadonlyArrayViewFrom(list: List<E>): JsReadonlyArray<E> =
|
||||
createJsArrayViewWith(
|
||||
listSize = { list.size },
|
||||
listGet = { i -> list[i] },
|
||||
listSet = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
listDecreaseSize = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
listIncreaseSize = ::UNSUPPORTED_OPERATION.asDynamic()
|
||||
)
|
||||
|
||||
internal fun <E> createJsArrayViewFrom(list: MutableList<E>): JsArray<E> =
|
||||
createJsArrayViewWith(
|
||||
listSize = { list.size },
|
||||
listGet = { i -> list[i] },
|
||||
listSet = { i, v -> list[i] = v },
|
||||
listDecreaseSize = { size -> list.subList(list.size - size, list.size).clear() },
|
||||
listIncreaseSize = ::UNSUPPORTED_OPERATION.asDynamic()
|
||||
)
|
||||
|
||||
@Suppress("UNUSED_VARIABLE", "UNUSED_PARAMETER")
|
||||
private fun <E> createJsArrayViewWith(
|
||||
listSize: () -> Int,
|
||||
listGet: (Int) -> E,
|
||||
listSet: (Int, E) -> Unit,
|
||||
listDecreaseSize: (Int) -> Unit,
|
||||
listIncreaseSize: (Int) -> Unit,
|
||||
): dynamic {
|
||||
val arrayView = objectCreate<JsArrayView<*>>()
|
||||
|
||||
return js("""
|
||||
new Proxy(arrayView, {
|
||||
get: function(target, prop, receiver) {
|
||||
if (prop === "length") return listSize();
|
||||
var type = typeof prop
|
||||
var index = type === "string" || type === "number" ? +prop : undefined
|
||||
if (!isNaN(index)) return listGet(index);
|
||||
return target[prop]
|
||||
},
|
||||
has: function(target, key) { return !isNaN(key) && key < listSize() },
|
||||
set: function(obj, prop, value) {
|
||||
if (prop === "length") {
|
||||
var size = listSize();
|
||||
var newSize = type === "string" || type === "number" ? +prop : undefined
|
||||
if (isNaN(newSize)) throw new RangeError("invalid array length")
|
||||
if (newSize < size) listDecreaseSize(size - newSize)
|
||||
else listIncreaseSize(newSize - size)
|
||||
return true
|
||||
}
|
||||
|
||||
var type = typeof prop;
|
||||
var index = type === "string" || type === "number" ? +prop : undefined;
|
||||
|
||||
if (isNaN(index)) return false;
|
||||
|
||||
listSet(index, value)
|
||||
|
||||
return true
|
||||
},
|
||||
})
|
||||
""")
|
||||
}
|
||||
|
||||
private class JsSetView<E> : JsSet<E>()
|
||||
|
||||
internal fun <E> createJsReadonlySetViewFrom(set: Set<E>): JsReadonlySet<E> =
|
||||
createJsSetViewWith<E>(
|
||||
setSize = { set.size },
|
||||
setAdd = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
setRemove = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
setClear = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
setContains = { v -> set.contains(v) },
|
||||
valuesIterator = { createJsIteratorFrom(set.iterator()) },
|
||||
entriesIterator = { createJsIteratorFrom(set.iterator()) { arrayOf(it, it) } },
|
||||
forEach = { cb, t -> forEach(cb, t) }
|
||||
)
|
||||
|
||||
internal fun <E> createJsSetViewFrom(set: MutableSet<E>): JsSet<E> =
|
||||
createJsSetViewWith<E>(
|
||||
setSize = { set.size },
|
||||
setAdd = { v -> set.add(v) },
|
||||
setRemove = { v -> set.remove(v) },
|
||||
setClear = { set.clear() },
|
||||
setContains = { v -> set.contains(v) },
|
||||
valuesIterator = { createJsIteratorFrom(set.iterator()) },
|
||||
entriesIterator = { createJsIteratorFrom(set.iterator()) { arrayOf(it, it) } },
|
||||
forEach = { cb, t -> forEach(cb, t) }
|
||||
)
|
||||
|
||||
@Suppress("UNUSED_VARIABLE", "UNUSED_PARAMETER")
|
||||
private fun <E> createJsSetViewWith(
|
||||
setSize: () -> Int,
|
||||
setAdd: (E) -> Unit,
|
||||
setRemove: (E) -> Boolean,
|
||||
setClear: () -> Unit,
|
||||
setContains: (E) -> Boolean,
|
||||
valuesIterator: () -> dynamic,
|
||||
entriesIterator: () -> dynamic,
|
||||
forEach: (dynamic, dynamic) -> Unit,
|
||||
): dynamic {
|
||||
val setView = objectCreate<JsSetView<E>>().also {
|
||||
js("it[Symbol.iterator] = valuesIterator")
|
||||
defineProp(it, "size", setSize, VOID)
|
||||
}
|
||||
|
||||
return js("""
|
||||
Object.assign(setView, {
|
||||
add: function(value) { setAdd(value); return this },
|
||||
'delete': setRemove,
|
||||
clear: setClear,
|
||||
has: setContains,
|
||||
keys: valuesIterator,
|
||||
values: valuesIterator,
|
||||
entries: entriesIterator,
|
||||
forEach: function (cb, thisArg) { forEach(cb, thisArg || setView) }
|
||||
})
|
||||
""")
|
||||
}
|
||||
|
||||
|
||||
private class JsMapView<K, V> : JsMap<K, V>()
|
||||
|
||||
internal fun <K, V> createJsReadonlyMapViewFrom(map: Map<K, V>): JsReadonlyMap<K, V> =
|
||||
createJsMapViewWith<K, V>(
|
||||
mapSize = { map.size },
|
||||
mapGet = { k -> map[k] },
|
||||
mapContains = { k -> map.containsKey(k) },
|
||||
mapPut = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
mapRemove = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
mapClear = ::UNSUPPORTED_OPERATION.asDynamic(),
|
||||
keysIterator = { createJsIteratorFrom(map.keys.iterator()) },
|
||||
valuesIterator = { createJsIteratorFrom(map.values.iterator()) },
|
||||
entriesIterator = { createJsIteratorFrom(map.entries.iterator()) { arrayOf(it.key, it.value) } },
|
||||
forEach = { cb, t -> forEach(cb, t) }
|
||||
)
|
||||
|
||||
internal fun <K, V> createJsMapViewFrom(map: MutableMap<K, V>): JsMap<K, V> =
|
||||
createJsMapViewWith<K, V>(
|
||||
mapSize = { map.size },
|
||||
mapGet = { k -> map[k] },
|
||||
mapContains = { k -> map.containsKey(k) },
|
||||
mapPut = { k, v -> map.put(k, v) },
|
||||
mapRemove = { k -> map.remove(k) },
|
||||
mapClear = { map.clear() },
|
||||
keysIterator = { createJsIteratorFrom(map.keys.iterator()) },
|
||||
valuesIterator = { createJsIteratorFrom(map.values.iterator()) },
|
||||
entriesIterator = { createJsIteratorFrom(map.entries.iterator()) { arrayOf(it.key, it.value) } },
|
||||
forEach = { cb, t -> forEach(cb, t) }
|
||||
)
|
||||
|
||||
@Suppress("UNUSED_VARIABLE", "UNUSED_PARAMETER")
|
||||
private fun <K, V> createJsMapViewWith(
|
||||
mapSize: () -> Int,
|
||||
mapGet: (K) -> V?,
|
||||
mapContains: (K) -> Boolean,
|
||||
mapPut: (K, V) -> Unit,
|
||||
mapRemove: (K) -> Unit,
|
||||
mapClear: () -> Unit,
|
||||
keysIterator: () -> dynamic,
|
||||
valuesIterator: () -> dynamic,
|
||||
entriesIterator: () -> dynamic,
|
||||
forEach: (dynamic, dynamic) -> Unit,
|
||||
): dynamic {
|
||||
val mapView = objectCreate<JsMapView<K, V>>().also {
|
||||
js("it[Symbol.iterator] = entriesIterator")
|
||||
defineProp(it, "size", mapSize, VOID)
|
||||
}
|
||||
|
||||
return js("""
|
||||
Object.assign(mapView, {
|
||||
get: mapGet,
|
||||
set: function(key, value) { mapPut(key, value); return this },
|
||||
'delete': mapRemove,
|
||||
clear: mapClear,
|
||||
has: mapContains,
|
||||
keys: valuesIterator,
|
||||
values: valuesIterator,
|
||||
entries: entriesIterator,
|
||||
forEach: function (cb, thisArg) { forEach(cb, thisArg || mapView) }
|
||||
})
|
||||
""")
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_VARIABLE", "UNUSED_PARAMETER")
|
||||
private fun <T> createJsIteratorFrom(iterator: Iterator<T>, transform: (T) -> dynamic = { it }): dynamic {
|
||||
val iteratorNext = { iterator.next() }
|
||||
val iteratorHasNext = { iterator.hasNext() }
|
||||
return js("""{
|
||||
next: function() {
|
||||
var result = { done: !iteratorHasNext() };
|
||||
if (!result.done) result.value = transform(iteratorNext());
|
||||
return result;
|
||||
}
|
||||
}""")
|
||||
}
|
||||
|
||||
private fun forEach(cb: (dynamic, dynamic, dynamic) -> Unit, thisArg: dynamic) {
|
||||
val iterator = thisArg.entries()
|
||||
var result = iterator.next()
|
||||
|
||||
while (!result.done) {
|
||||
val value = result.value
|
||||
cb(value[0], value[1], thisArg)
|
||||
result = iterator.next()
|
||||
}
|
||||
}
|
||||
@@ -208,7 +208,7 @@ internal fun protoOf(constructor: Any) =
|
||||
js("constructor.prototype")
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
internal fun <T> objectCreate(proto: T?) =
|
||||
internal fun <T> objectCreate(proto: T? = null): T =
|
||||
js("Object.create(proto)")
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
|
||||
@@ -44,16 +44,17 @@ internal fun safePropertySet(self: dynamic, setterName: String, propName: String
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
|
||||
internal annotation class JsFun(val code: String)
|
||||
|
||||
/**
|
||||
* The annotation is needed for annotating class declarations and type alias which are used inside exported declarations, but
|
||||
* doesn't contain @JsExport annotation
|
||||
* This information is used for generating special tagged types inside d.ts files, for more strict usage of implicitly exported entities
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class JsImplicitExport
|
||||
|
||||
/**
|
||||
* The annotation is needed for annotating function declarations that should be compiled as ES6 generators
|
||||
*/
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
internal annotation class JsGenerator
|
||||
|
||||
/**
|
||||
* The annotation is needed for annotating class declarations and type alias which are used inside exported declarations, but
|
||||
* doesn't contain @JsExport annotation
|
||||
* This information is used for generating special tagged types inside d.ts files, for more strict usage of implicitly exported entities
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class JsImplicitExport(val couldBeConvertedToExplicitExport: Boolean)
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.js.collections.JsArray
|
||||
|
||||
/**
|
||||
* Provides a [MutableList] implementation, which uses a resizable array as its backing storage.
|
||||
*
|
||||
@@ -178,6 +180,10 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
return js("[]").slice.call(array)
|
||||
}
|
||||
|
||||
@ExperimentalJsExport
|
||||
@ExperimentalJsCollectionsApi
|
||||
@SinceKotlin("1.9")
|
||||
override fun asJsArrayView(): JsArray<E> = array.unsafeCast<JsArray<E>>()
|
||||
|
||||
internal override fun checkIsMutable() {
|
||||
if (isReadOnly) throw UnsupportedOperationException()
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.js.collections
|
||||
|
||||
|
||||
/**
|
||||
* Exposes the TypeScript [ReadonlyArray](https://www.typescriptlang.org/docs/handbook/2/objects.html#the-readonlyarray-type) to Kotlin.
|
||||
*/
|
||||
@JsName("ReadonlyArray")
|
||||
@SinceKotlin("1.9")
|
||||
@ExperimentalJsCollectionsApi
|
||||
public external interface JsReadonlyArray<out E>
|
||||
|
||||
/**
|
||||
* Exposes the JavaScript [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) to Kotlin.
|
||||
*/
|
||||
@JsName("Array")
|
||||
@SinceKotlin("1.9")
|
||||
@ExperimentalJsCollectionsApi
|
||||
public external open class JsArray<E> : JsReadonlyArray<E>
|
||||
|
||||
/**
|
||||
* Exposes the TypeScript [ReadonlySet](https://github.com/microsoft/TypeScript/blob/bd952a7a83ce04b3541b952238b6c0e4316b7d5d/src/lib/es2015.collection.d.ts#L103) to Kotlin.
|
||||
*/
|
||||
@JsName("ReadonlySet")
|
||||
@SinceKotlin("1.9")
|
||||
@ExperimentalJsCollectionsApi
|
||||
public external interface JsReadonlySet<out E>
|
||||
|
||||
/**
|
||||
* Exposes the JavaScript [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) to Kotlin.
|
||||
*/
|
||||
@JsName("Set")
|
||||
@SinceKotlin("1.9")
|
||||
@ExperimentalJsCollectionsApi
|
||||
public external open class JsSet<E> : JsReadonlySet<E>
|
||||
|
||||
/**
|
||||
* Exposes the TypeScript [ReadonlyMap](https://github.com/microsoft/TypeScript/blob/bd952a7a83ce04b3541b952238b6c0e4316b7d5d/src/lib/es2015.collection.d.ts#L37) to Kotlin.
|
||||
*/
|
||||
@JsName("ReadonlyMap")
|
||||
@SinceKotlin("1.9")
|
||||
@ExperimentalJsCollectionsApi
|
||||
public external interface JsReadonlyMap<K, out V>
|
||||
|
||||
/**
|
||||
* Exposes the JavaScript [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) to Kotlin.
|
||||
*/
|
||||
@JsName("Map")
|
||||
@SinceKotlin("1.9")
|
||||
@ExperimentalJsCollectionsApi
|
||||
public external open class JsMap<K, V> : JsReadonlyMap<K, V>
|
||||
Reference in New Issue
Block a user