JS backend: fix native spread call

This commit is contained in:
Erokhin Stanislav
2014-01-28 21:52:58 +04:00
parent 4bffff43aa
commit 42437eb755
5 changed files with 46 additions and 10 deletions
@@ -37,6 +37,7 @@ public final class Namer {
public static final String OUTER_CLASS_NAME = "$outer";
private static final String CALL_FUNCTION = "call";
private static final String APPLY_FUNCTION = "apply";
private static final String CLASS_OBJECT_NAME = "createClass";
private static final String TRAIT_OBJECT_NAME = "createTrait";
private static final String OBJECT_OBJECT_NAME = "createObject";
@@ -139,6 +140,10 @@ public final class Namer {
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
return new JsNameRef(CALL_FUNCTION, functionExpression);
}
@NotNull
public static JsNameRef getFunctionApplyRef(@NotNull JsExpression functionExpression) {
return new JsNameRef(APPLY_FUNCTION, functionExpression);
}
@NotNull
public static Namer newInstance(@NotNull JsScope rootScope) {
@@ -505,7 +505,7 @@ public final class StaticContext {
return null;
}
};
//TODO: hack!
//TODO: hack! it seems like needed, only for Inheritance from native class
Rule<Boolean> nativeObjectsHaveNoQualifiers = new Rule<Boolean>() {
@Override
public Boolean apply(@NotNull DeclarationDescriptor descriptor) {
@@ -33,6 +33,7 @@ import org.jetbrains.k2js.translate.utils.TranslationUtils
import org.jetbrains.k2js.translate.general.Translation
import org.jetbrains.k2js.translate.utils.PsiUtils
import com.google.dart.compiler.backend.js.ast.JsLiteral
import com.google.dart.compiler.backend.js.ast.JsName
public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpression>) : List<JsExpression> {
if (arguments.isEmpty())
@@ -53,35 +54,41 @@ class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) {
return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
}
// TODO: refactor after fix ArgumentsInfo - duplicate code
private fun nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, functionName: JsName): JsExpression {
val cachedReceiver = argumentsInfo.getCachedReceiver()!!
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName, cachedReceiver.assignmentExpression()))
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
}
override fun FunctionCallInfo.thisObject(): JsExpression {
if (isNative() && hasSpreadOperator()) {
val cachedReceiver = argumentsInfo.getCachedReceiver()!!
val functionCallRef = Namer.getFunctionCallRef(JsNameRef(functionName, cachedReceiver.assignmentExpression()))
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName)
}
val functionRef = JsNameRef(functionName, thisObject!!)
return JsInvocation(functionRef, argumentsInfo.getTranslateArguments())
}
// TODO: refactor after fix ArgumentsInfo - duplicate code
override fun FunctionCallInfo.receiverArgument(): JsExpression {
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
if (isNative() && hasSpreadOperator()) {
val functionCallRef = Namer.getFunctionCallRef(JsNameRef(functionName, qualifierForFunction))
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName)
}
if (isNative()) {
return JsInvocation(JsNameRef(functionName, receiverObject), argumentsInfo.getTranslateArguments())
}
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
val functionCall = JsNameRef(functionName, qualifierForFunction) // TODO: remake to call
return JsInvocation(functionCall, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
}
override fun FunctionCallInfo.noReceivers(): JsExpression {
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
if (isNative() && hasSpreadOperator()) {
val functionCallRef = Namer.getFunctionCallRef(JsNameRef(functionName, qualifierForFunction))
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName))
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
}
if (isNative()) {
return JsInvocation(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
}
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
val functionCall = JsNameRef(functionName, qualifierForFunction)
return JsInvocation(functionCall, argumentsInfo.getTranslateArguments())
}
@@ -121,6 +128,9 @@ class InvokeIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) {
class ConstructorCallCase(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) {
override fun FunctionCallInfo.noReceivers(): JsExpression {
if (isNative()) {
return JsNew(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
}
return JsNew(context.getQualifiedReference(callableDescriptor), argumentsInfo.getTranslateArguments())
}
}
@@ -14,6 +14,12 @@ fun count(vararg a : Int) = paramCount(*a)
// test spread operator
fun anotherCount(vararg a : Int) = anotherParamCount(*a)
native
fun test3(bar:Bar, dummy: Int, vararg args: Int): Boolean = js.noImpl
native
fun Bar.test2(order: Int, dummy: Int, vararg args: Int): Boolean = js.noImpl
native
class Bar(val size: Int, order: Int = 0) {
fun test(order: Int, dummy: Int, vararg args: Int): Boolean = js.noImpl
@@ -32,6 +38,10 @@ fun spreadInMethodCall(size: Int, vararg args: Int) = Bar(size).test(0, 1, *args
fun spreadInObjectMethodCall(size: Int, vararg args: Int) = obj.test(size, *args)
fun spreadInMethodCallWithReceiver(size: Int, vararg args: Int) = Bar(size).test2(0, 1, *args)
fun spreadInPackageMethodCall(size: Int, vararg args: Int) = test3(Bar(size), 1, *args)
native
fun testNativeVarargWithFunLit(vararg args: Int, f: (a: IntArray) -> Boolean): Boolean = js.noImpl
@@ -79,6 +89,12 @@ fun box(): String {
if (!(spreadInObjectMethodCall(2, 1, 2)))
return "failed when call method of object using spread operator"
if (!spreadInMethodCallWithReceiver(2, 1, 2))
return "failed when call method using spread operator with receiver"
if (!spreadInPackageMethodCall(2, 1, 2))
return "failed when call package method using spread operator"
if (!(testNativeVarargWithFunLit(1, 2, 3) { args -> args.size == 3 }))
return "failed when call native function with vararg and fun literal"
@@ -41,6 +41,11 @@ Bar.prototype.test = function (order, dummy /*, args */) {
Bar.checkOrder(order);
return dummy === 1 && (arguments.length - 2) === this.size;
};
Bar.prototype.test2 = Bar.prototype.test;
function test3(bar, dummy /*, args */) {
return dummy === 1 && (arguments.length - 2) === bar.size;
}
var obj = {
test : function (size /*, args */) {