Index: pkg/compiler/lib/src/js_model/closure_visitors.dart |
diff --git a/pkg/compiler/lib/src/js_model/closure_visitors.dart b/pkg/compiler/lib/src/js_model/closure_visitors.dart |
index 1dcb29f8de16034239276ab4e1abeaba32bf6eaa..1c8ebdff2d1197646b2a05da9b66e49c8464b443 100644 |
--- a/pkg/compiler/lib/src/js_model/closure_visitors.dart |
+++ b/pkg/compiler/lib/src/js_model/closure_visitors.dart |
@@ -17,13 +17,17 @@ class ClosureScopeBuilder extends ir.Visitor { |
/// variables are captured/used. Each ir.Node key corresponds to a scope that |
/// was encountered while visiting a closure (initially called through |
/// [translateLazyIntializer] or [translateConstructorOrProcedure]). |
- Map<ir.Node, ClosureScope> _closureInfoMap = <ir.Node, ClosureScope>{}; |
+ final Map<ir.Node, ClosureScope> _scopesCapturedInClosureMap; |
+ |
+ /// Map entities to their corresponding scope information (such as what |
+ /// variables are captured/used). |
+ final Map<Entity, ScopeInfo> _scopeInfoMap; |
/// A map of the nodes that we have flagged as necessary to generate closure |
/// classes for in a later stage. We map that node to information ascertained |
/// about variable usage in the surrounding scope. |
- Map<ir.TreeNode /* ir.Field | ir.FunctionNode */, ScopeInfo> |
- _closuresToGenerate = <ir.TreeNode, ScopeInfo>{}; |
+ final Map<ir.TreeNode /* ir.Field | ir.FunctionNode */, ScopeInfo> |
+ _closuresToGenerate; |
/// The local variables that have been declared in the current scope. |
List<ir.VariableDeclaration> _scopeVariables; |
@@ -61,8 +65,17 @@ class ClosureScopeBuilder extends ir.Visitor { |
final KernelToElementMap _kernelToElementMap; |
- ClosureScopeBuilder(this._closureInfoMap, this._closuresToGenerate, |
- this._localsMap, this._kernelToElementMap); |
+ /// The original entity from which we start the tree-walk to find closure and |
+ /// scope information. |
+ final Entity _originalEntity; |
+ |
+ ClosureScopeBuilder( |
+ this._scopesCapturedInClosureMap, |
+ this._scopeInfoMap, |
+ this._originalEntity, |
+ this._closuresToGenerate, |
+ this._localsMap, |
+ this._kernelToElementMap); |
/// Update the [ClosureScope] object corresponding to |
/// this node if any variables are captured. |
@@ -89,14 +102,19 @@ class ClosureScopeBuilder extends ir.Visitor { |
thisLocal = new ThisLocal(_kernelToElementMap.getConstructor(node)); |
} |
- Entity context; |
- if (_executableContext is ir.Member) { |
- context = _kernelToElementMap.getMember(_executableContext); |
- } else { |
- context = _kernelToElementMap.getLocalFunction(_executableContext); |
- } |
- _closureInfoMap[node] = |
- new KernelClosureScope(capturedVariablesForScope, context, thisLocal); |
+ assert(_scopeInfoMap[_nodeToEntity(node)] != null); |
+ _scopesCapturedInClosureMap[node] = new KernelClosureScope( |
+ capturedVariablesForScope, |
+ _nodeToEntity(_executableContext), |
+ thisLocal); |
+ } |
+ } |
+ |
+ Entity _nodeToEntity(ir.Node node) { |
+ if (node is ir.Member) { |
+ return _kernelToElementMap.getMember(node); |
+ } else { |
+ return _kernelToElementMap.getLocalFunction(node); |
} |
} |
@@ -197,10 +215,13 @@ class ClosureScopeBuilder extends ir.Visitor { |
} |
} |
}); |
- KernelClosureScope scope = _closureInfoMap[node]; |
+ KernelClosureScope scope = _scopesCapturedInClosureMap[node]; |
if (scope == null) return; |
- _closureInfoMap[node] = new KernelLoopClosureScope(scope.boxedVariables, |
- boxedLoopVariables, scope.context, scope.thisLocal); |
+ _scopesCapturedInClosureMap[node] = new KernelLoopClosureScope( |
+ scope.boxedVariables, |
+ boxedLoopVariables, |
+ scope.context, |
+ scope.thisLocal); |
} |
void visitInvokable(ir.TreeNode node) { |
@@ -212,11 +233,13 @@ class ClosureScopeBuilder extends ir.Visitor { |
// field, constructor, or method that is being analyzed. |
_isInsideClosure = _outermostNode != null; |
_executableContext = node; |
- if (!_isInsideClosure) { |
+ _currentScopeInfo = new KernelScopeInfo(_nodeToThisLocal(node)); |
+ if (_isInsideClosure) { |
+ _closuresToGenerate[node] = _currentScopeInfo; |
+ } else { |
_outermostNode = node; |
+ _scopeInfoMap[_originalEntity] = _currentScopeInfo; |
} |
- _currentScopeInfo = new KernelScopeInfo(_nodeToThisLocal(node)); |
- _closuresToGenerate[node] = _currentScopeInfo; |
enterNewScope(node, () { |
node.visitChildren(this); |