diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ClosureTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ClosureTest.java index d42809704d5..78bc7bac66d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ClosureTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ClosureTest.java @@ -39,4 +39,8 @@ public final class ClosureTest extends SingleFileTranslationTest { public void testLocalParameterInLocalNamedFunction() throws Exception { fooBoxTest(); } + + public void testObjectAsConstructorParameter() throws Exception { + fooBoxTest(); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.java index b049f979dd3..3c3d7a28d89 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.java @@ -133,40 +133,20 @@ public final class UsageTracker { } public void forEachCaptured(Consumer consumer) { - forEachCaptured(consumer, this, children == null ? null : new THashSet()); + forEachCaptured(consumer, memberDescriptor, children == null ? null : new THashSet()); } - 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 consumer, UsageTracker requestor, @Nullable THashSet visited) { + private void forEachCaptured(Consumer consumer, MemberDescriptor requestorDescriptor, @Nullable THashSet 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); } } } diff --git a/js/js.translator/testFiles/closure/cases/objectAsConstructorParameter.kt b/js/js.translator/testFiles/closure/cases/objectAsConstructorParameter.kt new file mode 100644 index 00000000000..f07c97c0d3c --- /dev/null +++ b/js/js.translator/testFiles/closure/cases/objectAsConstructorParameter.kt @@ -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" +}