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..e3d1c97f8168959d73e04df9e75412ab82f9b0e6 100644 |
--- a/pkg/compiler/lib/src/js_model/closure_visitors.dart |
+++ b/pkg/compiler/lib/src/js_model/closure_visitors.dart |
@@ -17,13 +17,22 @@ 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>{}; |
+ // TODODODOOOOOO |
+ final Map<ir.Statement, LoopClosureScope> _loopClosureScopeMap; |
+ |
+ /// Map entities to their corresponding scope information (such as what |
+ /// variables are captured/used). The distinction between this map and |
+ /// [_closureInfoMap] is that [_closureInfoMap] stores this data for closures |
+ /// specifically, whereas [_scopeInfoMap] stores this information for entities |
+ /// that are *not* closures (this information is used by the locals handler). |
+ /// The union of these two maps represents all the scopes encountered. |
+ 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 +70,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._loopClosureScopeMap, |
+ 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 +107,18 @@ 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); |
+ _scopeInfoMap[_nodeToEntity(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 +219,13 @@ class ClosureScopeBuilder extends ir.Visitor { |
} |
} |
}); |
- KernelClosureScope scope = _closureInfoMap[node]; |
+ KernelClosureScope scope = _scopeInfoMap[_nodeToEntity(node)]; |
if (scope == null) return; |
- _closureInfoMap[node] = new KernelLoopClosureScope(scope.boxedVariables, |
- boxedLoopVariables, scope.context, scope.thisLocal); |
+ _loopClosureScopeMap[node] = new KernelLoopClosureScope( |
+ scope.boxedVariables, |
+ boxedLoopVariables, |
+ scope.context, |
+ scope.thisLocal); |
} |
void visitInvokable(ir.TreeNode node) { |
@@ -212,11 +237,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); |