JS: extension lambdas translated same as local lambdas (KT-13312 fixed)

This commit is contained in:
Anton Bannykh
2017-01-16 16:24:06 +03:00
parent 5021be351d
commit 07bb7ef4d3
32 changed files with 123 additions and 183 deletions
@@ -0,0 +1,23 @@
fun test1(f: (Int) -> Int) = f(1)
fun test2(f: Int.() -> Int) = 2.f()
class A(val foo: Int.() -> Int)
fun box(): String {
val a: (Int) -> Int = { it }
val b: Int.() -> Int = { this }
if (test1(a) != 1) return "fail 1a"
if (test1(b) != 1) return "fail 1b"
if (test2(a) != 2) return "fail 2a"
if (test2(b) != 2) return "fail 2b"
val x = A({ this })
if (x.foo(3) != 3) return "fail 3"
if (with(x) { foo(4) } != 4) return "fail 4"
if (with(x) { 5.foo() } != 5) return "fail 5"
return "OK"
}
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
fun test(cl: Int.() -> Int):Int = 11.cl()
class Foo {
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
fun box(): String {
val f = fun (s: String): String = s
val g = f as String.() -> String
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
class It(val id: String)
fun box(): String {
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
fun box(): String {
operator fun Int?.inc() = (this ?: 0) + 1
var counter: Int? = null
@@ -1,6 +1,3 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
// WITH_REFLECT
fun doStuff(fn: String.() -> String) = "ok".fn()
@@ -1,5 +1,3 @@
// Enable when using lambdas as extension lambdas is supported (KT-13312)
// IGNORE_BACKEND: JS
// FILE: 1.kt
package test
@@ -1,5 +1,3 @@
// Enable when using lambdas as extension lambdas is supported (KT-13312)
// IGNORE_BACKEND: JS
// FILE: 1.kt
package test
@@ -1,5 +1,3 @@
// Enable when using lambdas as extension lambdas is supported (KT-13312)
// IGNORE_BACKEND: JS
// FILE: 1.kt
package test
@@ -0,0 +1,13 @@
@kotlin.Metadata
public final class A {
private final @org.jetbrains.annotations.NotNull field foo: kotlin.jvm.functions.Function1
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
public final @org.jetbrains.annotations.NotNull method getFoo(): kotlin.jvm.functions.Function1
}
@kotlin.Metadata
public final class Kt13312Kt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public final static method test1(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): int
public final static method test2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): int
}
@@ -7142,6 +7142,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("kt13312.kt")
public void testKt13312() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt");
doTest(fileName);
}
@TestMetadata("kt1776.kt")
public void testKt1776() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt");
@@ -7142,6 +7142,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("kt13312.kt")
public void testKt13312() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt");
doTest(fileName);
}
@TestMetadata("kt1776.kt")
public void testKt1776() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt");
@@ -7142,6 +7142,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis
doTest(fileName);
}
@TestMetadata("kt13312.kt")
public void testKt13312() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt");
doTest(fileName);
}
@TestMetadata("kt1776.kt")
public void testKt1776() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt");
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
import org.jetbrains.kotlin.js.inline.util.IdentitySet
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.inline.util.rewriters.ContinueReplacingVisitor
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.*
@@ -288,8 +288,8 @@ internal class ExpressionDecomposer private constructor(
private fun Callable.process() {
qualifier = accept(qualifier)
val matchedIndices = arguments.indicesOfExtractable
if (!matchedIndices.hasNext()) return
var matchedIndices = arguments.indicesOfExtractable
if (matchedIndices.isEmpty()) return
if (qualifier in containsNodeWithSideEffect) {
val callee = qualifier as? JsNameRef
@@ -307,20 +307,27 @@ internal class ExpressionDecomposer private constructor(
else {
if (receiver != null && applyBindIfNecessary) {
val receiverTmp = receiver.extractToTemporary()
qualifier = JsAstUtils.invokeBind(receiverTmp, pureFqn(callee.ident, receiverTmp))
val fqn = JsNameRef(callee.ident, receiverTmp).apply {
synthetic = true
callee.name?.let { sideEffects = it.sideEffects }
}
qualifier = fqn.extractToTemporary()
qualifier = Namer.getFunctionCallRef(qualifier)
arguments.add(0, receiverTmp)
matchedIndices = matchedIndices.map { it + 1 }
}
else {
qualifier = qualifier.extractToTemporary()
}
qualifier = qualifier.extractToTemporary()
}
}
processByIndices(arguments, matchedIndices)
}
private fun processByIndices(elements: MutableList<JsExpression>, matchedIndices: Iterator<Int>) {
private fun processByIndices(elements: MutableList<JsExpression>, matchedIndices: List<Int>) {
var prev = 0
while (matchedIndices.hasNext()) {
val curr = matchedIndices.next()
for (curr in matchedIndices) {
for (i in prev..curr-1) {
val arg = elements[i]
if (arg !in containsNodeWithSideEffect) continue
@@ -374,8 +381,8 @@ internal class ExpressionDecomposer private constructor(
}
}
private val List<JsNode>.indicesOfExtractable: Iterator<Int>
get() = indices.filter { get(it) in containsExtractable }.iterator()
private val List<JsNode>.indicesOfExtractable: List<Int>
get() = indices.filter { get(it) in containsExtractable }
}
/**
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.js.inline.clean.removeDefaultInitializers
import org.jetbrains.kotlin.js.inline.context.InliningContext
import org.jetbrains.kotlin.js.inline.util.*
import org.jetbrains.kotlin.js.inline.util.rewriters.ReturnReplacingVisitor
import org.jetbrains.kotlin.js.translate.context.Namer
class FunctionInlineMutator
private constructor(
@@ -77,7 +78,7 @@ private constructor(
return when (qualifier) {
is JsInvocation -> qualifier
is JsNameRef -> {
val callee = if (qualifier.ident == "call") qualifier.qualifier else (qualifier.name?.staticRef as? JsExpression)
val callee = if (qualifier.ident == Namer.CALL_FUNCTION) qualifier.qualifier else (qualifier.name?.staticRef as? JsExpression)
callee?.let { getInnerCall(it) }
}
else -> null
@@ -171,7 +171,6 @@ private fun JsFunction.markInlineArguments(descriptor: CallableDescriptor) {
val params = descriptor.valueParameters
val paramsJs = parameters
val inlineFuns = IdentitySet<JsName>()
val inlineExtensionFuns = IdentitySet<JsName>()
val offset = if (descriptor.isExtension) 1 else 0
for ((i, param) in params.withIndex()) {
@@ -180,25 +179,21 @@ private fun JsFunction.markInlineArguments(descriptor: CallableDescriptor) {
val type = param.type
if (!type.isFunctionTypeOrSubtype) continue
val namesSet = if (type.isExtensionFunctionType) inlineExtensionFuns else inlineFuns
namesSet.add(paramsJs[i + offset].name)
inlineFuns.add(paramsJs[i + offset].name)
}
val visitor = object: JsVisitorWithContextImpl() {
override fun endVisit(x: JsInvocation, ctx: JsContext<*>) {
val qualifier: JsExpression?
val namesSet: Set<JsName>
if (isCallInvocation(x)) {
qualifier = (x.qualifier as? JsNameRef)?.qualifier
namesSet = inlineExtensionFuns
} else {
qualifier = x.qualifier
namesSet = inlineFuns
}
(qualifier as? JsNameRef)?.name?.let { name ->
if (name in namesSet) {
if (name in inlineFuns) {
x.inlineStrategy = InlineStrategy.IN_PLACE
}
}
@@ -18,14 +18,14 @@ package org.jetbrains.kotlin.js.inline.clean
import org.jetbrains.kotlin.js.backend.ast.JsFunction
class FunctionPostProcessor(root: JsFunction) {
class FunctionPostProcessor(val root: JsFunction) {
val optimizations = listOf(
//{ TemporaryAssignmentElimination(root.body).apply() },
{ RedundantLabelRemoval(root.body).apply() },
{ WhileConditionFolding(root.body).apply() },
{ DoWhileGuardElimination(root.body).apply() },
{ TemporaryVariableElimination(root).apply() },
{ RedundantBindElimination(root.body).apply() },
{ RedundantCallElimination(root.body).apply() },
{ IfStatementReduction(root.body).apply() },
{ DeadCodeElimination(root.body).apply() },
{ RedundantVariableDeclarationElimination(root.body).apply() },
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* 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.
@@ -20,11 +20,11 @@ import org.jetbrains.kotlin.js.backend.ast.JsBlock
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
import org.jetbrains.kotlin.js.backend.ast.RecursiveJsVisitor
import org.jetbrains.kotlin.js.inline.util.getCallerQualifier
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
// TODO: this optimization is a little unfair. It tries to recognize pattern like this a.bind(b)(args) and
// replace it with b.a(args). However, we can't be completely sure that `a` is a Function.
// Using JS-independent AST should solve the issue (as well as many other issues).
class RedundantBindElimination(private val root: JsBlock) {
// Replaces a.foo.call(a, b) with a.foo(b)
class RedundantCallElimination(private val root: JsBlock) {
private var changed = false
fun apply(): Boolean {
@@ -35,15 +35,18 @@ class RedundantBindElimination(private val root: JsBlock) {
}
private fun tryEliminate(invocation: JsInvocation) {
val qualifier = invocation.qualifier as? JsInvocation ?: return
if (!isCallInvocation(invocation)) return
val outerQualifier = qualifier.qualifier as? JsNameRef ?: return
val name = outerQualifier.ident
if (name != "bind") return
val qualifier = getCallerQualifier(invocation) as? JsNameRef ?: return
val qualifierReplacement = outerQualifier.qualifier ?: return
invocation.qualifier = qualifierReplacement
changed = true
val receiver = qualifier.qualifier as? JsNameRef ?: return
val firstArg = invocation.arguments.firstOrNull() as? JsNameRef ?: return
if (receiver.qualifier == null && receiver.name != null && firstArg.qualifier == null && receiver.name == firstArg.name) {
invocation.arguments.removeAt(0)
invocation.qualifier = qualifier
changed = true
}
}
})
+2 -2
View File
@@ -28,7 +28,7 @@ import kotlin.coroutines.intrinsics.*
public fun <R, T> (suspend R.() -> T).createCoroutine(
receiver: R,
completion: Continuation<T>
): Continuation<Unit> = this.asDynamic().call(receiver, completion, true).facade
): Continuation<Unit> = this.asDynamic()(receiver, completion, true).facade
/**
* Starts coroutine with receiver type [R] and result type [T].
@@ -40,7 +40,7 @@ public fun <R, T> (suspend R.() -> T).startCoroutine(
receiver: R,
completion: Continuation<T>
) {
this.asDynamic().call(receiver, completion)
this.asDynamic()(receiver, completion)
}
/**
@@ -45,20 +45,6 @@ Kotlin.getBoundCallableRefForExtensionFunction = function (receiver, extFun) {
};
};
Kotlin.getCallableRefForLocalExtensionFunction = function (extFun) {
return function () {
var args = [].slice.call(arguments);
var instance = args.shift();
return extFun.apply(instance, args);
};
};
Kotlin.getBoundCallableRefForLocalExtensionFunction = function (receiver, extFun) {
return function () {
return extFun.apply(receiver, arguments);
};
};
Kotlin.getCallableRefForConstructor = function (klass) {
return function () {
var obj = Object.create(klass.prototype);
@@ -39,25 +39,13 @@ public class CallableReferenceInlineTestsGenerated extends AbstractCallableRefer
@TestMetadata("classLevel.kt")
public void testClassLevel() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/classLevel.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("classLevel2.kt")
public void testClassLevel2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/classLevel2.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("constructor.kt")
@@ -111,13 +99,7 @@ public class CallableReferenceInlineTestsGenerated extends AbstractCallableRefer
@TestMetadata("topLevelExtension.kt")
public void testTopLevelExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("topLevelProperty.kt")
@@ -8127,6 +8127,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("kt13312.kt")
public void testKt13312() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt");
doTest(fileName);
}
@TestMetadata("kt1776.kt")
public void testKt1776() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt");
@@ -8160,13 +8166,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("kt3646.kt")
public void testKt3646() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt3646.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("kt3969.kt")
@@ -8966,13 +8966,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("castFunctionToExtension.kt")
public void testCastFunctionToExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/invoke/castFunctionToExtension.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("extensionInvokeOnExpr.kt")
@@ -9173,13 +9167,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("kt4989.kt")
public void testKt4989() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/kt4989.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("localExtensionOnNullableParameter.kt")
@@ -12657,13 +12645,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("kt4987.kt")
public void testKt4987() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/operatorConventions/kt4987.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("nestedMaps.kt")
@@ -16607,13 +16589,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("functionFromStdlib.kt")
public void testFunctionFromStdlib() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("functionReferenceErasedToKFunction.kt")
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.js.translate.callTranslator
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.PredefinedAnnotation
import org.jetbrains.kotlin.js.backend.ast.*
@@ -101,20 +100,12 @@ object DefaultFunctionCallCase : FunctionCallCase() {
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
val referenceToCall =
if (callableDescriptor.visibility == Visibilities.LOCAL) {
Namer.getFunctionCallRef(functionRef)
}
else {
functionRef
}
return JsInvocation(referenceToCall, argumentsInfo.argsWithReceiver(extensionReceiver!!))
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(extensionReceiver!!))
}
override fun FunctionCallInfo.bothReceivers(): JsExpression {
// TODO: think about crazy case: spreadOperator + native
val functionRef = JsNameRef(functionName, dispatchReceiver!!)
val functionRef = JsAstUtils.pureFqn(functionName, dispatchReceiver!!)
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(extensionReceiver!!))
}
}
@@ -170,14 +161,7 @@ object InvokeIntrinsic : FunctionCallCase() {
}
override fun FunctionCallInfo.dispatchReceiver(): JsExpression {
val receiver = resolvedCall.dispatchReceiver!!
val jsReceiver = if (receiver.type.isExtensionFunctionType) {
pureFqn(Namer.CALL_FUNCTION, dispatchReceiver)
}
else {
dispatchReceiver!!
}
return JsInvocation(jsReceiver, argumentsInfo.translateArguments)
return JsInvocation(dispatchReceiver!!, argumentsInfo.translateArguments)
}
/**
@@ -194,7 +178,7 @@ object InvokeIntrinsic : FunctionCallCase() {
* extLambda.call(obj, some, args)
*/
override fun FunctionCallInfo.bothReceivers(): JsExpression {
return JsInvocation(Namer.getFunctionCallRef(dispatchReceiver!!), argumentsInfo.argsWithReceiver(extensionReceiver!!))
return JsInvocation(dispatchReceiver!!, argumentsInfo.argsWithReceiver(extensionReceiver!!))
}
}
@@ -130,7 +130,7 @@ object DefaultVariableAccessCase : VariableAccessCase() {
}
override fun VariableAccessInfo.bothReceivers(): JsExpression {
val funRef = JsNameRef(context.getNameForDescriptor(getAccessDescriptorIfNeeded()), dispatchReceiver!!)
val funRef = JsAstUtils.pureFqn(context.getNameForDescriptor(getAccessDescriptorIfNeeded()), dispatchReceiver!!)
return JsInvocation(funRef, extensionReceiver!!, *additionalArguments.toTypedArray())
}
}
@@ -211,10 +211,6 @@ public final class Namer {
@NotNull
private final JsName boundCallableRefForExtensionFunctionName;
@NotNull
private final JsName callableRefForLocalExtensionFunctionName;
@NotNull
private final JsName boundCallableRefForLocalExtensionFunctionName;
@NotNull
private final JsName callableRefForConstructorName;
@NotNull
private final JsName callableRefForTopLevelProperty;
@@ -244,8 +240,6 @@ public final class Namer {
boundCallableRefForMemberFunctionName = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME);
callableRefForExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME);
boundCallableRefForExtensionFunctionName = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME);
callableRefForLocalExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME);
boundCallableRefForLocalExtensionFunctionName = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME);
callableRefForConstructorName = kotlinScope.declareName(CALLABLE_REF_FOR_CONSTRUCTOR_NAME);
callableRefForTopLevelProperty = kotlinScope.declareName(CALLABLE_REF_FOR_TOP_LEVEL_PROPERTY);
callableRefForMemberProperty = kotlinScope.declareName(CALLABLE_REF_FOR_MEMBER_PROPERTY);
@@ -287,16 +281,6 @@ public final class Namer {
return kotlin(boundCallableRefForExtensionFunctionName);
}
@NotNull
public JsExpression callableRefForLocalExtensionFunctionReference() {
return kotlin(callableRefForLocalExtensionFunctionName);
}
@NotNull
public JsExpression boundCallableRefForLocalExtensionFunctionReference() {
return kotlin(boundCallableRefForLocalExtensionFunctionName);
}
@NotNull
public JsExpression callableRefForConstructorReference() {
return kotlin(callableRefForConstructorName);
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.expression
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.backend.ast.JsFunction
import org.jetbrains.kotlin.js.backend.ast.JsParameter
@@ -77,7 +76,7 @@ private fun FunctionDescriptor.getCorrectTypeParameters() =
private val FunctionDescriptor.requiresExtensionReceiverParameter
get() = DescriptorUtils.isExtension(this) && visibility != Visibilities.LOCAL
get() = DescriptorUtils.isExtension(this)
fun TranslationContext.translateFunction(declaration: KtDeclarationWithBody, function: JsFunction) {
val descriptor = BindingUtils.getFunctionDescriptor(bindingContext(), declaration)
@@ -223,15 +223,7 @@ object CallableReferenceTranslator {
receiver: JsExpression?
): JsExpression {
val jsFunctionRef = ReferenceTranslator.translateAsValueReference(descriptor, context)
if (descriptor.visibility == Visibilities.LOCAL) {
if (receiver == null) {
return JsInvocation(context.namer().callableRefForLocalExtensionFunctionReference(), jsFunctionRef)
}
else {
return JsInvocation(context.namer().boundCallableRefForLocalExtensionFunctionReference(), receiver, jsFunctionRef)
}
}
else if (AnnotationsUtils.isNativeObject(descriptor)) {
if (AnnotationsUtils.isNativeObject(descriptor)) {
return translateForMemberFunction(descriptor, context, receiver)
}
else {
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.js.translate.reference;
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation;
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.kotlin.js.backend.ast.JsNameRef;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation;
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.kotlin.js.backend.ast.JsNameRef;
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
@@ -18,11 +18,9 @@
package org.jetbrains.kotlin.js.translate.utils
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
import org.jetbrains.kotlin.js.backend.ast.metadata.inlineStrategy
import org.jetbrains.kotlin.js.backend.ast.metadata.psiElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.*
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
@@ -3,5 +3,5 @@ function A(v) {
}
function nativeBox(b) {
return b.bar_asnz92$(new A("foo"), function(i, s) { return "" + this.v + s + i })
return b.bar_asnz92$(new A("foo"), function($reciever, i, s) { return "" + $reciever.v + s + i })
}
@@ -3,5 +3,5 @@ function A(v) {
}
function bar(a, extLambda) {
return extLambda.call(a, 4, "boo")
return extLambda(a, 4, "boo")
}
@@ -1,3 +1,3 @@
function bar(a, extLambda) {
return extLambda.call(a, 4, "boo")
return extLambda(a, 4, "boo")
}