Avoid parsing formal type parameters a second time from inside an async body,

as default values may not be resolved correctly and may conflict with already
parsed formal parameters (fixes #27659).
Added regression test.

R=hausner@google.com

Review URL: https://codereview.chromium.org/2452623002 .
This commit is contained in:
Regis Crelier 2016-10-25 08:11:37 -07:00
parent 6418f8f36c
commit 3342380ff8
2 changed files with 41 additions and 22 deletions

View file

@ -3504,12 +3504,10 @@ SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
ASSERT(func.NumParameters() == params.parameters->length());
if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
// Parse and discard any formal parameters. They are accessed as
// context variables.
ParamList discarded_params;
ParseFormalParameterList(allow_explicit_default_values,
false,
&discarded_params);
// Skip formal parameters. They are accessed as context variables.
// Parsing them again (and discarding them) does not work in case of
// default values with same name as already parsed formal parameter.
SkipToMatchingParenthesis();
}
} else if (func.IsSyncGenClosure()) {
AddSyncGenClosureParameters(&params);
@ -3517,12 +3515,10 @@ SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
AddFormalParamsToScope(&params, current_block_->scope);
ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
// Parse and discard any formal parameters. They are accessed as
// context variables.
ParamList discarded_params;
ParseFormalParameterList(allow_explicit_default_values,
false,
&discarded_params);
// Skip formal parameters. They are accessed as context variables.
// Parsing them again (and discarding them) does not work in case of
// default values with same name as already parsed formal parameter.
SkipToMatchingParenthesis();
}
} else if (func.IsAsyncGenClosure()) {
AddAsyncGenClosureParameters(&params);
@ -3531,12 +3527,10 @@ SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
ASSERT(func.NumParameters() == params.parameters->length());
if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
// Parse and discard any formal parameters. They are accessed as
// context variables.
ParamList discarded_params;
ParseFormalParameterList(allow_explicit_default_values,
false,
&discarded_params);
// Skip formal parameters. They are accessed as context variables.
// Parsing them again (and discarding them) does not work in case of
// default values with same name as already parsed formal parameter.
SkipToMatchingParenthesis();
}
} else {
ParseFormalParameterList(allow_explicit_default_values, false, &params);
@ -14702,10 +14696,7 @@ void Parser::SkipFunctionLiteral() {
ExpectIdentifier("function name expected");
}
if (CurrentToken() == Token::kLPAREN) {
const bool allow_explicit_default_values = true;
ParamList params;
params.skipped = true;
ParseFormalParameterList(allow_explicit_default_values, false, &params);
SkipToMatchingParenthesis();
}
RawFunction::AsyncModifier async_modifier = ParseFunctionModifier();
BoolScope allow_await(&this->await_is_keyword_,

View file

@ -0,0 +1,28 @@
// Copyright (c) 2016, 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.
const String lineLength = '120';
foo({lineLength: lineLength}) {
print(lineLength);
}
bar({lineLength: lineLength}) async {
print(lineLength);
}
baz([lineLength = lineLength]) {
print(lineLength);
}
qux([lineLength = lineLength]) async {
print(lineLength);
}
main() {
foo();
bar();
baz();
qux();
}