Version 1.9.0-dev.10.11

svn merge -c 44558 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44559 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44592 https://dart.googlecode.com/svn/branches/bleeding_edge trunk (mf conflict resolution for ast_printer.cc)

git-svn-id: http://dart.googlecode.com/svn/trunk@44593 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 8e900c0..83611e2 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -749,7 +749,12 @@
     js.Expression leftHandSide = node.leftHandSide;
     if (leftHandSide is js.VariableUse) {
       return withExpression(node.value, (js.Expression value) {
-        return new js.Assignment(leftHandSide, value);
+        // A non-compound [js.Assignment] has `op==null`. So it works out to
+        // use [js.Assignment.compound] for all cases.
+        // Visit the [js.VariableUse] to ensure renaming is done correctly.
+        return new js.Assignment.compound(visitExpression(leftHandSide),
+                                          node.op,
+                                          value);
       }, store: false);
     } else if (leftHandSide is js.PropertyAccess) {
       return withExpressions([
@@ -1211,7 +1216,7 @@
     if (node.op == "++" || node.op == "--") {
       js.Expression argument = node.argument;
       if (argument is js.VariableUse) {
-        return new js.Postfix(node.op, argument);
+        return new js.Postfix(node.op, visitExpression(argument));
       } else if (argument is js.PropertyAccess) {
         return withExpression2(argument.receiver, argument.selector,
             (receiver, selector) {
@@ -1233,7 +1238,7 @@
     if (node.op == "++" || node.op == "--") {
       js.Expression argument = node.argument;
       if (argument is js.VariableUse) {
-        return new js.Prefix(node.op, argument);
+        return new js.Prefix(node.op, visitExpression(argument));
       } else if (argument is js.PropertyAccess) {
         return withExpression2(argument.receiver, argument.selector,
             (receiver, selector) {
@@ -1528,7 +1533,7 @@
 
   @override
   js.Expression visitVariableDeclarationList(js.VariableDeclarationList node) {
-    List<js.Assignment> initializations = new List<js.Assignment>();
+    List<js.Expression> initializations = new List<js.Expression>();
 
     // Declaration of local variables is hoisted outside the helper but the
     // initialization is done here.
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 18db66c..7c8293e 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -611,6 +611,7 @@
 
   Assignment(leftHandSide, value)
       : this.compound(leftHandSide, null, value);
+  // If `this.op == null` this will be a non-compound assignment.
   Assignment.compound(this.leftHandSide, this.op, this.value);
 
   int get precedenceLevel => ASSIGNMENT;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index e175da5..fdbe56a 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3782,7 +3782,10 @@
         Bind(new(I) AllocateContextInstr(node->token_pos(),
                                          num_context_variables));
     { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
-      if (HasContextScope() || !is_top_level_sequence) {
+      if (!is_top_level_sequence || HasContextScope()) {
+        ASSERT(is_top_level_sequence ||
+               (nested_block.ContextLevel() ==
+                nested_block.outer()->ContextLevel() + 1));
         Value* tmp_val = Bind(new(I) LoadLocalInstr(*tmp_var));
         Value* parent_context = Bind(BuildCurrentContext());
         Do(new(I) StoreInstanceFieldInstr(Context::parent_offset(),
@@ -3991,7 +3994,7 @@
 
   if (is_open() &&
       (num_context_variables > 0) &&
-      (HasContextScope() || !is_top_level_sequence)) {
+      (!is_top_level_sequence || HasContextScope())) {
     UnchainContexts(1);
   }
 
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index df9a50c..6bf6b45 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2473,17 +2473,13 @@
   const int first_parameter_index = 0;
   const int num_parameters = 0;
   const int first_frame_index = -1;
-  LocalScope* loop_owner = parent_scope;
-  LocalScope* context_owner = NULL;   // No context allocated yet.
   bool found_captured_vars = false;
   int next_frame_index = parent_scope->AllocateVariables(first_parameter_index,
                                                          num_parameters,
                                                          first_frame_index,
-                                                         loop_owner,
-                                                         &context_owner,
+                                                         NULL,
                                                          &found_captured_vars);
   EXPECT_EQ(first_frame_index, next_frame_index);  // a and c not in frame.
-  EXPECT_EQ(parent_scope, context_owner);  // parent_scope allocated a context.
   const intptr_t parent_scope_context_level = 1;
   EXPECT_EQ(parent_scope_context_level, parent_scope->context_level());
   EXPECT(found_captured_vars);
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 7103b61..4f8be44 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -220,14 +220,12 @@
 
   // Allocate parameters and local variables, either in the local frame or
   // in the context(s).
-  LocalScope* context_owner = NULL;  // No context needed yet.
   bool found_captured_variables = false;
   int next_free_frame_index =
       scope->AllocateVariables(first_parameter_index_,
                                num_params,
                                first_stack_local_index_,
-                               scope,
-                               &context_owner,
+                               NULL,
                                &found_captured_variables);
 
   // Frame indices are relative to the frame pointer and are decreasing.
@@ -9411,7 +9409,7 @@
     // restore saved_try_context
 
     SequenceNode* true_branch =
-        new(Z) SequenceNode(Scanner::kNoSourcePos, current_block_->scope);
+        new(Z) SequenceNode(Scanner::kNoSourcePos, NULL);
     AstNode* return_from_generator = new(Z) ReturnNode(yield_pos);
     true_branch->Add(return_from_generator);
     AddNodeForFinallyInlining(return_from_generator);
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index ca7a261..b2819b0 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -277,9 +277,9 @@
 
       // function main uses one ctx var at (1); saves caller ctx.
       "main\n"
-      " 0 ContextLevel  level=1   scope=1   begin=2   end=37\n"
-      " 1 CurrentCtx    scope=0   begin=0   end=0"
+      " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
+      " 1 ContextLevel  level=1   scope=2   begin=4   end=37\n"
       " 2 ContextVar    level=1   begin=10  end=37  name=value\n"
       " 3 StackVar      scope=2   begin=12  end=37  name=f\n",
       CaptureVarsAtLine(lib, "main", 4));
@@ -318,9 +318,9 @@
       // happens here and not in the outermost function.  We always
       // save the entry context at the last possible moment.
       "a.b\n"
-      " 0 ContextLevel  level=1   scope=1   begin=8   end=38\n"
-      " 1 CurrentCtx    scope=0   begin=0   end=0"
+      " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
+      " 1 ContextLevel  level=1   scope=2   begin=10  end=38\n"
       " 2 ContextVar    level=1   begin=16  end=38  name=value\n"
       " 3 StackVar      scope=2   begin=18  end=38  name=c\n"
 
@@ -377,9 +377,9 @@
       // of chaining from b.  This keeps us from holding onto closures
       // that we would never access.
       "a.b.aa\n"
-      " 0 ContextLevel  level=1   scope=1   begin=20  end=50\n"
-      " 1 CurrentCtx    scope=0   begin=0   end=0"
+      " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
+      " 1 ContextLevel  level=1   scope=2   begin=22  end=50\n"
       " 2 ContextVar    level=1   begin=28  end=50  name=value2\n"
       " 3 StackVar      scope=2   begin=30  end=50  name=bb\n"
 
@@ -404,9 +404,9 @@
 
       // a shares value1, saves entry ctx.
       "a\n"
-      " 0 ContextLevel  level=1   scope=1   begin=2   end=68\n"
-      " 1 CurrentCtx    scope=0   begin=0   end=0"
+      " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
+      " 1 ContextLevel  level=1   scope=2   begin=4   end=68\n"
       " 2 ContextVar    level=1   begin=10  end=68  name=value1\n"
       " 3 StackVar      scope=2   begin=12  end=68  name=b\n",
       CaptureVarsAtLine(lib, "a", 7));
@@ -557,9 +557,9 @@
       "   name=:current_context_var\n"
 
       "a\n"
-      " 0 ContextLevel  level=1   scope=1   begin=1   end=76\n"
-      " 1 CurrentCtx    scope=0   begin=0   end=0"
+      " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
+      " 1 ContextLevel  level=1   scope=2   begin=3   end=76\n"
       " 2 ContextVar    level=1   begin=9   end=76  name=x\n"
       " 3 StackVar      scope=2   begin=11  end=76  name=b\n",
       CaptureVarsAtLine(lib, "a", 10));
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index b92feae..f25d71a 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -139,44 +139,44 @@
 void LocalScope::AllocateContextVariable(LocalVariable* variable,
                                          LocalScope** context_owner) {
   ASSERT(variable->is_captured());
-  ASSERT(variable->owner()->loop_level() == loop_level());
-  if (num_context_variables_ == 0) {
-    // This scope will allocate and chain a new context.
-    int new_context_level = ((*context_owner) == NULL) ?
-        1 : (*context_owner)->context_level() + 1;
-    // This scope becomes the current context owner.
-    *context_owner = this;
-    set_context_level(new_context_level);
-  }
+  ASSERT(variable->owner() == this);
   // The context level in the owner scope of a captured variable indicates at
   // code generation time how far to walk up the context chain in order to
   // access the variable from the current context level.
-  if (!variable->owner()->HasContextLevel()) {
-    ASSERT(variable->owner() != this);
-    variable->owner()->set_context_level(context_level());
+  if ((*context_owner) == NULL) {
+    ASSERT(num_context_variables_ == 0);
+    // This scope becomes the current context owner.
+    set_context_level(1);
+    *context_owner = this;
+  } else if ((*context_owner)->loop_level() < loop_level()) {
+    // The captured variable is at a deeper loop level than the current context.
+    // This scope will allocate and chain a new context.
+    ASSERT(num_context_variables_ == 0);
+    // This scope becomes the current context owner.
+    set_context_level((*context_owner)->context_level() + 1);
+    *context_owner = this;
   } else {
-    ASSERT(variable->owner()->context_level() == context_level());
+    // Allocate the captured variable in the current context.
+    if (!HasContextLevel()) {
+      ASSERT(variable->owner() != *context_owner);
+      set_context_level((*context_owner)->context_level());
+    } else {
+      ASSERT(context_level() == (*context_owner)->context_level());
+    }
   }
-  variable->set_index(num_context_variables_++);
+  variable->set_index((*context_owner)->num_context_variables_++);
 }
 
 
 int LocalScope::AllocateVariables(int first_parameter_index,
                                   int num_parameters,
                                   int first_frame_index,
-                                  LocalScope* loop_owner,
-                                  LocalScope** context_owner,
+                                  LocalScope* context_owner,
                                   bool* found_captured_variables) {
   // We should not allocate variables of nested functions while compiling an
   // enclosing function.
   ASSERT(function_level() == 0);
   ASSERT(num_parameters >= 0);
-
-  // Keep track of the current loop owner scope, that is of the highest parent
-  // scope at the same loop level as this scope.
-  if (loop_level() > loop_owner->loop_level()) {
-    loop_owner = this;
-  }
   // Parameters must be listed first and must all appear in the top scope.
   ASSERT(num_parameters <= num_variables());
   int pos = 0;  // Current variable position.
@@ -194,7 +194,7 @@
       // context, where it gets copied to. The parameter index reflects the
       // context allocation index.
       frame_index--;
-      loop_owner->AllocateContextVariable(parameter, context_owner);
+      AllocateContextVariable(parameter, &context_owner);
       *found_captured_variables = true;
     } else {
       parameter->set_index(frame_index--);
@@ -208,7 +208,7 @@
     pos++;
     if (variable->owner() == this) {
       if (variable->is_captured()) {
-        loop_owner->AllocateContextVariable(variable, context_owner);
+        AllocateContextVariable(variable, &context_owner);
         *found_captured_variables = true;
       } else {
         variable->set_index(frame_index--);
@@ -216,27 +216,19 @@
     }
   }
   // Allocate variables of all children.
-  int min_frame_index = frame_index;
+  int min_frame_index = frame_index;  // Frame index decreases with allocations.
   LocalScope* child = this->child();
   while (child != NULL) {
-    LocalScope* child_context_owner = *context_owner;
     int const dummy_parameter_index = 0;  // Ignored, since no parameters.
     int const num_parameters_in_child = 0;  // No parameters in children scopes.
     int child_frame_index = child->AllocateVariables(dummy_parameter_index,
                                                      num_parameters_in_child,
                                                      frame_index,
-                                                     loop_owner,
-                                                     &child_context_owner,
+                                                     context_owner,
                                                      found_captured_variables);
     if (child_frame_index < min_frame_index) {
       min_frame_index = child_frame_index;
     }
-    // A context allocated at a deeper loop level than the current loop level is
-    // not shared between children.
-    if ((child_context_owner != *context_owner) &&
-        (child_context_owner->loop_level() <= loop_owner->loop_level())) {
-      *context_owner = child_context_owner;  // Share context between siblings.
-    }
     child = child->sibling();
   }
   return min_frame_index;
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index 2cbb3f0..faa56a8 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -313,8 +313,7 @@
   int AllocateVariables(int first_parameter_index,
                         int num_parameters,
                         int first_frame_index,
-                        LocalScope* loop_owner,
-                        LocalScope** context_owner,
+                        LocalScope* context_owner,
                         bool* found_captured_variables);
 
   // Creates variable info for the scope and all its nested scopes.
diff --git a/tests/compiler/dart2js/async_await_js_transform_test.dart b/tests/compiler/dart2js/async_await_js_transform_test.dart
index a193616..36aa10d 100644
--- a/tests/compiler/dart2js/async_await_js_transform_test.dart
+++ b/tests/compiler/dart2js/async_await_js_transform_test.dart
@@ -597,7 +597,7 @@
           return thenHelper(foo2(), __body, __completer);
         case 11:
           // returning from await.
-          i = __result;
+          i += __result;
           // goto for condition
           __goto = 3;
           break;
@@ -1059,4 +1059,83 @@
   }
   return thenHelper(null, __body, __completer, null);
 }""");
+
+  testTransform("""
+  function(m) async {
+    var exception = 1;
+    try {
+      await 42;
+      throw 42;
+    } catch (exception) {
+      exception = await 10;
+      exception += await 10;
+      exception++;
+      exception--;
+      ++exception;
+      --exception;
+      exception += 10;
+    }
+    print(exception);
+  }""", """
+function(m) {
+  var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, __next = [], exception, __exception;
+  function __body(__errorCode, __result) {
+    if (__errorCode === 1) {
+      __currentError = __result;
+      __goto = __handler;
+    }
+    while (true)
+      switch (__goto) {
+        case 0:
+          // Function start
+          exception = 1;
+          __handler = 3;
+          __goto = 6;
+          return thenHelper(42, __body, __completer);
+        case 6:
+          // returning from await.
+          throw 42;
+          __handler = 1;
+          // goto after finally
+          __goto = 5;
+          break;
+        case 3:
+          // catch
+          __handler = 2;
+          __exception = __currentError;
+          __goto = 7;
+          return thenHelper(10, __body, __completer);
+        case 7:
+          // returning from await.
+          __exception = __result;
+          __goto = 8;
+          return thenHelper(10, __body, __completer);
+        case 8:
+          // returning from await.
+          __exception += __result;
+          __exception++;
+          __exception--;
+          ++__exception;
+          --__exception;
+          __exception += 10;
+          // goto after finally
+          __goto = 5;
+          break;
+        case 2:
+          // uncaught
+          // goto rethrow
+          __goto = 1;
+          break;
+        case 5:
+          // after finally
+          print(exception);
+          // implicit return
+          return thenHelper(null, 0, __completer, null);
+        case 1:
+          // rethrow
+          return thenHelper(__currentError, 1, __completer);
+      }
+  }
+  return thenHelper(null, __body, __completer, null);
+}""");
 }
diff --git a/tests/language/async_await_catch_regression_test.dart b/tests/language/async_await_catch_regression_test.dart
new file mode 100644
index 0000000..b0df58e
--- /dev/null
+++ b/tests/language/async_await_catch_regression_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+foo() async {
+  throw 42;
+}
+
+test() async {
+  var exception;
+  try {
+    await foo();
+  } catch (e) {
+    print(await(e));
+    await (exception = await e);
+  }
+  Expect.equals(42, exception);
+}
+
+main() {
+  asyncStart();
+  test().then((_) => asyncEnd());
+}
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 2d179b1..567fdbd 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -58,7 +58,6 @@
 vm/*: Skip # Issue 12699
 
 [ $compiler == dart2js && $checked ]
-await_postfix_expr_test: Fail # Issue 22742
 type_variable_bounds_test/02: Fail # Issue 12702
 type_variable_bounds2_test/01: Fail # Issue 12702
 type_variable_bounds2_test/04: Fail # Issue 12702
diff --git a/tests/language/regress_22858_test.dart b/tests/language/regress_22858_test.dart
new file mode 100644
index 0000000..a22ded5
--- /dev/null
+++ b/tests/language/regress_22858_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+main() {
+  var good = "good";
+
+  f1() {
+    {
+      var bad = "bad";
+      f2() { bad; }
+    }
+
+    Expect.equals("good", good);
+    do {
+      Expect.equals("good", good);
+      int ugly = 0;
+      f3() { ugly; }
+    } while (false);
+  }
+
+  f1();
+}
diff --git a/tools/VERSION b/tools/VERSION
index 669823c..6c07f66 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 9
 PATCH 0
 PRERELEASE 10
-PRERELEASE_PATCH 10
+PRERELEASE_PATCH 11