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 {
|
public void testLocalParameterInLocalNamedFunction() throws Exception {
|
||||||
fooBoxTest();
|
fooBoxTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testObjectAsConstructorParameter() throws Exception {
|
||||||
|
fooBoxTest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,40 +133,20 @@ public final class UsageTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void forEachCaptured(Consumer<CallableDescriptor> consumer) {
|
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) {
|
private void forEachCaptured(Consumer<CallableDescriptor> consumer, MemberDescriptor requestorDescriptor, @Nullable THashSet<CallableDescriptor> visited) {
|
||||||
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) {
|
|
||||||
if (capturedVariables != null) {
|
if (capturedVariables != null) {
|
||||||
for (CallableDescriptor variable : capturedVariables) {
|
for (CallableDescriptor callableDescriptor : capturedVariables) {
|
||||||
if (variable instanceof VariableDescriptor && isOneOfTheMyParentsIsAncestor((VariableDescriptor) variable, requestor)) {
|
if (!isAncestor(requestorDescriptor, callableDescriptor) && (visited == null || visited.add(callableDescriptor))) {
|
||||||
continue;
|
consumer.consume(callableDescriptor);
|
||||||
}
|
|
||||||
|
|
||||||
if (visited == null || visited.add(variable)) {
|
|
||||||
consumer.consume(variable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (children != null) {
|
if (children != null) {
|
||||||
for (UsageTracker child : children) {
|
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