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:
develar
2012-09-06 18:30:58 +04:00
committed by Zalim Bashorov
parent 4a37d56a1b
commit 462e1bdc98
3 changed files with 38 additions and 26 deletions
@@ -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"
}