JS backend: fixed the variable capturing in deeply nested functions which mixed with the object declaration.
(cherry picked from commit 41cb0ab)
This commit is contained in:
@@ -39,4 +39,8 @@ public final class ClosureTest extends SingleFileTranslationTest {
|
||||
public void testLocalParameterInLocalNamedFunction() throws Exception {
|
||||
fooBoxTest();
|
||||
}
|
||||
|
||||
public void testObjectAsConstructorParameter() throws Exception {
|
||||
fooBoxTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,40 +133,20 @@ public final class UsageTracker {
|
||||
}
|
||||
|
||||
public void forEachCaptured(Consumer<CallableDescriptor> consumer) {
|
||||
forEachCaptured(consumer, this, children == null ? null : new THashSet<CallableDescriptor>());
|
||||
forEachCaptured(consumer, memberDescriptor, children == null ? null : new THashSet<CallableDescriptor>());
|
||||
}
|
||||
|
||||
private boolean isOneOfTheMyParentsIsAncestor(VariableDescriptor parameterDescriptor, UsageTracker requestor) {
|
||||
if (requestor == this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionDescriptor paramOwner = (FunctionDescriptor) parameterDescriptor.getContainingDeclaration();
|
||||
UsageTracker p = parent;
|
||||
do {
|
||||
if (p.memberDescriptor == paramOwner) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while ((p = p.parent) != null && p != requestor);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void forEachCaptured(Consumer<CallableDescriptor> consumer, UsageTracker requestor, @Nullable THashSet<CallableDescriptor> visited) {
|
||||
private void forEachCaptured(Consumer<CallableDescriptor> consumer, MemberDescriptor requestorDescriptor, @Nullable THashSet<CallableDescriptor> visited) {
|
||||
if (capturedVariables != null) {
|
||||
for (CallableDescriptor variable : capturedVariables) {
|
||||
if (variable instanceof VariableDescriptor && isOneOfTheMyParentsIsAncestor((VariableDescriptor) variable, requestor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (visited == null || visited.add(variable)) {
|
||||
consumer.consume(variable);
|
||||
for (CallableDescriptor callableDescriptor : capturedVariables) {
|
||||
if (!isAncestor(requestorDescriptor, callableDescriptor) && (visited == null || visited.add(callableDescriptor))) {
|
||||
consumer.consume(callableDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (children != null) {
|
||||
for (UsageTracker child : children) {
|
||||
child.forEachCaptured(consumer, requestor, visited);
|
||||
child.forEachCaptured(consumer, requestorDescriptor, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package foo
|
||||
|
||||
fun getLastFocused(callback: (window: Any?)->Unit) {
|
||||
callback(null)
|
||||
}
|
||||
|
||||
abstract class TabService(val ctorParam: String) {
|
||||
abstract fun query(callback: (tabs: String)->Unit)
|
||||
}
|
||||
|
||||
abstract class PageManager(val tabService: TabService)
|
||||
|
||||
class ChromePageManager(val expected: String) : PageManager(object : TabService(expected) {
|
||||
override fun query(callback: (tabs: String)->Unit) {
|
||||
getLastFocused {
|
||||
callback(expected)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
fun box(): Boolean {
|
||||
var result = ""
|
||||
val tabService = ChromePageManager("result").tabService
|
||||
tabService.query {
|
||||
result = it
|
||||
}
|
||||
return result == "result" && tabService.ctorParam == "result"
|
||||
}
|
||||
Reference in New Issue
Block a user