From d8cd926a8c5b69b86b2450ba72346b0edde6edd7 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 15 Dec 2017 19:26:17 +0300 Subject: [PATCH] Do not leak primitiveness of an array wrapped with asList A primitive array wrapped in a List with asList had incorrect implementation of toArray method: while it declares that an object array is returned, it returned a primitive array. Therefore the methods such as `Collection.toTypedArray()` and its dependents `ArrayList(collection)`, `Collection + Iterable` might behave incorrectly having relied on `toTypedArray` returned an object array. #KT-21828 Fixed --- js/js.libraries/src/core/collections/ArrayList.kt | 2 +- libraries/stdlib/test/js/JsCollectionsTest.kt | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/js/js.libraries/src/core/collections/ArrayList.kt b/js/js.libraries/src/core/collections/ArrayList.kt index 63bc17cc00a..1d7f21ba451 100644 --- a/js/js.libraries/src/core/collections/ArrayList.kt +++ b/js/js.libraries/src/core/collections/ArrayList.kt @@ -117,7 +117,7 @@ public open class ArrayList internal constructor(private var array: Array = array.copyOf() + override fun toArray(): Array = js("[]").slice.call(array) private fun rangeCheck(index: Int) = index.apply { diff --git a/libraries/stdlib/test/js/JsCollectionsTest.kt b/libraries/stdlib/test/js/JsCollectionsTest.kt index 3cf5fe2170e..8cea1d5591f 100644 --- a/libraries/stdlib/test/js/JsCollectionsTest.kt +++ b/libraries/stdlib/test/js/JsCollectionsTest.kt @@ -36,6 +36,13 @@ class JsCollectionsTest { snapshotDoesNotCreateView(arrayOf("first", "last"), { arrayListOf(*it) }) } + @Suppress("USELESS_CAST") + @Test fun asListHidesPrimitivenessOfArray() { + assertTrue(intArrayOf(1).asList().toTypedArray() as Any is Array<*>, "IntArray primitiveness leaks") + assertTrue(longArrayOf(1).asList().toTypedArray() as Any is Array<*>, "LongArray primitiveness leaks") + assertTrue(charArrayOf(' ').asList().toTypedArray() as Any is Array<*>, "CharArray primitiveness leaks") + } + @Test fun arrayListCapacity() { val list = ArrayList(20) list.ensureCapacity(100)