Skip to content

Commit 3e436d4

Browse files
Alexey AndreevAlexey Andreev
Alexey Andreev
authored and
Alexey Andreev
committed
JS: allow to call non-suspend controller functions from coroutine lambda
1 parent e7f044b commit 3e436d4

File tree

5 files changed

+32
-21
lines changed

5 files changed

+32
-21
lines changed

js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ var JsInvocation.isSuspend: Boolean by MetadataProperty(default = false)
6666

6767
var JsInvocation.isHandleResult: Boolean by MetadataProperty(default = false)
6868

69+
var JsNameRef.coroutineController by MetadataProperty(default = false)
70+
6971
enum class TypeCheck {
7072
TYPEOF,
7173
INSTANCEOF,

js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineBodyTransformer.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -507,9 +507,6 @@ class CoroutineBodyTransformer(val program: JsProgram, val scope: JsScope, val t
507507
}
508508

509509
private fun handleSuspend(invocation: JsInvocation): JsExpression {
510-
val methodRef = invocation.qualifier as JsNameRef
511-
methodRef.qualifier = JsNameRef(controllerFieldName, methodRef.qualifier)
512-
513510
invocation.arguments += JsLiteral.THIS
514511
val nextBlock = CoroutineBlock()
515512
currentStatements += state(nextBlock)

js/js.inliner/src/org/jetbrains/kotlin/js/coroutine/CoroutineFunctionTransformer.kt

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package org.jetbrains.kotlin.js.coroutine
1818

1919
import com.google.dart.compiler.backend.js.ast.*
20-
import com.google.dart.compiler.backend.js.ast.metadata.isHandleResult
20+
import com.google.dart.compiler.backend.js.ast.metadata.coroutineController
2121
import com.google.dart.compiler.backend.js.ast.metadata.isSuspend
2222
import org.jetbrains.kotlin.descriptors.ClassDescriptor
2323
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -69,8 +69,7 @@ class CoroutineFunctionTransformer(
6969
val coroutineBlocks = bodyTransformer.postProcess()
7070

7171
for (coroutineBlock in coroutineBlocks) {
72-
coroutineBlock.jsBlock.replaceLocalVariables(function.scope)
73-
coroutineBlock.jsBlock.replaceHandleResult(bodyTransformer)
72+
coroutineBlock.jsBlock.replaceLocalVariables(function.scope, bodyTransformer)
7473
}
7574

7675
val additionalStatements = mutableListOf<JsStatement>()
@@ -229,19 +228,7 @@ class CoroutineFunctionTransformer(
229228
return listOf(throwExceptionIfNeeded, loop)
230229
}
231230

232-
private fun JsBlock.replaceHandleResult(transformer: CoroutineBodyTransformer) {
233-
accept(object : RecursiveJsVisitor() {
234-
override fun visitInvocation(invocation: JsInvocation) {
235-
super.visitInvocation(invocation)
236-
if (invocation.isHandleResult) {
237-
val methodRef = invocation.qualifier as JsNameRef
238-
methodRef.qualifier = JsNameRef(transformer.controllerFieldName, methodRef.qualifier)
239-
}
240-
}
241-
})
242-
}
243-
244-
private fun JsBlock.replaceLocalVariables(scope: JsScope) {
231+
private fun JsBlock.replaceLocalVariables(scope: JsScope, transformer: CoroutineBodyTransformer) {
245232
accept(object : RecursiveJsVisitor() {
246233
override fun visit(x: JsVars.JsVar) {
247234
super.visit(x)
@@ -251,6 +238,9 @@ class CoroutineFunctionTransformer(
251238

252239
val visitor = object : JsVisitorWithContextImpl() {
253240
override fun endVisit(x: JsNameRef, ctx: JsContext<in JsNode>) {
241+
if (x.coroutineController) {
242+
ctx.replaceMe(JsNameRef(transformer.controllerFieldName, x.qualifier))
243+
}
254244
if (x.qualifier == null && x.name in localVariables) {
255245
val fieldName = scope.getFieldName(x.name!!)
256246
ctx.replaceMe(JsNameRef(fieldName, JsLiteral.THIS))

js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TranslationContext.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
package org.jetbrains.kotlin.js.translate.context;
1818

1919
import com.google.dart.compiler.backend.js.ast.*;
20+
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
2021
import com.intellij.psi.PsiElement;
2122
import org.jetbrains.annotations.NotNull;
2223
import org.jetbrains.annotations.Nullable;
2324
import org.jetbrains.kotlin.descriptors.*;
25+
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
2426
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
2527
import org.jetbrains.kotlin.js.config.JsConfig;
2628
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
@@ -356,6 +358,16 @@ public JsExpression getDispatchReceiver(@NotNull ReceiverParameterDescriptor des
356358
if (alias != null) {
357359
return alias;
358360
}
361+
if (descriptor.getContainingDeclaration() instanceof AnonymousFunctionDescriptor) {
362+
AnonymousFunctionDescriptor function = (AnonymousFunctionDescriptor) descriptor.getContainingDeclaration();
363+
if (function.isCoroutine()) {
364+
assert function.getExtensionReceiverParameter() != null;
365+
JsNameRef result = new JsNameRef("$$controller$$", JsLiteral.THIS);
366+
MetadataProperties.setCoroutineController(result, true);
367+
return result;
368+
}
369+
}
370+
359371
if (DescriptorUtils.isObject(descriptor.getContainingDeclaration())) {
360372
if (isConstructorOrDirectScope(descriptor.getContainingDeclaration())) {
361373
return JsLiteral.THIS;

js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2015 JetBrains s.r.o.
2+
* Copyright 2010-2016 JetBrains s.r.o.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
import org.jetbrains.annotations.Nullable;
2424
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
2525
import org.jetbrains.kotlin.descriptors.*;
26+
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
2627
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor;
2728
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
2829
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator;
@@ -36,6 +37,7 @@
3637
import org.jetbrains.kotlin.resolve.DescriptorUtils;
3738
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
3839
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
40+
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
3941
import org.jetbrains.kotlin.types.KotlinType;
4042

4143
import java.util.ArrayList;
@@ -325,7 +327,15 @@ else if (KotlinBuiltIns.isUnit(returnType)) {
325327
aliases.put(continuationArgument.getArgumentExpression(), JsLiteral.THIS);
326328

327329
TranslationContext returnContext = context.innerContextWithAliasesForExpressions(aliases);
328-
JsInvocation handleResultInvocation = (JsInvocation) CallTranslator.translate(returnContext, returnCall, JsLiteral.THIS);
330+
331+
ImplicitReceiver receiver = (ImplicitReceiver) returnCall.getDispatchReceiver();
332+
assert receiver != null;
333+
AnonymousFunctionDescriptor lambdaDescriptor = (AnonymousFunctionDescriptor) receiver.getDeclarationDescriptor();
334+
ReceiverParameterDescriptor receiverParameter = lambdaDescriptor.getExtensionReceiverParameter();
335+
assert receiverParameter != null;
336+
JsExpression jsReceiver = returnContext.getDispatchReceiver(receiverParameter);
337+
338+
JsInvocation handleResultInvocation = (JsInvocation) CallTranslator.translate(returnContext, returnCall, jsReceiver);
329339
MetadataProperties.setHandleResult(handleResultInvocation, true);
330340

331341
return handleResultInvocation;

0 commit comments

Comments
 (0)