JS: add boxing/unboxing to default accessors of non-simple properties
See KT-21421
This commit is contained in:
@@ -833,6 +833,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("derivedFunctionReturningChar.kt")
|
||||||
public void testDerivedFunctionReturningChar() throws Exception {
|
public void testDerivedFunctionReturningChar() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/derivedFunctionReturningChar.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/derivedFunctionReturningChar.kt");
|
||||||
|
|||||||
+11
-3
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
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.callTranslator.CallTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer.getReceiverParameterName
|
import org.jetbrains.kotlin.js.translate.context.Namer.getReceiverParameterName
|
||||||
@@ -94,13 +95,14 @@ class DefaultPropertyTranslator(
|
|||||||
|
|
||||||
assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" }
|
assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" }
|
||||||
assert(descriptor is PropertyDescriptor) { "Property descriptor expected: $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) {
|
if (getterDescriptor is PropertyAccessorDescriptor && getterDescriptor.correspondingProperty.isLateInit) {
|
||||||
val throwFunction = context().getReferenceToIntrinsic(Namer.THROW_UNINITIALIZED_PROPERTY_ACCESS_EXCEPTION)
|
val throwFunction = context().getReferenceToIntrinsic(Namer.THROW_UNINITIALIZED_PROPERTY_ACCESS_EXCEPTION)
|
||||||
function.body.statements += JsIf(JsBinaryOperation(JsBinaryOperator.EQ, result, JsNullLiteral()),
|
function.body.statements += JsIf(JsBinaryOperation(JsBinaryOperator.EQ, result, JsNullLiteral()),
|
||||||
JsReturn(JsInvocation(throwFunction,
|
JsReturn(JsInvocation(throwFunction,
|
||||||
JsStringLiteral(getterDescriptor.correspondingProperty.name.asString()))))
|
JsStringLiteral(getterDescriptor.correspondingProperty.name.asString()))))
|
||||||
}
|
}
|
||||||
|
result = TranslationUtils.coerce(context(), result, TranslationUtils.getReturnTypeForCoercion(getterDescriptor))
|
||||||
function.body.statements += JsReturn(result).apply { source = descriptor.source.getPsi() }
|
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" }
|
assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" }
|
||||||
val correspondingPropertyName = setterDescriptor.correspondingVariable.name.asString()
|
val correspondingPropertyName = setterDescriptor.correspondingVariable.name.asString()
|
||||||
val valueParameter = function.addParameter(correspondingPropertyName).name
|
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]
|
val delegatedCall = bindingContext()[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor]
|
||||||
|
|
||||||
if (delegatedCall != null) {
|
if (delegatedCall != null) {
|
||||||
@@ -142,7 +145,12 @@ class DefaultPropertyTranslator(
|
|||||||
else {
|
else {
|
||||||
assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" }
|
assert(!descriptor.isExtension) { "Unexpected extension property $descriptor}" }
|
||||||
assert(descriptor is PropertyDescriptor) { "Property descriptor expected: $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())
|
function.addStatement(assignment.apply { source = descriptor.source.getPsi() }.makeStmt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user