Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: src/preparser.cc

Issue 157453003: Unify function parameter checking in PreParser and Parser. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: . Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698