OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <cmath> | 5 #include <cmath> |
6 | 6 |
7 #include "src/allocation.h" | 7 #include "src/allocation.h" |
8 #include "src/base/logging.h" | 8 #include "src/base/logging.h" |
9 #include "src/conversions-inl.h" | 9 #include "src/conversions-inl.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 | 155 |
156 | 156 |
157 #define CHECK_OK ok); \ | 157 #define CHECK_OK ok); \ |
158 if (!*ok) return kUnknownSourceElements; \ | 158 if (!*ok) return kUnknownSourceElements; \ |
159 ((void)0 | 159 ((void)0 |
160 #define DUMMY ) // to make indentation work | 160 #define DUMMY ) // to make indentation work |
161 #undef DUMMY | 161 #undef DUMMY |
162 | 162 |
163 | 163 |
164 PreParser::Statement PreParser::ParseSourceElement(bool* ok) { | 164 PreParser::Statement PreParser::ParseSourceElement(bool* ok) { |
165 // (Ecma 262 5th Edition, clause 14): | 165 // ECMA 262 6th Edition |
166 // SourceElement: | 166 // StatementListItem[Yield, Return] : |
167 // Statement | 167 // Statement[?Yield, ?Return] |
168 // FunctionDeclaration | 168 // Declaration[?Yield] |
169 // | 169 // |
170 // In harmony mode we allow additionally the following productions | 170 // Declaration[Yield] : |
171 // SourceElement: | 171 // HoistableDeclaration[?Yield] |
172 // LetDeclaration | 172 // ClassDeclaration[?Yield] |
173 // ConstDeclaration | 173 // LexicalDeclaration[In, ?Yield] |
174 // GeneratorDeclaration | 174 // |
| 175 // HoistableDeclaration[Yield, Default] : |
| 176 // FunctionDeclaration[?Yield, ?Default] |
| 177 // GeneratorDeclaration[?Yield, ?Default] |
| 178 // |
| 179 // LexicalDeclaration[In, Yield] : |
| 180 // LetOrConst BindingList[?In, ?Yield] ; |
175 | 181 |
176 switch (peek()) { | 182 switch (peek()) { |
177 case Token::FUNCTION: | 183 case Token::FUNCTION: |
178 return ParseFunctionDeclaration(ok); | 184 return ParseFunctionDeclaration(ok); |
179 case Token::CLASS: | 185 case Token::CLASS: |
180 return ParseClassDeclaration(ok); | 186 return ParseClassDeclaration(ok); |
181 case Token::CONST: | 187 case Token::CONST: |
182 return ParseVariableStatement(kSourceElement, ok); | 188 return ParseVariableStatement(kSourceElement, ok); |
183 case Token::LET: | 189 case Token::LET: |
184 DCHECK(allow_harmony_scoping()); | 190 DCHECK(allow_harmony_scoping()); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 PreParserTraits::ReportMessageAt(start_location.beg_pos, | 304 PreParserTraits::ReportMessageAt(start_location.beg_pos, |
299 end_location.end_pos, | 305 end_location.end_pos, |
300 "strict_function"); | 306 "strict_function"); |
301 *ok = false; | 307 *ok = false; |
302 return Statement::Default(); | 308 return Statement::Default(); |
303 } else { | 309 } else { |
304 return statement; | 310 return statement; |
305 } | 311 } |
306 } | 312 } |
307 | 313 |
308 case Token::CLASS: | |
309 return ParseClassDeclaration(CHECK_OK); | |
310 | |
311 case Token::DEBUGGER: | 314 case Token::DEBUGGER: |
312 return ParseDebuggerStatement(ok); | 315 return ParseDebuggerStatement(ok); |
313 | 316 |
314 case Token::VAR: | 317 case Token::VAR: |
315 case Token::CONST: | |
316 return ParseVariableStatement(kStatement, ok); | 318 return ParseVariableStatement(kStatement, ok); |
317 | 319 |
318 case Token::LET: | 320 case Token::CONST: |
319 DCHECK(allow_harmony_scoping()); | 321 // In ES6 CONST is not allowed as a Statement, only as a |
320 if (strict_mode() == STRICT) { | 322 // LexicalDeclaration, however we continue to allow it in sloppy mode for |
| 323 // backwards compatibility. |
| 324 if (strict_mode() == SLOPPY) { |
321 return ParseVariableStatement(kStatement, ok); | 325 return ParseVariableStatement(kStatement, ok); |
322 } | 326 } |
323 // Fall through. | 327 |
| 328 // Fall through. |
324 default: | 329 default: |
325 return ParseExpressionOrLabelledStatement(ok); | 330 return ParseExpressionOrLabelledStatement(ok); |
326 } | 331 } |
327 } | 332 } |
328 | 333 |
329 | 334 |
330 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 335 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
331 // FunctionDeclaration :: | 336 // FunctionDeclaration :: |
332 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 337 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
333 // GeneratorDeclaration :: | 338 // GeneratorDeclaration :: |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' | 439 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
435 // | 440 // |
436 // * It is a Syntax Error if the code that matches this production is not | 441 // * It is a Syntax Error if the code that matches this production is not |
437 // contained in extended code. | 442 // contained in extended code. |
438 // | 443 // |
439 // However disallowing const in sloppy mode will break compatibility with | 444 // However disallowing const in sloppy mode will break compatibility with |
440 // existing pages. Therefore we keep allowing const with the old | 445 // existing pages. Therefore we keep allowing const with the old |
441 // non-harmony semantics in sloppy mode. | 446 // non-harmony semantics in sloppy mode. |
442 Consume(Token::CONST); | 447 Consume(Token::CONST); |
443 if (strict_mode() == STRICT) { | 448 if (strict_mode() == STRICT) { |
444 if (allow_harmony_scoping()) { | 449 DCHECK(var_context != kStatement); |
445 if (var_context != kSourceElement && var_context != kForStatement) { | 450 if (!allow_harmony_scoping()) { |
446 ReportMessageAt(scanner()->peek_location(), "unprotected_const"); | |
447 *ok = false; | |
448 return Statement::Default(); | |
449 } | |
450 is_strict_const = true; | |
451 require_initializer = var_context != kForStatement; | |
452 } else { | |
453 Scanner::Location location = scanner()->peek_location(); | 451 Scanner::Location location = scanner()->peek_location(); |
454 ReportMessageAt(location, "strict_const"); | 452 ReportMessageAt(location, "strict_const"); |
455 *ok = false; | 453 *ok = false; |
456 return Statement::Default(); | 454 return Statement::Default(); |
457 } | 455 } |
| 456 is_strict_const = true; |
| 457 require_initializer = var_context != kForStatement; |
458 } | 458 } |
459 } else if (peek() == Token::LET && strict_mode() == STRICT) { | 459 } else if (peek() == Token::LET && strict_mode() == STRICT) { |
460 Consume(Token::LET); | 460 Consume(Token::LET); |
461 if (var_context != kSourceElement && var_context != kForStatement) { | 461 DCHECK(var_context != kStatement); |
462 ReportMessageAt(scanner()->peek_location(), "unprotected_let"); | |
463 *ok = false; | |
464 return Statement::Default(); | |
465 } | |
466 } else { | 462 } else { |
467 *ok = false; | 463 *ok = false; |
468 return Statement::Default(); | 464 return Statement::Default(); |
469 } | 465 } |
470 | 466 |
471 // The scope of a var/const declared variable anywhere inside a function | 467 // The scope of a var/const declared variable anywhere inside a function |
472 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | 468 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
473 // of a let declared variable is the scope of the immediately enclosing | 469 // of a let declared variable is the scope of the immediately enclosing |
474 // block. | 470 // block. |
475 int nvars = 0; // the number of variables declared | 471 int nvars = 0; // the number of variables declared |
(...skipping 14 matching lines...) Expand all Loading... |
490 if (num_decl != NULL) *num_decl = nvars; | 486 if (num_decl != NULL) *num_decl = nvars; |
491 return Statement::Default(); | 487 return Statement::Default(); |
492 } | 488 } |
493 | 489 |
494 | 490 |
495 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { | 491 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
496 // ExpressionStatement | LabelledStatement :: | 492 // ExpressionStatement | LabelledStatement :: |
497 // Expression ';' | 493 // Expression ';' |
498 // Identifier ':' Statement | 494 // Identifier ':' Statement |
499 | 495 |
| 496 switch (peek()) { |
| 497 case Token::FUNCTION: |
| 498 case Token::LBRACE: |
| 499 UNREACHABLE(); // Always handled by the callers. |
| 500 case Token::CLASS: |
| 501 ReportUnexpectedToken(Next()); |
| 502 *ok = false; |
| 503 return Statement::Default(); |
| 504 |
| 505 // TODO(arv): Handle `let [` |
| 506 // https://code.google.com/p/v8/issues/detail?id=3847 |
| 507 |
| 508 default: |
| 509 break; |
| 510 } |
| 511 |
500 bool starts_with_identifier = peek_any_identifier(); | 512 bool starts_with_identifier = peek_any_identifier(); |
501 Expression expr = ParseExpression(true, CHECK_OK); | 513 Expression expr = ParseExpression(true, CHECK_OK); |
502 // Even if the expression starts with an identifier, it is not necessarily an | 514 // Even if the expression starts with an identifier, it is not necessarily an |
503 // identifier. For example, "foo + bar" starts with an identifier but is not | 515 // identifier. For example, "foo + bar" starts with an identifier but is not |
504 // an identifier. | 516 // an identifier. |
505 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { | 517 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { |
506 // Expression is a single identifier, and not, e.g., a parenthesized | 518 // Expression is a single identifier, and not, e.g., a parenthesized |
507 // identifier. | 519 // identifier. |
508 DCHECK(!expr.AsIdentifier().IsFutureReserved()); | 520 DCHECK(!expr.AsIdentifier().IsFutureReserved()); |
509 DCHECK(strict_mode() == SLOPPY || | 521 DCHECK(strict_mode() == SLOPPY || |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); | 1027 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
1016 ParseArguments(ok); | 1028 ParseArguments(ok); |
1017 | 1029 |
1018 return Expression::Default(); | 1030 return Expression::Default(); |
1019 } | 1031 } |
1020 | 1032 |
1021 #undef CHECK_OK | 1033 #undef CHECK_OK |
1022 | 1034 |
1023 | 1035 |
1024 } } // v8::internal | 1036 } } // v8::internal |
OLD | NEW |