JS: add tests to prove that compiler does not optimize RTTI and safe calls based on type information. Remove corresponding optimization for !! operation. See KT-14033
This commit is contained in:
@@ -1,6 +1,3 @@
|
|||||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
|
|
||||||
fun <T> foo(t: T) {
|
fun <T> foo(t: T) {
|
||||||
t!!
|
t!!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1753,6 +1753,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("explicitUpcast.kt")
|
||||||
|
public void testExplicitUpcast() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/cast/explicitUpcast.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("implicitCastToLong.kt")
|
@TestMetadata("implicitCastToLong.kt")
|
||||||
public void testImplicitCastToLong() throws Exception {
|
public void testImplicitCastToLong() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/cast/implicitCastToLong.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/cast/implicitCastToLong.kt");
|
||||||
@@ -6887,6 +6893,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/safeCall"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/safeCall"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("redundantSafeAccess.kt")
|
||||||
|
public void testRedundantSafeAccess() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/safeCall/redundantSafeAccess.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("safeAccess.kt")
|
@TestMetadata("safeAccess.kt")
|
||||||
public void testSafeAccess() throws Exception {
|
public void testSafeAccess() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/safeCall/safeAccess.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/safeCall/safeAccess.kt");
|
||||||
|
|||||||
+1
-7
@@ -7851,13 +7851,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
@TestMetadata("genericNull.kt")
|
@TestMetadata("genericNull.kt")
|
||||||
public void testGenericNull() throws Exception {
|
public void testGenericNull() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/exclExcl/genericNull.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/exclExcl/genericNull.kt");
|
||||||
try {
|
doTest(fileName);
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("primitive.kt")
|
@TestMetadata("primitive.kt")
|
||||||
|
|||||||
+1
-4
@@ -29,12 +29,10 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
|||||||
import org.jetbrains.kotlin.psi.KtConstantExpression;
|
import org.jetbrains.kotlin.psi.KtConstantExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtUnaryExpression;
|
import org.jetbrains.kotlin.psi.KtUnaryExpression;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
|
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCompileTimeValue;
|
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCompileTimeValue;
|
||||||
@@ -55,9 +53,8 @@ public final class UnaryOperationTranslator {
|
|||||||
IElementType operationToken = expression.getOperationReference().getReferencedNameElementType();
|
IElementType operationToken = expression.getOperationReference().getReferencedNameElementType();
|
||||||
if (operationToken == KtTokens.EXCLEXCL) {
|
if (operationToken == KtTokens.EXCLEXCL) {
|
||||||
KtExpression baseExpression = getBaseExpression(expression);
|
KtExpression baseExpression = getBaseExpression(expression);
|
||||||
KotlinType type = BindingContextUtils.getTypeNotNull(context.bindingContext(), baseExpression);
|
|
||||||
JsExpression translatedExpression = translateAsExpression(baseExpression, context);
|
JsExpression translatedExpression = translateAsExpression(baseExpression, context);
|
||||||
return type.isMarkedNullable() ? sure(translatedExpression, context) : translatedExpression;
|
return sure(translatedExpression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operationToken == KtTokens.MINUS) {
|
if (operationToken == KtTokens.MINUS) {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
function createWrongObject() {
|
||||||
|
return new (JS_TESTS.foo.C);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
open class A
|
||||||
|
|
||||||
|
class B : A()
|
||||||
|
|
||||||
|
class C
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var b: B = createWrongObject()
|
||||||
|
if (b is A) return "fail1: is"
|
||||||
|
if (b as? A != null) return "fail1: as?"
|
||||||
|
try {
|
||||||
|
println(b as A)
|
||||||
|
return "fail1: as"
|
||||||
|
}
|
||||||
|
catch (e: ClassCastException) {
|
||||||
|
// It's expected
|
||||||
|
}
|
||||||
|
|
||||||
|
b = B()
|
||||||
|
if (b !is A) return "fail2: is"
|
||||||
|
if (b as? A == null) return "fail2: as?"
|
||||||
|
try {
|
||||||
|
if ((b as A) != b) return "fail2: as"
|
||||||
|
}
|
||||||
|
catch (e: ClassCastException) {
|
||||||
|
return "fail2a: as"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
external fun createWrongObject(): B
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
function createWrongObject() {
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A(val x: String) {
|
||||||
|
fun foo() = x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var b: A = createWrongObject()
|
||||||
|
if (b?.x != null) return "fail1: ?."
|
||||||
|
if (b?.foo() != null) return "fail1a: ?."
|
||||||
|
try {
|
||||||
|
println(b!!.x)
|
||||||
|
return "fail1: !!"
|
||||||
|
}
|
||||||
|
catch (e: NullPointerException) {
|
||||||
|
// It's expected
|
||||||
|
}
|
||||||
|
|
||||||
|
b = A("OK")
|
||||||
|
if (b?.x != "OK") return "fail2: ?."
|
||||||
|
if (b?.foo() != "OK") return "fail2a: ?."
|
||||||
|
try {
|
||||||
|
if (b!!.x != "OK") return "fail2: !!"
|
||||||
|
}
|
||||||
|
catch (e: NullPointerException) {
|
||||||
|
return "fail2a: !!"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
external fun createWrongObject(): A
|
||||||
Reference in New Issue
Block a user