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(¶ms, 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.