| 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 24 matching lines...) Expand all Loading... |
| 35 #include "conversions-inl.h" | 35 #include "conversions-inl.h" |
| 36 #include "globals.h" | 36 #include "globals.h" |
| 37 #include "hashmap.h" | 37 #include "hashmap.h" |
| 38 #include "list.h" | 38 #include "list.h" |
| 39 #include "preparse-data-format.h" | 39 #include "preparse-data-format.h" |
| 40 #include "preparse-data.h" | 40 #include "preparse-data.h" |
| 41 #include "preparser.h" | 41 #include "preparser.h" |
| 42 #include "unicode.h" | 42 #include "unicode.h" |
| 43 #include "utils.h" | 43 #include "utils.h" |
| 44 | 44 |
| 45 #if V8_CC_MSVC && (_MSC_VER < 1800) | 45 #if V8_LIBC_MSVCRT && (_MSC_VER < 1800) |
| 46 namespace std { | 46 namespace std { |
| 47 | 47 |
| 48 // Usually defined in math.h, but not in MSVC until VS2013+. | 48 // Usually defined in math.h, but not in MSVC until VS2013+. |
| 49 // Abstracted to work | 49 // Abstracted to work |
| 50 int isfinite(double value); | 50 int isfinite(double value); |
| 51 | 51 |
| 52 } // namespace std | 52 } // namespace std |
| 53 #endif | 53 #endif |
| 54 | 54 |
| 55 namespace v8 { | 55 namespace v8 { |
| 56 namespace internal { | 56 namespace internal { |
| 57 | 57 |
| 58 void PreParserTraits::ReportMessageAt(Scanner::Location location, |
| 59 const char* message, |
| 60 Vector<const char*> args) { |
| 61 ReportMessageAt(location.beg_pos, |
| 62 location.end_pos, |
| 63 message, |
| 64 args.length() > 0 ? args[0] : NULL); |
| 65 } |
| 66 |
| 67 |
| 68 void PreParserTraits::ReportMessageAt(Scanner::Location location, |
| 69 const char* type, |
| 70 const char* name_opt) { |
| 71 pre_parser_->log_ |
| 72 ->LogMessage(location.beg_pos, location.end_pos, type, name_opt); |
| 73 } |
| 74 |
| 75 |
| 76 void PreParserTraits::ReportMessageAt(int start_pos, |
| 77 int end_pos, |
| 78 const char* type, |
| 79 const char* name_opt) { |
| 80 pre_parser_->log_->LogMessage(start_pos, end_pos, type, name_opt); |
| 81 } |
| 82 |
| 83 |
| 84 PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) { |
| 85 pre_parser_->LogSymbol(); |
| 86 if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) { |
| 87 return PreParserIdentifier::FutureReserved(); |
| 88 } else if (scanner->current_token() == |
| 89 Token::FUTURE_STRICT_RESERVED_WORD) { |
| 90 return PreParserIdentifier::FutureStrictReserved(); |
| 91 } else if (scanner->current_token() == Token::YIELD) { |
| 92 return PreParserIdentifier::Yield(); |
| 93 } |
| 94 if (scanner->is_literal_ascii()) { |
| 95 // Detect strict-mode poison words. |
| 96 if (scanner->literal_length() == 4 && |
| 97 !strncmp(scanner->literal_ascii_string().start(), "eval", 4)) { |
| 98 return PreParserIdentifier::Eval(); |
| 99 } |
| 100 if (scanner->literal_length() == 9 && |
| 101 !strncmp(scanner->literal_ascii_string().start(), "arguments", 9)) { |
| 102 return PreParserIdentifier::Arguments(); |
| 103 } |
| 104 } |
| 105 return PreParserIdentifier::Default(); |
| 106 } |
| 107 |
| 108 |
| 109 PreParserExpression PreParserTraits::ExpressionFromString( |
| 110 int pos, Scanner* scanner, PreParserFactory* factory) { |
| 111 const int kUseStrictLength = 10; |
| 112 const char* kUseStrictChars = "use strict"; |
| 113 pre_parser_->LogSymbol(); |
| 114 if (scanner->is_literal_ascii() && |
| 115 scanner->literal_length() == kUseStrictLength && |
| 116 !scanner->literal_contains_escapes() && |
| 117 !strncmp(scanner->literal_ascii_string().start(), kUseStrictChars, |
| 118 kUseStrictLength)) { |
| 119 return PreParserExpression::UseStrictStringLiteral(); |
| 120 } |
| 121 return PreParserExpression::StringLiteral(); |
| 122 } |
| 123 |
| 124 |
| 125 PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) { |
| 126 return pre_parser_->ParseObjectLiteral(ok); |
| 127 } |
| 128 |
| 129 |
| 130 PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN, |
| 131 bool* ok) { |
| 132 return pre_parser_->ParseAssignmentExpression(accept_IN, ok); |
| 133 } |
| 134 |
| 135 |
| 136 PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) { |
| 137 return pre_parser_->ParseV8Intrinsic(ok); |
| 138 } |
| 139 |
| 140 |
| 58 PreParser::PreParseResult PreParser::PreParseLazyFunction( | 141 PreParser::PreParseResult PreParser::PreParseLazyFunction( |
| 59 LanguageMode mode, bool is_generator, ParserRecorder* log) { | 142 LanguageMode mode, bool is_generator, ParserRecorder* log) { |
| 60 log_ = log; | 143 log_ = log; |
| 61 // Lazy functions always have trivial outer scopes (no with/catch scopes). | 144 // Lazy functions always have trivial outer scopes (no with/catch scopes). |
| 62 Scope top_scope(&scope_, kTopLevelScope); | 145 PreParserScope top_scope(scope_, GLOBAL_SCOPE); |
| 63 set_language_mode(mode); | 146 FunctionState top_state(&function_state_, &scope_, &top_scope); |
| 64 Scope function_scope(&scope_, kFunctionScope); | 147 scope_->SetLanguageMode(mode); |
| 65 function_scope.set_is_generator(is_generator); | 148 PreParserScope function_scope(scope_, FUNCTION_SCOPE); |
| 149 FunctionState function_state(&function_state_, &scope_, &function_scope); |
| 150 function_state.set_is_generator(is_generator); |
| 66 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); | 151 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); |
| 67 bool ok = true; | 152 bool ok = true; |
| 68 int start_position = peek_position(); | 153 int start_position = peek_position(); |
| 69 ParseLazyFunctionLiteralBody(&ok); | 154 ParseLazyFunctionLiteralBody(&ok); |
| 70 if (stack_overflow()) return kPreParseStackOverflow; | 155 if (stack_overflow()) return kPreParseStackOverflow; |
| 71 if (!ok) { | 156 if (!ok) { |
| 72 ReportUnexpectedToken(scanner()->current_token()); | 157 ReportUnexpectedToken(scanner()->current_token()); |
| 73 } else { | 158 } else { |
| 74 ASSERT_EQ(Token::RBRACE, scanner()->peek()); | 159 ASSERT_EQ(Token::RBRACE, scanner()->peek()); |
| 75 if (!is_classic_mode()) { | 160 if (!scope_->is_classic_mode()) { |
| 76 int end_pos = scanner()->location().end_pos; | 161 int end_pos = scanner()->location().end_pos; |
| 77 CheckOctalLiteral(start_position, end_pos, &ok); | 162 CheckOctalLiteral(start_position, end_pos, &ok); |
| 78 if (ok) { | |
| 79 CheckDelayedStrictModeViolation(start_position, end_pos, &ok); | |
| 80 } | |
| 81 } | 163 } |
| 82 } | 164 } |
| 83 return kPreParseSuccess; | 165 return kPreParseSuccess; |
| 84 } | 166 } |
| 85 | 167 |
| 86 | 168 |
| 87 // Preparsing checks a JavaScript program and emits preparse-data that helps | 169 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 88 // a later parsing to be faster. | 170 // a later parsing to be faster. |
| 89 // See preparser-data.h for the data. | 171 // See preparser-data.h for the data. |
| 90 | 172 |
| 91 // The PreParser checks that the syntax follows the grammar for JavaScript, | 173 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 92 // and collects some information about the program along the way. | 174 // and collects some information about the program along the way. |
| 93 // The grammar check is only performed in order to understand the program | 175 // The grammar check is only performed in order to understand the program |
| 94 // sufficiently to deduce some information about it, that can be used | 176 // 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, | 177 // 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. | 178 // rather it is to speed up properly written and correct programs. |
| 97 // That means that contextual checks (like a label being declared where | 179 // That means that contextual checks (like a label being declared where |
| 98 // it is used) are generally omitted. | 180 // it is used) are generally omitted. |
| 99 | 181 |
| 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 ScannerBase::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 | 182 |
| 132 #define CHECK_OK ok); \ | 183 #define CHECK_OK ok); \ |
| 133 if (!*ok) return kUnknownSourceElements; \ | 184 if (!*ok) return kUnknownSourceElements; \ |
| 134 ((void)0 | 185 ((void)0 |
| 135 #define DUMMY ) // to make indentation work | 186 #define DUMMY ) // to make indentation work |
| 136 #undef DUMMY | 187 #undef DUMMY |
| 137 | 188 |
| 138 | 189 |
| 139 PreParser::Statement PreParser::ParseSourceElement(bool* ok) { | 190 PreParser::Statement PreParser::ParseSourceElement(bool* ok) { |
| 140 // (Ecma 262 5th Edition, clause 14): | 191 // (Ecma 262 5th Edition, clause 14): |
| (...skipping 17 matching lines...) Expand all Loading... |
| 158 return ParseStatement(ok); | 209 return ParseStatement(ok); |
| 159 } | 210 } |
| 160 } | 211 } |
| 161 | 212 |
| 162 | 213 |
| 163 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, | 214 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
| 164 bool* ok) { | 215 bool* ok) { |
| 165 // SourceElements :: | 216 // SourceElements :: |
| 166 // (Statement)* <end_token> | 217 // (Statement)* <end_token> |
| 167 | 218 |
| 168 bool allow_directive_prologue = true; | 219 bool directive_prologue = true; |
| 169 while (peek() != end_token) { | 220 while (peek() != end_token) { |
| 221 if (directive_prologue && peek() != Token::STRING) { |
| 222 directive_prologue = false; |
| 223 } |
| 170 Statement statement = ParseSourceElement(CHECK_OK); | 224 Statement statement = ParseSourceElement(CHECK_OK); |
| 171 if (allow_directive_prologue) { | 225 if (directive_prologue) { |
| 172 if (statement.IsUseStrictLiteral()) { | 226 if (statement.IsUseStrictLiteral()) { |
| 173 set_language_mode(allow_harmony_scoping() ? | 227 scope_->SetLanguageMode(allow_harmony_scoping() ? |
| 174 EXTENDED_MODE : STRICT_MODE); | 228 EXTENDED_MODE : STRICT_MODE); |
| 175 } else if (!statement.IsStringLiteral()) { | 229 } else if (!statement.IsStringLiteral()) { |
| 176 allow_directive_prologue = false; | 230 directive_prologue = false; |
| 177 } | 231 } |
| 178 } | 232 } |
| 179 } | 233 } |
| 180 return kUnknownSourceElements; | 234 return kUnknownSourceElements; |
| 181 } | 235 } |
| 182 | 236 |
| 183 | 237 |
| 184 #undef CHECK_OK | 238 #undef CHECK_OK |
| 185 #define CHECK_OK ok); \ | 239 #define CHECK_OK ok); \ |
| 186 if (!*ok) return Statement::Default(); \ | 240 if (!*ok) return Statement::Default(); \ |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 case Token::SWITCH: | 309 case Token::SWITCH: |
| 256 return ParseSwitchStatement(ok); | 310 return ParseSwitchStatement(ok); |
| 257 | 311 |
| 258 case Token::THROW: | 312 case Token::THROW: |
| 259 return ParseThrowStatement(ok); | 313 return ParseThrowStatement(ok); |
| 260 | 314 |
| 261 case Token::TRY: | 315 case Token::TRY: |
| 262 return ParseTryStatement(ok); | 316 return ParseTryStatement(ok); |
| 263 | 317 |
| 264 case Token::FUNCTION: { | 318 case Token::FUNCTION: { |
| 265 ScannerBase::Location start_location = scanner()->peek_location(); | 319 Scanner::Location start_location = scanner()->peek_location(); |
| 266 Statement statement = ParseFunctionDeclaration(CHECK_OK); | 320 Statement statement = ParseFunctionDeclaration(CHECK_OK); |
| 267 ScannerBase::Location end_location = scanner()->location(); | 321 Scanner::Location end_location = scanner()->location(); |
| 268 if (!is_classic_mode()) { | 322 if (!scope_->is_classic_mode()) { |
| 269 ReportMessageAt(start_location.beg_pos, end_location.end_pos, | 323 PreParserTraits::ReportMessageAt(start_location.beg_pos, |
| 270 "strict_function", NULL); | 324 end_location.end_pos, |
| 325 "strict_function", |
| 326 NULL); |
| 271 *ok = false; | 327 *ok = false; |
| 272 return Statement::Default(); | 328 return Statement::Default(); |
| 273 } else { | 329 } else { |
| 274 return statement; | 330 return statement; |
| 275 } | 331 } |
| 276 } | 332 } |
| 277 | 333 |
| 278 case Token::DEBUGGER: | 334 case Token::DEBUGGER: |
| 279 return ParseDebuggerStatement(ok); | 335 return ParseDebuggerStatement(ok); |
| 280 | 336 |
| 281 default: | 337 default: |
| 282 return ParseExpressionOrLabelledStatement(ok); | 338 return ParseExpressionOrLabelledStatement(ok); |
| 283 } | 339 } |
| 284 } | 340 } |
| 285 | 341 |
| 286 | 342 |
| 287 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 343 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
| 288 // FunctionDeclaration :: | 344 // FunctionDeclaration :: |
| 289 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 345 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 290 // GeneratorDeclaration :: | 346 // GeneratorDeclaration :: |
| 291 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 347 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
| 292 // '{' FunctionBody '}' | 348 // '{' FunctionBody '}' |
| 293 Expect(Token::FUNCTION, CHECK_OK); | 349 Expect(Token::FUNCTION, CHECK_OK); |
| 294 | 350 |
| 295 bool is_generator = allow_generators() && Check(Token::MUL); | 351 bool is_generator = allow_generators() && Check(Token::MUL); |
| 296 Identifier identifier = ParseIdentifier(CHECK_OK); | 352 bool is_strict_reserved = false; |
| 297 ScannerBase::Location location = scanner()->location(); | 353 Identifier name = ParseIdentifierOrStrictReservedWord( |
| 298 | 354 &is_strict_reserved, CHECK_OK); |
| 299 Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK); | 355 ParseFunctionLiteral(name, |
| 300 | 356 scanner()->location(), |
| 301 if (function_value.IsStrictFunction() && | 357 is_strict_reserved, |
| 302 !identifier.IsValidStrictVariable()) { | 358 is_generator, |
| 303 // Strict mode violation, using either reserved word or eval/arguments | 359 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(); | 360 return Statement::FunctionDeclaration(); |
| 313 } | 361 } |
| 314 | 362 |
| 315 | 363 |
| 316 PreParser::Statement PreParser::ParseBlock(bool* ok) { | 364 PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| 317 // Block :: | 365 // Block :: |
| 318 // '{' Statement* '}' | 366 // '{' Statement* '}' |
| 319 | 367 |
| 320 // Note that a Block does not introduce a new execution scope! | 368 // Note that a Block does not introduce a new execution scope! |
| 321 // (ECMA-262, 3rd, 12.2) | 369 // (ECMA-262, 3rd, 12.2) |
| 322 // | 370 // |
| 323 Expect(Token::LBRACE, CHECK_OK); | 371 Expect(Token::LBRACE, CHECK_OK); |
| 324 while (peek() != Token::RBRACE) { | 372 while (peek() != Token::RBRACE) { |
| 325 if (is_extended_mode()) { | 373 if (scope_->is_extended_mode()) { |
| 326 ParseSourceElement(CHECK_OK); | 374 ParseSourceElement(CHECK_OK); |
| 327 } else { | 375 } else { |
| 328 ParseStatement(CHECK_OK); | 376 ParseStatement(CHECK_OK); |
| 329 } | 377 } |
| 330 } | 378 } |
| 331 Expect(Token::RBRACE, ok); | 379 Expect(Token::RBRACE, ok); |
| 332 return Statement::Default(); | 380 return Statement::Default(); |
| 333 } | 381 } |
| 334 | 382 |
| 335 | 383 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 // | 427 // |
| 380 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' | 428 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
| 381 // | 429 // |
| 382 // * It is a Syntax Error if the code that matches this production is not | 430 // * It is a Syntax Error if the code that matches this production is not |
| 383 // contained in extended code. | 431 // contained in extended code. |
| 384 // | 432 // |
| 385 // However disallowing const in classic mode will break compatibility with | 433 // However disallowing const in classic mode will break compatibility with |
| 386 // existing pages. Therefore we keep allowing const with the old | 434 // existing pages. Therefore we keep allowing const with the old |
| 387 // non-harmony semantics in classic mode. | 435 // non-harmony semantics in classic mode. |
| 388 Consume(Token::CONST); | 436 Consume(Token::CONST); |
| 389 switch (language_mode()) { | 437 switch (scope_->language_mode()) { |
| 390 case CLASSIC_MODE: | 438 case CLASSIC_MODE: |
| 391 break; | 439 break; |
| 392 case STRICT_MODE: { | 440 case STRICT_MODE: { |
| 393 ScannerBase::Location location = scanner()->peek_location(); | 441 Scanner::Location location = scanner()->peek_location(); |
| 394 ReportMessageAt(location, "strict_const", NULL); | 442 ReportMessageAt(location, "strict_const"); |
| 395 *ok = false; | 443 *ok = false; |
| 396 return Statement::Default(); | 444 return Statement::Default(); |
| 397 } | 445 } |
| 398 case EXTENDED_MODE: | 446 case EXTENDED_MODE: |
| 399 if (var_context != kSourceElement && | 447 if (var_context != kSourceElement && |
| 400 var_context != kForStatement) { | 448 var_context != kForStatement) { |
| 401 ScannerBase::Location location = scanner()->peek_location(); | 449 ReportMessageAt(scanner()->peek_location(), "unprotected_const"); |
| 402 ReportMessageAt(location.beg_pos, location.end_pos, | |
| 403 "unprotected_const", NULL); | |
| 404 *ok = false; | 450 *ok = false; |
| 405 return Statement::Default(); | 451 return Statement::Default(); |
| 406 } | 452 } |
| 407 require_initializer = true; | 453 require_initializer = true; |
| 408 break; | 454 break; |
| 409 } | 455 } |
| 410 } else if (peek() == Token::LET) { | 456 } else if (peek() == Token::LET) { |
| 411 // ES6 Draft Rev4 section 12.2.1: | 457 // ES6 Draft Rev4 section 12.2.1: |
| 412 // | 458 // |
| 413 // LetDeclaration : let LetBindingList ; | 459 // LetDeclaration : let LetBindingList ; |
| 414 // | 460 // |
| 415 // * It is a Syntax Error if the code that matches this production is not | 461 // * It is a Syntax Error if the code that matches this production is not |
| 416 // contained in extended code. | 462 // contained in extended code. |
| 417 if (!is_extended_mode()) { | 463 if (!scope_->is_extended_mode()) { |
| 418 ScannerBase::Location location = scanner()->peek_location(); | 464 ReportMessageAt(scanner()->peek_location(), "illegal_let"); |
| 419 ReportMessageAt(location.beg_pos, location.end_pos, | |
| 420 "illegal_let", NULL); | |
| 421 *ok = false; | 465 *ok = false; |
| 422 return Statement::Default(); | 466 return Statement::Default(); |
| 423 } | 467 } |
| 424 Consume(Token::LET); | 468 Consume(Token::LET); |
| 425 if (var_context != kSourceElement && | 469 if (var_context != kSourceElement && |
| 426 var_context != kForStatement) { | 470 var_context != kForStatement) { |
| 427 ScannerBase::Location location = scanner()->peek_location(); | 471 ReportMessageAt(scanner()->peek_location(), "unprotected_let"); |
| 428 ReportMessageAt(location.beg_pos, location.end_pos, | |
| 429 "unprotected_let", NULL); | |
| 430 *ok = false; | 472 *ok = false; |
| 431 return Statement::Default(); | 473 return Statement::Default(); |
| 432 } | 474 } |
| 433 } else { | 475 } else { |
| 434 *ok = false; | 476 *ok = false; |
| 435 return Statement::Default(); | 477 return Statement::Default(); |
| 436 } | 478 } |
| 437 | 479 |
| 438 // The scope of a var/const declared variable anywhere inside a function | 480 // 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 | 481 // 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 | 482 // of a let declared variable is the scope of the immediately enclosing |
| 441 // block. | 483 // block. |
| 442 int nvars = 0; // the number of variables declared | 484 int nvars = 0; // the number of variables declared |
| 443 do { | 485 do { |
| 444 // Parse variable name. | 486 // Parse variable name. |
| 445 if (nvars > 0) Consume(Token::COMMA); | 487 if (nvars > 0) Consume(Token::COMMA); |
| 446 Identifier identifier = ParseIdentifier(CHECK_OK); | 488 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++; | 489 nvars++; |
| 455 if (peek() == Token::ASSIGN || require_initializer) { | 490 if (peek() == Token::ASSIGN || require_initializer) { |
| 456 Expect(Token::ASSIGN, CHECK_OK); | 491 Expect(Token::ASSIGN, CHECK_OK); |
| 457 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | 492 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
| 458 if (decl_props != NULL) *decl_props = kHasInitializers; | 493 if (decl_props != NULL) *decl_props = kHasInitializers; |
| 459 } | 494 } |
| 460 } while (peek() == Token::COMMA); | 495 } while (peek() == Token::COMMA); |
| 461 | 496 |
| 462 if (num_decl != NULL) *num_decl = nvars; | 497 if (num_decl != NULL) *num_decl = nvars; |
| 463 return Statement::Default(); | 498 return Statement::Default(); |
| 464 } | 499 } |
| 465 | 500 |
| 466 | 501 |
| 467 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { | 502 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
| 468 // ExpressionStatement | LabelledStatement :: | 503 // ExpressionStatement | LabelledStatement :: |
| 469 // Expression ';' | 504 // Expression ';' |
| 470 // Identifier ':' Statement | 505 // Identifier ':' Statement |
| 471 | 506 |
| 507 bool starts_with_identifier = peek_any_identifier(); |
| 472 Expression expr = ParseExpression(true, CHECK_OK); | 508 Expression expr = ParseExpression(true, CHECK_OK); |
| 473 if (expr.IsRawIdentifier()) { | 509 // Even if the expression starts with an identifier, it is not necessarily an |
| 510 // identifier. For example, "foo + bar" starts with an identifier but is not |
| 511 // an identifier. |
| 512 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { |
| 513 // Expression is a single identifier, and not, e.g., a parenthesized |
| 514 // identifier. |
| 474 ASSERT(!expr.AsIdentifier().IsFutureReserved()); | 515 ASSERT(!expr.AsIdentifier().IsFutureReserved()); |
| 475 ASSERT(is_classic_mode() || | 516 ASSERT(scope_->is_classic_mode() || |
| 476 (!expr.AsIdentifier().IsFutureStrictReserved() && | 517 (!expr.AsIdentifier().IsFutureStrictReserved() && |
| 477 !expr.AsIdentifier().IsYield())); | 518 !expr.AsIdentifier().IsYield())); |
| 478 if (peek() == Token::COLON) { | 519 Consume(Token::COLON); |
| 479 Consume(Token::COLON); | 520 return ParseStatement(ok); |
| 480 return ParseStatement(ok); | |
| 481 } | |
| 482 // Preparsing is disabled for extensions (because the extension details | 521 // Preparsing is disabled for extensions (because the extension details |
| 483 // aren't passed to lazily compiled functions), so we don't | 522 // aren't passed to lazily compiled functions), so we don't |
| 484 // accept "native function" in the preparser. | 523 // accept "native function" in the preparser. |
| 485 } | 524 } |
| 486 // Parsed expression statement. | 525 // Parsed expression statement. |
| 487 ExpectSemicolon(CHECK_OK); | 526 ExpectSemicolon(CHECK_OK); |
| 488 return Statement::ExpressionStatement(expr); | 527 return Statement::ExpressionStatement(expr); |
| 489 } | 528 } |
| 490 | 529 |
| 491 | 530 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 509 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { | 548 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { |
| 510 // ContinueStatement :: | 549 // ContinueStatement :: |
| 511 // 'continue' [no line terminator] Identifier? ';' | 550 // 'continue' [no line terminator] Identifier? ';' |
| 512 | 551 |
| 513 Expect(Token::CONTINUE, CHECK_OK); | 552 Expect(Token::CONTINUE, CHECK_OK); |
| 514 Token::Value tok = peek(); | 553 Token::Value tok = peek(); |
| 515 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 554 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 516 tok != Token::SEMICOLON && | 555 tok != Token::SEMICOLON && |
| 517 tok != Token::RBRACE && | 556 tok != Token::RBRACE && |
| 518 tok != Token::EOS) { | 557 tok != Token::EOS) { |
| 519 ParseIdentifier(CHECK_OK); | 558 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 559 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 520 } | 560 } |
| 521 ExpectSemicolon(CHECK_OK); | 561 ExpectSemicolon(CHECK_OK); |
| 522 return Statement::Default(); | 562 return Statement::Default(); |
| 523 } | 563 } |
| 524 | 564 |
| 525 | 565 |
| 526 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { | 566 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
| 527 // BreakStatement :: | 567 // BreakStatement :: |
| 528 // 'break' [no line terminator] Identifier? ';' | 568 // 'break' [no line terminator] Identifier? ';' |
| 529 | 569 |
| 530 Expect(Token::BREAK, CHECK_OK); | 570 Expect(Token::BREAK, CHECK_OK); |
| 531 Token::Value tok = peek(); | 571 Token::Value tok = peek(); |
| 532 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 572 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 533 tok != Token::SEMICOLON && | 573 tok != Token::SEMICOLON && |
| 534 tok != Token::RBRACE && | 574 tok != Token::RBRACE && |
| 535 tok != Token::EOS) { | 575 tok != Token::EOS) { |
| 536 ParseIdentifier(CHECK_OK); | 576 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 577 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 537 } | 578 } |
| 538 ExpectSemicolon(CHECK_OK); | 579 ExpectSemicolon(CHECK_OK); |
| 539 return Statement::Default(); | 580 return Statement::Default(); |
| 540 } | 581 } |
| 541 | 582 |
| 542 | 583 |
| 543 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { | 584 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
| 544 // ReturnStatement :: | 585 // ReturnStatement :: |
| 545 // 'return' [no line terminator] Expression? ';' | 586 // 'return' [no line terminator] Expression? ';' |
| 546 | 587 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 563 } | 604 } |
| 564 ExpectSemicolon(CHECK_OK); | 605 ExpectSemicolon(CHECK_OK); |
| 565 return Statement::Default(); | 606 return Statement::Default(); |
| 566 } | 607 } |
| 567 | 608 |
| 568 | 609 |
| 569 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { | 610 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
| 570 // WithStatement :: | 611 // WithStatement :: |
| 571 // 'with' '(' Expression ')' Statement | 612 // 'with' '(' Expression ')' Statement |
| 572 Expect(Token::WITH, CHECK_OK); | 613 Expect(Token::WITH, CHECK_OK); |
| 573 if (!is_classic_mode()) { | 614 if (!scope_->is_classic_mode()) { |
| 574 ScannerBase::Location location = scanner()->location(); | 615 ReportMessageAt(scanner()->location(), "strict_mode_with"); |
| 575 ReportMessageAt(location, "strict_mode_with", NULL); | |
| 576 *ok = false; | 616 *ok = false; |
| 577 return Statement::Default(); | 617 return Statement::Default(); |
| 578 } | 618 } |
| 579 Expect(Token::LPAREN, CHECK_OK); | 619 Expect(Token::LPAREN, CHECK_OK); |
| 580 ParseExpression(true, CHECK_OK); | 620 ParseExpression(true, CHECK_OK); |
| 581 Expect(Token::RPAREN, CHECK_OK); | 621 Expect(Token::RPAREN, CHECK_OK); |
| 582 | 622 |
| 583 Scope::InsideWith iw(scope_); | 623 PreParserScope with_scope(scope_, WITH_SCOPE); |
| 624 BlockState block_state(&scope_, &with_scope); |
| 584 ParseStatement(CHECK_OK); | 625 ParseStatement(CHECK_OK); |
| 585 return Statement::Default(); | 626 return Statement::Default(); |
| 586 } | 627 } |
| 587 | 628 |
| 588 | 629 |
| 589 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { | 630 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { |
| 590 // SwitchStatement :: | 631 // SwitchStatement :: |
| 591 // 'switch' '(' Expression ')' '{' CaseClause* '}' | 632 // 'switch' '(' Expression ')' '{' CaseClause* '}' |
| 592 | 633 |
| 593 Expect(Token::SWITCH, CHECK_OK); | 634 Expect(Token::SWITCH, CHECK_OK); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 return Statement::Default(); | 750 return Statement::Default(); |
| 710 } | 751 } |
| 711 | 752 |
| 712 | 753 |
| 713 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { | 754 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { |
| 714 // ThrowStatement :: | 755 // ThrowStatement :: |
| 715 // 'throw' [no line terminator] Expression ';' | 756 // 'throw' [no line terminator] Expression ';' |
| 716 | 757 |
| 717 Expect(Token::THROW, CHECK_OK); | 758 Expect(Token::THROW, CHECK_OK); |
| 718 if (scanner()->HasAnyLineTerminatorBeforeNext()) { | 759 if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
| 719 ScannerBase::Location pos = scanner()->location(); | 760 ReportMessageAt(scanner()->location(), "newline_after_throw"); |
| 720 ReportMessageAt(pos, "newline_after_throw", NULL); | |
| 721 *ok = false; | 761 *ok = false; |
| 722 return Statement::Default(); | 762 return Statement::Default(); |
| 723 } | 763 } |
| 724 ParseExpression(true, CHECK_OK); | 764 ParseExpression(true, CHECK_OK); |
| 725 ExpectSemicolon(ok); | 765 ExpectSemicolon(ok); |
| 726 return Statement::Default(); | 766 return Statement::Default(); |
| 727 } | 767 } |
| 728 | 768 |
| 729 | 769 |
| 730 PreParser::Statement PreParser::ParseTryStatement(bool* ok) { | 770 PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
| 731 // TryStatement :: | 771 // TryStatement :: |
| 732 // 'try' Block Catch | 772 // 'try' Block Catch |
| 733 // 'try' Block Finally | 773 // 'try' Block Finally |
| 734 // 'try' Block Catch Finally | 774 // 'try' Block Catch Finally |
| 735 // | 775 // |
| 736 // Catch :: | 776 // Catch :: |
| 737 // 'catch' '(' Identifier ')' Block | 777 // 'catch' '(' Identifier ')' Block |
| 738 // | 778 // |
| 739 // Finally :: | 779 // Finally :: |
| 740 // 'finally' Block | 780 // 'finally' Block |
| 741 | 781 |
| 742 // In preparsing, allow any number of catch/finally blocks, including zero | |
| 743 // of both. | |
| 744 | |
| 745 Expect(Token::TRY, CHECK_OK); | 782 Expect(Token::TRY, CHECK_OK); |
| 746 | 783 |
| 747 ParseBlock(CHECK_OK); | 784 ParseBlock(CHECK_OK); |
| 748 | 785 |
| 749 bool catch_or_finally_seen = false; | 786 Token::Value tok = peek(); |
| 750 if (peek() == Token::CATCH) { | 787 if (tok != Token::CATCH && tok != Token::FINALLY) { |
| 788 ReportMessageAt(scanner()->location(), "no_catch_or_finally"); |
| 789 *ok = false; |
| 790 return Statement::Default(); |
| 791 } |
| 792 if (tok == Token::CATCH) { |
| 751 Consume(Token::CATCH); | 793 Consume(Token::CATCH); |
| 752 Expect(Token::LPAREN, CHECK_OK); | 794 Expect(Token::LPAREN, CHECK_OK); |
| 753 Identifier id = ParseIdentifier(CHECK_OK); | 795 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); | 796 Expect(Token::RPAREN, CHECK_OK); |
| 762 { Scope::InsideWith iw(scope_); | 797 { |
| 798 PreParserScope with_scope(scope_, WITH_SCOPE); |
| 799 BlockState block_state(&scope_, &with_scope); |
| 763 ParseBlock(CHECK_OK); | 800 ParseBlock(CHECK_OK); |
| 764 } | 801 } |
| 765 catch_or_finally_seen = true; | 802 tok = peek(); |
| 766 } | 803 } |
| 767 if (peek() == Token::FINALLY) { | 804 if (tok == Token::FINALLY) { |
| 768 Consume(Token::FINALLY); | 805 Consume(Token::FINALLY); |
| 769 ParseBlock(CHECK_OK); | 806 ParseBlock(CHECK_OK); |
| 770 catch_or_finally_seen = true; | |
| 771 } | |
| 772 if (!catch_or_finally_seen) { | |
| 773 *ok = false; | |
| 774 } | 807 } |
| 775 return Statement::Default(); | 808 return Statement::Default(); |
| 776 } | 809 } |
| 777 | 810 |
| 778 | 811 |
| 779 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { | 812 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
| 780 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 813 // 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 | 814 // contexts this is used as a statement which invokes the debugger as if a |
| 782 // break point is present. | 815 // break point is present. |
| 783 // DebuggerStatement :: | 816 // DebuggerStatement :: |
| 784 // 'debugger' ';' | 817 // 'debugger' ';' |
| 785 | 818 |
| 786 Expect(Token::DEBUGGER, CHECK_OK); | 819 Expect(Token::DEBUGGER, CHECK_OK); |
| 787 ExpectSemicolon(ok); | 820 ExpectSemicolon(ok); |
| 788 return Statement::Default(); | 821 return Statement::Default(); |
| 789 } | 822 } |
| 790 | 823 |
| 791 | 824 |
| 792 #undef CHECK_OK | 825 #undef CHECK_OK |
| 793 #define CHECK_OK ok); \ | 826 #define CHECK_OK ok); \ |
| 794 if (!*ok) return Expression::Default(); \ | 827 if (!*ok) return Expression::Default(); \ |
| 795 ((void)0 | 828 ((void)0 |
| 796 #define DUMMY ) // to make indentation work | 829 #define DUMMY ) // to make indentation work |
| 797 #undef DUMMY | 830 #undef DUMMY |
| 798 | 831 |
| 799 | 832 |
| 800 // Precedence = 1 | |
| 801 PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) { | |
| 802 // Expression :: | |
| 803 // AssignmentExpression | |
| 804 // Expression ',' AssignmentExpression | |
| 805 | |
| 806 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK); | |
| 807 while (peek() == Token::COMMA) { | |
| 808 Expect(Token::COMMA, CHECK_OK); | |
| 809 ParseAssignmentExpression(accept_IN, CHECK_OK); | |
| 810 result = Expression::Default(); | |
| 811 } | |
| 812 return result; | |
| 813 } | |
| 814 | |
| 815 | |
| 816 // Precedence = 2 | 833 // Precedence = 2 |
| 817 PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, | 834 PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, |
| 818 bool* ok) { | 835 bool* ok) { |
| 819 // AssignmentExpression :: | 836 // AssignmentExpression :: |
| 820 // ConditionalExpression | 837 // ConditionalExpression |
| 821 // YieldExpression | 838 // YieldExpression |
| 822 // LeftHandSideExpression AssignmentOperator AssignmentExpression | 839 // LeftHandSideExpression AssignmentOperator AssignmentExpression |
| 823 | 840 |
| 824 if (scope_->is_generator() && peek() == Token::YIELD) { | 841 if (function_state_->is_generator() && peek() == Token::YIELD) { |
| 825 return ParseYieldExpression(ok); | 842 return ParseYieldExpression(ok); |
| 826 } | 843 } |
| 827 | 844 |
| 828 ScannerBase::Location before = scanner()->peek_location(); | 845 Scanner::Location before = scanner()->peek_location(); |
| 829 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); | 846 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
| 830 | 847 |
| 831 if (!Token::IsAssignmentOp(peek())) { | 848 if (!Token::IsAssignmentOp(peek())) { |
| 832 // Parsed conditional expression only (no assignment). | 849 // Parsed conditional expression only (no assignment). |
| 833 return expression; | 850 return expression; |
| 834 } | 851 } |
| 835 | 852 |
| 836 if (!is_classic_mode() && | 853 if (!scope_->is_classic_mode() && |
| 837 expression.IsIdentifier() && | 854 expression.IsIdentifier() && |
| 838 expression.AsIdentifier().IsEvalOrArguments()) { | 855 expression.AsIdentifier().IsEvalOrArguments()) { |
| 839 ScannerBase::Location after = scanner()->location(); | 856 Scanner::Location after = scanner()->location(); |
| 840 ReportMessageAt(before.beg_pos, after.end_pos, | 857 PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos, |
| 841 "strict_lhs_assignment", NULL); | 858 "strict_eval_arguments", NULL); |
| 842 *ok = false; | 859 *ok = false; |
| 843 return Expression::Default(); | 860 return Expression::Default(); |
| 844 } | 861 } |
| 845 | 862 |
| 846 Token::Value op = Next(); // Get assignment operator. | 863 Token::Value op = Next(); // Get assignment operator. |
| 847 ParseAssignmentExpression(accept_IN, CHECK_OK); | 864 ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 848 | 865 |
| 849 if ((op == Token::ASSIGN) && expression.IsThisProperty()) { | 866 if ((op == Token::ASSIGN) && expression.IsThisProperty()) { |
| 850 scope_->AddProperty(); | 867 function_state_->AddProperty(); |
| 851 } | 868 } |
| 852 | 869 |
| 853 return Expression::Default(); | 870 return Expression::Default(); |
| 854 } | 871 } |
| 855 | 872 |
| 856 | 873 |
| 857 // Precedence = 3 | 874 // Precedence = 3 |
| 858 PreParser::Expression PreParser::ParseYieldExpression(bool* ok) { | 875 PreParser::Expression PreParser::ParseYieldExpression(bool* ok) { |
| 859 // YieldExpression :: | 876 // YieldExpression :: |
| 860 // 'yield' '*'? AssignmentExpression | 877 // 'yield' '*'? AssignmentExpression |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 // '~' UnaryExpression | 935 // '~' UnaryExpression |
| 919 // '!' UnaryExpression | 936 // '!' UnaryExpression |
| 920 | 937 |
| 921 Token::Value op = peek(); | 938 Token::Value op = peek(); |
| 922 if (Token::IsUnaryOp(op)) { | 939 if (Token::IsUnaryOp(op)) { |
| 923 op = Next(); | 940 op = Next(); |
| 924 ParseUnaryExpression(ok); | 941 ParseUnaryExpression(ok); |
| 925 return Expression::Default(); | 942 return Expression::Default(); |
| 926 } else if (Token::IsCountOp(op)) { | 943 } else if (Token::IsCountOp(op)) { |
| 927 op = Next(); | 944 op = Next(); |
| 928 ScannerBase::Location before = scanner()->peek_location(); | 945 Scanner::Location before = scanner()->peek_location(); |
| 929 Expression expression = ParseUnaryExpression(CHECK_OK); | 946 Expression expression = ParseUnaryExpression(CHECK_OK); |
| 930 if (!is_classic_mode() && | 947 if (!scope_->is_classic_mode() && |
| 931 expression.IsIdentifier() && | 948 expression.IsIdentifier() && |
| 932 expression.AsIdentifier().IsEvalOrArguments()) { | 949 expression.AsIdentifier().IsEvalOrArguments()) { |
| 933 ScannerBase::Location after = scanner()->location(); | 950 Scanner::Location after = scanner()->location(); |
| 934 ReportMessageAt(before.beg_pos, after.end_pos, | 951 PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos, |
| 935 "strict_lhs_prefix", NULL); | 952 "strict_eval_arguments", NULL); |
| 936 *ok = false; | 953 *ok = false; |
| 937 } | 954 } |
| 938 return Expression::Default(); | 955 return Expression::Default(); |
| 939 } else { | 956 } else { |
| 940 return ParsePostfixExpression(ok); | 957 return ParsePostfixExpression(ok); |
| 941 } | 958 } |
| 942 } | 959 } |
| 943 | 960 |
| 944 | 961 |
| 945 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { | 962 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { |
| 946 // PostfixExpression :: | 963 // PostfixExpression :: |
| 947 // LeftHandSideExpression ('++' | '--')? | 964 // LeftHandSideExpression ('++' | '--')? |
| 948 | 965 |
| 949 ScannerBase::Location before = scanner()->peek_location(); | 966 Scanner::Location before = scanner()->peek_location(); |
| 950 Expression expression = ParseLeftHandSideExpression(CHECK_OK); | 967 Expression expression = ParseLeftHandSideExpression(CHECK_OK); |
| 951 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 968 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 952 Token::IsCountOp(peek())) { | 969 Token::IsCountOp(peek())) { |
| 953 if (!is_classic_mode() && | 970 if (!scope_->is_classic_mode() && |
| 954 expression.IsIdentifier() && | 971 expression.IsIdentifier() && |
| 955 expression.AsIdentifier().IsEvalOrArguments()) { | 972 expression.AsIdentifier().IsEvalOrArguments()) { |
| 956 ScannerBase::Location after = scanner()->location(); | 973 Scanner::Location after = scanner()->location(); |
| 957 ReportMessageAt(before.beg_pos, after.end_pos, | 974 PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos, |
| 958 "strict_lhs_postfix", NULL); | 975 "strict_eval_arguments", NULL); |
| 959 *ok = false; | 976 *ok = false; |
| 960 return Expression::Default(); | 977 return Expression::Default(); |
| 961 } | 978 } |
| 962 Next(); | 979 Next(); |
| 963 return Expression::Default(); | 980 return Expression::Default(); |
| 964 } | 981 } |
| 965 return expression; | 982 return expression; |
| 966 } | 983 } |
| 967 | 984 |
| 968 | 985 |
| 969 PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { | 986 PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { |
| 970 // LeftHandSideExpression :: | 987 // LeftHandSideExpression :: |
| 971 // (NewExpression | MemberExpression) ... | 988 // (NewExpression | MemberExpression) ... |
| 972 | 989 |
| 973 Expression result = Expression::Default(); | 990 Expression result = ParseMemberWithNewPrefixesExpression(CHECK_OK); |
| 974 if (peek() == Token::NEW) { | |
| 975 result = ParseNewExpression(CHECK_OK); | |
| 976 } else { | |
| 977 result = ParseMemberExpression(CHECK_OK); | |
| 978 } | |
| 979 | 991 |
| 980 while (true) { | 992 while (true) { |
| 981 switch (peek()) { | 993 switch (peek()) { |
| 982 case Token::LBRACK: { | 994 case Token::LBRACK: { |
| 983 Consume(Token::LBRACK); | 995 Consume(Token::LBRACK); |
| 984 ParseExpression(true, CHECK_OK); | 996 ParseExpression(true, CHECK_OK); |
| 985 Expect(Token::RBRACK, CHECK_OK); | 997 Expect(Token::RBRACK, CHECK_OK); |
| 986 if (result.IsThis()) { | 998 if (result.IsThis()) { |
| 987 result = Expression::ThisProperty(); | 999 result = Expression::ThisProperty(); |
| 988 } else { | 1000 } else { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1008 break; | 1020 break; |
| 1009 } | 1021 } |
| 1010 | 1022 |
| 1011 default: | 1023 default: |
| 1012 return result; | 1024 return result; |
| 1013 } | 1025 } |
| 1014 } | 1026 } |
| 1015 } | 1027 } |
| 1016 | 1028 |
| 1017 | 1029 |
| 1018 PreParser::Expression PreParser::ParseNewExpression(bool* ok) { | 1030 PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( |
| 1031 bool* ok) { |
| 1019 // NewExpression :: | 1032 // NewExpression :: |
| 1020 // ('new')+ MemberExpression | 1033 // ('new')+ MemberExpression |
| 1021 | 1034 |
| 1022 // The grammar for new expressions is pretty warped. The keyword | 1035 // See Parser::ParseNewExpression. |
| 1023 // 'new' can either be a part of the new expression (where it isn't | 1036 |
| 1024 // followed by an argument list) or a part of the member expression, | 1037 if (peek() == Token::NEW) { |
| 1025 // where it must be followed by an argument list. To accommodate | |
| 1026 // this, we parse the 'new' keywords greedily and keep track of how | |
| 1027 // many we have parsed. This information is then passed on to the | |
| 1028 // member expression parser, which is only allowed to match argument | |
| 1029 // lists as long as it has 'new' prefixes left | |
| 1030 unsigned new_count = 0; | |
| 1031 do { | |
| 1032 Consume(Token::NEW); | 1038 Consume(Token::NEW); |
| 1033 new_count++; | 1039 ParseMemberWithNewPrefixesExpression(CHECK_OK); |
| 1034 } while (peek() == Token::NEW); | 1040 if (peek() == Token::LPAREN) { |
| 1035 | 1041 // NewExpression with arguments. |
| 1036 return ParseMemberWithNewPrefixesExpression(new_count, ok); | 1042 ParseArguments(CHECK_OK); |
| 1043 // The expression can still continue with . or [ after the arguments. |
| 1044 ParseMemberExpressionContinuation(Expression::Default(), CHECK_OK); |
| 1045 } |
| 1046 return Expression::Default(); |
| 1047 } |
| 1048 // No 'new' keyword. |
| 1049 return ParseMemberExpression(ok); |
| 1037 } | 1050 } |
| 1038 | 1051 |
| 1039 | 1052 |
| 1040 PreParser::Expression PreParser::ParseMemberExpression(bool* ok) { | 1053 PreParser::Expression PreParser::ParseMemberExpression(bool* ok) { |
| 1041 return ParseMemberWithNewPrefixesExpression(0, ok); | |
| 1042 } | |
| 1043 | |
| 1044 | |
| 1045 PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( | |
| 1046 unsigned new_count, bool* ok) { | |
| 1047 // MemberExpression :: | 1054 // MemberExpression :: |
| 1048 // (PrimaryExpression | FunctionLiteral) | 1055 // (PrimaryExpression | FunctionLiteral) |
| 1049 // ('[' Expression ']' | '.' Identifier | Arguments)* | 1056 // ('[' Expression ']' | '.' Identifier | Arguments)* |
| 1050 | 1057 |
| 1058 // The '[' Expression ']' and '.' Identifier parts are parsed by |
| 1059 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the |
| 1060 // caller. |
| 1061 |
| 1051 // Parse the initial primary or function expression. | 1062 // Parse the initial primary or function expression. |
| 1052 Expression result = Expression::Default(); | 1063 Expression result = Expression::Default(); |
| 1053 if (peek() == Token::FUNCTION) { | 1064 if (peek() == Token::FUNCTION) { |
| 1054 Consume(Token::FUNCTION); | 1065 Consume(Token::FUNCTION); |
| 1055 | 1066 |
| 1056 bool is_generator = allow_generators() && Check(Token::MUL); | 1067 bool is_generator = allow_generators() && Check(Token::MUL); |
| 1057 Identifier identifier = Identifier::Default(); | 1068 Identifier name = Identifier::Default(); |
| 1069 bool is_strict_reserved_name = false; |
| 1070 Scanner::Location function_name_location = Scanner::Location::invalid(); |
| 1058 if (peek_any_identifier()) { | 1071 if (peek_any_identifier()) { |
| 1059 identifier = ParseIdentifier(CHECK_OK); | 1072 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, |
| 1073 CHECK_OK); |
| 1074 function_name_location = scanner()->location(); |
| 1060 } | 1075 } |
| 1061 result = ParseFunctionLiteral(is_generator, CHECK_OK); | 1076 result = ParseFunctionLiteral(name, |
| 1062 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) { | 1077 function_name_location, |
| 1063 StrictModeIdentifierViolation(scanner()->location(), | 1078 is_strict_reserved_name, |
| 1064 "strict_function_name", | 1079 is_generator, |
| 1065 identifier, | 1080 CHECK_OK); |
| 1066 ok); | |
| 1067 return Expression::Default(); | |
| 1068 } | |
| 1069 } else { | 1081 } else { |
| 1070 result = ParsePrimaryExpression(CHECK_OK); | 1082 result = ParsePrimaryExpression(CHECK_OK); |
| 1071 } | 1083 } |
| 1084 result = ParseMemberExpressionContinuation(result, CHECK_OK); |
| 1085 return result; |
| 1086 } |
| 1072 | 1087 |
| 1088 |
| 1089 PreParser::Expression PreParser::ParseMemberExpressionContinuation( |
| 1090 PreParserExpression expression, bool* ok) { |
| 1091 // Parses this part of MemberExpression: |
| 1092 // ('[' Expression ']' | '.' Identifier)* |
| 1073 while (true) { | 1093 while (true) { |
| 1074 switch (peek()) { | 1094 switch (peek()) { |
| 1075 case Token::LBRACK: { | 1095 case Token::LBRACK: { |
| 1076 Consume(Token::LBRACK); | 1096 Consume(Token::LBRACK); |
| 1077 ParseExpression(true, CHECK_OK); | 1097 ParseExpression(true, CHECK_OK); |
| 1078 Expect(Token::RBRACK, CHECK_OK); | 1098 Expect(Token::RBRACK, CHECK_OK); |
| 1079 if (result.IsThis()) { | 1099 if (expression.IsThis()) { |
| 1080 result = Expression::ThisProperty(); | 1100 expression = Expression::ThisProperty(); |
| 1081 } else { | 1101 } else { |
| 1082 result = Expression::Default(); | 1102 expression = Expression::Default(); |
| 1083 } | 1103 } |
| 1084 break; | 1104 break; |
| 1085 } | 1105 } |
| 1086 case Token::PERIOD: { | 1106 case Token::PERIOD: { |
| 1087 Consume(Token::PERIOD); | 1107 Consume(Token::PERIOD); |
| 1088 ParseIdentifierName(CHECK_OK); | 1108 ParseIdentifierName(CHECK_OK); |
| 1089 if (result.IsThis()) { | 1109 if (expression.IsThis()) { |
| 1090 result = Expression::ThisProperty(); | 1110 expression = Expression::ThisProperty(); |
| 1091 } else { | 1111 } else { |
| 1092 result = Expression::Default(); | 1112 expression = Expression::Default(); |
| 1093 } | 1113 } |
| 1094 break; | 1114 break; |
| 1095 } | 1115 } |
| 1096 case Token::LPAREN: { | |
| 1097 if (new_count == 0) return result; | |
| 1098 // Consume one of the new prefixes (already parsed). | |
| 1099 ParseArguments(CHECK_OK); | |
| 1100 new_count--; | |
| 1101 result = Expression::Default(); | |
| 1102 break; | |
| 1103 } | |
| 1104 default: | 1116 default: |
| 1105 return result; | 1117 return expression; |
| 1106 } | 1118 } |
| 1107 } | 1119 } |
| 1120 ASSERT(false); |
| 1121 return PreParserExpression::Default(); |
| 1108 } | 1122 } |
| 1109 | 1123 |
| 1110 | 1124 |
| 1111 PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { | |
| 1112 // PrimaryExpression :: | |
| 1113 // 'this' | |
| 1114 // 'null' | |
| 1115 // 'true' | |
| 1116 // 'false' | |
| 1117 // Identifier | |
| 1118 // Number | |
| 1119 // String | |
| 1120 // ArrayLiteral | |
| 1121 // ObjectLiteral | |
| 1122 // RegExpLiteral | |
| 1123 // '(' Expression ')' | |
| 1124 | |
| 1125 Expression result = Expression::Default(); | |
| 1126 switch (peek()) { | |
| 1127 case Token::THIS: { | |
| 1128 Next(); | |
| 1129 result = Expression::This(); | |
| 1130 break; | |
| 1131 } | |
| 1132 | |
| 1133 case Token::FUTURE_RESERVED_WORD: | |
| 1134 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 1135 case Token::YIELD: | |
| 1136 case Token::IDENTIFIER: { | |
| 1137 Identifier id = ParseIdentifier(CHECK_OK); | |
| 1138 result = Expression::FromIdentifier(id); | |
| 1139 break; | |
| 1140 } | |
| 1141 | |
| 1142 case Token::NULL_LITERAL: | |
| 1143 case Token::TRUE_LITERAL: | |
| 1144 case Token::FALSE_LITERAL: | |
| 1145 case Token::NUMBER: { | |
| 1146 Next(); | |
| 1147 break; | |
| 1148 } | |
| 1149 case Token::STRING: { | |
| 1150 Next(); | |
| 1151 result = GetStringSymbol(); | |
| 1152 break; | |
| 1153 } | |
| 1154 | |
| 1155 case Token::ASSIGN_DIV: | |
| 1156 result = ParseRegExpLiteral(true, CHECK_OK); | |
| 1157 break; | |
| 1158 | |
| 1159 case Token::DIV: | |
| 1160 result = ParseRegExpLiteral(false, CHECK_OK); | |
| 1161 break; | |
| 1162 | |
| 1163 case Token::LBRACK: | |
| 1164 result = ParseArrayLiteral(CHECK_OK); | |
| 1165 break; | |
| 1166 | |
| 1167 case Token::LBRACE: | |
| 1168 result = ParseObjectLiteral(CHECK_OK); | |
| 1169 break; | |
| 1170 | |
| 1171 case Token::LPAREN: | |
| 1172 Consume(Token::LPAREN); | |
| 1173 parenthesized_function_ = (peek() == Token::FUNCTION); | |
| 1174 result = ParseExpression(true, CHECK_OK); | |
| 1175 Expect(Token::RPAREN, CHECK_OK); | |
| 1176 result = result.Parenthesize(); | |
| 1177 break; | |
| 1178 | |
| 1179 case Token::MOD: | |
| 1180 result = ParseV8Intrinsic(CHECK_OK); | |
| 1181 break; | |
| 1182 | |
| 1183 default: { | |
| 1184 Next(); | |
| 1185 *ok = false; | |
| 1186 return Expression::Default(); | |
| 1187 } | |
| 1188 } | |
| 1189 | |
| 1190 return result; | |
| 1191 } | |
| 1192 | |
| 1193 | |
| 1194 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { | |
| 1195 // ArrayLiteral :: | |
| 1196 // '[' Expression? (',' Expression?)* ']' | |
| 1197 Expect(Token::LBRACK, CHECK_OK); | |
| 1198 while (peek() != Token::RBRACK) { | |
| 1199 if (peek() != Token::COMMA) { | |
| 1200 ParseAssignmentExpression(true, CHECK_OK); | |
| 1201 } | |
| 1202 if (peek() != Token::RBRACK) { | |
| 1203 Expect(Token::COMMA, CHECK_OK); | |
| 1204 } | |
| 1205 } | |
| 1206 Expect(Token::RBRACK, CHECK_OK); | |
| 1207 | |
| 1208 scope_->NextMaterializedLiteralIndex(); | |
| 1209 return Expression::Default(); | |
| 1210 } | |
| 1211 | |
| 1212 | |
| 1213 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { | 1125 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { |
| 1214 // ObjectLiteral :: | 1126 // ObjectLiteral :: |
| 1215 // '{' ( | 1127 // '{' ( |
| 1216 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 1128 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
| 1217 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1129 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 1218 // )*[','] '}' | 1130 // )*[','] '}' |
| 1219 | 1131 |
| 1220 ObjectLiteralChecker checker(this, language_mode()); | 1132 ObjectLiteralChecker checker(this, scope_->language_mode()); |
| 1221 | 1133 |
| 1222 Expect(Token::LBRACE, CHECK_OK); | 1134 Expect(Token::LBRACE, CHECK_OK); |
| 1223 while (peek() != Token::RBRACE) { | 1135 while (peek() != Token::RBRACE) { |
| 1224 Token::Value next = peek(); | 1136 Token::Value next = peek(); |
| 1225 switch (next) { | 1137 switch (next) { |
| 1226 case Token::IDENTIFIER: | 1138 case Token::IDENTIFIER: |
| 1227 case Token::FUTURE_RESERVED_WORD: | 1139 case Token::FUTURE_RESERVED_WORD: |
| 1228 case Token::FUTURE_STRICT_RESERVED_WORD: { | 1140 case Token::FUTURE_STRICT_RESERVED_WORD: { |
| 1229 bool is_getter = false; | 1141 bool is_getter = false; |
| 1230 bool is_setter = false; | 1142 bool is_setter = false; |
| 1231 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 1143 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 1232 if ((is_getter || is_setter) && peek() != Token::COLON) { | 1144 if ((is_getter || is_setter) && peek() != Token::COLON) { |
| 1233 Token::Value name = Next(); | 1145 Token::Value name = Next(); |
| 1234 bool is_keyword = Token::IsKeyword(name); | 1146 bool is_keyword = Token::IsKeyword(name); |
| 1235 if (name != Token::IDENTIFIER && | 1147 if (name != Token::IDENTIFIER && |
| 1236 name != Token::FUTURE_RESERVED_WORD && | 1148 name != Token::FUTURE_RESERVED_WORD && |
| 1237 name != Token::FUTURE_STRICT_RESERVED_WORD && | 1149 name != Token::FUTURE_STRICT_RESERVED_WORD && |
| 1238 name != Token::NUMBER && | 1150 name != Token::NUMBER && |
| 1239 name != Token::STRING && | 1151 name != Token::STRING && |
| 1240 !is_keyword) { | 1152 !is_keyword) { |
| 1241 *ok = false; | 1153 *ok = false; |
| 1242 return Expression::Default(); | 1154 return Expression::Default(); |
| 1243 } | 1155 } |
| 1244 if (!is_keyword) { | 1156 if (!is_keyword) { |
| 1245 LogSymbol(); | 1157 LogSymbol(); |
| 1246 } | 1158 } |
| 1247 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | 1159 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; |
| 1248 checker.CheckProperty(name, type, CHECK_OK); | 1160 checker.CheckProperty(name, type, CHECK_OK); |
| 1249 ParseFunctionLiteral(false, CHECK_OK); | 1161 ParseFunctionLiteral(Identifier::Default(), |
| 1162 scanner()->location(), |
| 1163 false, // reserved words are allowed here |
| 1164 false, // not a generator |
| 1165 CHECK_OK); |
| 1250 if (peek() != Token::RBRACE) { | 1166 if (peek() != Token::RBRACE) { |
| 1251 Expect(Token::COMMA, CHECK_OK); | 1167 Expect(Token::COMMA, CHECK_OK); |
| 1252 } | 1168 } |
| 1253 continue; // restart the while | 1169 continue; // restart the while |
| 1254 } | 1170 } |
| 1255 checker.CheckProperty(next, kValueProperty, CHECK_OK); | 1171 checker.CheckProperty(next, kValueProperty, CHECK_OK); |
| 1256 break; | 1172 break; |
| 1257 } | 1173 } |
| 1258 case Token::STRING: | 1174 case Token::STRING: |
| 1259 Consume(next); | 1175 Consume(next); |
| 1260 checker.CheckProperty(next, kValueProperty, CHECK_OK); | 1176 checker.CheckProperty(next, kValueProperty, CHECK_OK); |
| 1261 GetStringSymbol(); | 1177 LogSymbol(); |
| 1262 break; | 1178 break; |
| 1263 case Token::NUMBER: | 1179 case Token::NUMBER: |
| 1264 Consume(next); | 1180 Consume(next); |
| 1265 checker.CheckProperty(next, kValueProperty, CHECK_OK); | 1181 checker.CheckProperty(next, kValueProperty, CHECK_OK); |
| 1266 break; | 1182 break; |
| 1267 default: | 1183 default: |
| 1268 if (Token::IsKeyword(next)) { | 1184 if (Token::IsKeyword(next)) { |
| 1269 Consume(next); | 1185 Consume(next); |
| 1270 checker.CheckProperty(next, kValueProperty, CHECK_OK); | 1186 checker.CheckProperty(next, kValueProperty, CHECK_OK); |
| 1187 LogSymbol(); |
| 1271 } else { | 1188 } else { |
| 1272 // Unexpected token. | 1189 // Unexpected token. |
| 1273 *ok = false; | 1190 *ok = false; |
| 1274 return Expression::Default(); | 1191 return Expression::Default(); |
| 1275 } | 1192 } |
| 1276 } | 1193 } |
| 1277 | 1194 |
| 1278 Expect(Token::COLON, CHECK_OK); | 1195 Expect(Token::COLON, CHECK_OK); |
| 1279 ParseAssignmentExpression(true, CHECK_OK); | 1196 ParseAssignmentExpression(true, CHECK_OK); |
| 1280 | 1197 |
| 1281 // TODO(1240767): Consider allowing trailing comma. | 1198 // TODO(1240767): Consider allowing trailing comma. |
| 1282 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 1199 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 1283 } | 1200 } |
| 1284 Expect(Token::RBRACE, CHECK_OK); | 1201 Expect(Token::RBRACE, CHECK_OK); |
| 1285 | 1202 |
| 1286 scope_->NextMaterializedLiteralIndex(); | 1203 function_state_->NextMaterializedLiteralIndex(); |
| 1287 return Expression::Default(); | 1204 return Expression::Default(); |
| 1288 } | 1205 } |
| 1289 | 1206 |
| 1290 | |
| 1291 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, | |
| 1292 bool* ok) { | |
| 1293 if (!scanner()->ScanRegExpPattern(seen_equal)) { | |
| 1294 Next(); | |
| 1295 ReportMessageAt(scanner()->location(), "unterminated_regexp", NULL); | |
| 1296 *ok = false; | |
| 1297 return Expression::Default(); | |
| 1298 } | |
| 1299 | |
| 1300 scope_->NextMaterializedLiteralIndex(); | |
| 1301 | |
| 1302 if (!scanner()->ScanRegExpFlags()) { | |
| 1303 Next(); | |
| 1304 ReportMessageAt(scanner()->location(), "invalid_regexp_flags", NULL); | |
| 1305 *ok = false; | |
| 1306 return Expression::Default(); | |
| 1307 } | |
| 1308 Next(); | |
| 1309 return Expression::Default(); | |
| 1310 } | |
| 1311 | |
| 1312 | 1207 |
| 1313 PreParser::Arguments PreParser::ParseArguments(bool* ok) { | 1208 PreParser::Arguments PreParser::ParseArguments(bool* ok) { |
| 1314 // Arguments :: | 1209 // Arguments :: |
| 1315 // '(' (AssignmentExpression)*[','] ')' | 1210 // '(' (AssignmentExpression)*[','] ')' |
| 1316 | 1211 |
| 1317 Expect(Token::LPAREN, ok); | 1212 Expect(Token::LPAREN, ok); |
| 1318 if (!*ok) return -1; | 1213 if (!*ok) return -1; |
| 1319 bool done = (peek() == Token::RPAREN); | 1214 bool done = (peek() == Token::RPAREN); |
| 1320 int argc = 0; | 1215 int argc = 0; |
| 1321 while (!done) { | 1216 while (!done) { |
| 1322 ParseAssignmentExpression(true, ok); | 1217 ParseAssignmentExpression(true, ok); |
| 1323 if (!*ok) return -1; | 1218 if (!*ok) return -1; |
| 1324 argc++; | 1219 argc++; |
| 1325 done = (peek() == Token::RPAREN); | 1220 done = (peek() == Token::RPAREN); |
| 1326 if (!done) { | 1221 if (!done) { |
| 1327 Expect(Token::COMMA, ok); | 1222 Expect(Token::COMMA, ok); |
| 1328 if (!*ok) return -1; | 1223 if (!*ok) return -1; |
| 1329 } | 1224 } |
| 1330 } | 1225 } |
| 1331 Expect(Token::RPAREN, ok); | 1226 Expect(Token::RPAREN, ok); |
| 1332 return argc; | 1227 return argc; |
| 1333 } | 1228 } |
| 1334 | 1229 |
| 1335 | 1230 PreParser::Expression PreParser::ParseFunctionLiteral( |
| 1336 PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator, | 1231 Identifier function_name, |
| 1337 bool* ok) { | 1232 Scanner::Location function_name_location, |
| 1233 bool name_is_strict_reserved, |
| 1234 bool is_generator, |
| 1235 bool* ok) { |
| 1338 // Function :: | 1236 // Function :: |
| 1339 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 1237 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 1340 | 1238 |
| 1341 // Parse function body. | 1239 // Parse function body. |
| 1342 ScopeType outer_scope_type = scope_->type(); | 1240 ScopeType outer_scope_type = scope_->type(); |
| 1343 bool inside_with = scope_->IsInsideWith(); | 1241 bool inside_with = scope_->inside_with(); |
| 1344 Scope function_scope(&scope_, kFunctionScope); | 1242 PreParserScope function_scope(scope_, FUNCTION_SCOPE); |
| 1345 function_scope.set_is_generator(is_generator); | 1243 FunctionState function_state(&function_state_, &scope_, &function_scope); |
| 1244 function_state.set_is_generator(is_generator); |
| 1346 // FormalParameterList :: | 1245 // FormalParameterList :: |
| 1347 // '(' (Identifier)*[','] ')' | 1246 // '(' (Identifier)*[','] ')' |
| 1348 Expect(Token::LPAREN, CHECK_OK); | 1247 Expect(Token::LPAREN, CHECK_OK); |
| 1349 int start_position = position(); | 1248 int start_position = position(); |
| 1350 bool done = (peek() == Token::RPAREN); | 1249 bool done = (peek() == Token::RPAREN); |
| 1351 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 1250 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
| 1251 // We don't yet know if the function will be strict, so we cannot yet produce |
| 1252 // errors for parameter names or duplicates. However, we remember the |
| 1253 // locations of these errors if they occur and produce the errors later. |
| 1254 Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); |
| 1255 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
| 1256 Scanner::Location reserved_error_loc = Scanner::Location::invalid(); |
| 1352 while (!done) { | 1257 while (!done) { |
| 1353 Identifier id = ParseIdentifier(CHECK_OK); | 1258 bool is_strict_reserved = false; |
| 1354 if (!id.IsValidStrictVariable()) { | 1259 Identifier param_name = |
| 1355 StrictModeIdentifierViolation(scanner()->location(), | 1260 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 1356 "strict_param_name", | 1261 if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) { |
| 1357 id, | 1262 eval_args_error_loc = scanner()->location(); |
| 1358 CHECK_OK); | |
| 1359 } | 1263 } |
| 1264 if (!reserved_error_loc.IsValid() && is_strict_reserved) { |
| 1265 reserved_error_loc = scanner()->location(); |
| 1266 } |
| 1267 |
| 1360 int prev_value; | 1268 int prev_value; |
| 1361 if (scanner()->is_literal_ascii()) { | 1269 if (scanner()->is_literal_ascii()) { |
| 1362 prev_value = | 1270 prev_value = |
| 1363 duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1); | 1271 duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1); |
| 1364 } else { | 1272 } else { |
| 1365 prev_value = | 1273 prev_value = |
| 1366 duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1); | 1274 duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1); |
| 1367 } | 1275 } |
| 1368 | 1276 |
| 1369 if (prev_value != 0) { | 1277 if (!dupe_error_loc.IsValid() && prev_value != 0) { |
| 1370 SetStrictModeViolation(scanner()->location(), | 1278 dupe_error_loc = scanner()->location(); |
| 1371 "strict_param_dupe", | |
| 1372 CHECK_OK); | |
| 1373 } | 1279 } |
| 1280 |
| 1374 done = (peek() == Token::RPAREN); | 1281 done = (peek() == Token::RPAREN); |
| 1375 if (!done) { | 1282 if (!done) { |
| 1376 Expect(Token::COMMA, CHECK_OK); | 1283 Expect(Token::COMMA, CHECK_OK); |
| 1377 } | 1284 } |
| 1378 } | 1285 } |
| 1379 Expect(Token::RPAREN, CHECK_OK); | 1286 Expect(Token::RPAREN, CHECK_OK); |
| 1380 | 1287 |
| 1381 // Determine if the function will be lazily compiled. | 1288 // See Parser::ParseFunctionLiteral for more information about lazy parsing |
| 1382 // Currently only happens to top-level functions. | 1289 // and lazy compilation. |
| 1383 // Optimistically assume that all top-level functions are lazily compiled. | 1290 bool is_lazily_parsed = (outer_scope_type == GLOBAL_SCOPE && |
| 1384 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && | 1291 !inside_with && allow_lazy() && |
| 1385 !inside_with && allow_lazy() && | 1292 !parenthesized_function_); |
| 1386 !parenthesized_function_); | |
| 1387 parenthesized_function_ = false; | 1293 parenthesized_function_ = false; |
| 1388 | 1294 |
| 1389 Expect(Token::LBRACE, CHECK_OK); | 1295 Expect(Token::LBRACE, CHECK_OK); |
| 1390 if (is_lazily_compiled) { | 1296 if (is_lazily_parsed) { |
| 1391 ParseLazyFunctionLiteralBody(CHECK_OK); | 1297 ParseLazyFunctionLiteralBody(CHECK_OK); |
| 1392 } else { | 1298 } else { |
| 1393 ParseSourceElements(Token::RBRACE, ok); | 1299 ParseSourceElements(Token::RBRACE, ok); |
| 1394 } | 1300 } |
| 1395 Expect(Token::RBRACE, CHECK_OK); | 1301 Expect(Token::RBRACE, CHECK_OK); |
| 1396 | 1302 |
| 1397 if (!is_classic_mode()) { | 1303 // Validate strict mode. We can do this only after parsing the function, |
| 1304 // since the function can declare itself strict. |
| 1305 if (!scope_->is_classic_mode()) { |
| 1306 if (function_name.IsEvalOrArguments()) { |
| 1307 ReportMessageAt(function_name_location, "strict_eval_arguments"); |
| 1308 *ok = false; |
| 1309 return Expression::Default(); |
| 1310 } |
| 1311 if (name_is_strict_reserved) { |
| 1312 ReportMessageAt(function_name_location, "unexpected_strict_reserved"); |
| 1313 *ok = false; |
| 1314 return Expression::Default(); |
| 1315 } |
| 1316 if (eval_args_error_loc.IsValid()) { |
| 1317 ReportMessageAt(eval_args_error_loc, "strict_eval_arguments"); |
| 1318 *ok = false; |
| 1319 return Expression::Default(); |
| 1320 } |
| 1321 if (dupe_error_loc.IsValid()) { |
| 1322 ReportMessageAt(dupe_error_loc, "strict_param_dupe"); |
| 1323 *ok = false; |
| 1324 return Expression::Default(); |
| 1325 } |
| 1326 if (reserved_error_loc.IsValid()) { |
| 1327 ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved"); |
| 1328 *ok = false; |
| 1329 return Expression::Default(); |
| 1330 } |
| 1331 |
| 1398 int end_position = scanner()->location().end_pos; | 1332 int end_position = scanner()->location().end_pos; |
| 1399 CheckOctalLiteral(start_position, end_position, CHECK_OK); | 1333 CheckOctalLiteral(start_position, end_position, CHECK_OK); |
| 1400 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); | |
| 1401 return Expression::StrictFunction(); | 1334 return Expression::StrictFunction(); |
| 1402 } | 1335 } |
| 1403 | 1336 |
| 1404 return Expression::Default(); | 1337 return Expression::Default(); |
| 1405 } | 1338 } |
| 1406 | 1339 |
| 1407 | 1340 |
| 1408 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { | 1341 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { |
| 1409 int body_start = position(); | 1342 int body_start = position(); |
| 1410 log_->PauseRecording(); | 1343 log_->PauseRecording(); |
| 1411 ParseSourceElements(Token::RBRACE, ok); | 1344 ParseSourceElements(Token::RBRACE, ok); |
| 1412 log_->ResumeRecording(); | 1345 log_->ResumeRecording(); |
| 1413 if (!*ok) return; | 1346 if (!*ok) return; |
| 1414 | 1347 |
| 1415 // Position right after terminal '}'. | 1348 // Position right after terminal '}'. |
| 1416 ASSERT_EQ(Token::RBRACE, scanner()->peek()); | 1349 ASSERT_EQ(Token::RBRACE, scanner()->peek()); |
| 1417 int body_end = scanner()->peek_location().end_pos; | 1350 int body_end = scanner()->peek_location().end_pos; |
| 1418 log_->LogFunction(body_start, body_end, | 1351 log_->LogFunction(body_start, body_end, |
| 1419 scope_->materialized_literal_count(), | 1352 function_state_->materialized_literal_count(), |
| 1420 scope_->expected_properties(), | 1353 function_state_->expected_property_count(), |
| 1421 language_mode()); | 1354 scope_->language_mode()); |
| 1422 } | 1355 } |
| 1423 | 1356 |
| 1424 | 1357 |
| 1425 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { | 1358 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
| 1426 // CallRuntime :: | 1359 // CallRuntime :: |
| 1427 // '%' Identifier Arguments | 1360 // '%' Identifier Arguments |
| 1428 Expect(Token::MOD, CHECK_OK); | 1361 Expect(Token::MOD, CHECK_OK); |
| 1429 if (!allow_natives_syntax()) { | 1362 if (!allow_natives_syntax()) { |
| 1430 *ok = false; | 1363 *ok = false; |
| 1431 return Expression::Default(); | 1364 return Expression::Default(); |
| 1432 } | 1365 } |
| 1433 ParseIdentifier(CHECK_OK); | 1366 // Allow "eval" or "arguments" for backward compatibility. |
| 1367 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| 1434 ParseArguments(ok); | 1368 ParseArguments(ok); |
| 1435 | 1369 |
| 1436 return Expression::Default(); | 1370 return Expression::Default(); |
| 1437 } | 1371 } |
| 1438 | 1372 |
| 1439 #undef CHECK_OK | 1373 #undef CHECK_OK |
| 1440 | 1374 |
| 1441 | 1375 |
| 1442 void PreParser::LogSymbol() { | 1376 void PreParser::LogSymbol() { |
| 1443 int identifier_pos = position(); | 1377 int identifier_pos = position(); |
| 1444 if (scanner()->is_literal_ascii()) { | 1378 if (scanner()->is_literal_ascii()) { |
| 1445 log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string()); | 1379 log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string()); |
| 1446 } else { | 1380 } else { |
| 1447 log_->LogUtf16Symbol(identifier_pos, scanner()->literal_utf16_string()); | 1381 log_->LogUtf16Symbol(identifier_pos, scanner()->literal_utf16_string()); |
| 1448 } | 1382 } |
| 1449 } | 1383 } |
| 1450 | 1384 |
| 1451 | 1385 |
| 1452 PreParser::Expression PreParser::GetStringSymbol() { | |
| 1453 const int kUseStrictLength = 10; | |
| 1454 const char* kUseStrictChars = "use strict"; | |
| 1455 LogSymbol(); | |
| 1456 if (scanner()->is_literal_ascii() && | |
| 1457 scanner()->literal_length() == kUseStrictLength && | |
| 1458 !scanner()->literal_contains_escapes() && | |
| 1459 !strncmp(scanner()->literal_ascii_string().start(), kUseStrictChars, | |
| 1460 kUseStrictLength)) { | |
| 1461 return Expression::UseStrictStringLiteral(); | |
| 1462 } | |
| 1463 return Expression::StringLiteral(); | |
| 1464 } | |
| 1465 | |
| 1466 | |
| 1467 PreParser::Identifier PreParser::GetIdentifierSymbol() { | |
| 1468 LogSymbol(); | |
| 1469 if (scanner()->current_token() == Token::FUTURE_RESERVED_WORD) { | |
| 1470 return Identifier::FutureReserved(); | |
| 1471 } else if (scanner()->current_token() == | |
| 1472 Token::FUTURE_STRICT_RESERVED_WORD) { | |
| 1473 return Identifier::FutureStrictReserved(); | |
| 1474 } else if (scanner()->current_token() == Token::YIELD) { | |
| 1475 return Identifier::Yield(); | |
| 1476 } | |
| 1477 if (scanner()->is_literal_ascii()) { | |
| 1478 // Detect strict-mode poison words. | |
| 1479 if (scanner()->literal_length() == 4 && | |
| 1480 !strncmp(scanner()->literal_ascii_string().start(), "eval", 4)) { | |
| 1481 return Identifier::Eval(); | |
| 1482 } | |
| 1483 if (scanner()->literal_length() == 9 && | |
| 1484 !strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) { | |
| 1485 return Identifier::Arguments(); | |
| 1486 } | |
| 1487 } | |
| 1488 return Identifier::Default(); | |
| 1489 } | |
| 1490 | |
| 1491 | |
| 1492 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { | |
| 1493 Token::Value next = Next(); | |
| 1494 switch (next) { | |
| 1495 case Token::FUTURE_RESERVED_WORD: { | |
| 1496 ScannerBase::Location location = scanner()->location(); | |
| 1497 ReportMessageAt(location.beg_pos, location.end_pos, | |
| 1498 "reserved_word", NULL); | |
| 1499 *ok = false; | |
| 1500 return GetIdentifierSymbol(); | |
| 1501 } | |
| 1502 case Token::YIELD: | |
| 1503 if (scope_->is_generator()) { | |
| 1504 // 'yield' in a generator is only valid as part of a YieldExpression. | |
| 1505 ReportMessageAt(scanner()->location(), "unexpected_token", "yield"); | |
| 1506 *ok = false; | |
| 1507 return Identifier::Yield(); | |
| 1508 } | |
| 1509 // FALLTHROUGH | |
| 1510 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 1511 if (!is_classic_mode()) { | |
| 1512 ScannerBase::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 } | |
| 1524 } | |
| 1525 | |
| 1526 | |
| 1527 void PreParser::SetStrictModeViolation(ScannerBase::Location location, | |
| 1528 const char* type, | |
| 1529 bool* ok) { | |
| 1530 if (!is_classic_mode()) { | |
| 1531 ReportMessageAt(location, type, NULL); | |
| 1532 *ok = false; | |
| 1533 return; | |
| 1534 } | |
| 1535 // Delay report in case this later turns out to be strict code | |
| 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 ScannerBase::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(ScannerBase::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 } | |
| 1578 | |
| 1579 | |
| 1580 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { | |
| 1581 Token::Value next = Next(); | |
| 1582 if (Token::IsKeyword(next)) { | |
| 1583 int pos = position(); | |
| 1584 const char* keyword = Token::String(next); | |
| 1585 log_->LogAsciiSymbol(pos, Vector<const char>(keyword, StrLength(keyword))); | |
| 1586 return Identifier::Default(); | |
| 1587 } | |
| 1588 if (next == Token::IDENTIFIER || | |
| 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 } | |
| 1596 | |
| 1597 #undef CHECK_OK | |
| 1598 | |
| 1599 | |
| 1600 // This function reads an identifier and determines whether or not it | |
| 1601 // is 'get' or 'set'. | |
| 1602 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get, | |
| 1603 bool* is_set, | |
| 1604 bool* ok) { | |
| 1605 Identifier result = ParseIdentifierName(ok); | |
| 1606 if (!*ok) return Identifier::Default(); | |
| 1607 if (scanner()->is_literal_ascii() && | |
| 1608 scanner()->literal_length() == 3) { | |
| 1609 const char* token = scanner()->literal_ascii_string().start(); | |
| 1610 *is_get = strncmp(token, "get", 3) == 0; | |
| 1611 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | |
| 1612 } | |
| 1613 return result; | |
| 1614 } | |
| 1615 | |
| 1616 | |
| 1617 void PreParser::ObjectLiteralChecker::CheckProperty(Token::Value property, | |
| 1618 PropertyKind type, | |
| 1619 bool* ok) { | |
| 1620 int old; | |
| 1621 if (property == Token::NUMBER) { | |
| 1622 old = finder_.AddNumber(scanner()->literal_ascii_string(), type); | |
| 1623 } else if (scanner()->is_literal_ascii()) { | |
| 1624 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type); | |
| 1625 } else { | |
| 1626 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type); | |
| 1627 } | |
| 1628 PropertyKind old_type = static_cast<PropertyKind>(old); | |
| 1629 if (HasConflict(old_type, type)) { | |
| 1630 if (IsDataDataConflict(old_type, type)) { | |
| 1631 // Both are data properties. | |
| 1632 if (language_mode_ == CLASSIC_MODE) return; | |
| 1633 parser()->ReportMessageAt(scanner()->location(), | |
| 1634 "strict_duplicate_property"); | |
| 1635 } else if (IsDataAccessorConflict(old_type, type)) { | |
| 1636 // Both a data and an accessor property with the same name. | |
| 1637 parser()->ReportMessageAt(scanner()->location(), | |
| 1638 "accessor_data_property"); | |
| 1639 } else { | |
| 1640 ASSERT(IsAccessorAccessorConflict(old_type, type)); | |
| 1641 // Both accessors of the same type. | |
| 1642 parser()->ReportMessageAt(scanner()->location(), | |
| 1643 "accessor_get_set"); | |
| 1644 } | |
| 1645 *ok = false; | |
| 1646 } | |
| 1647 } | |
| 1648 | |
| 1649 } } // v8::internal | 1386 } } // v8::internal |
| OLD | NEW |