| Index: src/preparser.cc
|
| diff --git a/src/preparser.cc b/src/preparser.cc
|
| index 463df83dbbbfeda503c8a1fee115063dc8522b84..1a3dd737c5d75f998bbda9361fa04fbb5289e88e 100644
|
| --- a/src/preparser.cc
|
| +++ b/src/preparser.cc
|
| @@ -112,6 +112,16 @@ void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
|
| #undef DUMMY
|
|
|
|
|
| +PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
|
| + switch (peek()) {
|
| + case i::Token::LET:
|
| + return ParseVariableStatement(kSourceElement, ok);
|
| + default:
|
| + return ParseStatement(ok);
|
| + }
|
| +}
|
| +
|
| +
|
| PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
|
| bool* ok) {
|
| // SourceElements ::
|
| @@ -119,7 +129,7 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
|
|
|
| bool allow_directive_prologue = true;
|
| while (peek() != end_token) {
|
| - Statement statement = ParseStatement(CHECK_OK);
|
| + Statement statement = ParseSourceElement(CHECK_OK);
|
| if (allow_directive_prologue) {
|
| if (statement.IsUseStrictLiteral()) {
|
| set_strict_mode();
|
| @@ -172,7 +182,7 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) {
|
|
|
| case i::Token::CONST:
|
| case i::Token::VAR:
|
| - return ParseVariableStatement(ok);
|
| + return ParseVariableStatement(kStatement, ok);
|
|
|
| case i::Token::SEMICOLON:
|
| Next();
|
| @@ -258,7 +268,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
|
| Expect(i::Token::LBRACE, CHECK_OK);
|
| while (peek() != i::Token::RBRACE) {
|
| i::Scanner::Location start_location = scanner_->peek_location();
|
| - Statement statement = ParseStatement(CHECK_OK);
|
| + Statement statement = ParseSourceElement(CHECK_OK);
|
| i::Scanner::Location end_location = scanner_->location();
|
| if (strict_mode() && statement.IsFunctionDeclaration()) {
|
| ReportMessageAt(start_location.beg_pos, end_location.end_pos,
|
| @@ -272,11 +282,15 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
|
| }
|
|
|
|
|
| -PreParser::Statement PreParser::ParseVariableStatement(bool* ok) {
|
| +PreParser::Statement PreParser::ParseVariableStatement(
|
| + VariableDeclarationContext var_context,
|
| + bool* ok) {
|
| // VariableStatement ::
|
| // VariableDeclarations ';'
|
|
|
| - Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
|
| + Statement result = ParseVariableDeclarations(var_context,
|
| + NULL,
|
| + CHECK_OK);
|
| ExpectSemicolon(CHECK_OK);
|
| return result;
|
| }
|
| @@ -287,9 +301,10 @@ PreParser::Statement PreParser::ParseVariableStatement(bool* ok) {
|
| // *var is untouched; in particular, it is the caller's responsibility
|
| // to initialize it properly. This mechanism is also used for the parsing
|
| // of 'for-in' loops.
|
| -PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN,
|
| - int* num_decl,
|
| - bool* ok) {
|
| +PreParser::Statement PreParser::ParseVariableDeclarations(
|
| + VariableDeclarationContext var_context,
|
| + int* num_decl,
|
| + bool* ok) {
|
| // VariableDeclarations ::
|
| // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
|
|
|
| @@ -304,13 +319,25 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN,
|
| return Statement::Default();
|
| }
|
| Consume(i::Token::CONST);
|
| + } else if (peek() == i::Token::LET) {
|
| + if (var_context != kSourceElement &&
|
| + var_context != kForStatement) {
|
| + i::Scanner::Location location = scanner_->peek_location();
|
| + ReportMessageAt(location.beg_pos, location.end_pos,
|
| + "unprotected_let", NULL);
|
| + *ok = false;
|
| + return Statement::Default();
|
| + }
|
| + Consume(i::Token::LET);
|
| } else {
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
|
|
| - // The scope of a variable/const declared anywhere inside a function
|
| - // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
|
| + // The scope of a var/const declared variable anywhere inside a function
|
| + // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
|
| + // of a let declared variable is the scope of the immediately enclosing
|
| + // block.
|
| int nvars = 0; // the number of variables declared
|
| do {
|
| // Parse variable name.
|
| @@ -326,7 +353,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN,
|
| nvars++;
|
| if (peek() == i::Token::ASSIGN) {
|
| Expect(i::Token::ASSIGN, CHECK_OK);
|
| - ParseAssignmentExpression(accept_IN, CHECK_OK);
|
| + ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
|
| }
|
| } while (peek() == i::Token::COMMA);
|
|
|
| @@ -535,9 +562,10 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
|
| Expect(i::Token::FOR, CHECK_OK);
|
| Expect(i::Token::LPAREN, CHECK_OK);
|
| if (peek() != i::Token::SEMICOLON) {
|
| - if (peek() == i::Token::VAR || peek() == i::Token::CONST) {
|
| + if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
|
| + peek() == i::Token::LET) {
|
| int decl_count;
|
| - ParseVariableDeclarations(false, &decl_count, CHECK_OK);
|
| + ParseVariableDeclarations(kForStatement, &decl_count, CHECK_OK);
|
| if (peek() == i::Token::IN && decl_count == 1) {
|
| Expect(i::Token::IN, CHECK_OK);
|
| ParseExpression(true, CHECK_OK);
|
|
|