| // TARGET_BACKEND: JS_IR, JS_IR_ES6 |
| // KJS_WITH_FULL_RUNTIME |
| /* |
| This tests that variables (aliases) are created for array literals. |
| |
| Let's say we have the following JS code: |
| |
| function f(a) { |
| a.push(0); |
| return a; |
| } |
| |
| // ... |
| console.log(f([])); |
| In this case copying f's argument a without creating a variable is incorrect because it would produce the following code: |
| |
| [].push(0); |
| console.log([]); |
| This is the correct version: |
| |
| var a = []; |
| a.push(0); |
| console.log(a); |
| The test was created because we don't want to create aliases for literals. |
| However in our class hierarchy JsArrayLiteral is subclass of JsLiteral, |
| which makes very easy to implement incorrect aliasing logic. |
| */ |
| |
| // FILE: lib.kt |
| package foo |
| |
| inline fun Array<Int>.push(element: Int): Unit = asDynamic().push(element) |
| |
| inline fun Array<Int>.splice(index: Int, howMany: Int): Unit = asDynamic().splice(index, howMany) |
| |
| data class PairArray<T, R>(val fst: Array<T>, val snd: Array<R>) |
| |
| inline fun moveTo(source: Array<Int>, sink: Array<Int>): PairArray<Int, Int> { |
| val size = source.size |
| for (i in 1..size) { |
| val element = source[0] |
| source.splice(0, 1) |
| sink.push(element) |
| } |
| |
| return PairArray(source, sink) |
| } |
| |
| // FILE: main.kt |
| // CHECK_NOT_CALLED: moveTo |
| // CHECK_BREAKS_COUNT: function=box count=0 |
| // CHECK_LABELS_COUNT: function=box name=$l$block count=0 |
| package foo |
| |
| fun box(): String { |
| val expected = PairArray<Int, Int>(arrayOf(), arrayOf(1,2,3,4)) |
| assertTrue(expected.deepEquals(moveTo(arrayOf(3, 4), arrayOf(1, 2)))) |
| |
| return "OK" |
| } |
| |
| fun <T, R> PairArray<T, R>.deepEquals(other: PairArray<T, R>): Boolean { |
| return fst.asList() == other.fst.asList() && snd.asList() == other.snd.asList() |
| } |