| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 function_scope.set_is_generator(is_generator); | 65 function_scope.set_is_generator(is_generator); |
| 66 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); | 66 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); |
| 67 bool ok = true; | 67 bool ok = true; |
| 68 int start_position = peek_position(); | 68 int start_position = peek_position(); |
| 69 ParseLazyFunctionLiteralBody(&ok); | 69 ParseLazyFunctionLiteralBody(&ok); |
| 70 if (stack_overflow()) return kPreParseStackOverflow; | 70 if (stack_overflow()) return kPreParseStackOverflow; |
| 71 if (!ok) { | 71 if (!ok) { |
| 72 ReportUnexpectedToken(scanner()->current_token()); | 72 ReportUnexpectedToken(scanner()->current_token()); |
| 73 } else { | 73 } else { |
| 74 ASSERT_EQ(Token::RBRACE, scanner()->peek()); | 74 ASSERT_EQ(Token::RBRACE, scanner()->peek()); |
| 75 if (!is_classic_mode()) { | 75 if (!scope_->is_classic_mode()) { |
| 76 int end_pos = scanner()->location().end_pos; | 76 int end_pos = scanner()->location().end_pos; |
| 77 CheckOctalLiteral(start_position, end_pos, &ok); | 77 CheckOctalLiteral(start_position, end_pos, &ok); |
| 78 if (ok) { | |
| 79 CheckDelayedStrictModeViolation(start_position, end_pos, &ok); | |
| 80 } | |
| 81 } | 78 } |
| 82 } | 79 } |
| 83 return kPreParseSuccess; | 80 return kPreParseSuccess; |
| 84 } | 81 } |
| 85 | 82 |
| 86 | 83 |
| 87 // Preparsing checks a JavaScript program and emits preparse-data that helps | 84 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 88 // a later parsing to be faster. | 85 // a later parsing to be faster. |
| 89 // See preparser-data.h for the data. | 86 // See preparser-data.h for the data. |
| 90 | 87 |
| 91 // The PreParser checks that the syntax follows the grammar for JavaScript, | 88 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 92 // and collects some information about the program along the way. | 89 // and collects some information about the program along the way. |
| 93 // The grammar check is only performed in order to understand the program | 90 // The grammar check is only performed in order to understand the program |
| 94 // sufficiently to deduce some information about it, that can be used | 91 // sufficiently to deduce some information about it, that can be used |
| 95 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 92 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 96 // rather it is to speed up properly written and correct programs. | 93 // rather it is to speed up properly written and correct programs. |
| 97 // That means that contextual checks (like a label being declared where | 94 // That means that contextual checks (like a label being declared where |
| 98 // it is used) are generally omitted. | 95 // it is used) are generally omitted. |
| 99 | 96 |
| 100 void PreParser::ReportUnexpectedToken(Token::Value token) { | |
| 101 // We don't report stack overflows here, to avoid increasing the | |
| 102 // stack depth even further. Instead we report it after parsing is | |
| 103 // over, in ParseProgram. | |
| 104 if (token == Token::ILLEGAL && stack_overflow()) { | |
| 105 return; | |
| 106 } | |
| 107 Scanner::Location source_location = scanner()->location(); | |
| 108 | |
| 109 // Four of the tokens are treated specially | |
| 110 switch (token) { | |
| 111 case Token::EOS: | |
| 112 return ReportMessageAt(source_location, "unexpected_eos", NULL); | |
| 113 case Token::NUMBER: | |
| 114 return ReportMessageAt(source_location, "unexpected_token_number", NULL); | |
| 115 case Token::STRING: | |
| 116 return ReportMessageAt(source_location, "unexpected_token_string", NULL); | |
| 117 case Token::IDENTIFIER: | |
| 118 return ReportMessageAt(source_location, | |
| 119 "unexpected_token_identifier", NULL); | |
| 120 case Token::FUTURE_RESERVED_WORD: | |
| 121 return ReportMessageAt(source_location, "unexpected_reserved", NULL); | |
| 122 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 123 return ReportMessageAt(source_location, | |
| 124 "unexpected_strict_reserved", NULL); | |
| 125 default: | |
| 126 const char* name = Token::String(token); | |
| 127 ReportMessageAt(source_location, "unexpected_token", name); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 | 97 |
| 132 #define CHECK_OK ok); \ | 98 #define CHECK_OK ok); \ |
| 133 if (!*ok) return kUnknownSourceElements; \ | 99 if (!*ok) return kUnknownSourceElements; \ |
| 134 ((void)0 | 100 ((void)0 |
| 135 #define DUMMY ) // to make indentation work | 101 #define DUMMY ) // to make indentation work |
| 136 #undef DUMMY | 102 #undef DUMMY |
| 137 | 103 |
| 138 | 104 |
| 139 PreParser::Statement PreParser::ParseSourceElement(bool* ok) { | 105 PreParser::Statement PreParser::ParseSourceElement(bool* ok) { |
| 140 // (Ecma 262 5th Edition, clause 14): | 106 // (Ecma 262 5th Edition, clause 14): |
| (...skipping 17 matching lines...) Expand all Loading... |
| 158 return ParseStatement(ok); | 124 return ParseStatement(ok); |
| 159 } | 125 } |
| 160 } | 126 } |
| 161 | 127 |
| 162 | 128 |
| 163 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, | 129 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
| 164 bool* ok) { | 130 bool* ok) { |
| 165 // SourceElements :: | 131 // SourceElements :: |
| 166 // (Statement)* <end_token> | 132 // (Statement)* <end_token> |
| 167 | 133 |
| 168 bool allow_directive_prologue = true; | 134 bool directive_prologue = true; |
| 169 while (peek() != end_token) { | 135 while (peek() != end_token) { |
| 136 if (directive_prologue && peek() != Token::STRING) { |
| 137 directive_prologue = false; |
| 138 } |
| 170 Statement statement = ParseSourceElement(CHECK_OK); | 139 Statement statement = ParseSourceElement(CHECK_OK); |
| 171 if (allow_directive_prologue) { | 140 if (directive_prologue) { |
| 172 if (statement.IsUseStrictLiteral()) { | 141 if (statement.IsUseStrictLiteral()) { |
| 173 set_language_mode(allow_harmony_scoping() ? | 142 set_language_mode(allow_harmony_scoping() ? |
| 174 EXTENDED_MODE : STRICT_MODE); | 143 EXTENDED_MODE : STRICT_MODE); |
| 175 } else if (!statement.IsStringLiteral()) { | 144 } else if (!statement.IsStringLiteral()) { |
| 176 allow_directive_prologue = false; | 145 directive_prologue = false; |
| 177 } | 146 } |
| 178 } | 147 } |
| 179 } | 148 } |
| 180 return kUnknownSourceElements; | 149 return kUnknownSourceElements; |
| 181 } | 150 } |
| 182 | 151 |
| 183 | 152 |
| 184 #undef CHECK_OK | 153 #undef CHECK_OK |
| 185 #define CHECK_OK ok); \ | 154 #define CHECK_OK ok); \ |
| 186 if (!*ok) return Statement::Default(); \ | 155 if (!*ok) return Statement::Default(); \ |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 case Token::THROW: | 227 case Token::THROW: |
| 259 return ParseThrowStatement(ok); | 228 return ParseThrowStatement(ok); |
| 260 | 229 |
| 261 case Token::TRY: | 230 case Token::TRY: |
| 262 return ParseTryStatement(ok); | 231 return ParseTryStatement(ok); |
| 263 | 232 |
| 264 case Token::FUNCTION: { | 233 case Token::FUNCTION: { |
| 265 Scanner::Location start_location = scanner()->peek_location(); | 234 Scanner::Location start_location = scanner()->peek_location(); |
| 266 Statement statement = ParseFunctionDeclaration(CHECK_OK); | 235 Statement statement = ParseFunctionDeclaration(CHECK_OK); |
| 267 Scanner::Location end_location = scanner()->location(); | 236 Scanner::Location end_location = scanner()->location(); |
| 268 if (!is_classic_mode()) { | 237 if (!scope_->is_classic_mode()) { |
| 269 ReportMessageAt(start_location.beg_pos, end_location.end_pos, | 238 ReportMessageAt(start_location.beg_pos, end_location.end_pos, |
| 270 "strict_function", NULL); | 239 "strict_function", NULL); |
| 271 *ok = false; | 240 *ok = false; |
| 272 return Statement::Default(); | 241 return Statement::Default(); |
| 273 } else { | 242 } else { |
| 274 return statement; | 243 return statement; |
| 275 } | 244 } |
| 276 } | 245 } |
| 277 | 246 |
| 278 case Token::DEBUGGER: | 247 case Token::DEBUGGER: |
| 279 return ParseDebuggerStatement(ok); | 248 return ParseDebuggerStatement(ok); |
| 280 | 249 |
| 281 default: | 250 default: |
| 282 return ParseExpressionOrLabelledStatement(ok); | 251 return ParseExpressionOrLabelledStatement(ok); |
| 283 } | 252 } |
| 284 } | 253 } |
| 285 | 254 |
| 286 | 255 |
| 287 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 256 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
| 288 // FunctionDeclaration :: | 257 // FunctionDeclaration :: |
| 289 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 258 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 290 // GeneratorDeclaration :: | 259 // GeneratorDeclaration :: |
| 291 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 260 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
| 292 // '{' FunctionBody '}' | 261 // '{' FunctionBody '}' |
| 293 Expect(Token::FUNCTION, CHECK_OK); | 262 Expect(Token::FUNCTION, CHECK_OK); |
| 294 | 263 |
| 295 bool is_generator = allow_generators() && Check(Token::MUL); | 264 bool is_generator = allow_generators() && Check(Token::MUL); |
| 296 Identifier identifier = ParseIdentifier(CHECK_OK); | 265 bool is_strict_reserved = false; |
| 297 Scanner::Location location = scanner()->location(); | 266 Identifier name = ParseIdentifierOrStrictReservedWord( |
| 298 | 267 &is_strict_reserved, CHECK_OK); |
| 299 Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK); | 268 ParseFunctionLiteral(name, |
| 300 | 269 scanner()->location(), |
| 301 if (function_value.IsStrictFunction() && | 270 is_strict_reserved, |
| 302 !identifier.IsValidStrictVariable()) { | 271 is_generator, |
| 303 // Strict mode violation, using either reserved word or eval/arguments | 272 CHECK_OK); |
| 304 // as name of strict function. | |
| 305 const char* type = "strict_function_name"; | |
| 306 if (identifier.IsFutureStrictReserved() || identifier.IsYield()) { | |
| 307 type = "strict_reserved_word"; | |
| 308 } | |
| 309 ReportMessageAt(location, type, NULL); | |
| 310 *ok = false; | |
| 311 } | |
| 312 return Statement::FunctionDeclaration(); | 273 return Statement::FunctionDeclaration(); |
| 313 } | 274 } |
| 314 | 275 |
| 315 | 276 |
| 316 PreParser::Statement PreParser::ParseBlock(bool* ok) { | 277 PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| 317 // Block :: | 278 // Block :: |
| 318 // '{' Statement* '}' | 279 // '{' Statement* '}' |
| 319 | 280 |
| 320 // Note that a Block does not introduce a new execution scope! | 281 // Note that a Block does not introduce a new execution scope! |
| 321 // (ECMA-262, 3rd, 12.2) | 282 // (ECMA-262, 3rd, 12.2) |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 } | 397 } |
| 437 | 398 |
| 438 // The scope of a var/const declared variable anywhere inside a function | 399 // The scope of a var/const declared variable anywhere inside a function |
| 439 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | 400 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
| 440 // of a let declared variable is the scope of the immediately enclosing | 401 // of a let declared variable is the scope of the immediately enclosing |
| 441 // block. | 402 // block. |
| 442 int nvars = 0; // the number of variables declared | 403 int nvars = 0; // the number of variables declared |
| 443 do { | 404 do { |
| 444 // Parse variable name. | 405 // Parse variable name. |
| 445 if (nvars > 0) Consume(Token::COMMA); | 406 if (nvars > 0) Consume(Token::COMMA); |
| 446 Identifier identifier = ParseIdentifier(CHECK_OK); | 407 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| 447 if (!is_classic_mode() && !identifier.IsValidStrictVariable()) { | |
| 448 StrictModeIdentifierViolation(scanner()->location(), | |
| 449 "strict_var_name", | |
| 450 identifier, | |
| 451 ok); | |
| 452 return Statement::Default(); | |
| 453 } | |
| 454 nvars++; | 408 nvars++; |
| 455 if (peek() == Token::ASSIGN || require_initializer) { | 409 if (peek() == Token::ASSIGN || require_initializer) { |
| 456 Expect(Token::ASSIGN, CHECK_OK); | 410 Expect(Token::ASSIGN, CHECK_OK); |
| 457 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | 411 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
| 458 if (decl_props != NULL) *decl_props = kHasInitializers; | 412 if (decl_props != NULL) *decl_props = kHasInitializers; |
| 459 } | 413 } |
| 460 } while (peek() == Token::COMMA); | 414 } while (peek() == Token::COMMA); |
| 461 | 415 |
| 462 if (num_decl != NULL) *num_decl = nvars; | 416 if (num_decl != NULL) *num_decl = nvars; |
| 463 return Statement::Default(); | 417 return Statement::Default(); |
| 464 } | 418 } |
| 465 | 419 |
| 466 | 420 |
| 467 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { | 421 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
| 468 // ExpressionStatement | LabelledStatement :: | 422 // ExpressionStatement | LabelledStatement :: |
| 469 // Expression ';' | 423 // Expression ';' |
| 470 // Identifier ':' Statement | 424 // Identifier ':' Statement |
| 471 | 425 |
| 426 bool starts_with_identifier = peek_any_identifier(); |
| 472 Expression expr = ParseExpression(true, CHECK_OK); | 427 Expression expr = ParseExpression(true, CHECK_OK); |
| 473 if (expr.IsRawIdentifier()) { | 428 // Even if the expression starts with an identifier, it is not necessarily an |
| 429 // identifier. For example, "foo + bar" starts with an identifier but is not |
| 430 // an identifier. |
| 431 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { |
| 432 // Expression is a single identifier, and not, e.g., a parenthesized |
| 433 // identifier. |
| 474 ASSERT(!expr.AsIdentifier().IsFutureReserved()); | 434 ASSERT(!expr.AsIdentifier().IsFutureReserved()); |
| 475 ASSERT(is_classic_mode() || | 435 ASSERT(scope_->is_classic_mode() || |
| 476 (!expr.AsIdentifier().IsFutureStrictReserved() && | 436 (!expr.AsIdentifier().IsFutureStrictReserved() && |
| 477 !expr.AsIdentifier().IsYield())); | 437 !expr.AsIdentifier().IsYield())); |
| 478 if (peek() == Token::COLON) { | 438 Consume(Token::COLON); |
| 479 Consume(Token::COLON); | 439 return ParseStatement(ok); |
| 480 return ParseStatement(ok); | |
| 481 } | |
| 482 // Preparsing is disabled for extensions (because the extension details | 440 // Preparsing is disabled for extensions (because the extension details |
| 483 // aren't passed to lazily compiled functions), so we don't | 441 // aren't passed to lazily compiled functions), so we don't |
| 484 // accept "native function" in the preparser. | 442 // accept "native function" in the preparser. |
| 485 } | 443 } |
| 486 // Parsed expression statement. | 444 // Parsed expression statement. |
| 487 ExpectSemicolon(CHECK_OK); | 445 ExpectSemicolon(CHECK_OK); |
| 488 return Statement::ExpressionStatement(expr); | 446 return Statement::ExpressionStatement(expr); |
| 489 } | 447 } |
| 490 | 448 |
| 491 | 449 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 509 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { | 467 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { |
| 510 // ContinueStatement :: | 468 // ContinueStatement :: |
| 511 // 'continue' [no line terminator] Identifier? ';' | 469 // 'continue' [no line terminator] Identifier? ';' |
| 512 | 470 |
| 513 Expect(Token::CONTINUE, CHECK_OK); | 471 Expect(Token::CONTINUE, CHECK_OK); |
| 514 Token::Value tok = peek(); | 472 Token::Value tok = peek(); |
| 515 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 473 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 516 tok != Token::SEMICOLON && | 474 tok != Token::SEMICOLON && |
| 517 tok != Token::RBRACE && | 475 tok != Token::RBRACE && |
| 518 tok != Token::EOS) { | 476 tok != Token::EOS) { |
| 519 ParseIdentifier(CHECK_OK); | 477 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 478 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 520 } | 479 } |
| 521 ExpectSemicolon(CHECK_OK); | 480 ExpectSemicolon(CHECK_OK); |
| 522 return Statement::Default(); | 481 return Statement::Default(); |
| 523 } | 482 } |
| 524 | 483 |
| 525 | 484 |
| 526 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { | 485 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
| 527 // BreakStatement :: | 486 // BreakStatement :: |
| 528 // 'break' [no line terminator] Identifier? ';' | 487 // 'break' [no line terminator] Identifier? ';' |
| 529 | 488 |
| 530 Expect(Token::BREAK, CHECK_OK); | 489 Expect(Token::BREAK, CHECK_OK); |
| 531 Token::Value tok = peek(); | 490 Token::Value tok = peek(); |
| 532 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 491 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 533 tok != Token::SEMICOLON && | 492 tok != Token::SEMICOLON && |
| 534 tok != Token::RBRACE && | 493 tok != Token::RBRACE && |
| 535 tok != Token::EOS) { | 494 tok != Token::EOS) { |
| 536 ParseIdentifier(CHECK_OK); | 495 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 496 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 537 } | 497 } |
| 538 ExpectSemicolon(CHECK_OK); | 498 ExpectSemicolon(CHECK_OK); |
| 539 return Statement::Default(); | 499 return Statement::Default(); |
| 540 } | 500 } |
| 541 | 501 |
| 542 | 502 |
| 543 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { | 503 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
| 544 // ReturnStatement :: | 504 // ReturnStatement :: |
| 545 // 'return' [no line terminator] Expression? ';' | 505 // 'return' [no line terminator] Expression? ';' |
| 546 | 506 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 563 } | 523 } |
| 564 ExpectSemicolon(CHECK_OK); | 524 ExpectSemicolon(CHECK_OK); |
| 565 return Statement::Default(); | 525 return Statement::Default(); |
| 566 } | 526 } |
| 567 | 527 |
| 568 | 528 |
| 569 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { | 529 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
| 570 // WithStatement :: | 530 // WithStatement :: |
| 571 // 'with' '(' Expression ')' Statement | 531 // 'with' '(' Expression ')' Statement |
| 572 Expect(Token::WITH, CHECK_OK); | 532 Expect(Token::WITH, CHECK_OK); |
| 573 if (!is_classic_mode()) { | 533 if (!scope_->is_classic_mode()) { |
| 574 Scanner::Location location = scanner()->location(); | 534 Scanner::Location location = scanner()->location(); |
| 575 ReportMessageAt(location, "strict_mode_with", NULL); | 535 ReportMessageAt(location, "strict_mode_with", NULL); |
| 576 *ok = false; | 536 *ok = false; |
| 577 return Statement::Default(); | 537 return Statement::Default(); |
| 578 } | 538 } |
| 579 Expect(Token::LPAREN, CHECK_OK); | 539 Expect(Token::LPAREN, CHECK_OK); |
| 580 ParseExpression(true, CHECK_OK); | 540 ParseExpression(true, CHECK_OK); |
| 581 Expect(Token::RPAREN, CHECK_OK); | 541 Expect(Token::RPAREN, CHECK_OK); |
| 582 | 542 |
| 583 Scope::InsideWith iw(scope_); | 543 Scope::InsideWith iw(scope_); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 // 'try' Block Catch | 692 // 'try' Block Catch |
| 733 // 'try' Block Finally | 693 // 'try' Block Finally |
| 734 // 'try' Block Catch Finally | 694 // 'try' Block Catch Finally |
| 735 // | 695 // |
| 736 // Catch :: | 696 // Catch :: |
| 737 // 'catch' '(' Identifier ')' Block | 697 // 'catch' '(' Identifier ')' Block |
| 738 // | 698 // |
| 739 // Finally :: | 699 // Finally :: |
| 740 // 'finally' Block | 700 // 'finally' Block |
| 741 | 701 |
| 742 // In preparsing, allow any number of catch/finally blocks, including zero | |
| 743 // of both. | |
| 744 | |
| 745 Expect(Token::TRY, CHECK_OK); | 702 Expect(Token::TRY, CHECK_OK); |
| 746 | 703 |
| 747 ParseBlock(CHECK_OK); | 704 ParseBlock(CHECK_OK); |
| 748 | 705 |
| 749 bool catch_or_finally_seen = false; | 706 Token::Value tok = peek(); |
| 750 if (peek() == Token::CATCH) { | 707 if (tok != Token::CATCH && tok != Token::FINALLY) { |
| 708 ReportMessageAt(scanner()->location(), "no_catch_or_finally", NULL); |
| 709 *ok = false; |
| 710 return Statement::Default(); |
| 711 } |
| 712 if (tok == Token::CATCH) { |
| 751 Consume(Token::CATCH); | 713 Consume(Token::CATCH); |
| 752 Expect(Token::LPAREN, CHECK_OK); | 714 Expect(Token::LPAREN, CHECK_OK); |
| 753 Identifier id = ParseIdentifier(CHECK_OK); | 715 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| 754 if (!is_classic_mode() && !id.IsValidStrictVariable()) { | |
| 755 StrictModeIdentifierViolation(scanner()->location(), | |
| 756 "strict_catch_variable", | |
| 757 id, | |
| 758 ok); | |
| 759 return Statement::Default(); | |
| 760 } | |
| 761 Expect(Token::RPAREN, CHECK_OK); | 716 Expect(Token::RPAREN, CHECK_OK); |
| 762 { Scope::InsideWith iw(scope_); | 717 { Scope::InsideWith iw(scope_); |
| 763 ParseBlock(CHECK_OK); | 718 ParseBlock(CHECK_OK); |
| 764 } | 719 } |
| 765 catch_or_finally_seen = true; | 720 tok = peek(); |
| 766 } | 721 } |
| 767 if (peek() == Token::FINALLY) { | 722 if (tok == Token::FINALLY) { |
| 768 Consume(Token::FINALLY); | 723 Consume(Token::FINALLY); |
| 769 ParseBlock(CHECK_OK); | 724 ParseBlock(CHECK_OK); |
| 770 catch_or_finally_seen = true; | |
| 771 } | |
| 772 if (!catch_or_finally_seen) { | |
| 773 *ok = false; | |
| 774 } | 725 } |
| 775 return Statement::Default(); | 726 return Statement::Default(); |
| 776 } | 727 } |
| 777 | 728 |
| 778 | 729 |
| 779 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { | 730 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
| 780 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 731 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
| 781 // contexts this is used as a statement which invokes the debugger as if a | 732 // contexts this is used as a statement which invokes the debugger as if a |
| 782 // break point is present. | 733 // break point is present. |
| 783 // DebuggerStatement :: | 734 // DebuggerStatement :: |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 } | 777 } |
| 827 | 778 |
| 828 Scanner::Location before = scanner()->peek_location(); | 779 Scanner::Location before = scanner()->peek_location(); |
| 829 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); | 780 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
| 830 | 781 |
| 831 if (!Token::IsAssignmentOp(peek())) { | 782 if (!Token::IsAssignmentOp(peek())) { |
| 832 // Parsed conditional expression only (no assignment). | 783 // Parsed conditional expression only (no assignment). |
| 833 return expression; | 784 return expression; |
| 834 } | 785 } |
| 835 | 786 |
| 836 if (!is_classic_mode() && | 787 if (!scope_->is_classic_mode() && |
| 837 expression.IsIdentifier() && | 788 expression.IsIdentifier() && |
| 838 expression.AsIdentifier().IsEvalOrArguments()) { | 789 expression.AsIdentifier().IsEvalOrArguments()) { |
| 839 Scanner::Location after = scanner()->location(); | 790 Scanner::Location after = scanner()->location(); |
| 840 ReportMessageAt(before.beg_pos, after.end_pos, | 791 ReportMessageAt(before.beg_pos, after.end_pos, |
| 841 "strict_lhs_assignment", NULL); | 792 "strict_eval_arguments", NULL); |
| 842 *ok = false; | 793 *ok = false; |
| 843 return Expression::Default(); | 794 return Expression::Default(); |
| 844 } | 795 } |
| 845 | 796 |
| 846 Token::Value op = Next(); // Get assignment operator. | 797 Token::Value op = Next(); // Get assignment operator. |
| 847 ParseAssignmentExpression(accept_IN, CHECK_OK); | 798 ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 848 | 799 |
| 849 if ((op == Token::ASSIGN) && expression.IsThisProperty()) { | 800 if ((op == Token::ASSIGN) && expression.IsThisProperty()) { |
| 850 scope_->AddProperty(); | 801 scope_->AddProperty(); |
| 851 } | 802 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 | 871 |
| 921 Token::Value op = peek(); | 872 Token::Value op = peek(); |
| 922 if (Token::IsUnaryOp(op)) { | 873 if (Token::IsUnaryOp(op)) { |
| 923 op = Next(); | 874 op = Next(); |
| 924 ParseUnaryExpression(ok); | 875 ParseUnaryExpression(ok); |
| 925 return Expression::Default(); | 876 return Expression::Default(); |
| 926 } else if (Token::IsCountOp(op)) { | 877 } else if (Token::IsCountOp(op)) { |
| 927 op = Next(); | 878 op = Next(); |
| 928 Scanner::Location before = scanner()->peek_location(); | 879 Scanner::Location before = scanner()->peek_location(); |
| 929 Expression expression = ParseUnaryExpression(CHECK_OK); | 880 Expression expression = ParseUnaryExpression(CHECK_OK); |
| 930 if (!is_classic_mode() && | 881 if (!scope_->is_classic_mode() && |
| 931 expression.IsIdentifier() && | 882 expression.IsIdentifier() && |
| 932 expression.AsIdentifier().IsEvalOrArguments()) { | 883 expression.AsIdentifier().IsEvalOrArguments()) { |
| 933 Scanner::Location after = scanner()->location(); | 884 Scanner::Location after = scanner()->location(); |
| 934 ReportMessageAt(before.beg_pos, after.end_pos, | 885 ReportMessageAt(before.beg_pos, after.end_pos, |
| 935 "strict_lhs_prefix", NULL); | 886 "strict_eval_arguments", NULL); |
| 936 *ok = false; | 887 *ok = false; |
| 937 } | 888 } |
| 938 return Expression::Default(); | 889 return Expression::Default(); |
| 939 } else { | 890 } else { |
| 940 return ParsePostfixExpression(ok); | 891 return ParsePostfixExpression(ok); |
| 941 } | 892 } |
| 942 } | 893 } |
| 943 | 894 |
| 944 | 895 |
| 945 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { | 896 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { |
| 946 // PostfixExpression :: | 897 // PostfixExpression :: |
| 947 // LeftHandSideExpression ('++' | '--')? | 898 // LeftHandSideExpression ('++' | '--')? |
| 948 | 899 |
| 949 Scanner::Location before = scanner()->peek_location(); | 900 Scanner::Location before = scanner()->peek_location(); |
| 950 Expression expression = ParseLeftHandSideExpression(CHECK_OK); | 901 Expression expression = ParseLeftHandSideExpression(CHECK_OK); |
| 951 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 902 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 952 Token::IsCountOp(peek())) { | 903 Token::IsCountOp(peek())) { |
| 953 if (!is_classic_mode() && | 904 if (!scope_->is_classic_mode() && |
| 954 expression.IsIdentifier() && | 905 expression.IsIdentifier() && |
| 955 expression.AsIdentifier().IsEvalOrArguments()) { | 906 expression.AsIdentifier().IsEvalOrArguments()) { |
| 956 Scanner::Location after = scanner()->location(); | 907 Scanner::Location after = scanner()->location(); |
| 957 ReportMessageAt(before.beg_pos, after.end_pos, | 908 ReportMessageAt(before.beg_pos, after.end_pos, |
| 958 "strict_lhs_postfix", NULL); | 909 "strict_eval_arguments", NULL); |
| 959 *ok = false; | 910 *ok = false; |
| 960 return Expression::Default(); | 911 return Expression::Default(); |
| 961 } | 912 } |
| 962 Next(); | 913 Next(); |
| 963 return Expression::Default(); | 914 return Expression::Default(); |
| 964 } | 915 } |
| 965 return expression; | 916 return expression; |
| 966 } | 917 } |
| 967 | 918 |
| 968 | 919 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 // MemberExpression :: | 998 // MemberExpression :: |
| 1048 // (PrimaryExpression | FunctionLiteral) | 999 // (PrimaryExpression | FunctionLiteral) |
| 1049 // ('[' Expression ']' | '.' Identifier | Arguments)* | 1000 // ('[' Expression ']' | '.' Identifier | Arguments)* |
| 1050 | 1001 |
| 1051 // Parse the initial primary or function expression. | 1002 // Parse the initial primary or function expression. |
| 1052 Expression result = Expression::Default(); | 1003 Expression result = Expression::Default(); |
| 1053 if (peek() == Token::FUNCTION) { | 1004 if (peek() == Token::FUNCTION) { |
| 1054 Consume(Token::FUNCTION); | 1005 Consume(Token::FUNCTION); |
| 1055 | 1006 |
| 1056 bool is_generator = allow_generators() && Check(Token::MUL); | 1007 bool is_generator = allow_generators() && Check(Token::MUL); |
| 1057 Identifier identifier = Identifier::Default(); | 1008 Identifier name = Identifier::Default(); |
| 1009 bool is_strict_reserved_name = false; |
| 1010 Scanner::Location function_name_location = Scanner::Location::invalid(); |
| 1058 if (peek_any_identifier()) { | 1011 if (peek_any_identifier()) { |
| 1059 identifier = ParseIdentifier(CHECK_OK); | 1012 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, |
| 1013 CHECK_OK); |
| 1014 function_name_location = scanner()->location(); |
| 1060 } | 1015 } |
| 1061 result = ParseFunctionLiteral(is_generator, CHECK_OK); | 1016 result = ParseFunctionLiteral(name, |
| 1062 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) { | 1017 function_name_location, |
| 1063 StrictModeIdentifierViolation(scanner()->location(), | 1018 is_strict_reserved_name, |
| 1064 "strict_function_name", | 1019 is_generator, |
| 1065 identifier, | 1020 CHECK_OK); |
| 1066 ok); | |
| 1067 return Expression::Default(); | |
| 1068 } | |
| 1069 } else { | 1021 } else { |
| 1070 result = ParsePrimaryExpression(CHECK_OK); | 1022 result = ParsePrimaryExpression(CHECK_OK); |
| 1071 } | 1023 } |
| 1072 | 1024 |
| 1073 while (true) { | 1025 while (true) { |
| 1074 switch (peek()) { | 1026 switch (peek()) { |
| 1075 case Token::LBRACK: { | 1027 case Token::LBRACK: { |
| 1076 Consume(Token::LBRACK); | 1028 Consume(Token::LBRACK); |
| 1077 ParseExpression(true, CHECK_OK); | 1029 ParseExpression(true, CHECK_OK); |
| 1078 Expect(Token::RBRACK, CHECK_OK); | 1030 Expect(Token::RBRACK, CHECK_OK); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 case Token::THIS: { | 1079 case Token::THIS: { |
| 1128 Next(); | 1080 Next(); |
| 1129 result = Expression::This(); | 1081 result = Expression::This(); |
| 1130 break; | 1082 break; |
| 1131 } | 1083 } |
| 1132 | 1084 |
| 1133 case Token::FUTURE_RESERVED_WORD: | 1085 case Token::FUTURE_RESERVED_WORD: |
| 1134 case Token::FUTURE_STRICT_RESERVED_WORD: | 1086 case Token::FUTURE_STRICT_RESERVED_WORD: |
| 1135 case Token::YIELD: | 1087 case Token::YIELD: |
| 1136 case Token::IDENTIFIER: { | 1088 case Token::IDENTIFIER: { |
| 1137 Identifier id = ParseIdentifier(CHECK_OK); | 1089 // Using eval or arguments in this context is OK even in strict mode. |
| 1090 Identifier id = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 1138 result = Expression::FromIdentifier(id); | 1091 result = Expression::FromIdentifier(id); |
| 1139 break; | 1092 break; |
| 1140 } | 1093 } |
| 1141 | 1094 |
| 1142 case Token::NULL_LITERAL: | 1095 case Token::NULL_LITERAL: |
| 1143 case Token::TRUE_LITERAL: | 1096 case Token::TRUE_LITERAL: |
| 1144 case Token::FALSE_LITERAL: | 1097 case Token::FALSE_LITERAL: |
| 1145 case Token::NUMBER: { | 1098 case Token::NUMBER: { |
| 1146 Next(); | 1099 Next(); |
| 1147 break; | 1100 break; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1166 | 1119 |
| 1167 case Token::LBRACE: | 1120 case Token::LBRACE: |
| 1168 result = ParseObjectLiteral(CHECK_OK); | 1121 result = ParseObjectLiteral(CHECK_OK); |
| 1169 break; | 1122 break; |
| 1170 | 1123 |
| 1171 case Token::LPAREN: | 1124 case Token::LPAREN: |
| 1172 Consume(Token::LPAREN); | 1125 Consume(Token::LPAREN); |
| 1173 parenthesized_function_ = (peek() == Token::FUNCTION); | 1126 parenthesized_function_ = (peek() == Token::FUNCTION); |
| 1174 result = ParseExpression(true, CHECK_OK); | 1127 result = ParseExpression(true, CHECK_OK); |
| 1175 Expect(Token::RPAREN, CHECK_OK); | 1128 Expect(Token::RPAREN, CHECK_OK); |
| 1176 result = result.Parenthesize(); | |
| 1177 break; | 1129 break; |
| 1178 | 1130 |
| 1179 case Token::MOD: | 1131 case Token::MOD: |
| 1180 result = ParseV8Intrinsic(CHECK_OK); | 1132 result = ParseV8Intrinsic(CHECK_OK); |
| 1181 break; | 1133 break; |
| 1182 | 1134 |
| 1183 default: { | 1135 default: { |
| 1184 Next(); | 1136 Token::Value next = Next(); |
| 1137 ReportUnexpectedToken(next); |
| 1185 *ok = false; | 1138 *ok = false; |
| 1186 return Expression::Default(); | 1139 return Expression::Default(); |
| 1187 } | 1140 } |
| 1188 } | 1141 } |
| 1189 | 1142 |
| 1190 return result; | 1143 return result; |
| 1191 } | 1144 } |
| 1192 | 1145 |
| 1193 | 1146 |
| 1194 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { | 1147 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 name != Token::STRING && | 1192 name != Token::STRING && |
| 1240 !is_keyword) { | 1193 !is_keyword) { |
| 1241 *ok = false; | 1194 *ok = false; |
| 1242 return Expression::Default(); | 1195 return Expression::Default(); |
| 1243 } | 1196 } |
| 1244 if (!is_keyword) { | 1197 if (!is_keyword) { |
| 1245 LogSymbol(); | 1198 LogSymbol(); |
| 1246 } | 1199 } |
| 1247 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | 1200 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; |
| 1248 checker.CheckProperty(name, type, CHECK_OK); | 1201 checker.CheckProperty(name, type, CHECK_OK); |
| 1249 ParseFunctionLiteral(false, CHECK_OK); | 1202 ParseFunctionLiteral(Identifier::Default(), |
| 1203 scanner()->location(), |
| 1204 false, // reserved words are allowed here |
| 1205 false, // not a generator |
| 1206 CHECK_OK); |
| 1250 if (peek() != Token::RBRACE) { | 1207 if (peek() != Token::RBRACE) { |
| 1251 Expect(Token::COMMA, CHECK_OK); | 1208 Expect(Token::COMMA, CHECK_OK); |
| 1252 } | 1209 } |
| 1253 continue; // restart the while | 1210 continue; // restart the while |
| 1254 } | 1211 } |
| 1255 checker.CheckProperty(next, kValueProperty, CHECK_OK); | 1212 checker.CheckProperty(next, kValueProperty, CHECK_OK); |
| 1256 break; | 1213 break; |
| 1257 } | 1214 } |
| 1258 case Token::STRING: | 1215 case Token::STRING: |
| 1259 Consume(next); | 1216 Consume(next); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 done = (peek() == Token::RPAREN); | 1282 done = (peek() == Token::RPAREN); |
| 1326 if (!done) { | 1283 if (!done) { |
| 1327 Expect(Token::COMMA, ok); | 1284 Expect(Token::COMMA, ok); |
| 1328 if (!*ok) return -1; | 1285 if (!*ok) return -1; |
| 1329 } | 1286 } |
| 1330 } | 1287 } |
| 1331 Expect(Token::RPAREN, ok); | 1288 Expect(Token::RPAREN, ok); |
| 1332 return argc; | 1289 return argc; |
| 1333 } | 1290 } |
| 1334 | 1291 |
| 1335 | 1292 PreParser::Expression PreParser::ParseFunctionLiteral( |
| 1336 PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator, | 1293 Identifier function_name, |
| 1337 bool* ok) { | 1294 Scanner::Location function_name_location, |
| 1295 bool name_is_strict_reserved, |
| 1296 bool is_generator, |
| 1297 bool* ok) { |
| 1338 // Function :: | 1298 // Function :: |
| 1339 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 1299 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 1340 | 1300 |
| 1341 // Parse function body. | 1301 // Parse function body. |
| 1342 ScopeType outer_scope_type = scope_->type(); | 1302 ScopeType outer_scope_type = scope_->type(); |
| 1343 bool inside_with = scope_->IsInsideWith(); | 1303 bool inside_with = scope_->IsInsideWith(); |
| 1344 Scope function_scope(&scope_, kFunctionScope); | 1304 Scope function_scope(&scope_, kFunctionScope); |
| 1345 function_scope.set_is_generator(is_generator); | 1305 function_scope.set_is_generator(is_generator); |
| 1346 // FormalParameterList :: | 1306 // FormalParameterList :: |
| 1347 // '(' (Identifier)*[','] ')' | 1307 // '(' (Identifier)*[','] ')' |
| 1348 Expect(Token::LPAREN, CHECK_OK); | 1308 Expect(Token::LPAREN, CHECK_OK); |
| 1349 int start_position = position(); | 1309 int start_position = position(); |
| 1350 bool done = (peek() == Token::RPAREN); | 1310 bool done = (peek() == Token::RPAREN); |
| 1351 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 1311 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
| 1312 // We don't yet know if the function will be strict, so we cannot yet produce |
| 1313 // errors for parameter names or duplicates. However, we remember the |
| 1314 // locations of these errors if they occur and produce the errors later. |
| 1315 Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); |
| 1316 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
| 1317 Scanner::Location reserved_error_loc = Scanner::Location::invalid(); |
| 1352 while (!done) { | 1318 while (!done) { |
| 1353 Identifier id = ParseIdentifier(CHECK_OK); | 1319 bool is_strict_reserved = false; |
| 1354 if (!id.IsValidStrictVariable()) { | 1320 Identifier param_name = |
| 1355 StrictModeIdentifierViolation(scanner()->location(), | 1321 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 1356 "strict_param_name", | 1322 if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) { |
| 1357 id, | 1323 eval_args_error_loc = scanner()->location(); |
| 1358 CHECK_OK); | |
| 1359 } | 1324 } |
| 1325 if (!reserved_error_loc.IsValid() && is_strict_reserved) { |
| 1326 reserved_error_loc = scanner()->location(); |
| 1327 } |
| 1328 |
| 1360 int prev_value; | 1329 int prev_value; |
| 1361 if (scanner()->is_literal_ascii()) { | 1330 if (scanner()->is_literal_ascii()) { |
| 1362 prev_value = | 1331 prev_value = |
| 1363 duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1); | 1332 duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1); |
| 1364 } else { | 1333 } else { |
| 1365 prev_value = | 1334 prev_value = |
| 1366 duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1); | 1335 duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1); |
| 1367 } | 1336 } |
| 1368 | 1337 |
| 1369 if (prev_value != 0) { | 1338 if (!dupe_error_loc.IsValid() && prev_value != 0) { |
| 1370 SetStrictModeViolation(scanner()->location(), | 1339 dupe_error_loc = scanner()->location(); |
| 1371 "strict_param_dupe", | |
| 1372 CHECK_OK); | |
| 1373 } | 1340 } |
| 1341 |
| 1374 done = (peek() == Token::RPAREN); | 1342 done = (peek() == Token::RPAREN); |
| 1375 if (!done) { | 1343 if (!done) { |
| 1376 Expect(Token::COMMA, CHECK_OK); | 1344 Expect(Token::COMMA, CHECK_OK); |
| 1377 } | 1345 } |
| 1378 } | 1346 } |
| 1379 Expect(Token::RPAREN, CHECK_OK); | 1347 Expect(Token::RPAREN, CHECK_OK); |
| 1380 | 1348 |
| 1381 // Determine if the function will be lazily compiled. | 1349 // Determine if the function will be lazily compiled. |
| 1382 // Currently only happens to top-level functions. | 1350 // Currently only happens to top-level functions. |
| 1383 // Optimistically assume that all top-level functions are lazily compiled. | 1351 // Optimistically assume that all top-level functions are lazily compiled. |
| 1384 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && | 1352 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && |
| 1385 !inside_with && allow_lazy() && | 1353 !inside_with && allow_lazy() && |
| 1386 !parenthesized_function_); | 1354 !parenthesized_function_); |
| 1387 parenthesized_function_ = false; | 1355 parenthesized_function_ = false; |
| 1388 | 1356 |
| 1389 Expect(Token::LBRACE, CHECK_OK); | 1357 Expect(Token::LBRACE, CHECK_OK); |
| 1390 if (is_lazily_compiled) { | 1358 if (is_lazily_compiled) { |
| 1391 ParseLazyFunctionLiteralBody(CHECK_OK); | 1359 ParseLazyFunctionLiteralBody(CHECK_OK); |
| 1392 } else { | 1360 } else { |
| 1393 ParseSourceElements(Token::RBRACE, ok); | 1361 ParseSourceElements(Token::RBRACE, ok); |
| 1394 } | 1362 } |
| 1395 Expect(Token::RBRACE, CHECK_OK); | 1363 Expect(Token::RBRACE, CHECK_OK); |
| 1396 | 1364 |
| 1397 if (!is_classic_mode()) { | 1365 // Validate strict mode. We can do this only after parsing the function, |
| 1366 // since the function can declare itself strict. |
| 1367 if (!scope_->is_classic_mode()) { |
| 1368 if (function_name.IsEvalOrArguments()) { |
| 1369 ReportMessageAt(function_name_location, "strict_eval_arguments", NULL); |
| 1370 *ok = false; |
| 1371 return Expression::Default(); |
| 1372 } |
| 1373 if (name_is_strict_reserved) { |
| 1374 ReportMessageAt( |
| 1375 function_name_location, "unexpected_strict_reserved", NULL); |
| 1376 *ok = false; |
| 1377 return Expression::Default(); |
| 1378 } |
| 1379 if (eval_args_error_loc.IsValid()) { |
| 1380 ReportMessageAt(eval_args_error_loc, "strict_eval_arguments", |
| 1381 Vector<const char*>::empty()); |
| 1382 *ok = false; |
| 1383 return Expression::Default(); |
| 1384 } |
| 1385 if (dupe_error_loc.IsValid()) { |
| 1386 ReportMessageAt(dupe_error_loc, "strict_param_dupe", |
| 1387 Vector<const char*>::empty()); |
| 1388 *ok = false; |
| 1389 return Expression::Default(); |
| 1390 } |
| 1391 if (reserved_error_loc.IsValid()) { |
| 1392 ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved", |
| 1393 Vector<const char*>::empty()); |
| 1394 *ok = false; |
| 1395 return Expression::Default(); |
| 1396 } |
| 1397 |
| 1398 int end_position = scanner()->location().end_pos; | 1398 int end_position = scanner()->location().end_pos; |
| 1399 CheckOctalLiteral(start_position, end_position, CHECK_OK); | 1399 CheckOctalLiteral(start_position, end_position, CHECK_OK); |
| 1400 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); | |
| 1401 return Expression::StrictFunction(); | 1400 return Expression::StrictFunction(); |
| 1402 } | 1401 } |
| 1403 | 1402 |
| 1404 return Expression::Default(); | 1403 return Expression::Default(); |
| 1405 } | 1404 } |
| 1406 | 1405 |
| 1407 | 1406 |
| 1408 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { | 1407 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { |
| 1409 int body_start = position(); | 1408 int body_start = position(); |
| 1410 log_->PauseRecording(); | 1409 log_->PauseRecording(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1423 | 1422 |
| 1424 | 1423 |
| 1425 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { | 1424 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
| 1426 // CallRuntime :: | 1425 // CallRuntime :: |
| 1427 // '%' Identifier Arguments | 1426 // '%' Identifier Arguments |
| 1428 Expect(Token::MOD, CHECK_OK); | 1427 Expect(Token::MOD, CHECK_OK); |
| 1429 if (!allow_natives_syntax()) { | 1428 if (!allow_natives_syntax()) { |
| 1430 *ok = false; | 1429 *ok = false; |
| 1431 return Expression::Default(); | 1430 return Expression::Default(); |
| 1432 } | 1431 } |
| 1433 ParseIdentifier(CHECK_OK); | 1432 // Allow "eval" or "arguments" for backward compatibility. |
| 1433 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 1434 ParseArguments(ok); | 1434 ParseArguments(ok); |
| 1435 | 1435 |
| 1436 return Expression::Default(); | 1436 return Expression::Default(); |
| 1437 } | 1437 } |
| 1438 | 1438 |
| 1439 #undef CHECK_OK | 1439 #undef CHECK_OK |
| 1440 | 1440 |
| 1441 | 1441 |
| 1442 void PreParser::LogSymbol() { | 1442 void PreParser::LogSymbol() { |
| 1443 int identifier_pos = position(); | 1443 int identifier_pos = position(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 } | 1482 } |
| 1483 if (scanner()->literal_length() == 9 && | 1483 if (scanner()->literal_length() == 9 && |
| 1484 !strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) { | 1484 !strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) { |
| 1485 return Identifier::Arguments(); | 1485 return Identifier::Arguments(); |
| 1486 } | 1486 } |
| 1487 } | 1487 } |
| 1488 return Identifier::Default(); | 1488 return Identifier::Default(); |
| 1489 } | 1489 } |
| 1490 | 1490 |
| 1491 | 1491 |
| 1492 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { | 1492 // Parses an identifier that is valid for the current scope, in particular it |
| 1493 // fails on strict mode future reserved keywords in a strict scope. If |
| 1494 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
| 1495 // "arguments" as identifier even in strict mode (this is needed in cases like |
| 1496 // "var foo = eval;"). |
| 1497 PreParser::Identifier PreParser::ParseIdentifier( |
| 1498 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
| 1499 bool* ok) { |
| 1493 Token::Value next = Next(); | 1500 Token::Value next = Next(); |
| 1494 switch (next) { | 1501 if (next == Token::IDENTIFIER) { |
| 1495 case Token::FUTURE_RESERVED_WORD: { | 1502 PreParser::Identifier name = GetIdentifierSymbol(); |
| 1496 Scanner::Location location = scanner()->location(); | 1503 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
| 1497 ReportMessageAt(location.beg_pos, location.end_pos, | 1504 !scope_->is_classic_mode() && name.IsEvalOrArguments()) { |
| 1498 "reserved_word", NULL); | 1505 ReportMessageAt(scanner()->location(), "strict_eval_arguments", NULL); |
| 1499 *ok = false; | 1506 *ok = false; |
| 1500 return GetIdentifierSymbol(); | |
| 1501 } | 1507 } |
| 1502 case Token::YIELD: | 1508 return name; |
| 1503 if (scope_->is_generator()) { | 1509 } else if (scope_->is_classic_mode() && |
| 1504 // 'yield' in a generator is only valid as part of a YieldExpression. | 1510 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 1505 ReportMessageAt(scanner()->location(), "unexpected_token", "yield"); | 1511 (next == Token::YIELD && !scope_->is_generator()))) { |
| 1506 *ok = false; | 1512 return GetIdentifierSymbol(); |
| 1507 return Identifier::Yield(); | 1513 } else { |
| 1508 } | 1514 ReportUnexpectedToken(next); |
| 1509 // FALLTHROUGH | 1515 *ok = false; |
| 1510 case Token::FUTURE_STRICT_RESERVED_WORD: | 1516 return Identifier::Default(); |
| 1511 if (!is_classic_mode()) { | |
| 1512 Scanner::Location location = scanner()->location(); | |
| 1513 ReportMessageAt(location.beg_pos, location.end_pos, | |
| 1514 "strict_reserved_word", NULL); | |
| 1515 *ok = false; | |
| 1516 } | |
| 1517 // FALLTHROUGH | |
| 1518 case Token::IDENTIFIER: | |
| 1519 return GetIdentifierSymbol(); | |
| 1520 default: | |
| 1521 *ok = false; | |
| 1522 return Identifier::Default(); | |
| 1523 } | 1517 } |
| 1524 } | 1518 } |
| 1525 | 1519 |
| 1526 | 1520 |
| 1527 void PreParser::SetStrictModeViolation(Scanner::Location location, | 1521 // Parses and identifier or a strict mode future reserved word, and indicate |
| 1528 const char* type, | 1522 // whether it is strict mode future reserved. |
| 1529 bool* ok) { | 1523 PreParser::Identifier PreParser::ParseIdentifierOrStrictReservedWord( |
| 1530 if (!is_classic_mode()) { | 1524 bool* is_strict_reserved, bool* ok) { |
| 1531 ReportMessageAt(location, type, NULL); | 1525 Token::Value next = Next(); |
| 1526 if (next == Token::IDENTIFIER) { |
| 1527 *is_strict_reserved = false; |
| 1528 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 1529 (next == Token::YIELD && !scope_->is_generator())) { |
| 1530 *is_strict_reserved = true; |
| 1531 } else { |
| 1532 ReportUnexpectedToken(next); |
| 1532 *ok = false; | 1533 *ok = false; |
| 1533 return; | 1534 return Identifier::Default(); |
| 1534 } | 1535 } |
| 1535 // Delay report in case this later turns out to be strict code | 1536 return GetIdentifierSymbol(); |
| 1536 // (i.e., for function names and parameters prior to a "use strict" | |
| 1537 // directive). | |
| 1538 // It's safe to overwrite an existing violation. | |
| 1539 // It's either from a function that turned out to be non-strict, | |
| 1540 // or it's in the current function (and we just need to report | |
| 1541 // one error), or it's in a unclosed nesting function that wasn't | |
| 1542 // strict (otherwise we would already be in strict mode). | |
| 1543 strict_mode_violation_location_ = location; | |
| 1544 strict_mode_violation_type_ = type; | |
| 1545 } | |
| 1546 | |
| 1547 | |
| 1548 void PreParser::CheckDelayedStrictModeViolation(int beg_pos, | |
| 1549 int end_pos, | |
| 1550 bool* ok) { | |
| 1551 Scanner::Location location = strict_mode_violation_location_; | |
| 1552 if (location.IsValid() && | |
| 1553 location.beg_pos > beg_pos && location.end_pos < end_pos) { | |
| 1554 ReportMessageAt(location, strict_mode_violation_type_, NULL); | |
| 1555 *ok = false; | |
| 1556 } | |
| 1557 } | |
| 1558 | |
| 1559 | |
| 1560 void PreParser::StrictModeIdentifierViolation(Scanner::Location location, | |
| 1561 const char* eval_args_type, | |
| 1562 Identifier identifier, | |
| 1563 bool* ok) { | |
| 1564 const char* type = eval_args_type; | |
| 1565 if (identifier.IsFutureReserved()) { | |
| 1566 type = "reserved_word"; | |
| 1567 } else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) { | |
| 1568 type = "strict_reserved_word"; | |
| 1569 } | |
| 1570 if (!is_classic_mode()) { | |
| 1571 ReportMessageAt(location, type, NULL); | |
| 1572 *ok = false; | |
| 1573 return; | |
| 1574 } | |
| 1575 strict_mode_violation_location_ = location; | |
| 1576 strict_mode_violation_type_ = type; | |
| 1577 } | 1537 } |
| 1578 | 1538 |
| 1579 | 1539 |
| 1580 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { | 1540 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { |
| 1581 Token::Value next = Next(); | 1541 Token::Value next = Next(); |
| 1582 if (Token::IsKeyword(next)) { | 1542 if (next != Token::IDENTIFIER && |
| 1583 int pos = position(); | 1543 next != Token::FUTURE_RESERVED_WORD && |
| 1584 const char* keyword = Token::String(next); | 1544 next != Token::FUTURE_STRICT_RESERVED_WORD && |
| 1585 log_->LogAsciiSymbol(pos, Vector<const char>(keyword, StrLength(keyword))); | 1545 !Token::IsKeyword(next)) { |
| 1546 ReportUnexpectedToken(next); |
| 1547 *ok = false; |
| 1586 return Identifier::Default(); | 1548 return Identifier::Default(); |
| 1587 } | 1549 } |
| 1588 if (next == Token::IDENTIFIER || | 1550 return GetIdentifierSymbol(); |
| 1589 next == Token::FUTURE_RESERVED_WORD || | |
| 1590 next == Token::FUTURE_STRICT_RESERVED_WORD) { | |
| 1591 return GetIdentifierSymbol(); | |
| 1592 } | |
| 1593 *ok = false; | |
| 1594 return Identifier::Default(); | |
| 1595 } | 1551 } |
| 1596 | 1552 |
| 1597 #undef CHECK_OK | 1553 #undef CHECK_OK |
| 1598 | 1554 |
| 1599 | 1555 |
| 1600 // This function reads an identifier and determines whether or not it | 1556 // This function reads an identifier and determines whether or not it |
| 1601 // is 'get' or 'set'. | 1557 // is 'get' or 'set'. |
| 1602 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get, | 1558 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get, |
| 1603 bool* is_set, | 1559 bool* is_set, |
| 1604 bool* ok) { | 1560 bool* ok) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1640 ASSERT(IsAccessorAccessorConflict(old_type, type)); | 1596 ASSERT(IsAccessorAccessorConflict(old_type, type)); |
| 1641 // Both accessors of the same type. | 1597 // Both accessors of the same type. |
| 1642 parser()->ReportMessageAt(scanner()->location(), | 1598 parser()->ReportMessageAt(scanner()->location(), |
| 1643 "accessor_get_set"); | 1599 "accessor_get_set"); |
| 1644 } | 1600 } |
| 1645 *ok = false; | 1601 *ok = false; |
| 1646 } | 1602 } |
| 1647 } | 1603 } |
| 1648 | 1604 |
| 1649 } } // v8::internal | 1605 } } // v8::internal |
| OLD | NEW |