From 7bee2ceac7a63ea1bbecc47de1c40aa31a95ea72 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 23 Nov 2017 19:36:19 +0300 Subject: [PATCH] JS: add boxing/unboxing to default accessors of non-simple properties See KT-21421 --- .../js/test/semantics/BoxJsTestGenerated.java | 6 ++++ .../declaration/PropertyTranslator.kt | 14 +++++++-- .../testData/box/coercion/defaultAccessors.kt | 29 +++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 js/js.translator/testData/box/coercion/defaultAccessors.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index febd8dac82a..a0519aae1c1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -833,6 +833,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("defaultAccessors.kt") + public void testDefaultAccessors() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/defaultAccessors.kt"); + doTest(fileName); + } + @TestMetadata("derivedFunctionReturningChar.kt") public void testDerivedFunctionReturningChar() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/derivedFunctionReturningChar.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PropertyTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PropertyTranslator.kt index fdf4ef32170..f4e260e34a5 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PropertyTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/PropertyTranslator.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic +import org.jetbrains.kotlin.js.backend.ast.metadata.type import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.Namer.getReceiverParameterName @@ -94,13 +95,14 @@ class DefaultPropertyTranslator( assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" } assert(descriptor is PropertyDescriptor) { "Property descriptor expected: $descriptor" } - val result = backingFieldReference(context(), descriptor as PropertyDescriptor) + var result: JsExpression = backingFieldReference(context(), descriptor as PropertyDescriptor) if (getterDescriptor is PropertyAccessorDescriptor && getterDescriptor.correspondingProperty.isLateInit) { val throwFunction = context().getReferenceToIntrinsic(Namer.THROW_UNINITIALIZED_PROPERTY_ACCESS_EXCEPTION) function.body.statements += JsIf(JsBinaryOperation(JsBinaryOperator.EQ, result, JsNullLiteral()), JsReturn(JsInvocation(throwFunction, JsStringLiteral(getterDescriptor.correspondingProperty.name.asString())))) } + result = TranslationUtils.coerce(context(), result, TranslationUtils.getReturnTypeForCoercion(getterDescriptor)) function.body.statements += JsReturn(result).apply { source = descriptor.source.getPsi() } } @@ -126,7 +128,8 @@ class DefaultPropertyTranslator( assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" } val correspondingPropertyName = setterDescriptor.correspondingVariable.name.asString() val valueParameter = function.addParameter(correspondingPropertyName).name - val withAliased = context().innerContextWithAliased(setterDescriptor.valueParameters[0], valueParameter.makeRef()) + val parameter = setterDescriptor.valueParameters[0] + val withAliased = context().innerContextWithAliased(parameter, valueParameter.makeRef()) val delegatedCall = bindingContext()[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor] if (delegatedCall != null) { @@ -142,7 +145,12 @@ class DefaultPropertyTranslator( else { assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" } assert(descriptor is PropertyDescriptor) { "Property descriptor expected: $descriptor" } - val assignment = assignmentToBackingField(withAliased, descriptor as PropertyDescriptor, valueParameter.makeRef()) + var value: JsExpression = valueParameter.makeRef().apply { + type = TranslationUtils.getReturnTypeForCoercion(setterDescriptor.correspondingVariable) + } + value = TranslationUtils.coerce( + context(), value, TranslationUtils.getReturnTypeForCoercion(setterDescriptor.correspondingVariable, true)) + val assignment = assignmentToBackingField(withAliased, descriptor as PropertyDescriptor, value) function.addStatement(assignment.apply { source = descriptor.source.getPsi() }.makeStmt()) } } diff --git a/js/js.translator/testData/box/coercion/defaultAccessors.kt b/js/js.translator/testData/box/coercion/defaultAccessors.kt new file mode 100644 index 00000000000..3a3ec9f6e14 --- /dev/null +++ b/js/js.translator/testData/box/coercion/defaultAccessors.kt @@ -0,0 +1,29 @@ +// EXPECTED_REACHABLE_NODES: 1140 +interface I { + val a: Char +} + +object X : I { + override var a = '#' +} + +var result = "" + +object Y : I { + override var a = '#' + get() { + result = jsTypeOf(field.asDynamic()) + return field + } +} + +fun box(): String { + val t = jsTypeOf(X.asDynamic().a) + if (t != "object") return "fail1: $t" + + Y.a = '@' + Y.a + if (result != "number") return "fail2: $result" + + return "OK" +}