| Index: pkg/front_end/lib/src/fasta/parser/parser.dart
 | 
| diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
 | 
| index 5158f046ec9efa7fc51149ea1d5a9b671d96d591..ffed72c807a5cd7f9092f07b32c4920afbfd5de6 100644
 | 
| --- a/pkg/front_end/lib/src/fasta/parser/parser.dart
 | 
| +++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
 | 
| @@ -1389,9 +1389,9 @@ class Parser {
 | 
|          if (looksLikeType &&
 | 
|              token.isIdentifier &&
 | 
|              isFunctionDeclaration(token.next)) {
 | 
| -          return parseFunctionExpression(begin);
 | 
| +          return parseNamedFunctionExpression(begin);
 | 
|          } else if (isFunctionDeclaration(begin.next)) {
 | 
| -          return parseFunctionExpression(begin);
 | 
| +          return parseNamedFunctionExpression(begin);
 | 
|          }
 | 
|          return parseSend(begin, continuationContext);
 | 
|  
 | 
| @@ -2446,9 +2446,22 @@ class Parser {
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  Token parseFunction(Token token) {
 | 
| +  Token parseFunctionExpression(Token token) {
 | 
| +    Token beginToken = token;
 | 
| +    listener.beginFunctionExpression(token);
 | 
| +    token = parseFormalParameters(token, MemberKind.Local);
 | 
| +    AsyncModifier savedAsyncModifier = asyncState;
 | 
| +    token = parseAsyncModifier(token);
 | 
| +    bool isBlock = optional('{', token);
 | 
| +    token = parseFunctionBody(token, true, false);
 | 
| +    asyncState = savedAsyncModifier;
 | 
| +    listener.endFunctionExpression(beginToken, token);
 | 
| +    return isBlock ? token.next : token;
 | 
| +  }
 | 
| +
 | 
| +  Token parseFunctionDeclaration(Token token) {
 | 
| +    listener.beginFunctionDeclaration(token);
 | 
|      Token beginToken = token;
 | 
| -    listener.beginFunction(token);
 | 
|      token = parseModifiers(token, MemberKind.Local);
 | 
|      listener.beginFunctionName(token);
 | 
|      token = parseIdentifier(token, IdentifierContext.localFunctionDeclaration);
 | 
| @@ -2462,37 +2475,27 @@ class Parser {
 | 
|      token = parseAsyncModifier(token);
 | 
|      token = parseFunctionBody(token, false, true);
 | 
|      asyncState = savedAsyncModifier;
 | 
| -    listener.endFunction(null, token);
 | 
| -    return token.next;
 | 
| -  }
 | 
| -
 | 
| -  Token parseUnnamedFunction(Token token) {
 | 
| -    Token beginToken = token;
 | 
| -    listener.beginUnnamedFunction(token);
 | 
| -    token = parseFormalParameters(token, MemberKind.Local);
 | 
| -    AsyncModifier savedAsyncModifier = asyncState;
 | 
| -    token = parseAsyncModifier(token);
 | 
| -    bool isBlock = optional('{', token);
 | 
| -    token = parseFunctionBody(token, true, false);
 | 
| -    asyncState = savedAsyncModifier;
 | 
| -    listener.endUnnamedFunction(beginToken, token);
 | 
| -    return isBlock ? token.next : token;
 | 
| -  }
 | 
| -
 | 
| -  Token parseFunctionDeclaration(Token token) {
 | 
| -    listener.beginFunctionDeclaration(token);
 | 
| -    token = parseFunction(token);
 | 
| +    token = token.next;
 | 
|      listener.endFunctionDeclaration(token);
 | 
|      return token;
 | 
|    }
 | 
|  
 | 
| -  Token parseFunctionExpression(Token token) {
 | 
| +  /// Parses a named function expression which isn't legal syntax in Dart.
 | 
| +  /// Useful for recovering from Javascript code being pasted into a Dart
 | 
| +  /// proram, as it will interpret `function foo() {}` as a named function
 | 
| +  /// expression with return type `function` and name `foo`.
 | 
| +  Token parseNamedFunctionExpression(Token token) {
 | 
|      Token beginToken = token;
 | 
| -    listener.beginFunction(token);
 | 
| +    listener.beginNamedFunctionExpression(token);
 | 
|      listener.handleModifiers(0);
 | 
|      token = parseType(token, TypeContinuation.Optional);
 | 
| +    if (token != beginToken) {
 | 
| +      reportRecoverableErrorCode(token, fasta.codeReturnTypeFunctionExpression);
 | 
| +    }
 | 
|      listener.beginFunctionName(token);
 | 
| +    Token nameToken = token;
 | 
|      token = parseIdentifier(token, IdentifierContext.functionExpressionName);
 | 
| +    reportRecoverableErrorCode(nameToken, fasta.codeNamedFunctionExpression);
 | 
|      listener.endFunctionName(beginToken, token);
 | 
|      token = parseTypeVariablesOpt(token);
 | 
|      token = parseFormalParameters(token, MemberKind.Local);
 | 
| @@ -2502,7 +2505,7 @@ class Parser {
 | 
|      bool isBlock = optional('{', token);
 | 
|      token = parseFunctionBody(token, true, false);
 | 
|      asyncState = savedAsyncModifier;
 | 
| -    listener.endFunction(null, token);
 | 
| +    listener.endNamedFunctionExpression(token);
 | 
|      return isBlock ? token.next : token;
 | 
|    }
 | 
|  
 | 
| @@ -3113,7 +3116,7 @@ class Parser {
 | 
|        } else if (identical(value, "const")) {
 | 
|          return parseConstExpression(token);
 | 
|        } else if (identical(value, "void")) {
 | 
| -        return parseFunctionExpression(token);
 | 
| +        return parseNamedFunctionExpression(token);
 | 
|        } else if (!inPlainSync &&
 | 
|            (identical(value, "yield") || identical(value, "async"))) {
 | 
|          return expressionExpected(token);
 | 
| @@ -3158,7 +3161,7 @@ class Parser {
 | 
|                  (optional('async', nextToken) ||
 | 
|                      optional('sync', nextToken))))) {
 | 
|        listener.handleNoTypeVariables(token);
 | 
| -      return parseUnnamedFunction(token);
 | 
| +      return parseFunctionExpression(token);
 | 
|      } else {
 | 
|        bool old = mayParseFunctionExpressions;
 | 
|        mayParseFunctionExpressions = true;
 | 
| @@ -3278,7 +3281,7 @@ class Parser {
 | 
|            identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
 | 
|            (identical(kind, KEYWORD_TOKEN) &&
 | 
|                (optional('async', nextToken) || optional('sync', nextToken)))) {
 | 
| -        return parseUnnamedFunction(token);
 | 
| +        return parseFunctionExpression(token);
 | 
|        }
 | 
|        // Fall through.
 | 
|      }
 | 
| 
 |