@@ -3065,70 +3065,86 @@ class ProgramCompiler
3065
3065
return body;
3066
3066
}
3067
3067
3068
+ JS .Statement translateLoop (Statement node, JS .Statement action ()) {
3069
+ var savedBreakTargets;
3070
+ if (_currentBreakTargets.isNotEmpty &&
3071
+ _effectiveTargets[_currentBreakTargets.first] != node) {
3072
+ // If breaking without a label targets some other (outer) loop, then
3073
+ // this loop prevents breaking to that loop without a label. This loop
3074
+ // was not labeled for a break in Kernel, otherwise it would be the
3075
+ // effective target of the current break targets, so it is not itself the
3076
+ // target of a break.
3077
+ savedBreakTargets = _currentBreakTargets;
3078
+ _currentBreakTargets = < LabeledStatement > [];
3079
+ }
3080
+ var savedContinueTargets = _currentContinueTargets;
3081
+ var result = action ();
3082
+ if (savedBreakTargets != null ) _currentBreakTargets = savedBreakTargets;
3083
+ _currentContinueTargets = savedContinueTargets;
3084
+ return result;
3085
+ }
3086
+
3068
3087
@override
3069
3088
JS .While visitWhileStatement (WhileStatement node) {
3070
- var condition = _visitTest (node.condition);
3071
-
3072
- var saved = _currentContinueTargets;
3073
- var body = _visitScope (effectiveBodyOf (node, node.body));
3074
- _currentContinueTargets = saved;
3075
-
3076
- return new JS .While (condition, body);
3089
+ return translateLoop (node, () {
3090
+ var condition = _visitTest (node.condition);
3091
+ var body = _visitScope (effectiveBodyOf (node, node.body));
3092
+ return new JS .While (condition, body);
3093
+ });
3077
3094
}
3078
3095
3079
3096
@override
3080
3097
JS .Do visitDoStatement (DoStatement node) {
3081
- var saved = _currentContinueTargets;
3082
- var body = _visitScope (effectiveBodyOf (node, node.body));
3083
- _currentContinueTargets = saved ;
3084
-
3085
- return new JS . Do (body, _visitTest (node.condition) );
3098
+ return translateLoop (node, () {
3099
+ var body = _visitScope (effectiveBodyOf (node, node.body));
3100
+ var condition = _visitTest (node.condition) ;
3101
+ return new JS . Do (body, condition);
3102
+ } );
3086
3103
}
3087
3104
3088
3105
@override
3089
3106
JS .For visitForStatement (ForStatement node) {
3090
- emitForInitializer (VariableDeclaration v) => new JS .VariableInitialization (
3091
- _emitVariableRef (v)..sourceInformation = v,
3092
- _visitInitializer (v.initializer, v.annotations));
3093
-
3094
- var init = node.variables.map (emitForInitializer).toList ();
3095
- var initList =
3096
- init.isEmpty ? null : new JS .VariableDeclarationList ('let' , init);
3097
- var updates = node.updates;
3098
- JS .Expression update;
3099
- if (updates.isNotEmpty) {
3100
- update = new JS .Expression .binary (
3101
- updates.map (_visitAndMarkExpression).toList (), ',' )
3102
- .toVoidExpression ();
3103
- }
3104
- var condition = _visitTest (node.condition);
3105
-
3106
- var saved = _currentContinueTargets;
3107
- var body = _visitScope (effectiveBodyOf (node, node.body));
3108
- _currentContinueTargets = saved;
3107
+ return translateLoop (node, () {
3108
+ emitForInitializer (VariableDeclaration v) =>
3109
+ new JS .VariableInitialization (
3110
+ _emitVariableRef (v)..sourceInformation = v,
3111
+ _visitInitializer (v.initializer, v.annotations));
3112
+
3113
+ var init = node.variables.map (emitForInitializer).toList ();
3114
+ var initList =
3115
+ init.isEmpty ? null : new JS .VariableDeclarationList ('let' , init);
3116
+ var updates = node.updates;
3117
+ JS .Expression update;
3118
+ if (updates.isNotEmpty) {
3119
+ update = new JS .Expression .binary (
3120
+ updates.map (_visitAndMarkExpression).toList (), ',' )
3121
+ .toVoidExpression ();
3122
+ }
3123
+ var condition = _visitTest (node.condition);
3124
+ var body = _visitScope (effectiveBodyOf (node, node.body));
3109
3125
3110
- return new JS .For (initList, condition, update, body);
3126
+ return new JS .For (initList, condition, update, body);
3127
+ });
3111
3128
}
3112
3129
3113
3130
@override
3114
3131
JS .Statement visitForInStatement (ForInStatement node) {
3115
- if (node.isAsync) {
3116
- return _emitAwaitFor (node);
3117
- }
3118
-
3119
- var iterable = _visitAndMarkExpression (node.iterable);
3132
+ return translateLoop (node, () {
3133
+ if (node.isAsync) {
3134
+ return _emitAwaitFor (node);
3135
+ }
3120
3136
3121
- var saved = _currentContinueTargets;
3122
- var body = _visitScope (effectiveBodyOf (node, node.body));
3123
- _currentContinueTargets = saved;
3137
+ var iterable = _visitAndMarkExpression (node.iterable);
3138
+ var body = _visitScope (effectiveBodyOf (node, node.body));
3124
3139
3125
- var v = _emitVariableRef (node.variable);
3126
- var init = js.call ('let #' , v);
3127
- if (_annotatedNullCheck (node.variable.annotations)) {
3128
- body = new JS .Block ([_nullParameterCheck (v), body]);
3129
- }
3140
+ var v = _emitVariableRef (node.variable);
3141
+ var init = js.call ('let #' , v);
3142
+ if (_annotatedNullCheck (node.variable.annotations)) {
3143
+ body = new JS .Block ([_nullParameterCheck (v), body]);
3144
+ }
3130
3145
3131
- return new JS .ForOf (init, iterable, body);
3146
+ return new JS .ForOf (init, iterable, body);
3147
+ });
3132
3148
}
3133
3149
3134
3150
JS .Statement _emitAwaitFor (ForInStatement node) {
0 commit comments