JS: don't generate object literal for local delegated properties, generate call to getValue/setValue on each use site instead.

This commit is contained in:
Alexey Andreev
2017-01-31 14:08:35 +03:00
parent 0f049a90aa
commit b929db1b07
2 changed files with 28 additions and 17 deletions
@@ -24,14 +24,17 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.js.backend.ast.JsLiteral
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
import org.jetbrains.kotlin.js.translate.declaration.contextWithPropertyMetadataCreationIntrinsified
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.reference.buildReifiedTypeArgs
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import java.util.*
@@ -100,9 +103,20 @@ object DefaultVariableAccessCase : VariableAccessCase() {
val localVariableDescriptor = resolvedCall.resultingDescriptor as? LocalVariableDescriptor
val accessorDescriptor = if (isGetAccess()) localVariableDescriptor?.getter else localVariableDescriptor?.setter
if (accessorDescriptor != null) {
val funRef = JsNameRef(TranslationUtils.getAccessorFunctionName(accessorDescriptor), ref)
return JsInvocation(funRef, *additionalArguments.toTypedArray())
val delegatedCall = accessorDescriptor?.let { context.bindingContext()[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, it] }
if (delegatedCall != null) {
val delegateContext = context.contextWithPropertyMetadataCreationIntrinsified(
delegatedCall, localVariableDescriptor!!, JsLiteral.NULL)
val delegateContextWithArgs = if (!isGetAccess()) {
val valueArg = delegatedCall.valueArgumentsByIndex!![2].arguments[0].getArgumentExpression()
delegateContext.innerContextWithAliasesForExpressions(mapOf(valueArg to value!!))
}
else {
delegateContext
}
val localVariableRef = context.getAliasForDescriptor(localVariableDescriptor) ?:
JsAstUtils.pureFqn(context.getNameForDescriptor(localVariableDescriptor), null)
return CallTranslator.translate(delegateContextWithArgs, delegatedCall, localVariableRef)
}
return constructAccessExpression(ref)
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.js.translate.expression;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
@@ -36,7 +35,10 @@ import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
import org.jetbrains.kotlin.js.translate.operation.BinaryOperationTranslator;
import org.jetbrains.kotlin.js.translate.operation.UnaryOperationTranslator;
import org.jetbrains.kotlin.js.translate.reference.*;
import org.jetbrains.kotlin.js.translate.utils.*;
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -134,6 +136,8 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
JsExpression jsReturnExpression = translateAsExpression(returned, context);
KotlinType returnedType = context.bindingContext().getType(returned);
assert returnedType != null : "Resolved return expression is expected to have type: " +
PsiUtilsKt.getTextWithLocation(jetReturnExpression);
if (KotlinBuiltIns.isCharOrNullableChar(returnedType) &&
TranslationUtils.shouldBoxReturnValue((CallableDescriptor)context.getDeclarationDescriptor())) {
@@ -203,19 +207,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
JsExpression initializer = translateInitializerForProperty(expression, context);
KtExpression delegateExpression = expression.getDelegateExpression();
if (delegateExpression != null) {
SmartList<JsPropertyInitializer> propertyInitializers = new SmartList<JsPropertyInitializer>();
PropertyTranslatorKt.translateAccessors((VariableDescriptorWithAccessors) descriptor, propertyInitializers, context);
JsExpression initializerValue = PropertyTranslatorKt.translateDelegateOrInitializerExpression(context, expression);
assert initializerValue != null : "Initializer must be non-null for property with delegate";
JsPropertyInitializer delegateInitializer = new JsPropertyInitializer(
context.program().getStringLiteral(Namer.getDelegateName(descriptor.getName().asString())), initializerValue);
propertyInitializers.add(delegateInitializer);
initializer = new JsObjectLiteral(propertyInitializers, true);
}
JsName name = context.getNameForDescriptor(descriptor);
if (isVarCapturedInClosure(context.bindingContext(), descriptor)) {
if (delegateExpression != null) {
initializer = PropertyTranslatorKt.translateDelegateOrInitializerExpression(context, expression);
assert initializer != null : "Initializer must be non-null for property with delegate";
}
else if (isVarCapturedInClosure(context.bindingContext(), descriptor)) {
JsNameRef alias = getCapturedVarAccessor(name.makeRef());
initializer = JsAstUtils.wrapValue(alias, initializer == null ? JsLiteral.NULL : initializer);
}