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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 (!scope_->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 |
(...skipping 1197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 if (!done) { | 1285 if (!done) { |
1289 Expect(Token::COMMA, ok); | 1286 Expect(Token::COMMA, ok); |
1290 if (!*ok) return -1; | 1287 if (!*ok) return -1; |
1291 } | 1288 } |
1292 } | 1289 } |
1293 Expect(Token::RPAREN, ok); | 1290 Expect(Token::RPAREN, ok); |
1294 return argc; | 1291 return argc; |
1295 } | 1292 } |
1296 | 1293 |
1297 PreParser::Expression PreParser::ParseFunctionLiteral( | 1294 PreParser::Expression PreParser::ParseFunctionLiteral( |
1298 Identifier name, | 1295 Identifier function_name, |
1299 Scanner::Location function_name_location, | 1296 Scanner::Location function_name_location, |
1300 bool name_is_strict_reserved, | 1297 bool name_is_strict_reserved, |
1301 bool is_generator, | 1298 bool is_generator, |
1302 bool* ok) { | 1299 bool* ok) { |
1303 // Function :: | 1300 // Function :: |
1304 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 1301 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
1305 | 1302 |
1306 // Parse function body. | 1303 // Parse function body. |
1307 ScopeType outer_scope_type = scope_->type(); | 1304 ScopeType outer_scope_type = scope_->type(); |
1308 bool inside_with = scope_->IsInsideWith(); | 1305 bool inside_with = scope_->IsInsideWith(); |
1309 Scope function_scope(&scope_, kFunctionScope); | 1306 Scope function_scope(&scope_, kFunctionScope); |
1310 function_scope.set_is_generator(is_generator); | 1307 function_scope.set_is_generator(is_generator); |
1311 // FormalParameterList :: | 1308 // FormalParameterList :: |
1312 // '(' (Identifier)*[','] ')' | 1309 // '(' (Identifier)*[','] ')' |
1313 Expect(Token::LPAREN, CHECK_OK); | 1310 Expect(Token::LPAREN, CHECK_OK); |
1314 int start_position = position(); | 1311 int start_position = position(); |
1315 bool done = (peek() == Token::RPAREN); | 1312 bool done = (peek() == Token::RPAREN); |
1316 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 1313 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
| 1314 // We don't yet know if the function will be strict, so we cannot yet produce |
| 1315 // errors for parameter names or duplicates. However, we remember the |
| 1316 // locations of these errors if they occur and produce the errors later. |
| 1317 Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); |
| 1318 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
| 1319 Scanner::Location reserved_error_loc = Scanner::Location::invalid(); |
1317 while (!done) { | 1320 while (!done) { |
1318 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | 1321 bool is_strict_reserved = false; |
| 1322 Identifier param_name = |
| 1323 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 1324 if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) { |
| 1325 eval_args_error_loc = scanner()->location(); |
| 1326 } |
| 1327 if (!reserved_error_loc.IsValid() && is_strict_reserved) { |
| 1328 reserved_error_loc = scanner()->location(); |
| 1329 } |
| 1330 |
1319 int prev_value; | 1331 int prev_value; |
1320 if (scanner()->is_literal_ascii()) { | 1332 if (scanner()->is_literal_ascii()) { |
1321 prev_value = | 1333 prev_value = |
1322 duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1); | 1334 duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1); |
1323 } else { | 1335 } else { |
1324 prev_value = | 1336 prev_value = |
1325 duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1); | 1337 duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1); |
1326 } | 1338 } |
1327 | 1339 |
1328 if (prev_value != 0) { | 1340 if (!dupe_error_loc.IsValid() && prev_value != 0) { |
1329 SetStrictModeViolation(scanner()->location(), | 1341 dupe_error_loc = scanner()->location(); |
1330 "strict_param_dupe", | |
1331 CHECK_OK); | |
1332 } | 1342 } |
| 1343 |
1333 done = (peek() == Token::RPAREN); | 1344 done = (peek() == Token::RPAREN); |
1334 if (!done) { | 1345 if (!done) { |
1335 Expect(Token::COMMA, CHECK_OK); | 1346 Expect(Token::COMMA, CHECK_OK); |
1336 } | 1347 } |
1337 } | 1348 } |
1338 Expect(Token::RPAREN, CHECK_OK); | 1349 Expect(Token::RPAREN, CHECK_OK); |
1339 | 1350 |
1340 // Determine if the function will be lazily compiled. | 1351 // Determine if the function will be lazily compiled. |
1341 // Currently only happens to top-level functions. | 1352 // Currently only happens to top-level functions. |
1342 // Optimistically assume that all top-level functions are lazily compiled. | 1353 // Optimistically assume that all top-level functions are lazily compiled. |
1343 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && | 1354 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && |
1344 !inside_with && allow_lazy() && | 1355 !inside_with && allow_lazy() && |
1345 !parenthesized_function_); | 1356 !parenthesized_function_); |
1346 parenthesized_function_ = false; | 1357 parenthesized_function_ = false; |
1347 | 1358 |
1348 Expect(Token::LBRACE, CHECK_OK); | 1359 Expect(Token::LBRACE, CHECK_OK); |
1349 if (is_lazily_compiled) { | 1360 if (is_lazily_compiled) { |
1350 ParseLazyFunctionLiteralBody(CHECK_OK); | 1361 ParseLazyFunctionLiteralBody(CHECK_OK); |
1351 } else { | 1362 } else { |
1352 ParseSourceElements(Token::RBRACE, ok); | 1363 ParseSourceElements(Token::RBRACE, ok); |
1353 } | 1364 } |
1354 Expect(Token::RBRACE, CHECK_OK); | 1365 Expect(Token::RBRACE, CHECK_OK); |
1355 | 1366 |
1356 // Validate strict mode. | 1367 // Validate strict mode. We can do this only after parsing the function, |
| 1368 // since the function can declare itself strict. |
1357 if (!scope_->is_classic_mode()) { | 1369 if (!scope_->is_classic_mode()) { |
1358 if (name.IsEvalOrArguments()) { | 1370 if (function_name.IsEvalOrArguments()) { |
1359 ReportMessageAt(function_name_location, "strict_eval_arguments", NULL); | 1371 ReportMessageAt(function_name_location, "strict_eval_arguments", NULL); |
1360 *ok = false; | 1372 *ok = false; |
1361 return Expression::Default(); | 1373 return Expression::Default(); |
1362 } | 1374 } |
1363 if (name_is_strict_reserved) { | 1375 if (name_is_strict_reserved) { |
1364 ReportMessageAt( | 1376 ReportMessageAt( |
1365 function_name_location, "unexpected_strict_reserved", NULL); | 1377 function_name_location, "unexpected_strict_reserved", NULL); |
1366 *ok = false; | 1378 *ok = false; |
1367 return Expression::Default(); | 1379 return Expression::Default(); |
1368 } | 1380 } |
| 1381 if (eval_args_error_loc.IsValid()) { |
| 1382 ReportMessageAt(eval_args_error_loc, "strict_eval_arguments", |
| 1383 Vector<const char*>::empty()); |
| 1384 *ok = false; |
| 1385 return Expression::Default(); |
| 1386 } |
| 1387 if (dupe_error_loc.IsValid()) { |
| 1388 ReportMessageAt(dupe_error_loc, "strict_param_dupe", |
| 1389 Vector<const char*>::empty()); |
| 1390 *ok = false; |
| 1391 return Expression::Default(); |
| 1392 } |
| 1393 if (reserved_error_loc.IsValid()) { |
| 1394 ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved", |
| 1395 Vector<const char*>::empty()); |
| 1396 *ok = false; |
| 1397 return Expression::Default(); |
| 1398 } |
1369 | 1399 |
1370 int end_position = scanner()->location().end_pos; | 1400 int end_position = scanner()->location().end_pos; |
1371 CheckOctalLiteral(start_position, end_position, CHECK_OK); | 1401 CheckOctalLiteral(start_position, end_position, CHECK_OK); |
1372 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); | |
1373 return Expression::StrictFunction(); | 1402 return Expression::StrictFunction(); |
1374 } | 1403 } |
1375 | 1404 |
1376 return Expression::Default(); | 1405 return Expression::Default(); |
1377 } | 1406 } |
1378 | 1407 |
1379 | 1408 |
1380 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { | 1409 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { |
1381 int body_start = position(); | 1410 int body_start = position(); |
1382 log_->PauseRecording(); | 1411 log_->PauseRecording(); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1468 // "arguments" as identifier even in strict mode (this is needed in cases like | 1497 // "arguments" as identifier even in strict mode (this is needed in cases like |
1469 // "var foo = eval;"). | 1498 // "var foo = eval;"). |
1470 PreParser::Identifier PreParser::ParseIdentifier( | 1499 PreParser::Identifier PreParser::ParseIdentifier( |
1471 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, | 1500 AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
1472 bool* ok) { | 1501 bool* ok) { |
1473 Token::Value next = Next(); | 1502 Token::Value next = Next(); |
1474 if (next == Token::IDENTIFIER) { | 1503 if (next == Token::IDENTIFIER) { |
1475 PreParser::Identifier name = GetIdentifierSymbol(); | 1504 PreParser::Identifier name = GetIdentifierSymbol(); |
1476 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && | 1505 if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
1477 !scope_->is_classic_mode() && name.IsEvalOrArguments()) { | 1506 !scope_->is_classic_mode() && name.IsEvalOrArguments()) { |
1478 StrictModeIdentifierViolation(scanner()->location(), name, ok); | 1507 ReportMessageAt(scanner()->location(), "strict_eval_arguments", NULL); |
| 1508 *ok = false; |
1479 } | 1509 } |
1480 return name; | 1510 return name; |
1481 } else if (scope_->is_classic_mode() && | 1511 } else if (scope_->is_classic_mode() && |
1482 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 1512 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
1483 (next == Token::YIELD && !scope_->is_generator()))) { | 1513 (next == Token::YIELD && !scope_->is_generator()))) { |
1484 return GetIdentifierSymbol(); | 1514 return GetIdentifierSymbol(); |
1485 } else { | 1515 } else { |
1486 ReportUnexpectedToken(next); | 1516 ReportUnexpectedToken(next); |
1487 *ok = false; | 1517 *ok = false; |
1488 return Identifier::Default(); | 1518 return Identifier::Default(); |
1489 } | 1519 } |
1490 } | 1520 } |
1491 | 1521 |
1492 | 1522 |
1493 void PreParser::SetStrictModeViolation(Scanner::Location location, | |
1494 const char* type, | |
1495 bool* ok) { | |
1496 if (!scope_->is_classic_mode()) { | |
1497 ReportMessageAt(location, type, NULL); | |
1498 *ok = false; | |
1499 return; | |
1500 } | |
1501 // Delay report in case this later turns out to be strict code | |
1502 // (i.e., for function names and parameters prior to a "use strict" | |
1503 // directive). | |
1504 // It's safe to overwrite an existing violation. | |
1505 // It's either from a function that turned out to be non-strict, | |
1506 // or it's in the current function (and we just need to report | |
1507 // one error), or it's in a unclosed nesting function that wasn't | |
1508 // strict (otherwise we would already be in strict mode). | |
1509 strict_mode_violation_location_ = location; | |
1510 strict_mode_violation_type_ = type; | |
1511 } | |
1512 | |
1513 | |
1514 void PreParser::CheckDelayedStrictModeViolation(int beg_pos, | |
1515 int end_pos, | |
1516 bool* ok) { | |
1517 Scanner::Location location = strict_mode_violation_location_; | |
1518 if (location.IsValid() && | |
1519 location.beg_pos > beg_pos && location.end_pos < end_pos) { | |
1520 ReportMessageAt(location, strict_mode_violation_type_, NULL); | |
1521 *ok = false; | |
1522 } | |
1523 } | |
1524 | |
1525 | |
1526 void PreParser::StrictModeIdentifierViolation(Scanner::Location location, | |
1527 Identifier identifier, | |
1528 bool* ok) { | |
1529 const char* type = "strict_eval_arguments"; | |
1530 if (identifier.IsFutureReserved()) { | |
1531 type = "unexpected_reserved"; | |
1532 } else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) { | |
1533 type = "unexpected_strict_reserved"; | |
1534 } | |
1535 if (!scope_->is_classic_mode()) { | |
1536 ReportMessageAt(location, type, NULL); | |
1537 *ok = false; | |
1538 return; | |
1539 } | |
1540 strict_mode_violation_location_ = location; | |
1541 strict_mode_violation_type_ = type; | |
1542 } | |
1543 | |
1544 | |
1545 // Parses and identifier or a strict mode future reserved word, and indicate | 1523 // Parses and identifier or a strict mode future reserved word, and indicate |
1546 // whether it is strict mode future reserved. | 1524 // whether it is strict mode future reserved. |
1547 PreParser::Identifier PreParser::ParseIdentifierOrStrictReservedWord( | 1525 PreParser::Identifier PreParser::ParseIdentifierOrStrictReservedWord( |
1548 bool* is_strict_reserved, bool* ok) { | 1526 bool* is_strict_reserved, bool* ok) { |
1549 Token::Value next = Next(); | 1527 Token::Value next = Next(); |
1550 if (next == Token::IDENTIFIER) { | 1528 if (next == Token::IDENTIFIER) { |
1551 *is_strict_reserved = false; | 1529 *is_strict_reserved = false; |
1552 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || | 1530 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || |
1553 (next == Token::YIELD && !scope_->is_generator())) { | 1531 (next == Token::YIELD && !scope_->is_generator())) { |
1554 *is_strict_reserved = true; | 1532 *is_strict_reserved = true; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1620 ASSERT(IsAccessorAccessorConflict(old_type, type)); | 1598 ASSERT(IsAccessorAccessorConflict(old_type, type)); |
1621 // Both accessors of the same type. | 1599 // Both accessors of the same type. |
1622 parser()->ReportMessageAt(scanner()->location(), | 1600 parser()->ReportMessageAt(scanner()->location(), |
1623 "accessor_get_set"); | 1601 "accessor_get_set"); |
1624 } | 1602 } |
1625 *ok = false; | 1603 *ok = false; |
1626 } | 1604 } |
1627 } | 1605 } |
1628 | 1606 |
1629 } } // v8::internal | 1607 } } // v8::internal |
OLD | NEW |