File tree Expand file tree Collapse file tree 7 files changed +97
-5
lines changed Expand file tree Collapse file tree 7 files changed +97
-5
lines changed Original file line number Diff line number Diff line change @@ -38,6 +38,10 @@ abstract class ClosureData {
3838 /// the SSA builder.
3939 CapturedScope getCapturedScope (MemberEntity entity);
4040
41+ /// Look up scope information about a block. Used by the SSA builder to box
42+ /// variables if needed.
43+ CapturedScope getCapturedBlockScope (ir.Block node);
44+
4145 /// If [entity] is a closure call method or closure signature method, the
4246 /// original enclosing member is returned. Otherwise [entity] is returned.
4347 ///
Original file line number Diff line number Diff line change @@ -487,6 +487,11 @@ class KernelSourceInformationBuilder implements SourceInformationBuilder {
487487 return _buildTreeNode (node);
488488 }
489489
490+ @override
491+ SourceInformation buildBlock (ir.TreeNode node) {
492+ return _buildTreeNode (node);
493+ }
494+
490495 @override
491496 SourceInformation buildCall (
492497 covariant ir.TreeNode receiver,
Original file line number Diff line number Diff line change @@ -181,6 +181,9 @@ class SourceInformationBuilder {
181181 /// Generate [SourceInformation] for the if statement in [node] .
182182 SourceInformation ? buildIf (ir.TreeNode node) => null ;
183183
184+ /// Generate [SourceInformation] for the block statement in [node] .
185+ SourceInformation ? buildBlock (ir.TreeNode node) => null ;
186+
184187 /// Generate [SourceInformation] for the constructor invocation in [node] .
185188 SourceInformation ? buildNew (ir.TreeNode node) => null ;
186189
Original file line number Diff line number Diff line change @@ -205,10 +205,7 @@ class ScopeModelBuilder extends ir.VisitorDefault<EvaluationComplexity>
205205
206206 KernelCapturedScope capturedScope;
207207 var nodeBox = NodeBox (getBoxName (), _executableContext! );
208- if (node is ir.ForStatement ||
209- node is ir.ForInStatement ||
210- node is ir.WhileStatement ||
211- node is ir.DoStatement ) {
208+ if (node is ir.LoopStatement ) {
212209 capturedScope = KernelCapturedLoopScope (
213210 capturedVariablesForScope,
214211 nodeBox,
@@ -1373,7 +1370,17 @@ class ScopeModelBuilder extends ir.VisitorDefault<EvaluationComplexity>
13731370
13741371 @override
13751372 EvaluationComplexity visitBlock (ir.Block node) {
1376- visitNodes (node.statements);
1373+ final parent = node.parent;
1374+ if (parent is ir.FunctionNode || parent is ir.LoopStatement ) {
1375+ // Scoping for these blocks are handled by their parent nodes.
1376+ visitNodes (node.statements);
1377+ } else {
1378+ enterNewScope (node, () {
1379+ visitInVariableScope (node, () {
1380+ visitNodes (node.statements);
1381+ });
1382+ });
1383+ }
13771384 return const EvaluationComplexity .lazy ();
13781385 }
13791386
Original file line number Diff line number Diff line change @@ -200,6 +200,10 @@ class ClosureDataImpl implements ClosureData {
200200 }
201201 }
202202
203+ @override
204+ CapturedScope getCapturedBlockScope (ir.Block blockNode) =>
205+ _capturedScopesMap.loaded ()[blockNode] ?? const CapturedScope ();
206+
203207 @override
204208 // TODO(efortuna): Eventually capturedScopesMap[node] should always
205209 // be non-null, and we should just test that with an assert.
Original file line number Diff line number Diff line change @@ -2481,6 +2481,11 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
24812481 // a throwing prior subexpression, e.g. `[throw e, {...[]}]`.
24822482 if (! _isReachable) return ;
24832483
2484+ localsHandler.enterScope (
2485+ _closureDataLookup.getCapturedBlockScope (node),
2486+ _sourceInformationBuilder.buildBlock (node),
2487+ );
2488+
24842489 for (ir.Statement statement in node.statements) {
24852490 statement.accept (this );
24862491 if (! _isReachable) {
Original file line number Diff line number Diff line change 1+ import 'package:expect/expect.dart' ;
2+
3+ void testBlock () {
4+ List <void Function ()> functions = [];
5+ {
6+ var sub;
7+ functions.add (() {
8+ Expect .isNull (sub);
9+ sub = 1 ;
10+ });
11+ }
12+ {
13+ var sub;
14+ functions.add (() {
15+ Expect .equals (sub, 2 );
16+ });
17+ sub = 2 ;
18+ }
19+ for (var function in functions) function ();
20+ }
21+
22+ void testIf () {
23+ List <void Function ()> functions = [];
24+ if ('1234' .length > 2 ) {
25+ var sub;
26+ functions.add (() {
27+ Expect .isNull (sub);
28+ sub = 1 ;
29+ });
30+ }
31+ if ('1234' .length > 2 ) {
32+ var sub;
33+ functions.add (() {
34+ Expect .equals (sub, 2 );
35+ });
36+ sub = 2 ;
37+ }
38+ for (var function in functions) function ();
39+ }
40+
41+ void testTry () {
42+ List <void Function ()> functions = [];
43+ try {
44+ var sub;
45+ functions.add (() {
46+ Expect .isNull (sub);
47+ sub = 1 ;
48+ });
49+ } catch (e) {}
50+ try {
51+ var sub;
52+ functions.add (() {
53+ Expect .equals (sub, 2 );
54+ });
55+ sub = 2 ;
56+ } catch (e) {}
57+ for (var function in functions) function ();
58+ }
59+
60+ void main () {
61+ testBlock ();
62+ testIf ();
63+ testTry ();
64+ }
You can’t perform that action at this time.
0 commit comments