JS/RTTI: avoid possible side-effect for is-check on nullable type

#KT-7038 fixed
This commit is contained in:
Alexey Tsvetkov
2015-06-10 16:49:46 +03:00
committed by Alexey Andreev
parent c6cf6a0df7
commit 5fdede74a3
4 changed files with 66 additions and 6 deletions
@@ -77,6 +77,18 @@ public class RttiTestGenerated extends AbstractRttiTest {
doTest(fileName);
}
@TestMetadata("sideEffectMethod.kt")
public void testSideEffectMethod() throws Exception {
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/rtti/cases/sideEffectMethod.kt");
doTest(fileName);
}
@TestMetadata("sideEffectProperty.kt")
public void testSideEffectProperty() throws Exception {
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/rtti/cases/sideEffectProperty.kt");
doTest(fileName);
}
@TestMetadata("stdlibEmptyListClass.kt")
public void testStdlibEmptyListClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/rtti/cases/stdlibEmptyListClass.kt");
@@ -20,9 +20,7 @@ import com.google.dart.compiler.backend.js.ast.*
import com.google.dart.compiler.backend.js.ast.metadata.TypeCheck
import com.google.dart.compiler.backend.js.ast.metadata.typeCheck
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.or
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.typeOfIs
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isNullCheck
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
import java.util.*
fun expandIsCalls(node: JsNode, context: TranslationContext) {
@@ -71,9 +69,16 @@ private class TypeCheckRewritingVisitor(private val context: TranslationContext)
TypeCheck.INSTANCEOF ->
context.namer().isInstanceOf(argument, calleeArgument)
// Kotlin.orNull(calleeArgument)(argument) -> argument === null || calleeArgument(argument)
TypeCheck.OR_NULL ->
or(isNullCheck(argument), JsInvocation(calleeArgument, argument))
// Kotlin.orNull(calleeArgument)(argument) -> (tmp = argument) == null || calleeArgument(tmp)
TypeCheck.OR_NULL -> {
val currentScope = scopes.peek()
val tmp = currentScope.declareTemporary()
val statementContext = lastStatementLevelContext
statementContext.addPrevious(newVar(tmp, null))
val assignment = assignment(tmp.makeRef(), argument)
val tmpIsNull = TranslationUtils.isNullCheck(assignment)
or(tmpIsNull, JsInvocation(calleeArgument, tmp.makeRef()))
}
else ->
null
@@ -0,0 +1,21 @@
package foo
var counter = 0
class A {
fun getCounter(): Any? =
when (counter++) {
0 -> "0"
1 -> null
else -> counter
}
}
fun box(): String {
assertEquals(false, A().getCounter() is Int?, "(1)")
assertEquals(true, A().getCounter() is Int?, "(2)")
assertEquals(true, A().getCounter() is Int?, "(3)")
assertEquals(3, counter)
return "OK"
}
@@ -0,0 +1,22 @@
package foo
var counter = 0
class A {
val x: Any?
get() =
when (counter++) {
0 -> "0"
1 -> null
else -> counter
}
}
fun box(): String {
assertEquals(false, A().x is Int?, "(1)")
assertEquals(true, A().x is Int?, "(2)")
assertEquals(true, A().x is Int?, "(3)")
assertEquals(3, counter)
return "OK"
}