JS/RTTI: avoid possible side-effect for is-check on nullable type
#KT-7038 fixed
This commit is contained in:
committed by
Alexey Andreev
parent
c6cf6a0df7
commit
5fdede74a3
@@ -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"
|
||||
}
|
||||
Reference in New Issue
Block a user