JS: fixed <Type>Array.iterator methods; added -Xtypedarray compiler key

The <Type>Array.iterator used to lack next<Type>() method (KT-16626).

The -Xtypedarray compiler key enables translation of primitive arrays
to TypedArrays, and primitive array`is`-checks (KT-15358, KT-14007,
KT-14614, KT-16056).
This commit is contained in:
Anton Bannykh
2017-01-31 17:16:50 +03:00
parent ba5e78a917
commit 9b34e21619
45 changed files with 1668 additions and 473 deletions
@@ -71,6 +71,10 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
@ValueDescription("<path>")
public String outputPostfix;
@GradleOption(DefaultValues.BooleanFalseDefault.class)
@Argument(value = "Xtypedarrays", description = "Translate primitive arrays to JS typed arrays")
public boolean typedArrays;
@NotNull
public static K2JSCompilerArguments createDefaultInstance() {
K2JSCompilerArguments arguments = new K2JSCompilerArguments();
@@ -286,6 +286,10 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
ContainerUtil.addAllNotNull(libraries, arguments.libraries.split(File.pathSeparator));
}
if (arguments.typedArrays) {
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true);
}
configuration.put(JSConfigurationKeys.LIBRARIES, libraries);
String moduleKindName = arguments.moduleKind;
+1
View File
@@ -1,5 +1,6 @@
Usage: kotlinc-js <options> <source files>
where advanced options include:
-Xtypedarrays Translate primitive arrays to JS typed arrays
-Xno-inline Disable method inlining
-Xrepeat <count> Repeat compilation (for performance analysis)
-Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes)
+1 -2
View File
@@ -1,5 +1,4 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_WITHOUT_CHECK: JS
//test [], get and iterator calls
fun test(createIntNotLong: Boolean): String {
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
fun box(): String {
val a = ByteArray(5)
val x = a.iterator()
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
fun box(): String {
val a = LongArray(5)
val x = a.iterator()
+2 -2
View File
@@ -1,6 +1,6 @@
//KT-2997 Automatically cast error (Array)
// IGNORE_BACKEND: JS
// Unmute when JS implements primitive arrays via TypeArray
// IGNORE_BACKEND_WITHOUT_CHECK: JS
// Unmute when JS implements primitive arrays via TypedArray
fun foo(a: Any): Int {
if (a is IntArray) {
+2
View File
@@ -1,3 +1,5 @@
// IGNORE_BACKEND_WITHOUT_CHECK: JS
fun test(b: Boolean): String {
val a = if (b) IntArray(5) else LongArray(5)
if (a is IntArray) {
+196
View File
@@ -0,0 +1,196 @@
// WITH_RUNTIME
import kotlin.test.assertTrue
import kotlin.test.assertFalse
import kotlin.test.assertEquals
import kotlin.test.assertFails
fun box(): String {
assertTrue(eqBoolean(booleanArrayOf(false), BooleanArray(1)))
assertTrue(eqBoolean(booleanArrayOf(false, true, false), BooleanArray(3) { it % 2 != 0 }))
assertTrue(eqBoolean(booleanArrayOf(true), booleanArrayOf(true).copyOf()))
assertTrue(eqBoolean(booleanArrayOf(true, false), booleanArrayOf(true).copyOf(2)))
assertTrue(eqBoolean(booleanArrayOf(true), booleanArrayOf(true, true).copyOf(1)))
assertTrue(eqBoolean(booleanArrayOf(false, true), booleanArrayOf(false) + true))
assertTrue(eqBoolean(booleanArrayOf(false, true, false), booleanArrayOf(false) + listOf(true, false)))
assertTrue(eqBoolean(booleanArrayOf(true, false), booleanArrayOf(false, true, false, true).copyOfRange(1, 3)))
assertTrue(eqBoolean(booleanArrayOf(false, true, false, true), customBooleanArrayOf(false, *booleanArrayOf(true, false), true)))
assertTrue(booleanArrayOf(true).iterator() is BooleanIterator)
assertEquals(true, booleanArrayOf(true).iterator().nextBoolean())
assertEquals(true, booleanArrayOf(true).iterator().next())
assertFalse(booleanArrayOf().iterator().hasNext())
assertTrue(assertFails { booleanArrayOf().iterator().next() } is IndexOutOfBoundsException)
assertTrue(eqByte(byteArrayOf(0), ByteArray(1)))
assertTrue(eqByte(byteArrayOf(1, 2, 3), ByteArray(3) { (it + 1).toByte() }))
assertTrue(eqByte(byteArrayOf(1), byteArrayOf(1).copyOf()))
assertTrue(eqByte(byteArrayOf(1, 0), byteArrayOf(1).copyOf(2)))
assertTrue(eqByte(byteArrayOf(1), byteArrayOf(1, 2).copyOf(1)))
assertTrue(eqByte(byteArrayOf(1, 2), byteArrayOf(1) + 2))
assertTrue(eqByte(byteArrayOf(1, 2, 3), byteArrayOf(1) + listOf(2.toByte(), 3.toByte())))
assertTrue(eqByte(byteArrayOf(2, 3), byteArrayOf(1, 2, 3, 4).copyOfRange(1, 3)))
assertTrue(eqByte(byteArrayOf(1, 2, 3, 4), customByteArrayOf(1.toByte(), *byteArrayOf(2, 3), 4.toByte())))
assertTrue(byteArrayOf(1).iterator() is ByteIterator)
assertEquals(1, byteArrayOf(1).iterator().nextByte())
assertEquals(1, byteArrayOf(1).iterator().next())
assertFalse(byteArrayOf().iterator().hasNext())
assertTrue(assertFails { byteArrayOf().iterator().next() } is IndexOutOfBoundsException)
assertTrue(eqShort(shortArrayOf(0), ShortArray(1)))
assertTrue(eqShort(shortArrayOf(1, 2, 3), ShortArray(3) { (it + 1).toShort() }))
assertTrue(eqShort(shortArrayOf(1), shortArrayOf(1).copyOf()))
assertTrue(eqShort(shortArrayOf(1, 0), shortArrayOf(1).copyOf(2)))
assertTrue(eqShort(shortArrayOf(1), shortArrayOf(1, 2).copyOf(1)))
assertTrue(eqShort(shortArrayOf(1, 2), shortArrayOf(1) + 2))
assertTrue(eqShort(shortArrayOf(1, 2, 3), shortArrayOf(1) + listOf(2.toShort(), 3.toShort())))
assertTrue(eqShort(shortArrayOf(2, 3), shortArrayOf(1, 2, 3, 4).copyOfRange(1, 3)))
assertTrue(eqShort(shortArrayOf(1, 2, 3, 4), customShortArrayOf(1.toShort(), *shortArrayOf(2, 3), 4.toShort())))
assertTrue(shortArrayOf(1).iterator() is ShortIterator)
assertEquals(1, shortArrayOf(1).iterator().nextShort())
assertEquals(1, shortArrayOf(1).iterator().next())
assertFalse(shortArrayOf().iterator().hasNext())
assertTrue(assertFails { shortArrayOf().iterator().next() } is IndexOutOfBoundsException)
assertTrue(eqChar(charArrayOf(0.toChar()), CharArray(1)))
assertTrue(eqChar(charArrayOf('a', 'b', 'c'), CharArray(3) { 'a' + it }))
assertTrue(eqChar(charArrayOf('a'), charArrayOf('a').copyOf()))
assertTrue(eqChar(charArrayOf('a', 0.toChar()), charArrayOf('a').copyOf(2)))
assertTrue(eqChar(charArrayOf('a'), charArrayOf('a', 'b').copyOf(1)))
assertTrue(eqChar(charArrayOf('a', 'b'), charArrayOf('a') + 'b'))
assertTrue(eqChar(charArrayOf('a', 'b', 'c'), charArrayOf('a') + listOf('b', 'c')))
assertTrue(eqChar(charArrayOf('b', 'c'), charArrayOf('a', 'b', 'c', 'd').copyOfRange(1, 3)))
assertTrue(eqChar(charArrayOf('a', 'b', 'c', 'd'), customCharArrayOf('a', *charArrayOf('b', 'c'), 'd')))
assertTrue(charArrayOf('a').iterator() is CharIterator)
assertEquals('a', charArrayOf('a').iterator().nextChar())
assertEquals('a', charArrayOf('a').iterator().next())
assertFalse(charArrayOf().iterator().hasNext())
assertTrue(assertFails { charArrayOf().iterator().next() } is IndexOutOfBoundsException)
assertTrue(eqInt(intArrayOf(0), IntArray(1)))
assertTrue(eqInt(intArrayOf(1, 2, 3), IntArray(3) { it + 1 }))
assertTrue(eqInt(intArrayOf(1), intArrayOf(1).copyOf()))
assertTrue(eqInt(intArrayOf(1, 0), intArrayOf(1).copyOf(2)))
assertTrue(eqInt(intArrayOf(1), intArrayOf(1, 2).copyOf(1)))
assertTrue(eqInt(intArrayOf(1, 2), intArrayOf(1) + 2))
assertTrue(eqInt(intArrayOf(1, 2, 3), intArrayOf(1) + listOf(2, 3)))
assertTrue(eqInt(intArrayOf(2, 3), intArrayOf(1, 2, 3, 4).copyOfRange(1, 3)))
assertTrue(eqInt(intArrayOf(1, 2, 3, 4), customIntArrayOf(1, *intArrayOf(2, 3), 4)))
assertTrue(intArrayOf(1).iterator() is IntIterator)
assertEquals(1, intArrayOf(1).iterator().nextInt())
assertEquals(1, intArrayOf(1).iterator().next())
assertFalse(intArrayOf().iterator().hasNext())
assertTrue(assertFails { intArrayOf().iterator().next() } is IndexOutOfBoundsException)
assertTrue(eqFloat(floatArrayOf(0f), FloatArray(1)))
assertTrue(eqFloat(floatArrayOf(1f, 2f, 3f), FloatArray(3) { (it + 1).toFloat() }))
assertTrue(eqFloat(floatArrayOf(1f), floatArrayOf(1f).copyOf()))
assertTrue(eqFloat(floatArrayOf(1f, 0f), floatArrayOf(1f).copyOf(2)))
assertTrue(eqFloat(floatArrayOf(1f), floatArrayOf(1f, 2f).copyOf(1)))
assertTrue(eqFloat(floatArrayOf(1f, 2f), floatArrayOf(1f) + 2f))
assertTrue(eqFloat(floatArrayOf(1f, 2f, 3f), floatArrayOf(1f) + listOf(2f, 3f)))
assertTrue(eqFloat(floatArrayOf(2f, 3f), floatArrayOf(1f, 2f, 3f, 4f).copyOfRange(1, 3)))
assertTrue(eqFloat(floatArrayOf(1f, 2f, 3f, 4f), customFloatArrayOf(1f, *floatArrayOf(2f, 3f), 4f)))
assertTrue(floatArrayOf(1f).iterator() is FloatIterator)
assertEquals(1f, floatArrayOf(1f).iterator().nextFloat())
assertEquals(1f, floatArrayOf(1f).iterator().next())
assertFalse(floatArrayOf().iterator().hasNext())
assertTrue(assertFails { floatArrayOf().iterator().next() } is IndexOutOfBoundsException)
assertTrue(eqDouble(doubleArrayOf(0.0), DoubleArray(1)))
assertTrue(eqDouble(doubleArrayOf(1.0, 2.0, 3.0), DoubleArray(3) { (it + 1).toDouble() }))
assertTrue(eqDouble(doubleArrayOf(1.0), doubleArrayOf(1.0).copyOf()))
assertTrue(eqDouble(doubleArrayOf(1.0, 0.0), doubleArrayOf(1.0).copyOf(2)))
assertTrue(eqDouble(doubleArrayOf(1.0), doubleArrayOf(1.0, 2.0).copyOf(1)))
assertTrue(eqDouble(doubleArrayOf(1.0, 2.0), doubleArrayOf(1.0) + 2.0))
assertTrue(eqDouble(doubleArrayOf(1.0, 2.0, 3.0), doubleArrayOf(1.0) + listOf(2.0, 3.0)))
assertTrue(eqDouble(doubleArrayOf(2.0, 3.0), doubleArrayOf(1.0, 2.0, 3.0, 4.0).copyOfRange(1, 3)))
assertTrue(eqDouble(doubleArrayOf(1.0, 2.0, 3.0, 4.0), customDoubleArrayOf(1.0, *doubleArrayOf(2.0, 3.0), 4.0)))
assertTrue(doubleArrayOf(1.0).iterator() is DoubleIterator)
assertEquals(1.0, doubleArrayOf(1.0).iterator().nextDouble())
assertEquals(1.0, doubleArrayOf(1.0).iterator().next())
assertFalse(doubleArrayOf().iterator().hasNext())
assertTrue(assertFails { doubleArrayOf().iterator().next() } is IndexOutOfBoundsException)
assertTrue(eqLong(longArrayOf(0), LongArray(1)))
assertTrue(eqLong(longArrayOf(1, 2, 3), LongArray(3) { it + 1L }))
assertTrue(eqLong(longArrayOf(1), longArrayOf(1).copyOf()))
assertTrue(eqLong(longArrayOf(1, 0), longArrayOf(1).copyOf(2)))
assertTrue(eqLong(longArrayOf(1), longArrayOf(1, 2).copyOf(1)))
assertTrue(eqLong(longArrayOf(1, 2), longArrayOf(1) + 2))
assertTrue(eqLong(longArrayOf(1, 2, 3), longArrayOf(1) + listOf(2L, 3L)))
assertTrue(eqLong(longArrayOf(2, 3), longArrayOf(1, 2, 3, 4).copyOfRange(1, 3)))
assertTrue(eqLong(longArrayOf(1, 2, 3, 4), customLongArrayOf(1L, *longArrayOf(2, 3), 4L)))
assertTrue(longArrayOf(1).iterator() is LongIterator)
assertEquals(1L, longArrayOf(1).iterator().nextLong())
assertEquals(1L, longArrayOf(1).iterator().next())
assertFalse(longArrayOf().iterator().hasNext())
assertTrue(assertFails { longArrayOf().iterator().next() } is IndexOutOfBoundsException)
// If `is` checks work...
if (intArrayOf() is IntArray) {
assertTrue(booleanArrayOf(false) is BooleanArray)
assertTrue(byteArrayOf(0) is ByteArray)
assertTrue(shortArrayOf(0) is ShortArray)
assertTrue(charArrayOf('a') is CharArray)
assertTrue(intArrayOf(0) is IntArray)
assertTrue(floatArrayOf(0f) is FloatArray)
assertTrue(doubleArrayOf(0.0) is DoubleArray)
assertTrue(longArrayOf(0) is LongArray)
}
// Rhino `instanceof` fails to distinguish TypedArray's
if (intArrayOf() is IntArray && (byteArrayOf() as Any) !is IntArray) {
assertTrue(checkExactArrayType(booleanArrayOf(false), booleanArray = true))
assertTrue(checkExactArrayType(byteArrayOf(0), byteArray = true))
assertTrue(checkExactArrayType(shortArrayOf(0), shortArray = true))
assertTrue(checkExactArrayType(charArrayOf('a'), charArray = true))
assertTrue(checkExactArrayType(intArrayOf(0), intArray = true))
assertTrue(checkExactArrayType(floatArrayOf(0f), floatArray = true))
assertTrue(checkExactArrayType(doubleArrayOf(0.0), doubleArray = true))
assertTrue(checkExactArrayType(longArrayOf(0), longArray = true))
assertTrue(checkExactArrayType(arrayOf<Any?>(), array = true))
}
return "OK"
}
fun eqBoolean(expected: BooleanArray, actual: BooleanArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun eqByte(expected: ByteArray, actual: ByteArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun eqShort(expected: ShortArray, actual: ShortArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun eqChar(expected: CharArray, actual: CharArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun eqInt(expected: IntArray, actual: IntArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun eqLong(expected: LongArray, actual: LongArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun eqFloat(expected: FloatArray, actual: FloatArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun eqDouble(expected: DoubleArray, actual: DoubleArray): Boolean = actual.size == expected.size && actual.foldIndexed(true) { i, r, v -> r && expected[i] == v }
fun customBooleanArrayOf(vararg arr: Boolean): BooleanArray = arr
fun customByteArrayOf(vararg arr: Byte): ByteArray = arr
fun customShortArrayOf(vararg arr: Short): ShortArray = arr
fun customCharArrayOf(vararg arr: Char): CharArray = arr
fun customIntArrayOf(vararg arr: Int): IntArray = arr
fun customFloatArrayOf(vararg arr: Float): FloatArray = arr
fun customDoubleArrayOf(vararg arr: Double): DoubleArray = arr
fun customLongArrayOf(vararg arr: Long): LongArray = arr
fun checkExactArrayType(
a: Any?,
booleanArray: Boolean = false,
byteArray: Boolean = false,
shortArray: Boolean = false,
charArray: Boolean = false,
intArray: Boolean = false,
longArray: Boolean = false,
floatArray: Boolean = false,
doubleArray: Boolean = false,
array: Boolean = false
): Boolean {
return a is BooleanArray == booleanArray &&
a is ByteArray == byteArray &&
a is ShortArray == shortArray &&
a is CharArray == charArray &&
a is IntArray == intArray &&
a is LongArray == longArray &&
a is FloatArray == floatArray &&
a is DoubleArray == doubleArray &&
a is Array<*> == array
}
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_WITHOUT_CHECK: JS
// WITH_RUNTIME
import kotlin.test.assertEquals
@@ -0,0 +1,22 @@
@kotlin.Metadata
public final class PrimitiveArraysKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public synthetic static method checkExactArrayType$default(p0: java.lang.Object, p1: boolean, p2: boolean, p3: boolean, p4: boolean, p5: boolean, p6: boolean, p7: boolean, p8: boolean, p9: boolean, p10: int, p11: java.lang.Object): boolean
public final static method checkExactArrayType(@org.jetbrains.annotations.Nullable p0: java.lang.Object, p1: boolean, p2: boolean, p3: boolean, p4: boolean, p5: boolean, p6: boolean, p7: boolean, p8: boolean, p9: boolean): boolean
public final static @org.jetbrains.annotations.NotNull method customBooleanArrayOf(@org.jetbrains.annotations.NotNull p0: boolean[]): boolean[]
public final static @org.jetbrains.annotations.NotNull method customByteArrayOf(@org.jetbrains.annotations.NotNull p0: byte[]): byte[]
public final static @org.jetbrains.annotations.NotNull method customCharArrayOf(@org.jetbrains.annotations.NotNull p0: char[]): char[]
public final static @org.jetbrains.annotations.NotNull method customDoubleArrayOf(@org.jetbrains.annotations.NotNull p0: double[]): double[]
public final static @org.jetbrains.annotations.NotNull method customFloatArrayOf(@org.jetbrains.annotations.NotNull p0: float[]): float[]
public final static @org.jetbrains.annotations.NotNull method customIntArrayOf(@org.jetbrains.annotations.NotNull p0: int[]): int[]
public final static @org.jetbrains.annotations.NotNull method customLongArrayOf(@org.jetbrains.annotations.NotNull p0: long[]): long[]
public final static @org.jetbrains.annotations.NotNull method customShortArrayOf(@org.jetbrains.annotations.NotNull p0: short[]): short[]
public final static method eqBoolean(@org.jetbrains.annotations.NotNull p0: boolean[], @org.jetbrains.annotations.NotNull p1: boolean[]): boolean
public final static method eqByte(@org.jetbrains.annotations.NotNull p0: byte[], @org.jetbrains.annotations.NotNull p1: byte[]): boolean
public final static method eqChar(@org.jetbrains.annotations.NotNull p0: char[], @org.jetbrains.annotations.NotNull p1: char[]): boolean
public final static method eqDouble(@org.jetbrains.annotations.NotNull p0: double[], @org.jetbrains.annotations.NotNull p1: double[]): boolean
public final static method eqFloat(@org.jetbrains.annotations.NotNull p0: float[], @org.jetbrains.annotations.NotNull p1: float[]): boolean
public final static method eqInt(@org.jetbrains.annotations.NotNull p0: int[], @org.jetbrains.annotations.NotNull p1: int[]): boolean
public final static method eqLong(@org.jetbrains.annotations.NotNull p0: long[], @org.jetbrains.annotations.NotNull p1: long[]): boolean
public final static method eqShort(@org.jetbrains.annotations.NotNull p0: short[], @org.jetbrains.annotations.NotNull p1: short[]): boolean
}
@@ -611,6 +611,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("primitiveArrays.kt")
public void testPrimitiveArrays() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/primitiveArrays.kt");
doTest(fileName);
}
@TestMetadata("stdlib.kt")
public void testStdlib() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/stdlib.kt");
@@ -611,6 +611,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("primitiveArrays.kt")
public void testPrimitiveArrays() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/primitiveArrays.kt");
doTest(fileName);
}
@TestMetadata("stdlib.kt")
public void testStdlib() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/stdlib.kt");
@@ -611,6 +611,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("primitiveArrays.kt")
public void testPrimitiveArrays() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/primitiveArrays.kt");
doTest(fileName);
}
@TestMetadata("stdlib.kt")
public void testStdlib() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/stdlib.kt");
@@ -877,6 +877,20 @@ public abstract class KotlinBuiltIns {
return descriptor != null && getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null;
}
@Nullable
public static PrimitiveType getPrimitiveArrayElementType(@NotNull KotlinType type) {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
if (descriptor == null) return null;
return getPrimitiveTypeByArrayClassFqName(getFqName(descriptor));
}
@Nullable
public static PrimitiveType getPrimitiveType(@NotNull KotlinType type) {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
if (type.isMarkedNullable() || !(descriptor instanceof ClassDescriptor)) return null;
return getPrimitiveTypeByFqName(getFqName(descriptor));
}
public static boolean isPrimitiveType(@NotNull KotlinType type) {
return !type.isMarkedNullable() && isPrimitiveTypeOrNullablePrimitiveType(type);
}
@@ -1277,6 +1277,10 @@ fun main(args: Array<String>) {
testClass<AbstractEnumValuesInlineTests> {
model("codegen/boxInline/enum/", targetBackend = TargetBackend.JS)
}
testClass<AbstractJsTypedArraysBoxTest> {
model("codegen/box/arrays", targetBackend = TargetBackend.JS)
}
}
}
@@ -27,6 +27,7 @@ public class JSConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> SOURCE_MAP =
CompilerConfigurationKey.create("generate source map");
public static final CompilerConfigurationKey<Boolean> META_INFO =
CompilerConfigurationKey.create("generate .meta.js and .kjsm files");
@@ -38,4 +39,7 @@ public class JSConfigurationKeys {
public static final CompilerConfigurationKey<ModuleKind> MODULE_KIND =
CompilerConfigurationKey.create("module kind");
public static final CompilerConfigurationKey<Boolean> TYPED_ARRAYS_ENABLED =
CompilerConfigurationKey.create("TypedArrays enabled");
}
+47 -15
View File
@@ -19,22 +19,54 @@
external private fun <T> Array(size: Int): Array<T>
@JsName("newArray")
fun <T> newArray(size: Int, initValue: T): Array<T> {
return fillArray(Array(size), initValue)
}
private fun <T> fillArray(array: Array<T>, value: T): Array<T> {
for (i in 0..array.size - 1) {
array[i] = value
}
return array;
}
fun <T> newArray(size: Int, initValue: T) = fillArrayVal(Array<T>(size), initValue)
@JsName("newArrayF")
fun <T> arrayWithFun(size: Int, init: (Int) -> T): Array<T> {
var result = Array<T>(size)
for (i in 0..size - 1) {
result[i] = init(i)
fun <T> arrayWithFun(size: Int, init: (Int) -> T) = fillArrayFun(Array<T>(size), init)
@JsName("fillArray")
fun <T> fillArrayFun(array: Array<T>, init: (Int) -> T): Array<T> {
for (i in 0..array.size - 1) {
array[i] = init(i)
}
return result
return array
}
@JsName("booleanArray")
fun booleanArray(size: Int, init: dynamic): Array<Boolean> {
val result: dynamic = Array<Boolean>(size)
result.`$type$` = "BooleanArray"
return when (init) {
null, true -> fillArrayVal(result, false)
false -> result
else -> fillArrayFun<Boolean>(result, init)
}
}
@JsName("charArray")
fun charArray(size: Int, init: dynamic): Array<Char> {
val result = js("new Uint16Array(size)")
result.`$type$` = "CharArray"
return when (init) {
null, true, false -> result // For consistency
else -> fillArrayFun<Char>(result, init)
}
}
@JsName("longArray")
fun longArray(size: Int, init: dynamic): Array<Long> {
val result: dynamic = Array<Long>(size)
result.`$type$` = "LongArray"
return when (init) {
null, true -> fillArrayVal(result, 0L)
false -> result
else -> fillArrayFun<Long>(result, init)
}
}
private fun <T> fillArrayVal(array: Array<T>, initValue: T): Array<T> {
for (i in 0..array.size - 1) {
array[i] = initValue
}
return array
}
+129 -22
View File
@@ -15,21 +15,80 @@
*/
@JsName("arrayIterator")
internal fun arrayIterator(array: dynamic): MutableIterator<dynamic> {
return object : MutableIterator<dynamic> {
var index = 0;
override fun hasNext(): Boolean {
val length: Int = array.length
return index < length
}
override fun next() = array[index++]
override fun remove() {
array.splice(--index, 1)
internal fun arrayIterator(array: dynamic, type: String?) = when (type) {
null -> {
val arr: Array<dynamic> = array
object : Iterator<dynamic> {
var index = 0
override fun hasNext() = index < arr.size
override fun next() = if (index < arr.size) arr[index++] else throw IndexOutOfBoundsException("$index")
}
}
"BooleanArray" -> booleanArrayIterator(array)
"ByteArray" -> byteArrayIterator(array)
"ShortArray" -> shortArrayIterator(array)
"CharArray" -> charArrayIterator(array)
"IntArray" -> intArrayIterator(array)
"LongArray" -> longArrayIterator(array)
"FloatArray" -> floatArrayIterator(array)
"DoubleArray" -> doubleArrayIterator(array)
else -> throw IllegalStateException("Unsupported type argument for arrayIterator: $type")
}
@JsName("booleanArrayIterator")
internal fun booleanArrayIterator(array: BooleanArray) = object : BooleanIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextBoolean() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("byteArrayIterator")
internal fun byteArrayIterator(array: ByteArray) = object : ByteIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextByte() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("shortArrayIterator")
internal fun shortArrayIterator(array: ShortArray) = object : ShortIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextShort() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("charArrayIterator")
internal fun charArrayIterator(array: CharArray) = object : CharIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextChar() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("intArrayIterator")
internal fun intArrayIterator(array: IntArray) = object : IntIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextInt() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("floatArrayIterator")
internal fun floatArrayIterator(array: FloatArray) = object : FloatIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextFloat() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("doubleArrayIterator")
internal fun doubleArrayIterator(array: DoubleArray) = object : DoubleIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextDouble() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("longArrayIterator")
internal fun longArrayIterator(array: LongArray) = object : LongIterator() {
var index = 0
override fun hasNext() = index < array.size
override fun nextLong() = if (index < array.size) array[index++] else throw IndexOutOfBoundsException("$index")
}
@JsName("PropertyMetadata")
@@ -96,23 +155,71 @@ internal class BoxedChar(val c: Char) : Comparable<Char> {
}
}
/* For future binary compatibility with TypedArrays
* TODO: concat normal Array's and TypedArrays into an Array
internal inline fun <T> concat(args: Array<T>): T {
val typed = js("Array")(args.size)
for (i in 0..args.size - 1) {
val arr = args[i]
if (arr !is Array<*>) {
typed[i] = js("[]").slice.call(arr)
}
else {
typed[i] = arr
}
}
return js("[]").concat.apply(js("[]"), typed);
}
/** Concat regular Array's and TypedArray's into an Array.
*/
@PublishedApi
@JsName("arrayConcat")
internal fun <T> arrayConcat(a: T, b: T): T {
return a.asDynamic().concat.apply(js("[]"), js("arguments"));
return concat(js("arguments"))
}
/* For future binary compatibility with TypedArrays
* TODO: concat primitive arrays.
* For Byte-, Short-, Int-, Float-, and DoubleArray concat result into a TypedArray.
* For Boolean-, Char-, and LongArray return an Array with corresponding type property.
* Default to Array.prototype.concat for compatibility.
/** Concat primitive arrays. Main use: prepare vararg arguments.
* For compatibility with 1.1.0 the arguments may be a mixture of Array's and TypedArray's.
*
* If the first argument is TypedArray (Byte-, Short-, Char-, Int-, Float-, and DoubleArray) returns a TypedArray, otherwise an Array.
* If the first argument has the $type$ property (Boolean-, Char-, and LongArray) copy its value to result.$type$.
* If the first argument is a regular Array without the $type$ property default to arrayConcat.
*/
@PublishedApi
@JsName("primitiveArrayConcat")
internal fun <T> primitiveArrayConcat(a: T, b: T): T {
return a.asDynamic().concat.apply(js("[]"), js("arguments"));
val args: Array<T> = js("arguments")
if (a is Array<*> && a.asDynamic().`$type$` === undefined) {
return concat(args)
}
else {
var size = 0
for (i in 0..args.size - 1) {
size += args[i].asDynamic().length as Int
}
val result = js("new a.constructor(size)")
kotlin.copyArrayType(a, result)
size = 0
for (i in 0..args.size - 1) {
val arr = args[i].asDynamic()
for (j in 0..arr.length - 1) {
result[size++] = arr[j]
}
}
return result
}
}
@JsName("booleanArrayOf")
internal fun booleanArrayOf() = withType("BooleanArray", js("[].slice.call(arguments)"))
@JsName("charArrayOf") // The arguments have to be slice'd here because of Rhino (see KT-16974)
internal fun charArrayOf() = withType("CharArray", js("new Uint16Array([].slice.call(arguments))"))
@JsName("longArrayOf")
internal fun longArrayOf() = withType("LongArray", js("[].slice.call(arguments)"))
@JsName("withType")
internal inline fun withType(type: String, array: dynamic): dynamic {
array.`$type$` = type
return array
}
+1 -1
View File
@@ -49,7 +49,7 @@ public operator fun dynamic.iterator(): Iterator<dynamic> {
return when {
this["iterator"] != null ->
this["iterator"]()
js("Array").isArray(r) ->
js("Kotlin").isArrayish(r) ->
r.unsafeCast<Array<*>>().iterator()
else ->
+32 -37
View File
@@ -10,6 +10,7 @@ package kotlin.collections
import kotlin.js.*
import primitiveArrayConcat
import withType
import kotlin.comparisons.*
/**
@@ -13011,9 +13012,8 @@ public inline fun IntArray.copyOf(): IntArray {
/**
* Returns new array which is a copy of the original array.
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun LongArray.copyOf(): LongArray {
return this.asDynamic().slice()
public fun LongArray.copyOf(): LongArray {
return withType("LongArray", this.asDynamic().slice())
}
/**
@@ -13035,73 +13035,71 @@ public inline fun DoubleArray.copyOf(): DoubleArray {
/**
* Returns new array which is a copy of the original array.
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun BooleanArray.copyOf(): BooleanArray {
return this.asDynamic().slice()
public fun BooleanArray.copyOf(): BooleanArray {
return withType("BooleanArray", this.asDynamic().slice())
}
/**
* Returns new array which is a copy of the original array.
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun CharArray.copyOf(): CharArray {
return this.asDynamic().slice()
public fun CharArray.copyOf(): CharArray {
return withType("CharArray", this.asDynamic().slice())
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun ByteArray.copyOf(newSize: Int): ByteArray {
return arrayCopyResize(this, newSize, 0)
return fillFrom(this, ByteArray(newSize))
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun ShortArray.copyOf(newSize: Int): ShortArray {
return arrayCopyResize(this, newSize, 0)
return fillFrom(this, ShortArray(newSize))
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun IntArray.copyOf(newSize: Int): IntArray {
return arrayCopyResize(this, newSize, 0)
return fillFrom(this, IntArray(newSize))
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun LongArray.copyOf(newSize: Int): LongArray {
return arrayCopyResize(this, newSize, 0L)
return withType("LongArray", arrayCopyResize(this, newSize, 0L))
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun FloatArray.copyOf(newSize: Int): FloatArray {
return arrayCopyResize(this, newSize, 0.0f)
return fillFrom(this, FloatArray(newSize))
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun DoubleArray.copyOf(newSize: Int): DoubleArray {
return arrayCopyResize(this, newSize, 0.0)
return fillFrom(this, DoubleArray(newSize))
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun BooleanArray.copyOf(newSize: Int): BooleanArray {
return arrayCopyResize(this, newSize, false)
return withType("BooleanArray", arrayCopyResize(this, newSize, false))
}
/**
* Returns new array which is a copy of the original array, resized to the given [newSize].
*/
public fun CharArray.copyOf(newSize: Int): CharArray {
return arrayCopyResize(this, newSize, 0)
return withType("CharArray", fillFrom(this, CharArray(newSize)))
}
/**
@@ -13146,9 +13144,8 @@ public inline fun IntArray.copyOfRange(fromIndex: Int, toIndex: Int): IntArray {
/**
* Returns new array which is a copy of range of original array.
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun LongArray.copyOfRange(fromIndex: Int, toIndex: Int): LongArray {
return this.asDynamic().slice(fromIndex, toIndex)
public fun LongArray.copyOfRange(fromIndex: Int, toIndex: Int): LongArray {
return withType("LongArray", this.asDynamic().slice(fromIndex, toIndex))
}
/**
@@ -13170,17 +13167,15 @@ public inline fun DoubleArray.copyOfRange(fromIndex: Int, toIndex: Int): DoubleA
/**
* Returns new array which is a copy of range of original array.
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun BooleanArray.copyOfRange(fromIndex: Int, toIndex: Int): BooleanArray {
return this.asDynamic().slice(fromIndex, toIndex)
public fun BooleanArray.copyOfRange(fromIndex: Int, toIndex: Int): BooleanArray {
return withType("BooleanArray", this.asDynamic().slice(fromIndex, toIndex))
}
/**
* Returns new array which is a copy of range of original array.
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray {
return this.asDynamic().slice(fromIndex, toIndex)
public fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray {
return withType("CharArray", this.asDynamic().slice(fromIndex, toIndex))
}
/**
@@ -13266,21 +13261,21 @@ public operator fun <T> Array<out T>.plus(elements: Collection<T>): Array<T> {
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
public operator fun ByteArray.plus(elements: Collection<Byte>): ByteArray {
return arrayPlusCollection(this, elements)
return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
public operator fun ShortArray.plus(elements: Collection<Short>): ShortArray {
return arrayPlusCollection(this, elements)
return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
public operator fun IntArray.plus(elements: Collection<Int>): IntArray {
return arrayPlusCollection(this, elements)
return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)
}
/**
@@ -13294,14 +13289,14 @@ public operator fun LongArray.plus(elements: Collection<Long>): LongArray {
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
public operator fun FloatArray.plus(elements: Collection<Float>): FloatArray {
return arrayPlusCollection(this, elements)
return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)
}
/**
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
public operator fun DoubleArray.plus(elements: Collection<Double>): DoubleArray {
return arrayPlusCollection(this, elements)
return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)
}
/**
@@ -13315,7 +13310,7 @@ public operator fun BooleanArray.plus(elements: Collection<Boolean>): BooleanArr
* Returns an array containing all elements of the original array and then all elements of the given [elements] collection.
*/
public operator fun CharArray.plus(elements: Collection<Char>): CharArray {
return arrayPlusCollection(this, elements)
return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)
}
/**
@@ -13474,21 +13469,21 @@ public fun <T> Array<out T>.sortWith(comparator: Comparator<in T>): Unit {
* Returns a *typed* object array containing all of the elements of this primitive array.
*/
public fun ByteArray.toTypedArray(): Array<Byte> {
return copyOf().unsafeCast<Array<Byte>>()
return js("[]").slice.call(this)
}
/**
* Returns a *typed* object array containing all of the elements of this primitive array.
*/
public fun ShortArray.toTypedArray(): Array<Short> {
return copyOf().unsafeCast<Array<Short>>()
return js("[]").slice.call(this)
}
/**
* Returns a *typed* object array containing all of the elements of this primitive array.
*/
public fun IntArray.toTypedArray(): Array<Int> {
return copyOf().unsafeCast<Array<Int>>()
return js("[]").slice.call(this)
}
/**
@@ -13502,14 +13497,14 @@ public fun LongArray.toTypedArray(): Array<Long> {
* Returns a *typed* object array containing all of the elements of this primitive array.
*/
public fun FloatArray.toTypedArray(): Array<Float> {
return copyOf().unsafeCast<Array<Float>>()
return js("[]").slice.call(this)
}
/**
* Returns a *typed* object array containing all of the elements of this primitive array.
*/
public fun DoubleArray.toTypedArray(): Array<Double> {
return copyOf().unsafeCast<Array<Double>>()
return js("[]").slice.call(this)
}
/**
+23
View File
@@ -71,8 +71,18 @@ internal fun <T> arrayOfNulls(reference: Array<out T>, size: Int): Array<T> {
return arrayOfNulls<Any>(size).unsafeCast<Array<T>>()
}
internal fun fillFrom(src: dynamic, dst: dynamic): dynamic {
val srcLen: Int = src.length
val dstLen: Int = dst.length
var index: Int = 0
while (index < srcLen && index < dstLen) dst[index] = src[index++]
return dst
}
internal fun arrayCopyResize(source: dynamic, newSize: Int, defaultValue: Any?): dynamic {
val result = source.slice(0, newSize)
copyArrayType(source, result)
var index: Int = source.length
if (newSize > index) {
result.length = newSize
@@ -84,11 +94,24 @@ internal fun arrayCopyResize(source: dynamic, newSize: Int, defaultValue: Any?):
internal fun <T> arrayPlusCollection(array: dynamic, collection: Collection<T>): dynamic {
val result = array.slice()
result.length += collection.size
copyArrayType(array, result)
var index: Int = array.length
for (element in collection) result[index++] = element
return result
}
internal fun <T> fillFromCollection(dst: dynamic, startIndex: Int, collection: Collection<T>): dynamic {
var index = startIndex
for (element in collection) dst[index++] = element
return dst
}
internal inline fun copyArrayType(from: dynamic, to: dynamic) {
if (from.`$type$` !== undefined) {
to.`$type$` = from.`$type$`
}
}
// no singleton map implementation in js, return map as is
internal inline fun <K, V> Map<K, V>.toSingletonMapOrSelf(): Map<K, V> = this
+54 -9
View File
@@ -14,21 +14,65 @@
* limitations under the License.
*/
Kotlin.isBooleanArray = function (a) {
return (Array.isArray(a) || a instanceof Int8Array) && a.$type$ === "BooleanArray"
};
Kotlin.isByteArray = function (a) {
return a instanceof Int8Array && a.$type$ !== "BooleanArray"
};
Kotlin.isShortArray = function (a) {
return a instanceof Int16Array
};
Kotlin.isCharArray = function (a) {
return a instanceof Uint16Array && a.$type$ === "CharArray"
};
Kotlin.isIntArray = function (a) {
return a instanceof Int32Array
};
Kotlin.isFloatArray = function (a) {
return a instanceof Float32Array
};
Kotlin.isDoubleArray = function (a) {
return a instanceof Float64Array
};
Kotlin.isLongArray = function (a) {
return Array.isArray(a) && a.$type$ === "LongArray"
};
Kotlin.isArray = function (a) {
return Array.isArray(a) && !a.$type$;
};
Kotlin.isArrayish = function (a) {
return Array.isArray(a) || ArrayBuffer.isView(a)
};
Kotlin.arrayToString = function (a) {
return "[" + a.map(Kotlin.toString).join(", ") + "]";
};
Kotlin.arrayDeepToString = function (a, visited) {
visited = visited || [a];
return "[" + a.map(function(e) {
if (Array.isArray(e) && visited.indexOf(e) < 0) {
var toString = Kotlin.toString;
if (Kotlin.isCharArray(a)) {
toString = String.fromCharCode;
}
return "[" + a.map(function (e) {
if (Kotlin.isArrayish(e) && visited.indexOf(e) < 0) {
visited.push(e);
var result = Kotlin.arrayDeepToString(e, visited);
visited.pop();
return result;
}
else {
return Kotlin.toString(e);
return toString(e);
}
}).join(", ") + "]";
};
@@ -37,7 +81,7 @@ Kotlin.arrayEquals = function (a, b) {
if (a === b) {
return true;
}
if (!Array.isArray(b) || a.length !== b.length) {
if (!Kotlin.isArrayish(b) || a.length !== b.length) {
return false;
}
@@ -53,16 +97,17 @@ Kotlin.arrayDeepEquals = function (a, b) {
if (a === b) {
return true;
}
if (!Array.isArray(b) || a.length !== b.length) {
if (!Kotlin.isArrayish(b) || a.length !== b.length) {
return false;
}
for (var i = 0, n = a.length; i < n; i++) {
if (Array.isArray(a[i])) {
if (Kotlin.isArrayish(a[i])) {
if (!Kotlin.arrayDeepEquals(a[i], b[i])) {
return false;
}
} else if (!Kotlin.equals(a[i], b[i])) {
}
else if (!Kotlin.equals(a[i], b[i])) {
return false;
}
}
@@ -81,11 +126,11 @@ Kotlin.arrayDeepHashCode = function (arr) {
var result = 1;
for (var i = 0, n = arr.length; i < n; i++) {
var e = arr[i];
result = ((31 * result | 0) + (Array.isArray(e) ? Kotlin.arrayDeepHashCode(e) : Kotlin.hashCode(e))) | 0;
result = ((31 * result | 0) + (Kotlin.isArrayish(e) ? Kotlin.arrayDeepHashCode(e) : Kotlin.hashCode(e))) | 0;
}
return result;
};
Kotlin.primitiveArraySort = function(array) {
Kotlin.primitiveArraySort = function (array) {
array.sort(Kotlin.primitiveCompareTo)
};
+1 -1
View File
@@ -59,7 +59,7 @@ Kotlin.toString = function (o) {
if (o == null) {
return "null";
}
else if (Array.isArray(o)) {
else if (Kotlin.isArrayish(o)) {
return "[...]";
}
else {
@@ -60,7 +60,8 @@ import java.util.regex.Pattern
abstract class BasicBoxTest(
private val pathToTestDir: String,
private val pathToOutputDir: String
private val pathToOutputDir: String,
private val typedArraysEnabled: Boolean = false
) : KotlinTestWithEnvironment() {
private val COMMON_FILES_NAME = "_common"
private val COMMON_FILES_DIR = "_commonFiles/"
@@ -268,6 +269,10 @@ abstract class BasicBoxTest(
//configuration.put(JSConfigurationKeys.SOURCE_MAP, shouldGenerateSourceMap())
configuration.put(JSConfigurationKeys.META_INFO, multiModule)
if (typedArraysEnabled) {
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true)
}
return JsConfig(project, configuration)
}
@@ -191,6 +191,7 @@ public final class RhinoUtils {
private static ScriptableObject initScope(@NotNull EcmaVersion version, @NotNull Context context, @NotNull List<String> jsLibraries) {
ScriptableObject scope = context.initStandardObjects();
try {
runFileWithRhino(DIST_DIR_JS_PATH + "../../js/js.translator/testData/rhino-polyfills.js", context, scope);
runFileWithRhino(DIST_DIR_JS_PATH + "kotlin.js", context, scope);
runFileWithRhino(DIST_DIR_JS_PATH + "../classes/kotlin-test-js/kotlin-test.js", context, scope);
@@ -391,6 +391,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Arrays extends AbstractJsCodegenBoxTest {
@TestMetadata("arrayInstanceOf.kt")
public void ignoreArrayInstanceOf() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayInstanceOf.kt");
doTest(fileName);
}
@TestMetadata("kt2997.kt")
public void ignoreKt2997() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt2997.kt");
doTest(fileName);
}
@TestMetadata("kt7288.kt")
public void ignoreKt7288() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt7288.kt");
doTest(fileName);
}
public void testAllFilesPresentInArrays() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/arrays"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@@ -413,18 +431,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("arrayInstanceOf.kt")
public void testArrayInstanceOf() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayInstanceOf.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("arrayPlusAssign.kt")
public void testArrayPlusAssign() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayPlusAssign.kt");
@@ -590,13 +596,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("iteratorByteArrayNextByte.kt")
public void testIteratorByteArrayNextByte() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorByteArrayNextByte.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("iteratorCharArray.kt")
@@ -632,13 +632,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("iteratorLongArrayNextLong.kt")
public void testIteratorLongArrayNextLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorLongArrayNextLong.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("iteratorShortArray.kt")
@@ -659,18 +653,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("kt2997.kt")
public void testKt2997() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt2997.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("kt33.kt")
public void testKt33() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt33.kt");
@@ -737,12 +719,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("kt7288.kt")
public void testKt7288() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt7288.kt");
doTest(fileName);
}
@TestMetadata("kt7338.kt")
public void testKt7338() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt7338.kt");
@@ -803,6 +779,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("primitiveArrays.kt")
public void testPrimitiveArrays() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/primitiveArrays.kt");
doTest(fileName);
}
@TestMetadata("stdlib.kt")
public void testStdlib() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/stdlib.kt");
@@ -14894,6 +14876,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ForInIndices extends AbstractJsCodegenBoxTest {
@TestMetadata("kt13241_Array.kt")
public void ignoreKt13241_Array() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInIndices/kt13241_Array.kt");
doTest(fileName);
}
public void testAllFilesPresentInForInIndices() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInIndices"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@@ -14970,12 +14958,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("kt13241_Array.kt")
public void testKt13241_Array() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInIndices/kt13241_Array.kt");
doTest(fileName);
}
@TestMetadata("kt13241_CharSequence.kt")
public void testKt13241_CharSequence() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInIndices/kt13241_CharSequence.kt");
@@ -0,0 +1,557 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.js.test.semantics;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/box/arrays")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class JsTypedArraysBoxTestGenerated extends AbstractJsTypedArraysBoxTest {
@TestMetadata("arrayInstanceOf.kt")
public void ignoreArrayInstanceOf() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayInstanceOf.kt");
doTest(fileName);
}
@TestMetadata("kt2997.kt")
public void ignoreKt2997() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt2997.kt");
doTest(fileName);
}
@TestMetadata("kt7288.kt")
public void ignoreKt7288() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt7288.kt");
doTest(fileName);
}
public void testAllFilesPresentInArrays() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/arrays"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("arrayConstructorsSimple.kt")
public void testArrayConstructorsSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayConstructorsSimple.kt");
doTest(fileName);
}
@TestMetadata("arrayGetAssignMultiIndex.kt")
public void testArrayGetAssignMultiIndex() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayGetAssignMultiIndex.kt");
doTest(fileName);
}
@TestMetadata("arrayGetMultiIndex.kt")
public void testArrayGetMultiIndex() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayGetMultiIndex.kt");
doTest(fileName);
}
@TestMetadata("arrayPlusAssign.kt")
public void testArrayPlusAssign() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arrayPlusAssign.kt");
doTest(fileName);
}
@TestMetadata("arraysAreCloneable.kt")
public void testArraysAreCloneable() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arraysAreCloneable.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("cloneArray.kt")
public void testCloneArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/cloneArray.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("clonePrimitiveArrays.kt")
public void testClonePrimitiveArrays() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/clonePrimitiveArrays.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("collectionAssignGetMultiIndex.kt")
public void testCollectionAssignGetMultiIndex() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/collectionAssignGetMultiIndex.kt");
doTest(fileName);
}
@TestMetadata("collectionGetMultiIndex.kt")
public void testCollectionGetMultiIndex() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/collectionGetMultiIndex.kt");
doTest(fileName);
}
@TestMetadata("forEachBooleanArray.kt")
public void testForEachBooleanArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachBooleanArray.kt");
doTest(fileName);
}
@TestMetadata("forEachByteArray.kt")
public void testForEachByteArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachByteArray.kt");
doTest(fileName);
}
@TestMetadata("forEachCharArray.kt")
public void testForEachCharArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachCharArray.kt");
doTest(fileName);
}
@TestMetadata("forEachDoubleArray.kt")
public void testForEachDoubleArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachDoubleArray.kt");
doTest(fileName);
}
@TestMetadata("forEachFloatArray.kt")
public void testForEachFloatArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachFloatArray.kt");
doTest(fileName);
}
@TestMetadata("forEachIntArray.kt")
public void testForEachIntArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachIntArray.kt");
doTest(fileName);
}
@TestMetadata("forEachLongArray.kt")
public void testForEachLongArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachLongArray.kt");
doTest(fileName);
}
@TestMetadata("forEachShortArray.kt")
public void testForEachShortArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/forEachShortArray.kt");
doTest(fileName);
}
@TestMetadata("genericArrayInObjectLiteralConstructor.kt")
public void testGenericArrayInObjectLiteralConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/genericArrayInObjectLiteralConstructor.kt");
doTest(fileName);
}
@TestMetadata("hashMap.kt")
public void testHashMap() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/hashMap.kt");
doTest(fileName);
}
@TestMetadata("inProjectionAsParameter.kt")
public void testInProjectionAsParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/inProjectionAsParameter.kt");
doTest(fileName);
}
@TestMetadata("inProjectionOfArray.kt")
public void testInProjectionOfArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/inProjectionOfArray.kt");
doTest(fileName);
}
@TestMetadata("inProjectionOfList.kt")
public void testInProjectionOfList() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/inProjectionOfList.kt");
doTest(fileName);
}
@TestMetadata("indices.kt")
public void testIndices() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/indices.kt");
doTest(fileName);
}
@TestMetadata("indicesChar.kt")
public void testIndicesChar() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/indicesChar.kt");
doTest(fileName);
}
@TestMetadata("iterator.kt")
public void testIterator() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iterator.kt");
doTest(fileName);
}
@TestMetadata("iteratorBooleanArray.kt")
public void testIteratorBooleanArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorBooleanArray.kt");
doTest(fileName);
}
@TestMetadata("iteratorByteArray.kt")
public void testIteratorByteArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorByteArray.kt");
doTest(fileName);
}
@TestMetadata("iteratorByteArrayNextByte.kt")
public void testIteratorByteArrayNextByte() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorByteArrayNextByte.kt");
doTest(fileName);
}
@TestMetadata("iteratorCharArray.kt")
public void testIteratorCharArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorCharArray.kt");
doTest(fileName);
}
@TestMetadata("iteratorDoubleArray.kt")
public void testIteratorDoubleArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorDoubleArray.kt");
doTest(fileName);
}
@TestMetadata("iteratorFloatArray.kt")
public void testIteratorFloatArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorFloatArray.kt");
doTest(fileName);
}
@TestMetadata("iteratorIntArray.kt")
public void testIteratorIntArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorIntArray.kt");
doTest(fileName);
}
@TestMetadata("iteratorLongArray.kt")
public void testIteratorLongArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorLongArray.kt");
doTest(fileName);
}
@TestMetadata("iteratorLongArrayNextLong.kt")
public void testIteratorLongArrayNextLong() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorLongArrayNextLong.kt");
doTest(fileName);
}
@TestMetadata("iteratorShortArray.kt")
public void testIteratorShortArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/iteratorShortArray.kt");
doTest(fileName);
}
@TestMetadata("kt1291.kt")
public void testKt1291() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt1291.kt");
doTest(fileName);
}
@TestMetadata("kt238.kt")
public void testKt238() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt238.kt");
doTest(fileName);
}
@TestMetadata("kt33.kt")
public void testKt33() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt33.kt");
doTest(fileName);
}
@TestMetadata("kt3771.kt")
public void testKt3771() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt3771.kt");
doTest(fileName);
}
@TestMetadata("kt4118.kt")
public void testKt4118() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt4118.kt");
doTest(fileName);
}
@TestMetadata("kt4348.kt")
public void testKt4348() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt4348.kt");
doTest(fileName);
}
@TestMetadata("kt4357.kt")
public void testKt4357() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt4357.kt");
doTest(fileName);
}
@TestMetadata("kt503.kt")
public void testKt503() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt503.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("kt594.kt")
public void testKt594() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt594.kt");
doTest(fileName);
}
@TestMetadata("kt602.kt")
public void testKt602() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt602.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("kt7009.kt")
public void testKt7009() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt7009.kt");
doTest(fileName);
}
@TestMetadata("kt7338.kt")
public void testKt7338() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt7338.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("kt779.kt")
public void testKt779() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt779.kt");
doTest(fileName);
}
@TestMetadata("kt945.kt")
public void testKt945() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt945.kt");
doTest(fileName);
}
@TestMetadata("kt950.kt")
public void testKt950() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/kt950.kt");
doTest(fileName);
}
@TestMetadata("longAsIndex.kt")
public void testLongAsIndex() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/longAsIndex.kt");
doTest(fileName);
}
@TestMetadata("multiArrayConstructors.kt")
public void testMultiArrayConstructors() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiArrayConstructors.kt");
doTest(fileName);
}
@TestMetadata("nonLocalReturnArrayConstructor.kt")
public void testNonLocalReturnArrayConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/nonLocalReturnArrayConstructor.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("nonNullArray.kt")
public void testNonNullArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/nonNullArray.kt");
doTest(fileName);
}
@TestMetadata("primitiveArrays.kt")
public void testPrimitiveArrays() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/primitiveArrays.kt");
doTest(fileName);
}
@TestMetadata("stdlib.kt")
public void testStdlib() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/stdlib.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/arrays/multiDecl")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MultiDecl extends AbstractJsTypedArraysBoxTest {
public void testAllFilesPresentInMultiDecl() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/arrays/multiDecl"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("kt15560.kt")
public void testKt15560() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/kt15560.kt");
doTest(fileName);
}
@TestMetadata("kt15568.kt")
public void testKt15568() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/kt15568.kt");
doTest(fileName);
}
@TestMetadata("kt15575.kt")
public void testKt15575() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/kt15575.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclFor.kt")
public void testMultiDeclFor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/MultiDeclFor.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentExtensions.kt")
public void testMultiDeclForComponentExtensions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/MultiDeclForComponentExtensions.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentMemberExtensions.kt")
public void testMultiDeclForComponentMemberExtensions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/MultiDeclForComponentMemberExtensions.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentMemberExtensionsInExtensionFunction.kt")
public void testMultiDeclForComponentMemberExtensionsInExtensionFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/MultiDeclForComponentMemberExtensionsInExtensionFunction.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForValCaptured.kt")
public void testMultiDeclForValCaptured() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/MultiDeclForValCaptured.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/arrays/multiDecl/int")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Int extends AbstractJsTypedArraysBoxTest {
public void testAllFilesPresentInInt() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/arrays/multiDecl/int"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("MultiDeclForComponentExtensions.kt")
public void testMultiDeclForComponentExtensions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/int/MultiDeclForComponentExtensions.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentExtensionsValCaptured.kt")
public void testMultiDeclForComponentExtensionsValCaptured() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/int/MultiDeclForComponentExtensionsValCaptured.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentMemberExtensions.kt")
public void testMultiDeclForComponentMemberExtensions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/int/MultiDeclForComponentMemberExtensions.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentMemberExtensionsInExtensionFunction.kt")
public void testMultiDeclForComponentMemberExtensionsInExtensionFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/int/MultiDeclForComponentMemberExtensionsInExtensionFunction.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/arrays/multiDecl/long")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Long extends AbstractJsTypedArraysBoxTest {
public void testAllFilesPresentInLong() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/arrays/multiDecl/long"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("MultiDeclForComponentExtensions.kt")
public void testMultiDeclForComponentExtensions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/long/MultiDeclForComponentExtensions.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentExtensionsValCaptured.kt")
public void testMultiDeclForComponentExtensionsValCaptured() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/long/MultiDeclForComponentExtensionsValCaptured.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentMemberExtensions.kt")
public void testMultiDeclForComponentMemberExtensions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/long/MultiDeclForComponentMemberExtensions.kt");
doTest(fileName);
}
@TestMetadata("MultiDeclForComponentMemberExtensionsInExtensionFunction.kt")
public void testMultiDeclForComponentMemberExtensionsInExtensionFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/multiDecl/long/MultiDeclForComponentMemberExtensionsInExtensionFunction.kt");
doTest(fileName);
}
}
}
}
@@ -46,3 +46,9 @@ abstract class AbstractJsCodegenBoxTest : BasicBoxTest(
"compiler/testData/codegen/box/",
BasicBoxTest.TEST_DATA_DIR_PATH + "out/codegen/box/"
)
abstract class AbstractJsTypedArraysBoxTest : BasicBoxTest(
"compiler/testData/codegen/box/arrays/",
BasicBoxTest.TEST_DATA_DIR_PATH + "out/codegen/box/arrays-typedarrays/",
typedArraysEnabled = true
)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.translate.context;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
@@ -283,6 +284,16 @@ public final class Namer {
return kotlin(IS_CHAR_SEQUENCE);
}
@NotNull
public JsExpression isArray() {
return kotlin("isArray");
}
@NotNull
public JsExpression isPrimitiveArray(@NotNull PrimitiveType type) {
return kotlin("is" + type.getArrayTypeName().asString());
}
@NotNull
private JsExpression invokeFunctionAndSetTypeCheckMetadata(
@NotNull String functionName,
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.CompositeFIF
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.ArrayFIF
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.*
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopRange
@@ -165,7 +165,7 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
fun translateForOverArray(): JsStatement {
val rangeExpression = context.defineTemporary(Translation.translateAsExpression(loopRange, context))
val length = CompositeFIF.LENGTH_PROPERTY_INTRINSIC.apply(rangeExpression, listOf<JsExpression>(), context)
val length = ArrayFIF.LENGTH_PROPERTY_INTRINSIC.apply(rangeExpression, listOf<JsExpression>(), context)
val end = context.defineTemporary(length)
val index = context.declareTemporary(context.program().getNumberLiteral(0))
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsConditional;
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.kotlin.js.backend.ast.JsInvocation;
import org.jetbrains.kotlin.js.backend.ast.JsLiteral;
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
import org.jetbrains.kotlin.js.patterns.NamePredicate;
import org.jetbrains.kotlin.js.patterns.typePredicates.TypePredicatesKt;
import org.jetbrains.kotlin.js.translate.context.Namer;
@@ -34,9 +35,10 @@ import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.ArrayFIF;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.TopLevelFIF;
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
@@ -210,7 +212,15 @@ public final class PatternTranslator extends AbstractTranslator {
return namer().isTypeOf(program().getStringLiteral("function"));
}
if (isArray(type)) return Namer.IS_ARRAY_FUN_REF;
if (isArray(type)) {
if (ArrayFIF.typedArraysEnabled(context())) {
return namer().isArray();
}
else {
return Namer.IS_ARRAY_FUN_REF;
}
}
if (TypePredicatesKt.getCHAR_SEQUENCE().apply(type)) return namer().isCharSequence();
@@ -247,6 +257,14 @@ public final class PatternTranslator extends AbstractTranslator {
return namer().isTypeOf(program().getStringLiteral("number"));
}
if (ArrayFIF.typedArraysEnabled(context())) {
if (KotlinBuiltIns.isPrimitiveArray(type)) {
PrimitiveType arrayType = KotlinBuiltIns.getPrimitiveArrayElementType(type);
assert arrayType != null;
return namer().isPrimitiveArray(arrayType);
}
}
return null;
}
@@ -1,139 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
import org.jetbrains.kotlin.js.patterns.NamePredicate;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed;
import org.jetbrains.kotlin.name.Name;
import java.util.List;
import static com.intellij.openapi.util.text.StringUtil.decapitalize;
import static org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment;
public final class ArrayFIF extends CompositeFIF {
private static final NamePredicate NUMBER_ARRAY;
private static final NamePredicate CHAR_ARRAY;
private static final NamePredicate BOOLEAN_ARRAY;
private static final NamePredicate LONG_ARRAY;
private static final NamePredicate ARRAYS;
private static final DescriptorPredicate ARRAY_FACTORY_METHODS;
static {
List<Name> arrayTypeNames = Lists.newArrayList();
List<Name> arrayFactoryMethodNames = Lists.newArrayList(Name.identifier("arrayOf"));
for (PrimitiveType type : PrimitiveType.values()) {
Name arrayTypeName = type.getArrayTypeName();
if (type != PrimitiveType.CHAR && type != PrimitiveType.BOOLEAN && type != PrimitiveType.LONG) {
arrayTypeNames.add(arrayTypeName);
}
arrayFactoryMethodNames.add(Name.identifier(decapitalize(arrayTypeName.asString() + "Of")));
}
Name arrayName = KotlinBuiltIns.FQ_NAMES.array.shortName();
Name booleanArrayName = PrimitiveType.BOOLEAN.getArrayTypeName();
Name charArrayName = PrimitiveType.CHAR.getArrayTypeName();
Name longArrayName = PrimitiveType.LONG.getArrayTypeName();
NUMBER_ARRAY = new NamePredicate(arrayTypeNames);
CHAR_ARRAY = new NamePredicate(charArrayName);
BOOLEAN_ARRAY = new NamePredicate(booleanArrayName);
LONG_ARRAY = new NamePredicate(longArrayName);
arrayTypeNames.add(charArrayName);
arrayTypeNames.add(booleanArrayName);
arrayTypeNames.add(longArrayName);
arrayTypeNames.add(arrayName);
ARRAYS = new NamePredicate(arrayTypeNames);
ARRAY_FACTORY_METHODS = pattern(Namer.KOTLIN_LOWER_NAME, new NamePredicate(arrayFactoryMethodNames));
}
private static final FunctionIntrinsic ARRAY_INTRINSIC = new FunctionIntrinsicWithReceiverComputed() {
@NotNull
@Override
public JsExpression apply(
@Nullable JsExpression receiver,
@NotNull List<? extends JsExpression> arguments,
@NotNull TranslationContext context
) {
assert arguments.size() == 1;
return arguments.get(0);
}
};
@NotNull
public static final FunctionIntrinsic GET_INTRINSIC = new FunctionIntrinsicWithReceiverComputed() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<? extends JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 1 : "Array get expression must have one argument.";
JsExpression indexExpression = arguments.get(0);
return new JsArrayAccess(receiver, indexExpression);
}
};
@NotNull
public static final FunctionIntrinsic SET_INTRINSIC = new FunctionIntrinsicWithReceiverComputed() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<? extends JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 2 : "Array set expression must have two arguments.";
JsExpression indexExpression = arguments.get(0);
JsExpression value = arguments.get(1);
JsArrayAccess arrayAccess = new JsArrayAccess(receiver, indexExpression);
return assignment(arrayAccess, value);
}
};
@NotNull
public static final FunctionIntrinsicFactory INSTANCE = new ArrayFIF();
private ArrayFIF() {
add(pattern(ARRAYS, "get"), GET_INTRINSIC);
add(pattern(ARRAYS, "set"), SET_INTRINSIC);
add(pattern(ARRAYS, "<get-size>"), LENGTH_PROPERTY_INTRINSIC);
add(pattern(ARRAYS, "iterator"), new KotlinFunctionIntrinsic("arrayIterator"));
add(pattern(NUMBER_ARRAY, "<init>(Int)"), new KotlinFunctionIntrinsic("newArray", JsNumberLiteral.ZERO));
add(pattern(CHAR_ARRAY, "<init>(Int)"), new KotlinFunctionIntrinsic("newArray", JsNumberLiteral.ZERO));
add(pattern(BOOLEAN_ARRAY, "<init>(Int)"), new KotlinFunctionIntrinsic("newArray", JsLiteral.FALSE));
add(pattern(LONG_ARRAY, "<init>(Int)"), new KotlinFunctionIntrinsic("newArray", new JsNameRef(Namer.LONG_ZERO, Namer.kotlinLong())));
add(pattern(ARRAYS, "<init>(Int,Function1)"), new KotlinFunctionIntrinsic("newArrayF"));
add(pattern("kotlin", "arrayOfNulls"), new KotlinFunctionIntrinsic("newArray", JsLiteral.NULL));
add(ARRAY_FACTORY_METHODS, ARRAY_INTRINSIC);
}
}
@@ -0,0 +1,162 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
import com.intellij.openapi.util.text.StringUtil.decapitalize
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.PrimitiveType.*
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.patterns.NamePredicate
import org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.name.Name
import java.util.*
object ArrayFIF : CompositeFIF() {
@JvmField
val GET_INTRINSIC = intrinsify { receiver, arguments, _ ->
assert(arguments.size == 1) { "Array get expression must have one argument." }
val (indexExpression) = arguments
JsArrayAccess(receiver!!, indexExpression)
}
@JvmField
val SET_INTRINSIC = intrinsify { receiver, arguments, _ ->
assert(arguments.size == 2) { "Array set expression must have two arguments." }
val (indexExpression, value) = arguments
val arrayAccess = JsArrayAccess(receiver!!, indexExpression)
JsAstUtils.assignment(arrayAccess, value)
}
@JvmField
val LENGTH_PROPERTY_INTRINSIC = BuiltInPropertyIntrinsic("length")
@JvmStatic
fun typedArraysEnabled(ctx: TranslationContext) = ctx.config.configuration.getBoolean(JSConfigurationKeys.TYPED_ARRAYS_ENABLED)
fun castOrCreatePrimitiveArray(ctx: TranslationContext, type: PrimitiveType?, arg: JsArrayLiteral): JsExpression {
if (type == null || !typedArraysEnabled(ctx)) return arg
if (type in TYPED_ARRAY_MAP) {
return createTypedArray(type, arg)
}
else {
return JsAstUtils.invokeKotlinFunction(type.lowerCaseName + "ArrayOf", *arg.expressions.toTypedArray())
}
}
private val TYPED_ARRAY_MAP = EnumMap(mapOf(BYTE to "Int8",
SHORT to "Int16",
INT to "Int32",
FLOAT to "Float32",
DOUBLE to "Float64"))
private fun createTypedArray(type: PrimitiveType, arg: JsExpression): JsExpression {
assert(type in TYPED_ARRAY_MAP)
return JsNew(JsNameRef(TYPED_ARRAY_MAP[type] + "Array"), listOf(arg))
}
private val PrimitiveType.lowerCaseName
get() = typeName.asString().toLowerCase()
init {
val arrayName = KotlinBuiltIns.FQ_NAMES.array.shortName()
val arrayTypeNames = mutableListOf(arrayName)
PrimitiveType.values().mapTo(arrayTypeNames) { it.arrayTypeName }
val arrays = NamePredicate(arrayTypeNames)
add(pattern(arrays, "get"), GET_INTRINSIC)
add(pattern(arrays, "set"), SET_INTRINSIC)
add(pattern(arrays, "<get-size>"), LENGTH_PROPERTY_INTRINSIC)
for (type in PrimitiveType.values()) {
add(pattern(NamePredicate(type.arrayTypeName), "<init>(Int)"), intrinsify { _, arguments, context ->
assert(arguments.size == 1) { "Array <init>(Int) expression must have one argument." }
val (size) = arguments
if (typedArraysEnabled(context)) {
if (type in TYPED_ARRAY_MAP) {
createTypedArray(type, size)
}
else {
JsAstUtils.invokeKotlinFunction("${type.lowerCaseName}Array", size)
}
}
else {
val initValue = when (type) {
BOOLEAN -> JsLiteral.FALSE
LONG -> JsNameRef(Namer.LONG_ZERO, Namer.kotlinLong())
else -> JsNumberLiteral.ZERO
}
JsAstUtils.invokeKotlinFunction("newArray", size, initValue)
}
})
add(pattern(NamePredicate(type.arrayTypeName), "<init>(Int,Function1)"), intrinsify { _, arguments, context ->
assert(arguments.size == 2) { "Array <init>(Int,Function1) expression must have two arguments." }
val (size, fn) = arguments
if (typedArraysEnabled(context)) {
if (type in TYPED_ARRAY_MAP) {
JsAstUtils.invokeKotlinFunction("fillArray", createTypedArray(type, size), fn)
}
else {
JsAstUtils.invokeKotlinFunction("${type.lowerCaseName}Array", size, fn)
}
}
else {
JsAstUtils.invokeKotlinFunction("newArrayF", size, fn)
}
})
add(pattern(NamePredicate(type.arrayTypeName), "iterator"), intrinsify { receiver, _, context ->
if (typedArraysEnabled(context)) {
JsAstUtils.invokeKotlinFunction("${type.lowerCaseName}ArrayIterator", receiver!!)
}
else {
JsAstUtils.invokeKotlinFunction("arrayIterator", receiver!!,
context.program().getStringLiteral(type.arrayTypeName.asString()))
}
})
}
add(pattern(NamePredicate(arrayName), "<init>(Int,Function1)"), KotlinFunctionIntrinsic("newArrayF"))
add(pattern(NamePredicate(arrayName), "iterator"), KotlinFunctionIntrinsic("arrayIterator"))
add(pattern(Namer.KOTLIN_LOWER_NAME, "arrayOfNulls"), KotlinFunctionIntrinsic("newArray", JsLiteral.NULL))
val arrayFactoryMethodNames = arrayTypeNames.map { Name.identifier(decapitalize(it.asString() + "Of")) }
val arrayFactoryMethods = pattern(Namer.KOTLIN_LOWER_NAME, NamePredicate(arrayFactoryMethodNames))
add(arrayFactoryMethods, intrinsify { _, arguments, _ -> arguments[0] })
}
private fun intrinsify(f: (receiver: JsExpression?, arguments: List<JsExpression>, context: TranslationContext) -> JsExpression)
= object : FunctionIntrinsicWithReceiverComputed() {
override fun apply(receiver: JsExpression?, arguments: List<JsExpression>, context: TranslationContext): JsExpression {
return f(receiver, arguments, context)
}
}
}
@@ -22,15 +22,11 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import java.util.List;
public abstract class CompositeFIF implements FunctionIntrinsicFactory {
@NotNull
public static final BuiltInPropertyIntrinsic LENGTH_PROPERTY_INTRINSIC = new BuiltInPropertyIntrinsic("length");
@NotNull
private final List<Pair<Predicate<FunctionDescriptor>, FunctionIntrinsic>> patternsAndIntrinsics = Lists.newArrayList();
@@ -16,12 +16,14 @@
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.kotlin.js.backend.ast.JsInvocation;
import org.jetbrains.kotlin.js.backend.ast.JsNameRef;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
import org.jetbrains.kotlin.js.patterns.NamePredicate;
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo;
@@ -164,13 +166,14 @@ public final class TopLevelFIF extends CompositeFIF {
public static final KotlinFunctionIntrinsic TO_STRING = new KotlinFunctionIntrinsic("toString");
@NotNull
public static final FunctionIntrinsic CHAR_TO_STRING = new FunctionIntrinsic() {
public static final FunctionIntrinsic CHAR_TO_STRING = new FunctionIntrinsicWithReceiverComputed() {
@NotNull
@Override
public JsExpression apply(
@NotNull CallInfo callInfo, @NotNull List<? extends JsExpression> arguments, @NotNull TranslationContext context
@Nullable JsExpression receiver, @NotNull List<? extends JsExpression> arguments, @NotNull TranslationContext context
) {
return JsAstUtils.charToString(callInfo.getDispatchReceiver());
assert receiver != null;
return JsAstUtils.charToString(receiver);
}
};
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.js.translate.reference
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.expression.PatternTranslator
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.ArrayFIF
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
@@ -83,7 +85,7 @@ class CallArgumentTranslator private constructor(
var argsBeforeVararg: List<JsExpression>? = null
var concatArguments: MutableList<JsExpression>? = null
val argsToJsExpr = translateUnresolvedArguments(context(), resolvedCall)
var isVarargTypePrimitive: Boolean? = null
var varargPrimitiveType: PrimitiveType? = null
for (parameterDescriptor in valueParameters) {
val actualArgument = valueArgumentsByIndex[parameterDescriptor.index]
@@ -96,19 +98,21 @@ class CallArgumentTranslator private constructor(
hasSpreadOperator = arguments.any { it.getSpreadElement() != null }
}
isVarargTypePrimitive = KotlinBuiltIns.isPrimitiveType(parameterDescriptor.original.varargElementType!!)
varargPrimitiveType = KotlinBuiltIns.getPrimitiveType(parameterDescriptor.original.varargElementType!!)
if (hasSpreadOperator) {
if (isNativeFunctionCall) {
argsBeforeVararg = result
result = mutableListOf<JsExpression>()
concatArguments = prepareConcatArguments(arguments, translateResolvedArgument(actualArgument, argsToJsExpr))
concatArguments = prepareConcatArguments(arguments,
translateResolvedArgument(actualArgument, argsToJsExpr),
null)
}
else {
result.addAll(translateVarargArgument(actualArgument,
argsToJsExpr,
actualArgument.arguments.size > 1,
isVarargTypePrimitive))
varargPrimitiveType))
}
}
else {
@@ -116,7 +120,7 @@ class CallArgumentTranslator private constructor(
result.addAll(translateResolvedArgument(actualArgument, argsToJsExpr))
}
else {
result.addAll(translateVarargArgument(actualArgument, argsToJsExpr, true, isVarargTypePrimitive))
result.addAll(translateVarargArgument(actualArgument, argsToJsExpr, true, varargPrimitiveType))
}
}
}
@@ -130,14 +134,14 @@ class CallArgumentTranslator private constructor(
assert(concatArguments != null) { "concatArguments should not be null" }
if (!result.isEmpty()) {
concatArguments!!.add(JsArrayLiteral(result).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
concatArguments!!.add(toArray(null, result))
}
if (!argsBeforeVararg!!.isEmpty()) {
concatArguments!!.add(0, JsArrayLiteral(argsBeforeVararg).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
concatArguments!!.add(0, toArray(null, argsBeforeVararg))
}
result = mutableListOf(concatArgumentsIfNeeded(concatArguments!!, isVarargTypePrimitive!!, true))
result = mutableListOf(concatArgumentsIfNeeded(concatArguments!!, varargPrimitiveType, true))
if (receiver != null) {
cachedReceiver = context().getOrDeclareTemporaryConstVariable(receiver)
@@ -210,6 +214,74 @@ class CallArgumentTranslator private constructor(
return result
}
private fun translateVarargArgument(
resolvedArgument: ResolvedValueArgument,
translatedArgs: Map<ValueArgument, JsExpression>,
shouldWrapVarargInArray: Boolean,
varargPrimitiveType: PrimitiveType?
): List<JsExpression> {
val arguments = resolvedArgument.arguments
if (arguments.isEmpty()) {
return if (shouldWrapVarargInArray) {
return listOf(toArray(varargPrimitiveType, listOf<JsExpression>()))
}
else {
listOf()
}
}
val list = translateResolvedArgument(resolvedArgument, translatedArgs)
return if (shouldWrapVarargInArray) {
val concatArguments = prepareConcatArguments(arguments, list, varargPrimitiveType)
val concatExpression = concatArgumentsIfNeeded(concatArguments, varargPrimitiveType, false)
listOf(concatExpression)
}
else {
listOf(JsAstUtils.invokeMethod(list[0], "slice"))
}
}
private fun toArray(varargPrimitiveType: PrimitiveType?, elements: List<JsExpression>): JsExpression {
return ArrayFIF.castOrCreatePrimitiveArray(context(),
varargPrimitiveType,
JsArrayLiteral(elements).apply { sideEffects = SideEffectKind.PURE })
}
private fun prepareConcatArguments(
arguments: List<ValueArgument>,
list: List<JsExpression>,
varargPrimitiveType: PrimitiveType?
): MutableList<JsExpression> {
assert(arguments.isNotEmpty()) { "arguments.size should not be 0" }
assert(arguments.size == list.size) { "arguments.size: " + arguments.size + " != list.size: " + list.size }
val concatArguments = mutableListOf<JsExpression>()
var lastArrayContent = mutableListOf<JsExpression>()
val size = arguments.size
for (index in 0..size - 1) {
val valueArgument = arguments[index]
val expressionArgument = list[index]
if (valueArgument.getSpreadElement() != null) {
if (lastArrayContent.size > 0) {
concatArguments.add(toArray(varargPrimitiveType, lastArrayContent))
lastArrayContent = mutableListOf<JsExpression>()
}
concatArguments.add(expressionArgument)
}
else {
lastArrayContent.add(expressionArgument)
}
}
if (lastArrayContent.size > 0) {
concatArguments.add(toArray(varargPrimitiveType, lastArrayContent))
}
return concatArguments
}
companion object {
@JvmStatic fun translate(resolvedCall: ResolvedCall<*>, receiver: JsExpression?, context: TranslationContext): ArgumentsInfo {
@@ -240,43 +312,15 @@ class CallArgumentTranslator private constructor(
return resolvedArgument.arguments.map { translatedArgs[it]!! }
}
private fun translateVarargArgument(
resolvedArgument: ResolvedValueArgument,
translatedArgs: Map<ValueArgument, JsExpression>,
shouldWrapVarargInArray: Boolean,
isVarargTypePrimitive: Boolean
): List<JsExpression> {
val arguments = resolvedArgument.arguments
if (arguments.isEmpty()) {
return if (shouldWrapVarargInArray) {
return listOf(JsArrayLiteral(listOf<JsExpression>()).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
}
else {
listOf()
}
}
val list = translateResolvedArgument(resolvedArgument, translatedArgs)
return if (shouldWrapVarargInArray) {
val concatArguments = prepareConcatArguments(arguments, list)
val concatExpression = concatArgumentsIfNeeded(concatArguments, isVarargTypePrimitive, false)
listOf(concatExpression)
}
else {
listOf(JsAstUtils.invokeMethod(list[0], "slice"))
}
}
private fun concatArgumentsIfNeeded(
concatArguments: List<JsExpression>,
isVarargTypePrimitive: Boolean,
varargPrimitiveType: PrimitiveType?,
isMixed: Boolean
): JsExpression {
assert(concatArguments.isNotEmpty()) { "concatArguments.size should not be 0" }
if (concatArguments.size > 1) {
if (isVarargTypePrimitive) {
if (varargPrimitiveType != null) {
val method = if (isMixed) "arrayConcat" else "primitiveArrayConcat"
return JsAstUtils.invokeKotlinFunction(method, concatArguments[0],
*concatArguments.subList(1, concatArguments.size).toTypedArray())
@@ -289,39 +333,6 @@ class CallArgumentTranslator private constructor(
return concatArguments[0]
}
}
private fun prepareConcatArguments(arguments: List<ValueArgument>, list: List<JsExpression>): MutableList<JsExpression> {
assert(arguments.isNotEmpty()) { "arguments.size should not be 0" }
assert(arguments.size == list.size) { "arguments.size: " + arguments.size + " != list.size: " + list.size }
val concatArguments = mutableListOf<JsExpression>()
var lastArrayContent = mutableListOf<JsExpression>()
val size = arguments.size
for (index in 0..size - 1) {
val valueArgument = arguments[index]
val expressionArgument = list[index]
if (valueArgument.getSpreadElement() != null) {
if (lastArrayContent.size > 0) {
concatArguments.add(JsArrayLiteral(lastArrayContent).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
concatArguments.add(expressionArgument)
lastArrayContent = mutableListOf<JsExpression>()
}
else {
concatArguments.add(expressionArgument)
}
}
else {
lastArrayContent.add(expressionArgument)
}
}
if (lastArrayContent.size > 0) {
concatArguments.add(JsArrayLiteral(lastArrayContent).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
}
return concatArguments
}
}
}
@@ -16,13 +16,13 @@
package org.jetbrains.kotlin.js.translate.utils;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind;
import com.intellij.util.SmartList;
import kotlin.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
@@ -575,4 +575,13 @@ public final class JsAstUtils {
MetadataProperties.setCoroutineReceiver(result, true);
return result;
}
@NotNull
public static JsExpression comma(JsExpression first, JsExpression... tail) {
JsExpression result = first;
for (JsExpression e : tail) {
result = new JsBinaryOperation(JsBinaryOperator.COMMA, result, e);
}
return result;
}
}
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
function normalizeOffset(offset, length) {
if (offset < 0) return Math.max(0, offset + length);
return Math.min(offset, length);
}
function typedArraySlice(begin, end) {
if (typeof end === "undefined") {
end = this.length;
}
begin = normalizeOffset(begin || 0, this.length);
end = Math.max(begin, normalizeOffset(end, this.length));
return new this.constructor(this.subarray(begin, end));
}
var arrays = [Int8Array, Int16Array, Uint16Array, Int32Array, Float32Array, Float64Array];
for (var i = 0; i < arrays.length; ++i) {
var TypedArray = arrays[i];
if (typeof TypedArray.prototype.slice === "undefined") {
Object.defineProperty(TypedArray.prototype, 'slice', {
value: typedArraySlice
});
}
}
// Patch apply to work with TypedArrays if needed.
try {
(function() {}).apply(null, new Int32Array(0))
} catch (e) {
var apply = Function.prototype.apply;
Object.defineProperty(Function.prototype, 'apply', {
value: function(self, array) {
return apply.call(this, self, [].slice.call(array));
}
});
}
})();
+2 -2
View File
@@ -3,10 +3,10 @@
<head>
<script type="application/javascript" src="../../../dist/js/kotlin.js"></script>
<script type="application/javascript" src="../../../dist/classes/kotlin-test-js/kotlin-test.js"></script>
<script type="application/javascript" src="../../../js/js.translator/testData/out/box/standardClasses/stringBuilder_v5.js"></script>
<script type="application/javascript" src="../../../js/js.translator/testData/out/codegen/box/arrays/primitiveArrays_v5.js"></script>
<script type="application/javascript">
console.log(JS_TESTS.foo.box());
console.log(JS_TESTS.box());
</script>
</head>
<body>
@@ -228,11 +228,10 @@ class ArraysTest {
assertEquals(arr.asList().toString(), arr.contentToString())
}
// @Ignore("KT-16056")
// @Test fun contentDeepToString() {
// val arr = arrayOf("aa", 1, null, charArrayOf('d'))
// assertEquals("[aa, 1, null, [d]]", arr.contentDeepToString())
// }
@Test fun contentDeepToString() {
val arr = arrayOf("aa", 1, null, charArrayOf('d'))
assertEquals("[aa, 1, null, [d]]", arr.contentDeepToString())
}
@Test fun contentDeepToStringNoRecursion() {
// a[b[a, b]]
@@ -48,4 +48,10 @@ interface KotlinJsOptions : org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
* Default value: "v5"
*/
var target: kotlin.String
}
/**
* Translate primitive arrays to JS typed arrays
* Default value: false
*/
var typedArrays: kotlin.Boolean
}
@@ -59,6 +59,11 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko
get() = targetField ?: "v5"
set(value) { targetField = value }
private var typedArraysField: kotlin.Boolean? = null
override var typedArrays: kotlin.Boolean
get() = typedArraysField ?: false
set(value) { typedArraysField = value }
internal open fun updateArguments(args: org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments) {
apiVersionField?.let { args.apiVersion = it }
languageVersionField?.let { args.languageVersion = it }
@@ -71,6 +76,7 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko
outputFileField?.let { args.outputFile = it }
sourceMapField?.let { args.sourceMap = it }
targetField?.let { args.target = it }
typedArraysField?.let { args.typedArrays = it }
}
}
@@ -86,4 +92,5 @@ internal fun org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments.fil
outputFile = null
sourceMap = false
target = "v5"
}
typedArrays = false
}
@@ -103,6 +103,7 @@ private fun List<ConcreteFunction>.writeTo(file: File, sourceFile: SourceFile, p
writer.appendln("import kotlin.js.*")
if (sourceFile == SourceFile.Arrays) {
writer.appendln("import primitiveArrayConcat")
writer.appendln("import withType")
}
}
writer.append("import kotlin.comparisons.*\n\n")
@@ -211,33 +211,43 @@ object CommonArrays {
}
}
fun f_plusCollection() = f("plus(elements: Collection<T>)") {
operator(true)
fun f_plusCollection() =
(listOf(InvariantArraysOfObjects to null) + PrimitiveType.defaultPrimitives.map { ArraysOfPrimitives to it }).map {
val (family, primitive) = it
f("plus(elements: Collection<T>)") {
operator(true)
// TODO: inline arrayPlusCollection when @PublishedAPI is available
// inline(Platform.JS, Inline.Yes)
// annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
only(family)
if (family == InvariantArraysOfObjects) {
only(Platform.JS, ArraysOfObjects)
}
only(InvariantArraysOfObjects, ArraysOfPrimitives)
only(Platform.JS, ArraysOfObjects, ArraysOfPrimitives)
// TODO: inline arrayPlusCollection when @PublishedAPI is available
// inline(Platform.JS, Inline.Yes)
// annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
returns("SELF")
returns(Platform.JS, ArraysOfObjects) { "Array<T>" }
doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] collection." }
body(Platform.JVM) {
"""
var index = size
val result = java.util.Arrays.copyOf(this, index + elements.size)
for (element in elements) result[index++] = element
return result
"""
}
body(Platform.JS) {
"""
return arrayPlusCollection(this, elements)
"""
}
}
returns("SELF")
returns(Platform.JS, ArraysOfObjects) { "Array<T>" }
doc { "Returns an array containing all elements of the original array and then all elements of the given [elements] collection." }
body(Platform.JVM) {
"""
var index = size
val result = java.util.Arrays.copyOf(this, index + elements.size)
for (element in elements) result[index++] = element
return result
"""
}
if (primitive != null) {
only(primitive)
}
when (primitive) {
null, PrimitiveType.Boolean, PrimitiveType.Long ->
body(Platform.JS) { "return arrayPlusCollection(this, elements)" }
else ->
body(Platform.JS) { "return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)" }
}
}
}
fun f_plusArray() = f("plus(elements: SELF)") {
operator(true)
@@ -275,81 +285,110 @@ object CommonArrays {
}
fun f_copyOfRange() = f("copyOfRange(fromIndex: Int, toIndex: Int)") {
inline(Platform.JVM, Inline.Only)
inline(Platform.JS, Inline.Yes)
annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
fun f_copyOfRange() = (listOf(InvariantArraysOfObjects to null) + PrimitiveType.defaultPrimitives.map { ArraysOfPrimitives to it }).map {
val (family, primitive) = it
f("copyOfRange(fromIndex: Int, toIndex: Int)") {
only(family)
if (family == InvariantArraysOfObjects) {
only(Platform.JS, ArraysOfObjects)
}
only(InvariantArraysOfObjects, ArraysOfPrimitives)
only(Platform.JS, ArraysOfObjects, ArraysOfPrimitives)
inline(Platform.JVM, Inline.Only)
doc { "Returns new array which is a copy of range of original array." }
returns("SELF")
returns(Platform.JS, ArraysOfObjects) { "Array<T>" }
body(Platform.JVM) {
"return java.util.Arrays.copyOfRange(this, fromIndex, toIndex)"
}
body(Platform.JS) {
// TODO: Arguments checking as in java?
"return this.asDynamic().slice(fromIndex, toIndex)"
doc { "Returns new array which is a copy of range of original array." }
returns("SELF")
returns(Platform.JS, ArraysOfObjects) { "Array<T>" }
body(Platform.JVM) {
"return java.util.Arrays.copyOfRange(this, fromIndex, toIndex)"
}
if (primitive != null) {
only(primitive)
}
when (primitive) {
PrimitiveType.Char, PrimitiveType.Boolean, PrimitiveType.Long ->
body(Platform.JS) { "return withType(\"${primitive}Array\", this.asDynamic().slice(fromIndex, toIndex))" }
else -> {
annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
inline(Platform.JS, Inline.Yes)
body(Platform.JS) { "return this.asDynamic().slice(fromIndex, toIndex)" }
}
}
}
}
fun f_copyOf() = f("copyOf()") {
inline(Platform.JVM, Inline.Only)
inline(Platform.JS, Inline.Yes)
annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
fun f_copyOf() = (listOf(InvariantArraysOfObjects to null) + PrimitiveType.defaultPrimitives.map { ArraysOfPrimitives to it }).map {
val (family, primitive) = it
f("copyOf()") {
only(family)
if (family == InvariantArraysOfObjects) {
only(Platform.JS, ArraysOfObjects)
}
only(InvariantArraysOfObjects, ArraysOfPrimitives)
only(Platform.JS, ArraysOfObjects, ArraysOfPrimitives)
inline(Platform.JVM, Inline.Only)
only(InvariantArraysOfObjects, ArraysOfPrimitives)
doc { "Returns new array which is a copy of the original array." }
returns("SELF")
returns(Platform.JS, ArraysOfObjects) { "Array<T>" }
doc { "Returns new array which is a copy of the original array." }
returns("SELF")
returns(Platform.JS, ArraysOfObjects) { "Array<T>" }
body(Platform.JVM) {
"return java.util.Arrays.copyOf(this, size)"
}
body(Platform.JS) {
"return this.asDynamic().slice()"
body(Platform.JVM) {
"return java.util.Arrays.copyOf(this, size)"
}
body(Platform.JS) {
"return this.asDynamic().slice()"
}
if (primitive != null) {
only(primitive)
}
when (primitive) {
PrimitiveType.Char, PrimitiveType.Boolean, PrimitiveType.Long ->
body(Platform.JS) { "return withType(\"${primitive}Array\", this.asDynamic().slice())" }
else -> {
annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
inline(Platform.JS, Inline.Yes)
body(Platform.JS) { "return this.asDynamic().slice()" }
}
}
}
}
fun f_copyOfResized() =
(PrimitiveType.defaultPrimitives.map { ArraysOfPrimitives to it } + (InvariantArraysOfObjects to null)).map {
val (family, primitive) = it
f("copyOf(newSize: Int)") {
only(family)
if (family == InvariantArraysOfObjects) {
only(Platform.JS, ArraysOfObjects)
}
inline(Platform.JVM, Inline.Only)
doc { "Returns new array which is a copy of the original array, resized to the given [newSize]." }
val defaultValue: String
if (primitive != null) {
only(primitive)
returns("SELF")
defaultValue = when (primitive) {
PrimitiveType.Boolean -> false.toString()
PrimitiveType.Char -> "0"
else -> "ZERO"
(PrimitiveType.defaultPrimitives.map { ArraysOfPrimitives to it } + (InvariantArraysOfObjects to null)).map {
val (family, primitive) = it
f("copyOf(newSize: Int)") {
only(family)
if (family == InvariantArraysOfObjects) {
only(Platform.JS, ArraysOfObjects)
}
inline(Platform.JVM, Inline.Only)
doc { "Returns new array which is a copy of the original array, resized to the given [newSize]." }
if (primitive != null) {
only(primitive)
returns("SELF")
when (primitive) {
PrimitiveType.Boolean ->
body(Platform.JS) { "return withType(\"BooleanArray\", arrayCopyResize(this, newSize, false))" }
PrimitiveType.Char ->
body(Platform.JS) { "return withType(\"CharArray\", fillFrom(this, ${primitive}Array(newSize)))" }
PrimitiveType.Long ->
body(Platform.JS) { "return withType(\"LongArray\", arrayCopyResize(this, newSize, ZERO))" }
else ->
body(Platform.JS) { "return fillFrom(this, ${primitive}Array(newSize))" }
}
}
else {
returns { "Array<T?>" }
body(Platform.JS) { "return arrayCopyResize(this, newSize, null)" }
}
body(Platform.JVM) {
"return java.util.Arrays.copyOf(this, newSize)"
}
} else {
returns { "Array<T?>" }
defaultValue = "null"
}
body(Platform.JVM) {
"return java.util.Arrays.copyOf(this, newSize)"
}
body(Platform.JS) {
"""
return arrayCopyResize(this, newSize, $defaultValue)
"""
}
}
}
fun f_sortPrimitives() =
(PrimitiveType.numericPrimitives + PrimitiveType.Char).map { primitive ->
@@ -481,12 +520,13 @@ object CommonArrays {
return result as Array<T>
"""
}
if (primitive == PrimitiveType.Char) {
body(Platform.JS) { "return Array<Char>(size, { i -> this[i] })" }
}
else {
body(Platform.JS) { "return copyOf().unsafeCast<Array<T>>()" }
when (primitive) {
PrimitiveType.Char ->
body(Platform.JS) { "return Array<Char>(size, { i -> this[i] })" }
PrimitiveType.Boolean, PrimitiveType.Long ->
body(Platform.JS) { "return copyOf().unsafeCast<Array<T>>()" }
else ->
body(Platform.JS) { "return js(\"[]\").slice.call(this)" }
}
}
}
@@ -496,7 +536,10 @@ object CommonArrays {
fun templates() =
listOf(f_plusElement()) +
f_plusElementOperator() +
listOf(f_plusCollection(), f_plusArray(), f_copyOf(), f_copyOfRange()) +
f_plusCollection() +
listOf(f_plusArray()) +
f_copyOf() +
f_copyOfRange() +
f_copyOfResized() +
f_sortPrimitives() +
listOf(f_sort(), f_sortWith(), f_asList()) +