提交 a72ea641 编写于 作者: A Alexey Andreev

JS: fix translation of lambdas in public inline functions; fix AMD emulation for Ant test

上级 6791ed7b
......@@ -4,10 +4,16 @@
function define(name, dependencies, body) {
var resolvedDependencies = [];
var currentModule = {};
modules[name] = currentModule;
for (var i = 0; i < dependencies.length; ++i) {
resolvedDependencies[i] = modules[dependencies[i]];
var dependencyName = dependencies[i];
resolvedDependencies[i] = dependencyName === 'exports' ? currentModule : modules[dependencyName];
}
currentModule = body.apply(body, resolvedDependencies);
if (currentModule) {
modules[name] = currentModule;
}
modules[name] = body.apply(body, resolvedDependencies);
}
define.amd = {};
......
......@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.naming
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject
import org.jetbrains.kotlin.resolve.DescriptorUtils
......@@ -105,8 +104,29 @@ class NameSuggestion {
// Local functions and variables are always private with their own names as suggested names
is CallableDescriptor ->
if (DescriptorUtils.isDescriptorWithLocalVisibility(descriptor)) {
val name = getNameForAnnotatedObject(descriptor) ?: getSuggestedName(descriptor)
return SuggestedName(listOf(name), false, descriptor, descriptor.containingDeclaration)
val ownName = getNameForAnnotatedObject(descriptor) ?: getSuggestedName(descriptor)
var name = ownName
var scope = descriptor.containingDeclaration
// Local functions always lifted to the closest class or package when they are contained inside public inline function
if (descriptor is FunctionDescriptor) {
var container = descriptor.containingDeclaration
var liftedName = ownName
var hasInline = false
while (container is FunctionDescriptor) {
if (container.isInline && container.visibility.isPublicAPI) {
hasInline = true
}
liftedName = getSuggestedName(container) + "$" + liftedName
container = container.containingDeclaration
}
if (hasInline) {
scope = container
name = liftedName
}
}
return SuggestedName(listOf(name), false, descriptor, scope)
}
}
......
......@@ -16,15 +16,9 @@
package org.jetbrains.kotlin.js.inline.util
import com.google.dart.compiler.backend.js.ast.JsInvocation
import com.google.dart.compiler.backend.js.ast.JsName
import com.google.dart.compiler.backend.js.ast.JsExpression
import com.google.dart.compiler.backend.js.ast.JsNameRef
import com.google.dart.compiler.backend.js.ast.JsFunction
import org.jetbrains.kotlin.js.translate.context.Namer
import com.google.dart.compiler.backend.js.ast.HasName
import com.google.dart.compiler.backend.js.ast.JsNode
import com.google.dart.compiler.backend.js.ast.*
import com.google.dart.compiler.backend.js.ast.metadata.staticRef
import org.jetbrains.kotlin.js.translate.context.Namer
/**
* Gets invocation qualifier name.
......@@ -62,19 +56,6 @@ fun getSimpleIdent(call: JsInvocation): String? {
return null
}
/**
* Checks if JsInvocation is function creator call.
*
* Function creator is a function, that creates closure.
*/
fun isFunctionCreatorInvocation(invocation: JsInvocation): Boolean {
val staticRef = getStaticRef(invocation)
return when (staticRef) {
is JsFunction -> isFunctionCreator(staticRef)
else -> false
}
}
/**
* Tests if invocation is JavaScript call function
*
......@@ -116,12 +97,6 @@ private fun getCallerQualifierImpl(invocation: JsInvocation): JsExpression? {
return (invocation.qualifier as? JsNameRef)?.qualifier
}
private fun getStaticRef(invocation: JsInvocation): JsNode? {
val qualifier = invocation.qualifier
val qualifierName = (qualifier as? HasName)?.name
return qualifierName?.staticRef
}
/**
* If an expression A references to another expression B, which in turn references to C, or a corresponding expression
* at the end of a chain of references. They are usually JsNameRef expressions with JsFunction at the very end.
......@@ -131,8 +106,16 @@ private fun getStaticRef(invocation: JsInvocation): JsNode? {
val JsExpression.transitiveStaticRef: JsExpression
get() {
var qualifier = this
while (qualifier is JsNameRef) {
qualifier = qualifier.name?.staticRef as? JsExpression ?: break
loop@while (true) {
qualifier = when (qualifier) {
is JsNameRef -> {
qualifier.name?.staticRef as? JsExpression ?: break@loop
}
is JsInvocation -> {
getSimpleName(qualifier)?.staticRef as? JsExpression ?: break@loop
}
else -> break@loop
}
}
return qualifier
}
\ No newline at end of file
......@@ -803,6 +803,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName);
}
@TestMetadata("lambda.kt")
public void testLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/lambda.kt");
doTest(fileName);
}
@TestMetadata("object.kt")
public void testObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/object.kt");
......
......@@ -62,25 +62,25 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
tracker.getNameForCapturedDescriptor(descriptor)
}
else {
context().getInnerNameForDescriptor(descriptor)
invokingContext.getInnerNameForDescriptor(descriptor)
}
if (tracker.hasCapturedExceptContaining()) {
val lambdaCreator = simpleReturnFunction(invokingContext.scope(), lambda)
lambdaCreator.name = context().getInnerNameForDescriptor(descriptor)
lambdaCreator.name = invokingContext.getInnerNameForDescriptor(descriptor)
lambdaCreator.isLocal = true
if (!isRecursive) {
lambda.name = null
}
lambdaCreator.name.staticRef = lambdaCreator
return lambdaCreator.withCapturedParameters(functionContext, invokingContext)
return lambdaCreator.withCapturedParameters(descriptor, functionContext, invokingContext)
}
lambda.isLocal = true
context().addDeclarationStatement(lambda.makeStmt())
invokingContext.addDeclarationStatement(lambda.makeStmt())
lambda.name.staticRef = lambda
return lambda.name.makeRef().apply { sideEffects = SideEffectKind.PURE }
return getReferenceToLambda(invokingContext, descriptor, lambda.name)
}
fun ValueParameterDescriptorImpl.WithDestructuringDeclaration.translate(context: TranslationContext): JsVars {
......@@ -93,9 +93,13 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
}
}
fun JsFunction.withCapturedParameters(context: TranslationContext, invokingContext: TranslationContext): JsExpression {
fun JsFunction.withCapturedParameters(
descriptor: CallableMemberDescriptor,
context: TranslationContext,
invokingContext: TranslationContext
): JsExpression {
context.addDeclarationStatement(makeStmt())
val ref = name.makeRef().apply { sideEffects = SideEffectKind.PURE }
val ref = getReferenceToLambda(invokingContext, descriptor, name)
val invocation = JsInvocation(ref).apply { sideEffects = SideEffectKind.PURE }
val invocationArguments = invocation.arguments
......@@ -128,6 +132,19 @@ fun JsFunction.withCapturedParameters(context: TranslationContext, invokingConte
return invocation
}
private fun getReferenceToLambda(context: TranslationContext, descriptor: CallableMemberDescriptor, name: JsName): JsExpression {
return if (context.isPublicInlineFunction) {
val fqn = context.getQualifiedReference(descriptor)
if (fqn is JsNameRef) {
fqn.name?.let { it.staticRef = name.staticRef }
}
fqn
}
else {
JsAstUtils.pureFqn(name, null)
}
}
private data class CapturedArgsParams(val arguments: List<JsExpression> = listOf(), val parameters: List<JsParameter> = listOf())
/**
......
// MODULE: lib
// FILE: lib.kt
package lib
fun bar(f: () -> String) = f()
inline fun foo(): String {
return bar { "OK" }
}
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.*
fun box() = foo()
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册