Version 0.8.10.3

svn merge -c 29792 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 29794 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 29795 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 29796 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 29797 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 29799 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

Review URL: https://codereview.chromium.org//57813002

git-svn-id: http://dart.googlecode.com/svn/trunk@29803 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 4d384a4..1113f5e 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1220,17 +1220,11 @@
           field.set_value(Instance::Handle(Object::sentinel().raw()));
 
           // Create initializer function.
-          // We don't have the start position of the initializer expression
-          // here, but can compute it from the field identifier position:
-          // The initializer expression starts after the assignment token at +2.
-          const intptr_t initializer_pos = field.token_pos() + 2;
-          const Function& init_function = Function::ZoneHandle(
-              Function::NewStaticInitializer(
-                  String::Handle(field.name()),
-                  type,
-                  cls,
-                  initializer_pos));
-          cls.AddFunction(init_function);
+          if (!field.is_const()) {
+            const Function& init_function = Function::ZoneHandle(
+                Function::NewStaticInitializer(field));
+            cls.AddFunction(init_function);
+          }
         }
       }
     }
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index fb82608..296c27a 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3574,12 +3574,11 @@
   owner()->AddCatchEntry(catch_entry);
   ASSERT(!for_catch.is_open());
   AppendFragment(catch_entry, for_catch);
-  if (node->end_catch_label() != NULL) {
-    JoinEntryInstr* join = node->end_catch_label()->join_for_continue();
-    if (join != NULL) {
-      if (is_open()) Goto(join);
-      exit_ = join;
-    }
+
+  JoinEntryInstr* join = node->end_catch_label()->join_for_continue();
+  if (join != NULL) {
+    if (is_open()) Goto(join);
+    exit_ = join;
   }
 
   if (finally_block != NULL) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 0d4c8530..98a8c9c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4227,6 +4227,21 @@
 }
 
 
+RawField* Function::saved_static_field() const {
+  ASSERT(kind() == RawFunction::kStaticInitializer);
+  const Object& obj = Object::Handle(raw_ptr()->data_);
+  ASSERT(obj.IsField());
+  return Field::Cast(obj).raw();
+}
+
+
+void Function::set_saved_static_field(const Field& value) const {
+  ASSERT(kind() == RawFunction::kStaticInitializer);
+  ASSERT(raw_ptr()->data_ == Object::null());
+  set_data(value);
+}
+
+
 RawFunction* Function::parent_function() const {
   if (IsClosureFunction()) {
     const Object& obj = Object::Handle(raw_ptr()->data_);
@@ -5454,10 +5469,9 @@
 }
 
 
-RawFunction* Function::NewStaticInitializer(const String& field_name,
-                                            const AbstractType& result_type,
-                                            const Class& cls,
-                                            intptr_t initializer_pos) {
+RawFunction* Function::NewStaticInitializer(const Field& field) {
+  ASSERT(field.is_static());
+  const String& field_name = String::Handle(field.name());
   const String& init_name =
       String::Handle(Symbols::New(String::Handle(
           String::Concat(Symbols::InitPrefix(), field_name))));
@@ -5468,9 +5482,9 @@
                     false,  // !const
                     false,  // !abstract
                     false,  // !external
-                    cls,
-                    initializer_pos));
-  init_function.set_result_type(result_type);
+                    Class::Handle(field.owner()),
+                    field.token_pos()));
+  init_function.set_result_type(AbstractType::Handle(field.type()));
   // Static initializer functions are generated by the VM and are therfore
   // hidden from the user. Since they are only executed once, we avoid
   // optimizing and inlining them. After the field is initialized, the
@@ -5479,6 +5493,7 @@
   init_function.set_is_visible(false);
   init_function.set_is_optimizable(false);
   init_function.set_is_inlinable(false);
+  init_function.set_saved_static_field(field);
   return init_function.raw();
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 75ba0b8..281062a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1527,6 +1527,9 @@
   void set_saved_args_desc(const Array& array) const;
   RawArray* saved_args_desc() const;
 
+  void set_saved_static_field(const Field& array) const;
+  RawField* saved_static_field() const;
+
   bool IsMethodExtractor() const {
     return kind() == RawFunction::kMethodExtractor;
   }
@@ -1880,10 +1883,7 @@
 
   // Creates a new static initializer function which is invoked in the implicit
   // static getter function.
-  static RawFunction* NewStaticInitializer(const String& field_name,
-                                           const AbstractType& result_type,
-                                           const Class& cls,
-                                           intptr_t token_pos);
+  static RawFunction* NewStaticInitializer(const Field& field);
 
   // Allocate new function object, clone values from this function. The
   // owner of the clone is new_owner.
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 6ff23a5..91023c5 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -1015,23 +1015,17 @@
             ident_pos,
             field,
             new LiteralNode(ident_pos, Object::transition_sentinel())));
-    // TODO(hausner): If evaluation of the field value throws an exception,
-    // we leave the field value as 'transition_sentinel', which is wrong.
-    // A second reference to the field later throws a circular dependency
-    // exception. The field should instead be set to null after an exception.
-    const String& init_name =
-        String::Handle(Symbols::New(String::Handle(
-        String::Concat(Symbols::InitPrefix(), String::Handle(field.name())))));
+    const String& init_name = String::Handle(
+        Symbols::New(String::Handle(String::Concat(
+            Symbols::InitPrefix(), String::Handle(field.name())))));
     const Function& init_function = Function::ZoneHandle(
         field_class.LookupStaticFunction(init_name));
     ASSERT(!init_function.IsNull());
     ArgumentListNode* arguments = new ArgumentListNode(expr_pos);
     StaticCallNode* init_call =
         new StaticCallNode(expr_pos, init_function, arguments);
+    initialize_field->Add(init_call);
 
-    initialize_field->Add(new StoreStaticFieldNode(ident_pos,
-                                                   field,
-                                                   init_call));
     AstNode* uninitialized_check =
         new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL);
     current_block_->statements->Add(uninitialized_check);
@@ -1057,10 +1051,96 @@
   OpenFunctionBlock(func);
   AddFormalParamsToScope(&params, current_block_->scope);
 
-  intptr_t expr_pos = func.token_pos();
+  // Move forward to the start of the initializer expression.
+  ExpectIdentifier("identifier expected");
+  ExpectToken(Token::kASSIGN);
+  intptr_t token_pos = TokenPos();
+
+  // Synthesize a try-catch block to wrap the initializer expression.
+  LocalVariable* context_var =
+      current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar());
+  if (context_var == NULL) {
+    context_var = new LocalVariable(token_pos,
+                                    Symbols::SavedTryContextVar(),
+                                    Type::ZoneHandle(Type::DynamicType()));
+    current_block_->scope->AddVariable(context_var);
+  }
+  LocalVariable* catch_excp_var =
+      current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar());
+  if (catch_excp_var == NULL) {
+    catch_excp_var = new LocalVariable(token_pos,
+                                       Symbols::ExceptionVar(),
+                                       Type::ZoneHandle(Type::DynamicType()));
+    current_block_->scope->AddVariable(catch_excp_var);
+  }
+  LocalVariable* catch_trace_var =
+      current_block_->scope->LocalLookupVariable(Symbols::StacktraceVar());
+  if (catch_trace_var == NULL) {
+    catch_trace_var = new LocalVariable(token_pos,
+                                        Symbols::StacktraceVar(),
+                                        Type::ZoneHandle(Type::DynamicType()));
+    current_block_->scope->AddVariable(catch_trace_var);
+  }
+
+  OpenBlock();  // Start try block.
   AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
-  ReturnNode* return_node = new ReturnNode(expr_pos, expr);
-  current_block_->statements->Add(return_node);
+  const Field& field = Field::ZoneHandle(func.saved_static_field());
+  ASSERT(!field.is_const());
+  StoreStaticFieldNode* store = new StoreStaticFieldNode(field.token_pos(),
+                                                         field,
+                                                         expr);
+  current_block_->statements->Add(store);
+  SequenceNode* try_block = CloseBlock();  // End try block.
+
+  OpenBlock();  // Start catch handler list.
+  SourceLabel* end_catch_label =
+      SourceLabel::New(token_pos, NULL, SourceLabel::kCatch);
+  current_block_->scope->AddLabel(end_catch_label);
+
+  OpenBlock();  // Start catch clause.
+  AstNode* compare_transition_sentinel = new ComparisonNode(
+      token_pos,
+      Token::kEQ_STRICT,
+      new LoadStaticFieldNode(token_pos, field),
+      new LiteralNode(field.token_pos(), Object::transition_sentinel()));
+
+  SequenceNode* store_null = new SequenceNode(token_pos, NULL);
+  store_null->Add(new StoreStaticFieldNode(
+      field.token_pos(),
+      field,
+      new LiteralNode(token_pos, Instance::ZoneHandle())));
+  AstNode* transition_sentinel_check =
+      new IfNode(token_pos, compare_transition_sentinel, store_null, NULL);
+  current_block_->statements->Add(transition_sentinel_check);
+
+  current_block_->statements->Add(
+      new ThrowNode(token_pos,
+                    new LoadLocalNode(token_pos, catch_excp_var),
+                    new LoadLocalNode(token_pos, catch_trace_var)));
+  current_block_->statements->Add(
+      new JumpNode(token_pos, Token::kCONTINUE, end_catch_label));
+  SequenceNode* catch_clause = CloseBlock();  // End catch clause.
+
+  current_block_->statements->Add(catch_clause);
+  SequenceNode* catch_handler_list = CloseBlock();  // End catch handler list.
+  CatchClauseNode* catch_block =
+      new CatchClauseNode(token_pos,
+                          catch_handler_list,
+                          Array::ZoneHandle(Object::empty_array().raw()),
+                          context_var,
+                          catch_excp_var,
+                          catch_trace_var,
+                          CatchClauseNode::kInvalidTryIndex,
+                          false);  // No stack trace needed.
+
+  AstNode* try_catch_node = new TryCatchNode(token_pos,
+                                             try_block,
+                                             end_catch_label,
+                                             context_var,
+                                             catch_block,
+                                             NULL,  // No finally block.
+                                             AllocateTryIndex());
+  current_block_->statements->Add(try_catch_node);
   return CloseBlock();
 }
 
@@ -3307,7 +3387,6 @@
   Function& setter = Function::Handle();
   Field& class_field = Field::ZoneHandle();
   Instance& init_value = Instance::Handle();
-  intptr_t expr_pos = -1;
   while (true) {
     bool has_initializer = CurrentToken() == Token::kASSIGN;
     bool has_simple_literal = false;
@@ -3332,7 +3411,6 @@
           (LookaheadToken(1) == Token::kSEMICOLON)) {
         has_simple_literal = IsSimpleLiteral(*field->type, &init_value);
       }
-      expr_pos = TokenPos();
       SkipExpr();
     } else {
       // Static const and static final fields must have an initializer.
@@ -3377,13 +3455,12 @@
         getter.set_result_type(*field->type);
         members->AddFunction(getter);
 
-        // Create initializer function.
-        const Function& init_function = Function::ZoneHandle(
-            Function::NewStaticInitializer(*field->name,
-                                           *field->type,
-                                           current_class(),
-                                           expr_pos));
-        members->AddFunction(init_function);
+        // Create initializer function for non-const fields.
+        if (!class_field.is_const()) {
+          const Function& init_function = Function::ZoneHandle(
+              Function::NewStaticInitializer(class_field));
+          members->AddFunction(init_function);
+        }
       }
     }
 
@@ -4493,7 +4570,6 @@
       if ((is_const || is_final) && (LookaheadToken(1) == Token::kSEMICOLON)) {
         has_simple_literal = IsSimpleLiteral(type, &field_value);
       }
-      const intptr_t expr_pos = TokenPos();
       SkipExpr();
       field.set_value(field_value);
       if (!has_simple_literal) {
@@ -4511,12 +4587,11 @@
         top_level->functions.Add(getter);
 
         // Create initializer function.
-        const Function& init_function = Function::ZoneHandle(
-            Function::NewStaticInitializer(var_name,
-                                           type,
-                                           current_class(),
-                                           expr_pos));
-        top_level->functions.Add(init_function);
+        if (!field.is_const()) {
+          const Function& init_function = Function::ZoneHandle(
+              Function::NewStaticInitializer(field));
+          top_level->functions.Add(init_function);
+        }
       }
     } else if (is_final) {
       ErrorMsg(name_pos, "missing initializer for final or const variable");
@@ -6742,7 +6817,6 @@
   // operator.
   bool catch_seen = false;
   bool generic_catch_seen = false;
-  SequenceNode* catch_handler_list = NULL;
   const intptr_t handler_pos = TokenPos();
   OpenBlock();  // Start the catch block sequence.
   current_block_->scope->AddLabel(end_catch_label);
@@ -6866,7 +6940,7 @@
     // Add this individual catch handler to the catch handlers list.
     current_block_->statements->Add(catch_clause);
   }
-  catch_handler_list = CloseBlock();
+  SequenceNode* catch_handler_list = CloseBlock();
   TryBlocks* inner_try_block = PopTryBlock();
   const intptr_t try_index = inner_try_block->try_index();
   TryBlocks* outer_try_block = try_blocks_list_;
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index e324121..8951a02 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -54,8 +54,8 @@
 setlocal
 for %%i in (%1) do set result=%%~fi
 set current=
-for /f "tokens=2 delims=[]" %%i in ('dir /a:l ^"%~dp1^" 2^>nul ^
-                                     ^| find ">     %~n1 ["') do (
+for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
+                                             ^| find ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
index 3b4fe10..33e2c46 100644
--- a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
@@ -426,7 +426,10 @@
       String packageRoot) {
     _packageRoot = packageRoot;
     _exports = new ExportMap.parse(libraryList, packageRoot);
-    var librariesToAnalyze = _exports.allExportedFiles.toList();
+    var librariesToAnalyze =
+        _exports.allExportedFiles
+                .map((file) => new Uri.file(file).toString())
+                .toList();
     librariesToAnalyze.addAll(libraryList.map((uri) => uri.toString()));
 
     // dart2js takes a String, but it expects that to be a Uri, not a file
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index 16d0a1e..48bf58b 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.dart
@@ -80,12 +80,20 @@
   static String get executable => _Platform.executable;
 
   /**
-   * Returns the URI of the script being run in this
-   * isolate. If the URI is relative it is relative to the file URI of
-   * the working directory of the VM when it was started.
+   * Returns the absolute URI of the script being run in this
+   * isolate.
+   *
+   * If the script argument on the command line is relative,
+   * it is resolved to an absolute URI before fetching the script, and
+   * this absolute URI is returned.
+   *
+   * URI resolution only does string manipulation on the script path, and this
+   * may be different from the file system's path resolution behavior. For
+   * example, a symbolic link immediately followed by '..' will not be
+   * looked up.
    *
    * If the executable environment does not support [script] an empty
-   * URI is returned.
+   * [Uri] is returned.
    */
   static Uri get script => _Platform.script;
 
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index 3e018a0..40fe2f0 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -27,7 +27,7 @@
         s.startsWith('file:')) {
       return Uri.parse(s);
     } else {
-      return new Uri.file(s);
+      return Uri.base.resolveUri(new Uri.file(s));
     }
   }
 
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 6e93f45..8a2c9ec 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -54,6 +54,8 @@
 
 
 [ $runtime == vm || $runtime == dartium || $compiler == dart2dart || $compiler == dart2js ]
+Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: fail # co19 issue 648
+
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: fail, pass, ok # co19 issue 634
 Language/12_Expressions/12_Instance_Creation/2_Const_A09_t02: fail, pass, ok # co19 issue 634
 Language/12_Expressions/12_Instance_Creation/2_Const_A09_t03: fail, pass, ok # co19 issue 634
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index e7f75af..b4e5863 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -127,7 +127,6 @@
 Language/12_Expressions/22_Equality_A05_t01: fail # co19-roll r546: Please triage this failure
 Language/12_Expressions/27_Unary_Expressions_A01_t01: fail # co19-roll r546: Please triage this failure
 Language/12_Expressions/30_Identifier_Reference_A02_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/30_Identifier_Reference_A08_t02: fail # co19-roll r546: Please triage this failure
 Language/13_Statements/02_Expression_Statements_A01_t08: fail # co19-roll r546: Please triage this failure
 Language/13_Statements/06_For_A01_t11: fail # co19-roll r546: Please triage this failure
 Language/13_Statements/09_Switch_A01_t02: fail # co19-roll r546: Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 6915f46..48fa47f 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -33,7 +33,6 @@
 
 Language/05_Variables/05_Variables_A05_t01: fail # Dart issue 12539
 Language/05_Variables/05_Variables_A05_t02: fail # Dart issue 12539
-Language/12_Expressions/30_Identifier_Reference_A08_t02: fail # Dart issue 12593
 Language/13_Statements/06_For_A01_t11: fail # Dart issue 5675
 Language/13_Statements/09_Switch_A01_t02: fail # Dart issue 12908
 Language/13_Statements/12_Labels_A01_t03: fail # Dart issue 2238
diff --git a/tests/language/language.status b/tests/language/language.status
index 9c6fe8b..93c1e4b 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -9,7 +9,6 @@
 mixin_super_constructor_named_test: Fail # Issue 12631
 mixin_super_constructor_positionals_test: Fail # Issue 12631
 built_in_identifier_prefix_test: Fail # Issue 6970
-throwing_lazy_variable_test: Fail # Issue 5802
 f_bounded_equality_test: RuntimeError # Issue 14000
 
 # These bugs refer currently ongoing language discussions.
@@ -19,7 +18,6 @@
 closure_in_initializer_test: Fail # Issue 6422
 
 # Regular bugs which should be fixed.
-lazy_static3_test: Fail # Issue 12593
 duplicate_export_negative_test: Fail # Issue 6134
 mixin_forwarding_constructor2_test: Fail # Issue 13641
 
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 6ffdd63..03368b0 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -231,7 +231,6 @@
 map_literal3_test: Fail # Issue 12794
 external_test/13: Fail # Issue 12888
 built_in_identifier_test/01: Fail # Issue 13022
-lazy_static3_test: Fail # Issue 12593
 list_literal1_test/01: Fail # Issue 12993
 map_literal1_test/01: Fail # Issue 12993
 method_override4_test: Fail # Issue 12810
@@ -248,7 +247,6 @@
 constructor5_test: Fail
 constructor6_test: Fail
 closure_in_initializer_test: Fail
-throwing_lazy_variable_test: Fail # Issue 5802
 f_bounded_equality_test: RuntimeError # Issue 14000
 
 # Minified mode failures.
diff --git a/tests/standalone/io/print_env.dart b/tests/standalone/io/print_env.dart
index 28f926c..4337451 100644
--- a/tests/standalone/io/print_env.dart
+++ b/tests/standalone/io/print_env.dart
@@ -5,5 +5,8 @@
 import "dart:io";
 
 main(List<String> arguments) {
+  if (!Platform.script.isAbsolute) {
+    throw "Platform.script is not absolute: ${Platform.script}";
+  }
   print(Platform.environment[arguments[0]]);
 }
diff --git a/tests/standalone/io/process_environment_test.dart b/tests/standalone/io/process_environment_test.dart
index c36ef8c..4376aab 100644
--- a/tests/standalone/io/process_environment_test.dart
+++ b/tests/standalone/io/process_environment_test.dart
@@ -20,6 +20,14 @@
               environment: environment,
               includeParentEnvironment: includeParent)
       .then((result) {
+        if (result.exitCode != 0) {
+          print('print_env.dart subprocess failed '
+                'with exit code ${result.exitCode}');
+          print('stdout:');
+          print(result.stdout);
+          print('stderr:');
+          print(result.stderr);
+        }
         Expect.equals(0, result.exitCode);
         callback(result.stdout);
       });
diff --git a/tools/VERSION b/tools/VERSION
index a2eb097..ee5729d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 8
 BUILD 10
-PATCH 2
+PATCH 3
diff --git a/utils/apidoc/apidoc.dart b/utils/apidoc/apidoc.dart
index 1d29041..326cce2 100644
--- a/utils/apidoc/apidoc.dart
+++ b/utils/apidoc/apidoc.dart
@@ -116,7 +116,7 @@
   // TODO(amouravski): move HtmlDiff inside of the future chain below to re-use
   // the MirrorSystem already analyzed.
   _diff = new HtmlDiff(printWarnings:false);
-  Future htmlDiff = _diff.run(currentDirectory.resolve(libPath));
+  Future htmlDiff = _diff.run(currentDirectory.resolveUri(path.toUri(libPath)));
 
   // TODO(johnniwinther): Libraries for the compilation seem to be more like
   // URIs. Perhaps Path should have a toURI() method.