| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| index fd3695ee1cc3882ffec3af0a59fb7214493eced3..5e224e25438c518d8e2f62451d016941f83e659f 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
|
| @@ -2277,11 +2277,16 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
|
|
|
| final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
|
|
|
| -/// Determines which local variables should be boxed in a mutable variable
|
| -/// inside a given try block.
|
| -class TryBoxedVariables extends ast.Visitor {
|
| +/// Classifies local variables and local functions as captured, if they
|
| +/// are accessed from within a nested function.
|
| +///
|
| +/// This class is specific to the [DartIrBuilder], in that it gives up if it
|
| +/// sees a feature that is currently unsupport by that builder. In particular,
|
| +/// loop variables captured in a for-loop initializer, condition, or update
|
| +/// expression are unsupported.
|
| +class DartCapturedVariables extends ast.Visitor {
|
| final TreeElements elements;
|
| - TryBoxedVariables(this.elements);
|
| + DartCapturedVariables(this.elements);
|
|
|
| FunctionElement currentFunction;
|
| bool insideInitializer = false;
|
| @@ -2327,6 +2332,25 @@ class TryBoxedVariables extends ast.Visitor {
|
| node.visitChildren(this);
|
| }
|
|
|
| + visitFor(ast.For node) {
|
| + if (node.initializer != null) visit(node.initializer);
|
| + if (node.condition != null) visit(node.condition);
|
| + if (node.update != null) visit(node.update);
|
| +
|
| + // Give up if a variable was captured outside of the loop body.
|
| + if (node.initializer is ast.VariableDefinitions) {
|
| + ast.VariableDefinitions definitions = node.initializer;
|
| + for (ast.Node node in definitions.definitions.nodes) {
|
| + LocalElement loopVariable = elements[node];
|
| + if (capturedVariables.contains(loopVariable)) {
|
| + return giveup(node, 'For-loop variable captured in loop header');
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (node.body != null) visit(node.body);
|
| + }
|
| +
|
| void handleSend(ast.Send node) {
|
| Element element = elements[node];
|
| if (Elements.isLocal(element) &&
|
| @@ -2384,14 +2408,18 @@ class TryBoxedVariables extends ast.Visitor {
|
| if (currentFunction.asyncMarker != AsyncMarker.SYNC &&
|
| currentFunction.asyncMarker != AsyncMarker.SYNC_STAR &&
|
| currentFunction.asyncMarker != AsyncMarker.ASYNC) {
|
| - giveup(node, "cannot handle async* functions");
|
| + giveup(node, "cannot handle sync*/async* functions");
|
| }
|
|
|
| + bool savedInsideInitializer = insideInitializer;
|
| if (node.initializers != null) {
|
| + insideInitializer = true;
|
| visit(node.initializers);
|
| }
|
| + insideInitializer = false;
|
| visit(node.body);
|
| currentFunction = savedFunction;
|
| + insideInitializer = savedInsideInitializer;
|
| }
|
|
|
| visitTryStatement(ast.TryStatement node) {
|
| @@ -3099,8 +3127,8 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| return parameters;
|
| }
|
|
|
| - TryBoxedVariables _analyzeTryBoxedVariables(ast.Node node) {
|
| - TryBoxedVariables variables = new TryBoxedVariables(elements);
|
| + DartCapturedVariables _analyzeCapturedVariables(ast.Node node) {
|
| + DartCapturedVariables variables = new DartCapturedVariables(elements);
|
| try {
|
| variables.analyze(node);
|
| } catch (e) {
|
| @@ -3130,7 +3158,7 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| // error-prone.
|
| // TODO(kmillikin): We should combine closure conversion and try/catch
|
| // variable analysis in some way.
|
| - TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
|
| + DartCapturedVariables variables = _analyzeCapturedVariables(node);
|
| tryStatements = variables.tryStatements;
|
| IrBuilder builder = getBuilderFor(body);
|
|
|
| @@ -3155,7 +3183,7 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| element,
|
| node,
|
| elements);
|
| - TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
|
| + DartCapturedVariables variables = _analyzeCapturedVariables(node);
|
| tryStatements = variables.tryStatements;
|
| IrBuilder builder = getBuilderFor(element);
|
| return withBuilder(builder, () => _makeFunctionBody(element, node));
|
|
|