JS: generate aliases for intrinsics.

This makes generated code more friendly to UglifyJS.
For example, uglified circlet loses 15 kb.
This commit is contained in:
Alexey Andreev
2017-09-15 17:15:15 +03:00
parent 80ac8897ff
commit e6ab3dc936
17 changed files with 135 additions and 137 deletions
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.js.resolve.JsPlatform;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.ArrayFIF;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
@@ -87,16 +86,16 @@ public final class Namer {
private static final String RECEIVER_PARAMETER_NAME = "$receiver";
public static final String ANOTHER_THIS_PARAMETER_NAME = "$this";
private static final String THROW_NPE_FUN_NAME = "throwNPE";
private static final String THROW_CLASS_CAST_EXCEPTION_FUN_NAME = "throwCCE";
private static final String THROW_ILLEGAL_STATE_EXCEPTION_FUN_NAME = "throwISE";
private static final String THROW_UNINITIALIZED_PROPERTY_ACCESS_EXCEPTION = "throwUPAE";
public static final String THROW_NPE_FUN_NAME = "throwNPE";
public static final String THROW_CLASS_CAST_EXCEPTION_FUN_NAME = "throwCCE";
public static final String THROW_ILLEGAL_STATE_EXCEPTION_FUN_NAME = "throwISE";
public static final String THROW_UNINITIALIZED_PROPERTY_ACCESS_EXCEPTION = "throwUPAE";
private static final String PROTOTYPE_NAME = "prototype";
private static final String CAPTURED_VAR_FIELD = "v";
public static final JsNameRef IS_ARRAY_FUN_REF = new JsNameRef("isArray", "Array");
public static final String DEFINE_INLINE_FUNCTION = "defineInlineFunction";
public static final String WRAP_FUNCTION = "wrapFunction";
private static final String WRAP_FUNCTION = "wrapFunction";
public static final String DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX = "$default";
private static final JsNameRef JS_OBJECT = new JsNameRef("Object");
@@ -221,26 +220,6 @@ public final class Namer {
return suggested.getNames().get(0);
}
@NotNull
public static JsExpression throwNPEFunctionRef() {
return new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject());
}
@NotNull
public static JsExpression throwClassCastExceptionFunRef() {
return new JsNameRef(THROW_CLASS_CAST_EXCEPTION_FUN_NAME, kotlinObject());
}
@NotNull
public static JsExpression throwIllegalStateExceptionFunRef() {
return new JsNameRef(THROW_ILLEGAL_STATE_EXCEPTION_FUN_NAME, kotlinObject());
}
@NotNull
public static JsExpression throwUninitializedPropertyAccessExceptionFunRef() {
return new JsNameRef(THROW_UNINITIALIZED_PROPERTY_ACCESS_EXCEPTION, kotlinObject());
}
@NotNull
public static JsNameRef kotlin(@NotNull JsName name) {
return pureFqn(name, kotlinObject());
@@ -326,11 +305,6 @@ public final class Namer {
return result;
}
@NotNull
static String generatePackageName(@NotNull FqName packageFqName) {
return packageFqName.isRoot() ? getRootPackageName() : packageFqName.shortName().asString();
}
@NotNull
public static JsExpression getUndefinedExpression() {
return new JsPrefixOperation(JsUnaryOperator.VOID, new JsIntLiteral(0));
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.js.translate.context;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.LinkedHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -85,8 +83,6 @@ public final class StaticContext {
@NotNull
private final Generator<JsName> innerNames = new InnerNameGenerator();
@NotNull
private final Map<FqName, JsName> packageNames = Maps.newHashMap();
@NotNull
private final Generator<JsScope> scopes = new ScopeGenerator();
@NotNull
private final Generator<JsName> objectInstanceNames = new ObjectInstanceNameGenerator();
@@ -123,9 +119,6 @@ public final class StaticContext {
@NotNull
private final Map<JsImportedModuleKey, JsImportedModule> importedModules = new LinkedHashMap<>();
@NotNull
private final JsScope rootPackageScope;
@NotNull
private final DeclarationExporter exporter = new DeclarationExporter(this);
@@ -142,6 +135,8 @@ public final class StaticContext {
private final Map<SpecialFunction, JsName> specialFunctions = new EnumMap<>(SpecialFunction.class);
private final Map<String, JsName> intrinsicNames = new HashMap<>();
public StaticContext(
@NotNull BindingTrace bindingTrace,
@NotNull JsConfig config,
@@ -153,11 +148,10 @@ public final class StaticContext {
this.bindingTrace = bindingTrace;
this.namer = Namer.newInstance(program.getRootScope());
this.intrinsics = new Intrinsics(this);
this.intrinsics = new Intrinsics();
this.rootScope = fragment.getScope();
this.config = config;
this.currentModule = moduleDescriptor;
rootPackageScope = new JsObjectScope(rootScope, "<root package>");
JsName kotlinName = rootScope.declareName(Namer.KOTLIN_NAME);
createImportedModule(new JsImportedModuleKey(Namer.KOTLIN_LOWER_NAME, null), Namer.KOTLIN_LOWER_NAME, kotlinName, null);
@@ -329,12 +323,6 @@ public final class StaticContext {
return expression;
}
@NotNull
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
JsName packageName = getNameForPackage(packageFqName);
return pureFqn(packageName, packageFqName.isRoot() ? null : getQualifierForParentPackage(packageFqName.parent()));
}
@NotNull
public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.isAny((ClassDescriptor) descriptor)) {
@@ -438,47 +426,13 @@ public final class StaticContext {
return names;
}
@NotNull
private JsName getNameForPackage(@NotNull FqName packageFqName) {
return ContainerUtil.getOrCreate(packageNames, packageFqName, (Factory<JsName>) () -> {
String name = Namer.generatePackageName(packageFqName);
return rootPackageScope.declareName(name);
});
}
@NotNull
private JsNameRef getQualifierForParentPackage(@NotNull FqName packageFqName) {
JsNameRef result = null;
JsNameRef qualifier = null;
FqName fqName = packageFqName;
while (true) {
JsNameRef ref = pureFqn(getNameForPackage(fqName), null);
if (qualifier == null) {
result = ref;
}
else {
qualifier.setQualifier(ref);
}
qualifier = ref;
if (fqName.isRoot()) break;
fqName = fqName.parent();
}
return result;
}
@NotNull
public JsConfig getConfig() {
return config;
}
@NotNull
public JsName importDeclaration(@NotNull String suggestedName, @NotNull String tag, @NotNull JsExpression declaration) {
private JsName importDeclaration(@NotNull String suggestedName, @NotNull String tag, @NotNull JsExpression declaration) {
JsName result = importDeclarationImpl(suggestedName, tag, declaration);
fragment.getNameBindings().add(new JsNameBinding(tag, result));
return result;
@@ -871,4 +825,13 @@ public final class StaticContext {
return name;
});
}
@NotNull
public JsExpression getReferenceToIntrinsic(@NotNull String name) {
JsName resultName = intrinsicNames.computeIfAbsent(name, k ->
importDeclaration(NameSuggestion.sanitizeName(name), "intrinsic:" + name, TranslationUtils.getIntrinsicFqn(name)));
return pureFqn(resultName, null);
}
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction;
import org.jetbrains.kotlin.js.config.JsConfig;
import org.jetbrains.kotlin.js.naming.NameSuggestion;
import org.jetbrains.kotlin.js.naming.SuggestedName;
import org.jetbrains.kotlin.js.translate.declaration.ClassModelGenerator;
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
@@ -317,6 +318,27 @@ public class TranslationContext {
return name;
}
@NotNull
public JsExpression getReferenceToIntrinsic(@NotNull String intrinsicName) {
JsExpression result;
if (inlineFunctionContext == null || !isPublicInlineFunction()) {
result = staticContext.getReferenceToIntrinsic(intrinsicName);
}
else {
String tag = "intrinsic:" + intrinsicName;
result = pureFqn(inlineFunctionContext.getImports().computeIfAbsent(tag, t -> {
JsExpression imported = TranslationUtils.getIntrinsicFqn(intrinsicName);
JsName name = JsScope.declareTemporaryName(NameSuggestion.sanitizeName(intrinsicName));
MetadataProperties.setImported(name, true);
inlineFunctionContext.getImportBlock().getStatements().add(JsAstUtils.newVar(name, imported));
return name;
}), null);
}
return result;
}
@NotNull
public JsName getNameForObjectInstance(@NotNull ClassDescriptor descriptor) {
return staticContext.getNameForObjectInstance(descriptor);
@@ -208,13 +208,14 @@ class ClassTranslator private constructor(
private fun createMetadataRef() = JsNameRef(Namer.METADATA, context().getInnerReference(descriptor))
private fun addMetadataType() {
val kotlinType = JsNameRef(Namer.CLASS_KIND_ENUM, Namer.KOTLIN_NAME)
val typeRef = when {
DescriptorUtils.isInterface(descriptor) -> JsNameRef(Namer.CLASS_KIND_INTERFACE, kotlinType)
DescriptorUtils.isObject(descriptor) -> JsNameRef(Namer.CLASS_KIND_OBJECT, kotlinType)
else -> JsNameRef(Namer.CLASS_KIND_CLASS, kotlinType)
}
val kindBuilder = StringBuilder(Namer.CLASS_KIND_ENUM + ".")
kindBuilder.append(when {
DescriptorUtils.isInterface(descriptor) -> Namer.CLASS_KIND_INTERFACE
DescriptorUtils.isObject(descriptor) -> Namer.CLASS_KIND_OBJECT
else -> Namer.CLASS_KIND_CLASS
})
val typeRef = context().getReferenceToIntrinsic(kindBuilder.toString())
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_CLASS_KIND), typeRef)
val simpleName = descriptor.name
@@ -65,7 +65,8 @@ class EnumTranslator(
val message = JsBinaryOperation(JsBinaryOperator.ADD,
JsStringLiteral("No enum constant ${descriptor.fqNameSafe}."),
nameParam.makeRef())
val throwStatement = JsExpressionStatement(JsInvocation(Namer.throwIllegalStateExceptionFunRef(), message).source(psi))
val throwFunction = context().getReferenceToIntrinsic(Namer.THROW_ILLEGAL_STATE_EXCEPTION_FUN_NAME)
val throwStatement = JsExpressionStatement(JsInvocation(throwFunction, message).source(psi))
if (clauses.isNotEmpty()) {
val defaultCase = JsDefault().apply {
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.js.translate.expression.translateFunction
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
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.js.translate.utils.TranslationUtils.*
@@ -95,8 +94,9 @@ class DefaultPropertyTranslator(
assert(descriptor is PropertyDescriptor) { "Property descriptor expected: $descriptor" }
val result = 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(Namer.throwUninitializedPropertyAccessExceptionFunRef(),
JsReturn(JsInvocation(throwFunction,
JsStringLiteral(getterDescriptor.correspondingProperty.name.asString()))))
}
function.body.statements += JsReturn(result).apply { source = descriptor.source.getPsi() }
@@ -195,7 +195,7 @@ fun TranslationContext.contextWithPropertyMetadataCreationIntrinsified(
(delegatedCall.valueArgumentsByIndex!![1] as ExpressionValueArgument).valueArgument!!.getArgumentExpression()
return innerContextWithAliasesForExpressions(mapOf(
hostExpression to host,
fakeArgumentExpression to JsNew(pureFqn("PropertyMetadata", Namer.kotlinObject()), listOf(propertyNameLiteral))
fakeArgumentExpression to JsNew(getReferenceToIntrinsic("PropertyMetadata"), listOf(propertyNameLiteral))
))
}
@@ -263,7 +263,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
return new JsInvocation(context.namer().kotlin(GET_KCLASS_FROM_EXPRESSION), receiver);
}
return new JsInvocation(context.namer().kotlin(GET_KCLASS), UtilsKt.getReferenceToJsClass(lhs.getType(), context));
return new JsInvocation(context.getReferenceToIntrinsic(GET_KCLASS), UtilsKt.getReferenceToJsClass(lhs.getType(), context));
}
@@ -94,7 +94,7 @@ public final class PatternTranslator extends AbstractTranslator {
onFail = new JsNullLiteral();
}
else {
JsExpression throwCCEFunRef = Namer.throwClassCastExceptionFunRef();
JsExpression throwCCEFunRef = context().getReferenceToIntrinsic(Namer.THROW_CLASS_CAST_EXCEPTION_FUN_NAME);
onFail = new JsInvocation(throwCCEFunRef);
}
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.intrinsic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.js.translate.context.StaticContext;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.FunctionIntrinsics;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
@@ -37,8 +36,8 @@ public final class Intrinsics {
private final BinaryOperationIntrinsics binaryOperationIntrinsics = new BinaryOperationIntrinsics();
private final ObjectIntrinsics objectIntrinsics;
public Intrinsics(@NotNull StaticContext staticContext) {
objectIntrinsics = new ObjectIntrinsics(staticContext);
public Intrinsics() {
objectIntrinsics = new ObjectIntrinsics();
}
@NotNull
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
open class KotlinAliasedFunctionIntrinsic(private val functionName: String) : FunctionIntrinsicWithReceiverComputed() {
override fun apply(
receiver: JsExpression?,
arguments: List<JsExpression>,
context: TranslationContext
): JsExpression {
val function = context.getReferenceToIntrinsic(functionName)
return JsInvocation(function, if (receiver == null) arguments else TranslationUtils.generateInvocationArguments(receiver, arguments))
}
}
@@ -47,7 +47,7 @@ import static org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern;
public final class TopLevelFIF extends CompositeFIF {
public static final DescriptorPredicate EQUALS_IN_ANY = pattern("kotlin", "Any", "equals");
@NotNull
private static final KotlinFunctionIntrinsic KOTLIN_ANY_EQUALS = new KotlinFunctionIntrinsic("equals") {
private static final KotlinAliasedFunctionIntrinsic KOTLIN_ANY_EQUALS = new KotlinAliasedFunctionIntrinsic("equals") {
@NotNull
@Override
public JsExpression apply(
@@ -65,7 +65,7 @@ public final class TopLevelFIF extends CompositeFIF {
};
@NotNull
public static final KotlinFunctionIntrinsic KOTLIN_EQUALS = new KotlinFunctionIntrinsic("equals");
public static final KotlinAliasedFunctionIntrinsic KOTLIN_EQUALS = new KotlinAliasedFunctionIntrinsic("equals");
@NotNull
private static final KotlinFunctionIntrinsic KOTLIN_SUBSEQUENCE = new KotlinFunctionIntrinsic("subSequence");
@@ -73,7 +73,7 @@ public final class TopLevelFIF extends CompositeFIF {
@NotNull
private static final DescriptorPredicate HASH_CODE_IN_ANY = pattern("kotlin", "Any", "hashCode");
@NotNull
private static final KotlinFunctionIntrinsic KOTLIN_HASH_CODE = new KotlinFunctionIntrinsic("hashCode");
private static final KotlinAliasedFunctionIntrinsic KOTLIN_HASH_CODE = new KotlinAliasedFunctionIntrinsic("hashCode");
@NotNull
private static final FunctionIntrinsic RETURN_RECEIVER_INTRINSIC = new FunctionIntrinsicWithReceiverComputed() {
@@ -164,7 +164,7 @@ public final class TopLevelFIF extends CompositeFIF {
@NotNull
public static final KotlinFunctionIntrinsic TO_STRING = new KotlinFunctionIntrinsic("toString");
public static final KotlinAliasedFunctionIntrinsic TO_STRING = new KotlinAliasedFunctionIntrinsic("toString");
@NotNull
private static final FunctionIntrinsic CHAR_TO_STRING = new FunctionIntrinsicWithReceiverComputed() {
@@ -20,25 +20,16 @@ import org.jetbrains.kotlin.builtins.CompanionObjectMapping
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.backend.ast.JsName
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.StaticContext
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
class DefaultClassObjectIntrinsic(val staticContext: StaticContext, val tag: String, val fqName: FqName): ObjectIntrinsic {
private val innerName: JsName by lazy {
val declaration = JsAstUtils.replaceRootReference(staticContext.getQualifiedReference(fqName), Namer.kotlinObject())
staticContext.importDeclaration(fqName.shortName().asString(), tag, declaration)
}
override fun apply(context: TranslationContext) = JsAstUtils.pureFqn(innerName, null)
class DefaultClassObjectIntrinsic( val fqName: FqName): ObjectIntrinsic {
override fun apply(context: TranslationContext) = context.getReferenceToIntrinsic(fqName.asString())
}
class ObjectIntrinsics(private val staticContext: StaticContext) {
class ObjectIntrinsics {
private val cache = mutableMapOf<ClassDescriptor, ObjectIntrinsic>()
fun getIntrinsic(classDescriptor: ClassDescriptor) = cache.getOrPut(classDescriptor) { createIntrinsic(classDescriptor) }
@@ -53,8 +44,7 @@ class ObjectIntrinsics(private val staticContext: StaticContext) {
val containingDeclaration = classDescriptor.containingDeclaration
val name = Name.identifier(containingDeclaration.name.asString() + "CompanionObject")
return DefaultClassObjectIntrinsic(
staticContext, "intrinsic:kotlin.js.internal.${name.asString()}", FqName("kotlin.js.internal").child(name))
return DefaultClassObjectIntrinsic(FqName("kotlin.js.internal").child(name))
}
}
@@ -135,7 +135,7 @@ object CallableReferenceTranslator {
function.body.statements += JsReturn(TranslationUtils.coerce(context, invocation, context.currentModule.builtIns.anyType))
val rawCallableRef = bindIfNecessary(function, receiver)
return wrapFunctionCallableRef(expression.callableReference.getReferencedName(), rawCallableRef)
return context.wrapFunctionCallableRef(expression.callableReference.getReferencedName(), rawCallableRef)
}
private fun translateForProperty(
@@ -168,7 +168,7 @@ object CallableReferenceTranslator {
null
}
return wrapPropertyCallableRef(receiver, descriptor, expression.callableReference.getReferencedName(), getter, setter)
return context.wrapPropertyCallableRef(receiver, descriptor, expression.callableReference.getReferencedName(), getter, setter)
}
private fun isSetterVisible(descriptor: PropertyDescriptor, context: TranslationContext): Boolean {
@@ -225,7 +225,7 @@ object CallableReferenceTranslator {
}
}
private fun wrapPropertyCallableRef(
private fun TranslationContext.wrapPropertyCallableRef(
receiver: JsExpression?,
descriptor: PropertyDescriptor,
name: String,
@@ -238,7 +238,7 @@ object CallableReferenceTranslator {
}
val nameLiteral = JsStringLiteral(name)
val argCountLiteral = JsIntLiteral(argCount)
val invokeFun = JsNameRef(Namer.PROPERTY_CALLABLE_REF, Namer.kotlinObject())
val invokeFun = getReferenceToIntrinsic(Namer.PROPERTY_CALLABLE_REF)
val invocation = JsInvocation(invokeFun, nameLiteral, argCountLiteral, getter)
if (setter != null) {
invocation.arguments += setter
@@ -246,13 +246,12 @@ object CallableReferenceTranslator {
return invocation
}
private fun wrapFunctionCallableRef(
private fun TranslationContext.wrapFunctionCallableRef(
name: String,
function: JsExpression
): JsExpression {
val nameLiteral = JsStringLiteral(name)
val invokeName = Namer.FUNCTION_CALLABLE_REF
val invokeFun = JsNameRef(invokeName, Namer.kotlinObject())
val invokeFun = getReferenceToIntrinsic(Namer.FUNCTION_CALLABLE_REF)
invokeFun.sideEffects = SideEffectKind.PURE
val invocation = JsInvocation(invokeFun, nameLiteral, function)
invocation.isCallableReference = true
@@ -83,8 +83,8 @@ public class VariableAccessTranslator extends AbstractTranslator implements Acce
else if (original instanceof LocalVariableDescriptor) {
LocalVariableDescriptor originalLocal = (LocalVariableDescriptor) original;
if (originalLocal.isLateInit()) {
JsInvocation throwInvocation = new JsInvocation(Namer.throwUninitializedPropertyAccessExceptionFunRef(),
new JsStringLiteral(originalLocal.getName().asString()));
JsExpression throwFunction = context().getReferenceToIntrinsic(Namer.THROW_UNINITIALIZED_PROPERTY_ACCESS_EXCEPTION);
JsInvocation throwInvocation = new JsInvocation(throwFunction, new JsStringLiteral(originalLocal.getName().asString()));
return new JsConditional(new JsBinaryOperation(JsBinaryOperator.EQ, e, new JsNullLiteral()), throwInvocation, e);
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.js.translate.utils;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -226,17 +227,6 @@ public final class TranslationUtils {
return Translation.translateAsExpression(baseExpression, context);
}
@NotNull
public static JsExpression translateLeftExpression(
@NotNull TranslationContext context,
@NotNull KtBinaryExpression expression,
@NotNull JsBlock block
) {
KtExpression left = expression.getLeft();
assert left != null : "Binary expression should have a left expression: " + expression.getText();
return Translation.translateAsExpression(left, context, block);
}
@NotNull
public static JsExpression translateRightExpression(
@NotNull TranslationContext context,
@@ -305,7 +295,7 @@ public final class TranslationUtils {
@NotNull
public static JsConditional sure(@NotNull JsExpression expression, @NotNull TranslationContext context) {
JsInvocation throwNPE = new JsInvocation(Namer.throwNPEFunctionRef());
JsInvocation throwNPE = new JsInvocation(context.getReferenceToIntrinsic(Namer.THROW_NPE_FUN_NAME));
JsConditional ensureNotNull = notNullConditional(expression, throwNPE, context);
JsExpression thenExpression = ensureNotNull.getThenExpression();
@@ -548,4 +538,13 @@ public final class TranslationUtils {
public static String getTagForSpecialFunction(@NotNull SpecialFunction specialFunction) {
return "special:" + specialFunction.name();
}
@NotNull
public static JsExpression getIntrinsicFqn(@NotNull String name) {
JsExpression fqn = pureFqn(Namer.KOTLIN_NAME, null);
for (String part : StringUtil.split(name, ".")) {
fqn = pureFqn(part, fqn);
}
return fqn;
}
}
@@ -1,5 +1,5 @@
// EXPECTED_REACHABLE_NODES: 995
// HAS_NO_CAPTURED_VARS: function=A_init except=Kotlin;A
// HAS_NO_CAPTURED_VARS: function=A_init except=Kotlin;A;equals
class A() {
var y: String? = null
+1 -1
View File
@@ -21,4 +21,4 @@ fun bar(x: Int) {
println("%")
}
// LINES: 1 1 1 1 1 1 1 17 2 2 3 3 4 7 7 9 9 10 10 11 14 14 16 16 1 1 22 20 20 20 20 2 2 3 3 4 3 7 7 9 9 10 10 11 10 14 14 16 16 * 20 21 21
// LINES: 1 1 1 1 1 1 1 1 1 17 2 2 3 3 4 7 7 9 9 10 10 11 14 14 16 16 1 1 1 1 22 20 20 20 20 2 2 3 3 4 3 7 7 9 9 10 10 11 10 14 14 16 16 * 20 21 21