Version 1.9.0-dev.10.1
svn merge -c 44227 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44228 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44237 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44239 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44242 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44246 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44247 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44250 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@44252 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 44cca00..2fdf505 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -1189,9 +1189,15 @@
_updateEndOld = endOffsetOld;
_updateEndNew = endOffsetNew;
_updateDelta = newUnit.length - _oldUnit.length;
+ // A comment change.
+ if (firstPair.kind == _TokenDifferenceKind.COMMENT) {
+ bool success = _resolveComment(newUnit, firstPair);
+ logger.log('Comment change: $success');
+ return success;
+ }
// A Dart documentation comment change.
if (firstPair.kind == _TokenDifferenceKind.COMMENT_DOC) {
- bool success = _resolveComment(_oldUnit, newUnit, firstPair);
+ bool success = _resolveCommentDoc(newUnit, firstPair);
logger.log('Documentation comment resolved: $success');
return success;
}
@@ -1309,11 +1315,32 @@
}
/**
+ * Attempts to resolve a comment change.
+ * Returns `true` if success.
+ */
+ bool _resolveComment(CompilationUnit newUnit, _TokenPair firstPair) {
+ Token oldToken = firstPair.oldToken;
+ Token newToken = firstPair.newToken;
+ CommentToken newComments = newToken.precedingComments;
+ // update token references
+ _updateOffset = oldToken.offset - 1;
+ _shiftTokens(firstPair.oldToken);
+ _setPrecedingComments(oldToken, newComments);
+ // update elements
+ IncrementalResolver incrementalResolver = new IncrementalResolver(
+ _unitElement, _updateOffset, _updateEndOld, _updateEndNew);
+ incrementalResolver._updateElementNameOffsets();
+ incrementalResolver._shiftEntryErrors();
+ _updateEntry();
+ // OK
+ return true;
+ }
+
+ /**
* Attempts to resolve a documentation comment change.
* Returns `true` if success.
*/
- bool _resolveComment(
- CompilationUnit oldUnit, CompilationUnit newUnit, _TokenPair firstPair) {
+ bool _resolveCommentDoc(CompilationUnit newUnit, _TokenPair firstPair) {
Token oldToken = firstPair.oldToken;
Token newToken = firstPair.newToken;
CommentToken oldComments = oldToken.precedingComments;
@@ -1324,7 +1351,7 @@
// find nodes
int offset = oldComments.offset;
logger.log('offset: $offset');
- Comment oldComment = _findNodeCovering(oldUnit, offset, offset);
+ Comment oldComment = _findNodeCovering(_oldUnit, offset, offset);
Comment newComment = _findNodeCovering(newUnit, offset, offset);
logger.log('oldComment.beginToken: ${oldComment.beginToken}');
logger.log('newComment.beginToken: ${newComment.beginToken}');
@@ -1355,6 +1382,40 @@
return token;
}
+ /**
+ * Set the given [comment] as a "precedingComments" for [token].
+ */
+ void _setPrecedingComments(Token token, CommentToken comment) {
+ if (token is BeginTokenWithComment) {
+ token.precedingComments = comment;
+ } else if (token is KeywordTokenWithComment) {
+ token.precedingComments = comment;
+ } else if (token is KeywordToken) {
+ KeywordTokenWithComment newToken =
+ new KeywordTokenWithComment(token.keyword, token.offset, comment);
+ token.previous.setNext(newToken);
+ newToken.setNext(token.next);
+ if (_oldUnit.beginToken == token) {
+ _oldUnit.beginToken = newToken;
+ }
+ } else if (token is StringTokenWithComment) {
+ token.precedingComments = comment;
+ } else if (token is StringToken) {
+ StringTokenWithComment newToken = new StringTokenWithComment(
+ token.type, token.value(), token.offset, comment);
+ token.previous.setNext(newToken);
+ newToken.setNext(token.next);
+ if (_oldUnit.beginToken == token) {
+ _oldUnit.beginToken = newToken;
+ }
+ } else if (token is TokenWithComment) {
+ token.precedingComments = comment;
+ } else {
+ Type parentType = token != null ? token.runtimeType : null;
+ throw new AnalysisException('Uknown parent token type: $parentType');
+ }
+ }
+
void _shiftTokens(Token token) {
while (token != null) {
if (token.offset > _updateOffset) {
@@ -1518,24 +1579,6 @@
}
return count;
}
-
- /**
- * Set the given [comment] as a "precedingComments" for [parent].
- */
- static void _setPrecedingComments(Token parent, CommentToken comment) {
- if (parent is BeginTokenWithComment) {
- parent.precedingComments = comment;
- } else if (parent is KeywordTokenWithComment) {
- parent.precedingComments = comment;
- } else if (parent is StringTokenWithComment) {
- parent.precedingComments = comment;
- } else if (parent is TokenWithComment) {
- parent.precedingComments = comment;
- } else {
- Type parentType = parent != null ? parent.runtimeType : null;
- throw new AnalysisException('Uknown parent token type: $parentType');
- }
- }
}
/**
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 44a595c..c65b545 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -2843,6 +2843,55 @@
''');
}
+ void test_endOfLineComment_header_add() {
+ _resolveUnit(r'''
+main() {
+ Object x;
+ x.foo();
+}
+''');
+ _updateAndValidate(r'''
+// 000
+main() {
+ Object x;
+ x.foo();
+}
+''');
+ }
+
+ void test_endOfLineComment_header_remove() {
+ _resolveUnit(r'''
+// 000
+main() {
+ Object x;
+ x.foo();
+}
+''');
+ _updateAndValidate(r'''
+main() {
+ Object x;
+ x.foo();
+}
+''');
+ }
+
+ void test_endOfLineComment_header_update() {
+ _resolveUnit(r'''
+// 000
+main() {
+ Object x;
+ x.foo();
+}
+''');
+ _updateAndValidate(r'''
+// 10
+main() {
+ Object x;
+ x.foo();
+}
+''');
+ }
+
void test_endOfLineComment_localFunction_inTopLevelVariable() {
_resolveUnit(r'''
typedef int Binary(one, two, three);
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 66d94ab..1490ada 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -1770,14 +1770,33 @@
}
@override
- js.Fun finishFunction(List<js.Parameter> params,
+ js.Fun finishFunction(List<js.Parameter> parameters,
js.Statement rewrittenBody,
js.VariableDeclarationList variableDeclarations) {
+ // Each iterator invocation on the iterable should work on its own copy of
+ // the parameters.
+ // TODO(sigurdm): We only need to do this copying for parameters that are mutated.
+ List<js.VariableInitialization> declarations =
+ new List<js.VariableInitialization>();
+ List<js.Parameter> renamedParameters = new List<js.Parameter>();
+ for (js.Parameter parameter in parameters) {
+ String name = parameter.name;
+ String renamedName = freshName(name);
+ renamedParameters.add(new js.Parameter(renamedName));
+ declarations.add(
+ new js.VariableInitialization(new js.VariableDeclaration(name),
+ new js.VariableUse(renamedName)));
+ }
+ js.VariableDeclarationList copyParameters =
+ new js.VariableDeclarationList(declarations);
return js.js("""
- function (#params) {
+ function (#renamedParameters) {
if (#needsThis)
var #self = this;
return new #newIterable(function () {
+ if (#hasParameters) {
+ #copyParameters;
+ }
#varDecl;
return function #body(#errorCode, #result) {
if (#errorCode === #ERROR) {
@@ -1789,9 +1808,11 @@
});
}
""", {
- "params": params,
+ "renamedParameters": renamedParameters,
"needsThis": analysis.hasThis,
"helperBody": rewrittenBody,
+ "hasParameters": parameters.isNotEmpty,
+ "copyParameters": copyParameters,
"varDecl": variableDeclarations,
"errorCode": errorCodeName,
"newIterable": newIterable,
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 7fd5622..e57d0a9 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -279,16 +279,16 @@
// Class which describes an inlined finally block which is used to generate
// inlined code for the finally blocks when there is an exit from a try
// block using 'return', 'break' or 'continue'.
-class Parser::TryBlocks : public ZoneAllocated {
+class Parser::TryStack : public ZoneAllocated {
public:
- TryBlocks(Block* try_block, TryBlocks* outer_try_block, intptr_t try_index)
+ TryStack(Block* try_block, TryStack* outer_try, intptr_t try_index)
: try_block_(try_block),
inlined_finally_nodes_(),
- outer_try_block_(outer_try_block),
+ outer_try_(outer_try),
try_index_(try_index),
inside_catch_(false) { }
- TryBlocks* outer_try_block() const { return outer_try_block_; }
+ TryStack* outer_try() const { return outer_try_; }
Block* try_block() const { return try_block_; }
intptr_t try_index() const { return try_index_; }
bool inside_catch() const { return inside_catch_; }
@@ -305,15 +305,15 @@
private:
Block* try_block_;
GrowableArray<AstNode*> inlined_finally_nodes_;
- TryBlocks* outer_try_block_;
+ TryStack* outer_try_;
const intptr_t try_index_;
bool inside_catch_;
- DISALLOW_COPY_AND_ASSIGN(TryBlocks);
+ DISALLOW_COPY_AND_ASSIGN(TryStack);
};
-void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) {
+void Parser::TryStack::AddNodeForFinallyInlining(AstNode* node) {
inlined_finally_nodes_.Add(node);
}
@@ -335,7 +335,7 @@
literal_token_(LiteralToken::Handle(zone())),
current_class_(Class::Handle(zone())),
library_(Library::Handle(zone(), library.raw())),
- try_blocks_list_(NULL),
+ try_stack_(NULL),
last_used_try_index_(0),
unregister_pending_function_(false),
async_temp_scope_(NULL),
@@ -368,7 +368,7 @@
library_(Library::Handle(zone(), Class::Handle(
zone(),
parsed_function->function().origin()).library())),
- try_blocks_list_(NULL),
+ try_stack_(NULL),
last_used_try_index_(0),
unregister_pending_function_(false),
async_temp_scope_(NULL),
@@ -2153,6 +2153,7 @@
void Parser::GenerateSuperConstructorCall(const Class& cls,
intptr_t supercall_pos,
LocalVariable* receiver,
+ AstNode* phase_parameter,
ArgumentListNode* forwarding_args) {
const Class& super_class = Class::Handle(Z, cls.SuperClass());
// Omit the implicit super() if there is no super class (i.e.
@@ -2171,9 +2172,6 @@
AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver);
arguments->Add(implicit_argument);
// Implicit construction phase parameter is second argument.
- AstNode* phase_parameter =
- new LiteralNode(supercall_pos,
- Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll)));
arguments->Add(phase_parameter);
// If this is a super call in a forwarding constructor, add the user-
@@ -2564,7 +2562,10 @@
if (!super_init_seen) {
// Generate implicit super() if we haven't seen an explicit super call
// or constructor redirection.
- GenerateSuperConstructorCall(cls, TokenPos(), receiver, NULL);
+ AstNode* phase_parameter = new LiteralNode(
+ TokenPos(), Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll)));
+ GenerateSuperConstructorCall(
+ cls, TokenPos(), receiver, phase_parameter, NULL);
}
CheckFieldsInitialized(cls);
}
@@ -2686,10 +2687,12 @@
}
}
- GenerateSuperConstructorCall(current_class(),
- Scanner::kNoSourcePos,
- receiver,
- forwarding_args);
+ GenerateSuperConstructorCall(
+ current_class(),
+ Scanner::kNoSourcePos,
+ receiver,
+ new LoadLocalNode(Scanner::kNoSourcePos, phase_parameter),
+ forwarding_args);
CheckFieldsInitialized(current_class());
// Empty constructor body.
@@ -5979,8 +5982,8 @@
TRACE_PARSER("CloseAsyncGeneratorTryBlock");
// The generated try-catch-finally that wraps the async generator function
// body is the outermost try statement.
- ASSERT(try_blocks_list_ != NULL);
- ASSERT(try_blocks_list_->outer_try_block() == NULL);
+ ASSERT(try_stack_ != NULL);
+ ASSERT(try_stack_->outer_try() == NULL);
// We only get here when parsing an async generator body.
ASSERT(innermost_function().IsAsyncGenClosure());
@@ -5989,7 +5992,7 @@
// The try-block (closure body code) has been parsed. We are now
// generating the code for the catch block.
LocalScope* try_scope = current_block_->scope;
- try_blocks_list_->enter_catch();
+ try_stack_->enter_catch();
OpenBlock(); // Catch handler list.
OpenBlock(); // Catch block.
@@ -6070,8 +6073,8 @@
current_block_->statements->Add(catch_block);
SequenceNode* catch_handler_list = CloseBlock();
- TryBlocks* try_block = PopTryBlock();
- ASSERT(try_blocks_list_ == NULL); // We popped the outermost try block.
+ TryStack* try_statement = PopTry();
+ ASSERT(try_stack_ == NULL); // We popped the outermost try block.
// Finally block: closing the stream and returning. (Note: the return
// is necessary otherwise the back-end will append a rethrow of the
@@ -6095,7 +6098,7 @@
current_block_->statements->Add(return_node);
finally_clause = CloseBlock();
- AstNode* node_to_inline = try_block->GetNodeToInlineFinally(node_index);
+ AstNode* node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
if (node_to_inline != NULL) {
InlinedFinallyNode* node =
new(Z) InlinedFinallyNode(try_end_pos,
@@ -6125,7 +6128,7 @@
AllocateTryIndex(),
true);
- const intptr_t try_index = try_block->try_index();
+ const intptr_t try_index = try_statement->try_index();
AstNode* try_catch_node =
new(Z) TryCatchNode(Scanner::kNoSourcePos,
@@ -6141,12 +6144,12 @@
SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) {
// This is the outermost try-catch of the function.
- ASSERT(try_blocks_list_ != NULL);
- ASSERT(try_blocks_list_->outer_try_block() == NULL);
+ ASSERT(try_stack_ != NULL);
+ ASSERT(try_stack_->outer_try() == NULL);
ASSERT(innermost_function().IsAsyncClosure());
LocalScope* try_scope = current_block_->scope;
- try_blocks_list_->enter_catch();
+ try_stack_->enter_catch();
OpenBlock(); // Catch handler list.
OpenBlock(); // Catch block.
@@ -6231,8 +6234,8 @@
handler_types.SetLength(0);
handler_types.Add(*exception_param.type);
- TryBlocks* inner_try_block = PopTryBlock();
- const intptr_t try_index = inner_try_block->try_index();
+ TryStack* try_statement = PopTry();
+ const intptr_t try_index = try_statement->try_index();
CatchClauseNode* catch_clause = new (Z) CatchClauseNode(
Scanner::kNoSourcePos,
@@ -6277,8 +6280,8 @@
// Open the try block.
OpenBlock();
// This is the outermost try-catch in the function.
- ASSERT(try_blocks_list_ == NULL);
- PushTryBlock(current_block_);
+ ASSERT(try_stack_ == NULL);
+ PushTry(current_block_);
SetupSavedTryContext(context_var);
}
@@ -8150,20 +8153,18 @@
// If the await or yield being parsed is in a try block, the continuation code
// needs to restore the corresponding stack-based variable :saved_try_ctx_var,
-// and possibly the stack-based variable :saved_try_ctx_var of the outer try
-// block.
+// and the stack-based variable :saved_try_ctx_var of the outer try block.
// The inner :saved_try_ctx_var is used by a finally clause handling an
-// exception thrown by the continuation code in a catch clause. If no finally
-// clause exists, the catch or finally clause of the outer try block, if any,
-// uses the outer :saved_try_ctx_var to handle the exception.
+// exception thrown by the continuation code in a try block or catch block.
+// If no finally clause exists, the catch or finally clause of the outer try
+// block, if any, uses the outer :saved_try_ctx_var to handle the exception.
//
-// * Try blocks: Set the context variable for this try block.
-// * Catch blocks: Set the context variable for this try block and for any outer
-// try block (if existent).
-// * Finally blocks: Set the context variable for any outer try block (if
-// existent). Note that this try block is popped before
-// parsing the finally clause, so the outer try block (if
-// existent) is at the top of the try block list.
+// * Try blocks and catch blocks:
+// Set the context variable for this try block and for the outer try block.
+// * Finally blocks:
+// Set the context variable for the outer try block. Note that the try
+// declaring the finally is popped before parsing the finally clause, so the
+// outer try block is at the top of the try block list.
//
// TODO(regis): Could we return the variables instead of their containing
// scopes? Check if they are already setup at this point.
@@ -8175,20 +8176,21 @@
*try_index = CatchClauseNode::kInvalidTryIndex;
*outer_try_scope = NULL;
*outer_try_index = CatchClauseNode::kInvalidTryIndex;
- if (try_blocks_list_ != NULL) {
- LocalScope* scope = try_blocks_list_->try_block()->scope;
+ if (try_stack_ != NULL) {
+ LocalScope* scope = try_stack_->try_block()->scope;
const int current_function_level = current_block_->scope->function_level();
if (scope->function_level() == current_function_level) {
// The block declaring :saved_try_ctx_var variable is the parent of the
// pushed try block.
*try_scope = scope->parent();
- *try_index = try_blocks_list_->try_index();
- if (try_blocks_list_->inside_catch() &&
- (try_blocks_list_->outer_try_block() != NULL)) {
- scope = try_blocks_list_->outer_try_block()->try_block()->scope;
+ *try_index = try_stack_->try_index();
+ if (try_stack_->outer_try() != NULL) {
+ // TODO(regis): Collecting the outer try scope is not necessary if we
+ // are in a finally block. Add support for try_stack_->inside_finally().
+ scope = try_stack_->outer_try()->try_block()->scope;
if (scope->function_level() == current_function_level) {
*outer_try_scope = scope->parent();
- *outer_try_index = try_blocks_list_->outer_try_block()->try_index();
+ *outer_try_index = try_stack_->outer_try()->try_index();
}
}
}
@@ -8703,12 +8705,12 @@
// outer try block (if it exists). The current try block has already been
// removed from the stack of try blocks.
if (is_async) {
- if (try_blocks_list_ != NULL) {
- LocalScope* scope = try_blocks_list_->try_block()->scope;
+ if (try_stack_ != NULL) {
+ LocalScope* scope = try_stack_->try_block()->scope;
if (scope->function_level() == current_block_->scope->function_level()) {
current_block_->statements->Add(
AwaitTransformer::RestoreSavedTryContext(
- Z, scope->parent(), try_blocks_list_->try_index()));
+ Z, scope->parent(), try_stack_->try_index()));
}
}
// We need to save the exception variables as in catch clauses, whether
@@ -8729,18 +8731,16 @@
}
-void Parser::PushTryBlock(Block* try_block) {
+void Parser::PushTry(Block* try_block) {
intptr_t try_index = AllocateTryIndex();
- TryBlocks* block = new(Z) TryBlocks(
- try_block, try_blocks_list_, try_index);
- try_blocks_list_ = block;
+ try_stack_ = new(Z) TryStack(try_block, try_stack_, try_index);
}
-Parser::TryBlocks* Parser::PopTryBlock() {
- TryBlocks* innermost_try_block = try_blocks_list_;
- try_blocks_list_ = try_blocks_list_->outer_try_block();
- return innermost_try_block;
+Parser::TryStack* Parser::PopTry() {
+ TryStack* innermost_try = try_stack_;
+ try_stack_ = try_stack_->outer_try();
+ return innermost_try;
}
@@ -8749,7 +8749,7 @@
return;
}
ASSERT(node->IsReturnNode() || node->IsJumpNode());
- TryBlocks* iterator = try_blocks_list_;
+ TryStack* iterator = try_stack_;
while (iterator != NULL) {
// For continue and break node check if the target label is in scope.
if (node->IsJumpNode()) {
@@ -8766,7 +8766,7 @@
}
}
iterator->AddNodeForFinallyInlining(node);
- iterator = iterator->outer_try_block();
+ iterator = iterator->outer_try();
}
}
@@ -8963,9 +8963,9 @@
// In case of async closures, restore :saved_try_context_var before executing
// the catch clauses.
if (is_async && (current != NULL)) {
- ASSERT(try_blocks_list_ != NULL);
+ ASSERT(try_stack_ != NULL);
SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL);
- const TryBlocks* try_block = try_blocks_list_->outer_try_block();
+ const TryStack* try_block = try_stack_->outer_try();
if (try_block != NULL) {
LocalScope* scope = try_block->try_block()->scope;
if (scope->function_level() ==
@@ -9091,6 +9091,15 @@
AstNode* Parser::ParseTryStatement(String* label_name) {
TRACE_PARSER("ParseTryStatement");
+
+ const intptr_t try_pos = TokenPos();
+ SourceLabel* try_label = NULL;
+ if (label_name != NULL) {
+ try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement);
+ OpenBlock();
+ current_block_->scope->AddLabel(try_label);
+ }
+
const bool is_async = innermost_function().IsAsyncClosure() ||
innermost_function().IsAsyncFunction() ||
innermost_function().IsSyncGenClosure() ||
@@ -9110,19 +9119,11 @@
&saved_exception_var,
&saved_stack_trace_var);
- const intptr_t try_pos = TokenPos();
ConsumeToken(); // Consume the 'try'.
- SourceLabel* try_label = NULL;
- if (label_name != NULL) {
- try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement);
- OpenBlock();
- current_block_->scope->AddLabel(try_label);
- }
-
// Now parse the 'try' block.
OpenBlock();
- PushTryBlock(current_block_);
+ PushTry(current_block_);
ExpectToken(Token::kLBRACE);
if (is_async) {
@@ -9139,7 +9140,7 @@
}
// Now parse the 'catch' blocks if any.
- try_blocks_list_->enter_catch();
+ try_stack_->enter_catch();
const intptr_t handler_pos = TokenPos();
const GrowableObjectArray& handler_types =
GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
@@ -9154,12 +9155,11 @@
handler_types,
&needs_stack_trace);
- TryBlocks* inner_try_block = PopTryBlock();
- const intptr_t try_index = inner_try_block->try_index();
- TryBlocks* outer_try_block = try_blocks_list_;
- const intptr_t outer_try_index = (outer_try_block != NULL)
- ? outer_try_block->try_index()
- : CatchClauseNode::kInvalidTryIndex;
+ TryStack* try_statement = PopTry();
+ const intptr_t try_index = try_statement->try_index();
+ TryStack* outer_try = try_stack_;
+ const intptr_t outer_try_index = (outer_try != NULL) ?
+ outer_try->try_index() : CatchClauseNode::kInvalidTryIndex;
// Finally parse the 'finally' block.
SequenceNode* finally_block = NULL;
@@ -9168,8 +9168,7 @@
const intptr_t finally_pos = TokenPos();
// Add the finally block to the exit points recorded so far.
intptr_t node_index = 0;
- AstNode* node_to_inline =
- inner_try_block->GetNodeToInlineFinally(node_index);
+ AstNode* node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
while (node_to_inline != NULL) {
finally_block = ParseFinallyBlock(
is_async,
@@ -9183,7 +9182,7 @@
outer_try_index);
AddFinallyBlockToNode(is_async, node_to_inline, node);
node_index += 1;
- node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index);
+ node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
tokens_iterator_.SetCurrentPosition(finally_pos);
}
finally_block = ParseFinallyBlock(
@@ -9529,7 +9528,7 @@
ConsumeToken();
ExpectSemicolon();
// Check if it is ok to do a rethrow.
- if ((try_blocks_list_ == NULL) || !try_blocks_list_->inside_catch()) {
+ if ((try_stack_ == NULL) || !try_stack_->inside_catch()) {
ReportError(statement_pos, "rethrow of an exception is not valid here");
}
@@ -9537,7 +9536,7 @@
// instead of :exception_var and :stack_trace_var.
// These variables are bound in the block containing the try.
// Look in the try scope directly.
- LocalScope* scope = try_blocks_list_->try_block()->scope->parent();
+ LocalScope* scope = try_stack_->try_block()->scope->parent();
ASSERT(scope != NULL);
LocalVariable* excp_var;
LocalVariable* trace_var;
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index d72d655..0e3d694 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -223,7 +223,7 @@
friend class EffectGraphVisitor; // For BuildNoSuchMethodArguments.
struct Block;
- class TryBlocks;
+ class TryStack;
Parser(const Script& script, const Library& library, intptr_t token_pos);
Parser(const Script& script, ParsedFunction* function, intptr_t token_pos);
@@ -465,6 +465,7 @@
void GenerateSuperConstructorCall(const Class& cls,
intptr_t supercall_pos,
LocalVariable* receiver,
+ AstNode* phase_parameter,
ArgumentListNode* forwarding_args);
AstNode* ParseSuperInitializer(const Class& cls, LocalVariable* receiver);
AstNode* ParseInitializer(const Class& cls,
@@ -619,10 +620,10 @@
LocalVariable* stack_trace_var,
LocalVariable* rethrow_exception_var,
LocalVariable* rethrow_stack_trace_var);
- // Adds try block to the list of try blocks seen so far.
- void PushTryBlock(Block* try_block);
- // Pops the inner most try block from the list.
- TryBlocks* PopTryBlock();
+ // Push try block onto the stack of try blocks in scope.
+ void PushTry(Block* try_block);
+ // Pop the inner most try block from the stack.
+ TryStack* PopTry();
// Collect try block scopes and indices if await or yield is in try block.
void CheckAsyncOpInTryBlock(LocalScope** try_scope,
int16_t* try_index,
@@ -839,10 +840,10 @@
// defined, or the library of a mixin class where the function originates.
Library& library_;
- // List of try blocks seen so far, this is used to generate inlined finally
+ // Stack of try blocks in scope, this is used to generate inlined finally
// code at all points in the try block where an exit from the block is
// done using 'return', 'break' or 'continue' statements.
- TryBlocks* try_blocks_list_;
+ TryStack* try_stack_;
// Each try in this function gets its own try index.
int16_t AllocateTryIndex();
diff --git a/tests/language/async_break_in_finally_test.dart b/tests/language/async_break_in_finally_test.dart
new file mode 100644
index 0000000..4ac9994
--- /dev/null
+++ b/tests/language/async_break_in_finally_test.dart
@@ -0,0 +1,52 @@
+// 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";
+
+then43() async {
+ label: try {
+ return await 42;
+ } finally {
+ break label;
+ }
+ return await 43;
+}
+
+then42() async {
+ label: try {
+ return await 42;
+ } finally {
+ }
+ return await 43;
+}
+
+now43() {
+ label: try {
+ return 42;
+ } finally {
+ break label;
+ }
+ return 43;
+}
+
+now42() {
+ label: try {
+ return 42;
+ } finally {
+ }
+ return 43;
+}
+
+test() async {
+ Expect.equals(42, await then42());
+ Expect.equals(43, await then43());
+ Expect.equals(42, now42());
+ Expect.equals(43, now43());
+}
+
+main() {
+ asyncStart();
+ test().then((_) => asyncEnd());
+}
\ No newline at end of file
diff --git a/tests/language/constructor_with_mixin_test.dart b/tests/language/constructor_with_mixin_test.dart
new file mode 100644
index 0000000..0da9049
--- /dev/null
+++ b/tests/language/constructor_with_mixin_test.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// Test super constructor invocation with mixins.
+// Regression test for issue dartbug.com/22604
+
+import "package:expect/expect.dart";
+
+var a_count = 0;
+var b_count = 0;
+
+class A {
+ final int x;
+ A(int this.x) {
+ a_count++;
+ }
+}
+
+class I { }
+
+class B extends A with I {
+ int y;
+
+ B(int xx) : super(xx), y = 13 {
+ b_count++;
+ }
+}
+
+void main() {
+ var b = new B(17);
+ Expect.equals(1, a_count);
+ Expect.equals(1, b_count);
+}
+
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index f716bab..aead0c9 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -3,7 +3,6 @@
# BSD-style license that can be found in the LICENSE file.
[ $compiler == dart2js ]
-syncstar_yield_test/copyParameters: RuntimeError # Issue 22322
sync_generator2_test/07: MissingCompileTimeError # Issue 22324
sync_generator2_test/08: MissingCompileTimeError # Issue 22324
sync_generator2_test/10: MissingCompileTimeError # Issue 22324
diff --git a/tests/language/regress_22579_test.dart b/tests/language/regress_22579_test.dart
new file mode 100644
index 0000000..76c8f42
--- /dev/null
+++ b/tests/language/regress_22579_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 "dart:async";
+import "package:expect/expect.dart";
+
+foo() async {
+ try {
+ await 1;
+ } catch(e) {
+ }
+ throw "error";
+}
+
+main() async {
+ var error = "no error";
+ try {
+ await foo();
+ } catch (e) {
+ error = e;
+ }
+ Expect.equals("error", error);
+}
+
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index acc5091..3797f59 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -132,6 +132,7 @@
mirrors/invocation_fuzz_test: RuntimeError # Issue 15566
[ $compiler == dart2js && $runtime == jsshell ]
+async/timer_regress22626_test: RuntimeError # Non-zero timers not supported; Issue 7728.
async/future_test: RuntimeError # Timer interface not supported; Issue 7728.
async/slow_consumer2_test: RuntimeError # Timer interface not supported; Issue 7728.
async/slow_consumer3_test: RuntimeError # Timer interface not supported; Issue 7728.
diff --git a/tools/VERSION b/tools/VERSION
index 8b10fa7..2f4c24a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 9
PATCH 0
PRERELEASE 10
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1