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
|
@NotNull
|
||||||
private final MemberDescriptor memberDescriptor;
|
private final MemberDescriptor memberDescriptor;
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private final UsageTracker parent;
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private List<UsageTracker> children;
|
private List<UsageTracker> children;
|
||||||
|
|
||||||
@@ -47,7 +45,6 @@ public final class UsageTracker {
|
|||||||
public UsageTracker(@NotNull MemberDescriptor memberDescriptor, @Nullable UsageTracker parent, @Nullable ClassDescriptor trackedClassDescriptor) {
|
public UsageTracker(@NotNull MemberDescriptor memberDescriptor, @Nullable UsageTracker parent, @Nullable ClassDescriptor trackedClassDescriptor) {
|
||||||
this.memberDescriptor = memberDescriptor;
|
this.memberDescriptor = memberDescriptor;
|
||||||
this.trackedClassDescriptor = trackedClassDescriptor;
|
this.trackedClassDescriptor = trackedClassDescriptor;
|
||||||
this.parent = parent;
|
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.addChild(this);
|
parent.addChild(this);
|
||||||
}
|
}
|
||||||
@@ -119,16 +116,18 @@ public final class UsageTracker {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ClassDescriptor getOuterClassDescriptor() {
|
public ClassDescriptor getOuterClassDescriptor() {
|
||||||
if (outerClassDescriptor == null && parent != null) {
|
if (outerClassDescriptor != null || children == null) {
|
||||||
UsageTracker p = parent;
|
return outerClassDescriptor;
|
||||||
do {
|
|
||||||
if (p.outerClassDescriptor != null) {
|
|
||||||
return p.outerClassDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((p = p.parent) != null);
|
|
||||||
}
|
}
|
||||||
return outerClassDescriptor;
|
|
||||||
|
for (UsageTracker child : children) {
|
||||||
|
ClassDescriptor childOuterClassDescriptor = child.getOuterClassDescriptor();
|
||||||
|
if (childOuterClassDescriptor != null) {
|
||||||
|
return childOuterClassDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forEachCaptured(Consumer<CallableDescriptor> consumer) {
|
public void forEachCaptured(Consumer<CallableDescriptor> consumer) {
|
||||||
|
|||||||
+7
-5
@@ -116,7 +116,9 @@ public class LiteralFunctionTranslator {
|
|||||||
if (asInner) {
|
if (asInner) {
|
||||||
addRegularParameters(descriptor, fun, funContext, receiverName);
|
addRegularParameters(descriptor, fun, funContext, receiverName);
|
||||||
if (outerClass != null) {
|
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);
|
return new JsInvocation(rootContext.namer().kotlin("assignOwner"), fun, JsLiteral.THIS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -159,15 +161,15 @@ public class LiteralFunctionTranslator {
|
|||||||
@NotNull ClassTranslator classTranslator) {
|
@NotNull ClassTranslator classTranslator) {
|
||||||
JsFunction fun = createFunction();
|
JsFunction fun = createFunction();
|
||||||
JsNameRef outerClassRef = fun.getScope().declareName("$this").makeRef();
|
JsNameRef outerClassRef = fun.getScope().declareName("$this").makeRef();
|
||||||
TranslationContext funContext = rootContext
|
UsageTracker usageTracker = new UsageTracker(descriptor, null, outerClass);
|
||||||
.contextWithScope(fun, rootContext.aliasingContext().inner(outerClass, outerClassRef), new UsageTracker(descriptor, null,
|
TranslationContext funContext = rootContext.contextWithScope(fun, rootContext.aliasingContext().inner(outerClass, outerClassRef),
|
||||||
outerClass));
|
usageTracker);
|
||||||
|
|
||||||
fun.getBody().getStatements().add(new JsReturn(classTranslator.translate(funContext)));
|
fun.getBody().getStatements().add(new JsReturn(classTranslator.translate(funContext)));
|
||||||
JetClassBody body = declaration.getBody();
|
JetClassBody body = declaration.getBody();
|
||||||
assert body != null;
|
assert body != null;
|
||||||
InnerObjectTranslator translator = new InnerObjectTranslator(funContext, fun);
|
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