JS backend: detect outer class if used in child local fun.
Fix closure fields when use it from nested functions in method. (cherry picked from commit 20eea36)
This commit is contained in:
@@ -34,8 +34,6 @@ public final class UsageTracker {
|
||||
@NotNull
|
||||
private final MemberDescriptor memberDescriptor;
|
||||
|
||||
@Nullable
|
||||
private final UsageTracker parent;
|
||||
@Nullable
|
||||
private List<UsageTracker> children;
|
||||
|
||||
@@ -47,7 +45,6 @@ public final class UsageTracker {
|
||||
public UsageTracker(@NotNull MemberDescriptor memberDescriptor, @Nullable UsageTracker parent, @Nullable ClassDescriptor trackedClassDescriptor) {
|
||||
this.memberDescriptor = memberDescriptor;
|
||||
this.trackedClassDescriptor = trackedClassDescriptor;
|
||||
this.parent = parent;
|
||||
if (parent != null) {
|
||||
parent.addChild(this);
|
||||
}
|
||||
@@ -119,16 +116,18 @@ public final class UsageTracker {
|
||||
|
||||
@Nullable
|
||||
public ClassDescriptor getOuterClassDescriptor() {
|
||||
if (outerClassDescriptor == null && parent != null) {
|
||||
UsageTracker p = parent;
|
||||
do {
|
||||
if (p.outerClassDescriptor != null) {
|
||||
return p.outerClassDescriptor;
|
||||
}
|
||||
}
|
||||
while ((p = p.parent) != null);
|
||||
if (outerClassDescriptor != null || children == null) {
|
||||
return outerClassDescriptor;
|
||||
}
|
||||
return outerClassDescriptor;
|
||||
|
||||
for (UsageTracker child : children) {
|
||||
ClassDescriptor childOuterClassDescriptor = child.getOuterClassDescriptor();
|
||||
if (childOuterClassDescriptor != null) {
|
||||
return childOuterClassDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void forEachCaptured(Consumer<CallableDescriptor> consumer) {
|
||||
|
||||
+7
-5
@@ -116,7 +116,9 @@ public class LiteralFunctionTranslator {
|
||||
if (asInner) {
|
||||
addRegularParameters(descriptor, fun, funContext, receiverName);
|
||||
if (outerClass != null) {
|
||||
if (funContext.usageTracker().isUsed()) {
|
||||
UsageTracker usageTracker = funContext.usageTracker();
|
||||
assert usageTracker != null;
|
||||
if (usageTracker.isUsed()) {
|
||||
return new JsInvocation(rootContext.namer().kotlin("assignOwner"), fun, JsLiteral.THIS);
|
||||
}
|
||||
else {
|
||||
@@ -159,15 +161,15 @@ public class LiteralFunctionTranslator {
|
||||
@NotNull ClassTranslator classTranslator) {
|
||||
JsFunction fun = createFunction();
|
||||
JsNameRef outerClassRef = fun.getScope().declareName("$this").makeRef();
|
||||
TranslationContext funContext = rootContext
|
||||
.contextWithScope(fun, rootContext.aliasingContext().inner(outerClass, outerClassRef), new UsageTracker(descriptor, null,
|
||||
outerClass));
|
||||
UsageTracker usageTracker = new UsageTracker(descriptor, null, outerClass);
|
||||
TranslationContext funContext = rootContext.contextWithScope(fun, rootContext.aliasingContext().inner(outerClass, outerClassRef),
|
||||
usageTracker);
|
||||
|
||||
fun.getBody().getStatements().add(new JsReturn(classTranslator.translate(funContext)));
|
||||
JetClassBody body = declaration.getBody();
|
||||
assert body != null;
|
||||
InnerObjectTranslator translator = new InnerObjectTranslator(funContext, fun);
|
||||
return translator.translate(createReference(fun), funContext.usageTracker().isUsed() ? outerClassRef : null);
|
||||
return translator.translate(createReference(fun), usageTracker.isUsed() ? outerClassRef : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user