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

Side by Side Diff: src/preparser.cc

Issue 7193045: Make preparser detect duplicate parameters and object literal properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed review comments. Created 9 years, 5 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') | src/preparser-api.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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <math.h>
29
28 #include "../include/v8stdint.h" 30 #include "../include/v8stdint.h"
29 #include "unicode.h" 31 #include "unicode.h"
30 #include "globals.h" 32 #include "globals.h"
31 #include "checks.h" 33 #include "checks.h"
32 #include "allocation.h" 34 #include "allocation.h"
33 #include "utils.h" 35 #include "utils.h"
34 #include "list.h" 36 #include "list.h"
37 #include "conversions.h"
38 #include "hashmap.h"
35 39
36 #include "scanner-base.h" 40 #include "scanner-base.h"
37 #include "preparse-data-format.h" 41 #include "preparse-data-format.h"
38 #include "preparse-data.h" 42 #include "preparse-data.h"
39 #include "preparser.h" 43 #include "preparser.h"
40 44
41 #include "conversions-inl.h" 45 #include "conversions-inl.h"
42 46
43 namespace v8 { 47 namespace v8 {
44 namespace preparser { 48 namespace preparser {
(...skipping 18 matching lines...) Expand all
63 // stack depth even further. Instead we report it after parsing is 67 // stack depth even further. Instead we report it after parsing is
64 // over, in ParseProgram. 68 // over, in ParseProgram.
65 if (token == i::Token::ILLEGAL && stack_overflow_) { 69 if (token == i::Token::ILLEGAL && stack_overflow_) {
66 return; 70 return;
67 } 71 }
68 i::JavaScriptScanner::Location source_location = scanner_->location(); 72 i::JavaScriptScanner::Location source_location = scanner_->location();
69 73
70 // Four of the tokens are treated specially 74 // Four of the tokens are treated specially
71 switch (token) { 75 switch (token) {
72 case i::Token::EOS: 76 case i::Token::EOS:
73 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 77 return ReportMessageAt(source_location, "unexpected_eos", NULL);
74 "unexpected_eos", NULL);
75 case i::Token::NUMBER: 78 case i::Token::NUMBER:
76 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 79 return ReportMessageAt(source_location, "unexpected_token_number", NULL);
77 "unexpected_token_number", NULL);
78 case i::Token::STRING: 80 case i::Token::STRING:
79 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 81 return ReportMessageAt(source_location, "unexpected_token_string", NULL);
80 "unexpected_token_string", NULL);
81 case i::Token::IDENTIFIER: 82 case i::Token::IDENTIFIER:
82 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 83 return ReportMessageAt(source_location,
83 "unexpected_token_identifier", NULL); 84 "unexpected_token_identifier", NULL);
84 case i::Token::FUTURE_RESERVED_WORD: 85 case i::Token::FUTURE_RESERVED_WORD:
85 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 86 return ReportMessageAt(source_location, "unexpected_reserved", NULL);
86 "unexpected_reserved", NULL);
87 case i::Token::FUTURE_STRICT_RESERVED_WORD: 87 case i::Token::FUTURE_STRICT_RESERVED_WORD:
88 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 88 return ReportMessageAt(source_location,
89 "unexpected_strict_reserved", NULL); 89 "unexpected_strict_reserved", NULL);
90 default: 90 default:
91 const char* name = i::Token::String(token); 91 const char* name = i::Token::String(token);
92 ReportMessageAt(source_location.beg_pos, source_location.end_pos, 92 ReportMessageAt(source_location, "unexpected_token", name);
93 "unexpected_token", name);
94 } 93 }
95 } 94 }
96 95
97 96
98 // Checks whether octal literal last seen is between beg_pos and end_pos. 97 // Checks whether octal literal last seen is between beg_pos and end_pos.
99 // If so, reports an error. 98 // If so, reports an error.
100 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { 99 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
101 i::Scanner::Location octal = scanner_->octal_position(); 100 i::Scanner::Location octal = scanner_->octal_position();
102 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) { 101 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
103 ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL); 102 ReportMessageAt(octal, "strict_octal_literal", NULL);
104 scanner_->clear_octal_position(); 103 scanner_->clear_octal_position();
105 *ok = false; 104 *ok = false;
106 } 105 }
107 } 106 }
108 107
109 108
110 #define CHECK_OK ok); \ 109 #define CHECK_OK ok); \
111 if (!*ok) return kUnknownSourceElements; \ 110 if (!*ok) return kUnknownSourceElements; \
112 ((void)0 111 ((void)0
113 #define DUMMY ) // to make indentation work 112 #define DUMMY ) // to make indentation work
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 Expression function_value = ParseFunctionLiteral(CHECK_OK); 235 Expression function_value = ParseFunctionLiteral(CHECK_OK);
237 236
238 if (function_value.IsStrictFunction() && 237 if (function_value.IsStrictFunction() &&
239 !identifier.IsValidStrictVariable()) { 238 !identifier.IsValidStrictVariable()) {
240 // Strict mode violation, using either reserved word or eval/arguments 239 // Strict mode violation, using either reserved word or eval/arguments
241 // as name of strict function. 240 // as name of strict function.
242 const char* type = "strict_function_name"; 241 const char* type = "strict_function_name";
243 if (identifier.IsFutureStrictReserved()) { 242 if (identifier.IsFutureStrictReserved()) {
244 type = "strict_reserved_word"; 243 type = "strict_reserved_word";
245 } 244 }
246 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 245 ReportMessageAt(location, type, NULL);
247 *ok = false; 246 *ok = false;
248 } 247 }
249 return Statement::FunctionDeclaration(); 248 return Statement::FunctionDeclaration();
250 } 249 }
251 250
252 251
253 PreParser::Statement PreParser::ParseBlock(bool* ok) { 252 PreParser::Statement PreParser::ParseBlock(bool* ok) {
254 // Block :: 253 // Block ::
255 // '{' Statement* '}' 254 // '{' Statement* '}'
256 255
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 int* num_decl, 292 int* num_decl,
294 bool* ok) { 293 bool* ok) {
295 // VariableDeclarations :: 294 // VariableDeclarations ::
296 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] 295 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
297 296
298 if (peek() == i::Token::VAR) { 297 if (peek() == i::Token::VAR) {
299 Consume(i::Token::VAR); 298 Consume(i::Token::VAR);
300 } else if (peek() == i::Token::CONST) { 299 } else if (peek() == i::Token::CONST) {
301 if (strict_mode()) { 300 if (strict_mode()) {
302 i::Scanner::Location location = scanner_->peek_location(); 301 i::Scanner::Location location = scanner_->peek_location();
303 ReportMessageAt(location.beg_pos, location.end_pos, 302 ReportMessageAt(location, "strict_const", NULL);
304 "strict_const", NULL);
305 *ok = false; 303 *ok = false;
306 return Statement::Default(); 304 return Statement::Default();
307 } 305 }
308 Consume(i::Token::CONST); 306 Consume(i::Token::CONST);
309 } else { 307 } else {
310 *ok = false; 308 *ok = false;
311 return Statement::Default(); 309 return Statement::Default();
312 } 310 }
313 311
314 // The scope of a variable/const declared anywhere inside a function 312 // The scope of a variable/const declared anywhere inside a function
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 return Statement::Default(); 441 return Statement::Default();
444 } 442 }
445 443
446 444
447 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { 445 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
448 // WithStatement :: 446 // WithStatement ::
449 // 'with' '(' Expression ')' Statement 447 // 'with' '(' Expression ')' Statement
450 Expect(i::Token::WITH, CHECK_OK); 448 Expect(i::Token::WITH, CHECK_OK);
451 if (strict_mode()) { 449 if (strict_mode()) {
452 i::Scanner::Location location = scanner_->location(); 450 i::Scanner::Location location = scanner_->location();
453 ReportMessageAt(location.beg_pos, location.end_pos, 451 ReportMessageAt(location, "strict_mode_with", NULL);
454 "strict_mode_with", NULL);
455 *ok = false; 452 *ok = false;
456 return Statement::Default(); 453 return Statement::Default();
457 } 454 }
458 Expect(i::Token::LPAREN, CHECK_OK); 455 Expect(i::Token::LPAREN, CHECK_OK);
459 ParseExpression(true, CHECK_OK); 456 ParseExpression(true, CHECK_OK);
460 Expect(i::Token::RPAREN, CHECK_OK); 457 Expect(i::Token::RPAREN, CHECK_OK);
461 458
462 scope_->EnterWith(); 459 scope_->EnterWith();
463 ParseStatement(CHECK_OK); 460 ParseStatement(CHECK_OK);
464 scope_->LeaveWith(); 461 scope_->LeaveWith();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 } 576 }
580 577
581 578
582 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { 579 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
583 // ThrowStatement :: 580 // ThrowStatement ::
584 // 'throw' [no line terminator] Expression ';' 581 // 'throw' [no line terminator] Expression ';'
585 582
586 Expect(i::Token::THROW, CHECK_OK); 583 Expect(i::Token::THROW, CHECK_OK);
587 if (scanner_->HasAnyLineTerminatorBeforeNext()) { 584 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
588 i::JavaScriptScanner::Location pos = scanner_->location(); 585 i::JavaScriptScanner::Location pos = scanner_->location();
589 ReportMessageAt(pos.beg_pos, pos.end_pos, 586 ReportMessageAt(pos, "newline_after_throw", NULL);
590 "newline_after_throw", NULL);
591 *ok = false; 587 *ok = false;
592 return Statement::Default(); 588 return Statement::Default();
593 } 589 }
594 ParseExpression(true, CHECK_OK); 590 ParseExpression(true, CHECK_OK);
595 ExpectSemicolon(ok); 591 ExpectSemicolon(ok);
596 return Statement::Default(); 592 return Statement::Default();
597 } 593 }
598 594
599 595
600 PreParser::Statement PreParser::ParseTryStatement(bool* ok) { 596 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 ReportMessageAt(location.beg_pos, location.end_pos, 988 ReportMessageAt(location.beg_pos, location.end_pos,
993 "reserved_word", NULL); 989 "reserved_word", NULL);
994 *ok = false; 990 *ok = false;
995 return Expression::Default(); 991 return Expression::Default();
996 } 992 }
997 993
998 case i::Token::FUTURE_STRICT_RESERVED_WORD: 994 case i::Token::FUTURE_STRICT_RESERVED_WORD:
999 if (strict_mode()) { 995 if (strict_mode()) {
1000 Next(); 996 Next();
1001 i::Scanner::Location location = scanner_->location(); 997 i::Scanner::Location location = scanner_->location();
1002 ReportMessageAt(location.beg_pos, location.end_pos, 998 ReportMessageAt(location, "strict_reserved_word", NULL);
1003 "strict_reserved_word", NULL);
1004 *ok = false; 999 *ok = false;
1005 return Expression::Default(); 1000 return Expression::Default();
1006 } 1001 }
1007 // FALLTHROUGH 1002 // FALLTHROUGH
1008 case i::Token::IDENTIFIER: { 1003 case i::Token::IDENTIFIER: {
1009 Identifier id = ParseIdentifier(CHECK_OK); 1004 Identifier id = ParseIdentifier(CHECK_OK);
1010 result = Expression::FromIdentifier(id); 1005 result = Expression::FromIdentifier(id);
1011 break; 1006 break;
1012 } 1007 }
1013 1008
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 if (peek() != i::Token::RBRACK) { 1069 if (peek() != i::Token::RBRACK) {
1075 Expect(i::Token::COMMA, CHECK_OK); 1070 Expect(i::Token::COMMA, CHECK_OK);
1076 } 1071 }
1077 } 1072 }
1078 Expect(i::Token::RBRACK, CHECK_OK); 1073 Expect(i::Token::RBRACK, CHECK_OK);
1079 1074
1080 scope_->NextMaterializedLiteralIndex(); 1075 scope_->NextMaterializedLiteralIndex();
1081 return Expression::Default(); 1076 return Expression::Default();
1082 } 1077 }
1083 1078
1079 void PreParser::CheckDuplicate(DuplicateFinder* finder,
1080 i::Token::Value property,
1081 int type,
1082 bool* ok) {
1083 int old_type;
1084 if (property == i::Token::NUMBER) {
1085 old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
1086 } else if (scanner_->is_literal_ascii()) {
1087 old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1088 type);
1089 } else {
1090 old_type = finder->AddUC16Symbol(scanner_->literal_uc16_string(), type);
1091 }
1092 if (HasConflict(old_type, type)) {
1093 if (IsDataDataConflict(old_type, type)) {
1094 // Both are data properties.
1095 if (!strict_mode()) return;
1096 ReportMessageAt(scanner_->location(),
1097 "strict_duplicate_property", NULL);
1098 } else if (IsDataAccessorConflict(old_type, type)) {
1099 // Both a data and an accessor property with the same name.
1100 ReportMessageAt(scanner_->location(),
1101 "accessor_data_property", NULL);
1102 } else {
1103 ASSERT(IsAccessorAccessorConflict(old_type, type));
1104 // Both accessors of the same type.
1105 ReportMessageAt(scanner_->location(),
1106 "accessor_get_set", NULL);
1107 }
1108 *ok = false;
1109 }
1110 }
1111
1084 1112
1085 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { 1113 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1086 // ObjectLiteral :: 1114 // ObjectLiteral ::
1087 // '{' ( 1115 // '{' (
1088 // ((IdentifierName | String | Number) ':' AssignmentExpression) 1116 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1089 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) 1117 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1090 // )*[','] '}' 1118 // )*[','] '}'
1091 1119
1092 Expect(i::Token::LBRACE, CHECK_OK); 1120 Expect(i::Token::LBRACE, CHECK_OK);
1121 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1093 while (peek() != i::Token::RBRACE) { 1122 while (peek() != i::Token::RBRACE) {
1094 i::Token::Value next = peek(); 1123 i::Token::Value next = peek();
1095 switch (next) { 1124 switch (next) {
1096 case i::Token::IDENTIFIER: 1125 case i::Token::IDENTIFIER:
1097 case i::Token::FUTURE_RESERVED_WORD: 1126 case i::Token::FUTURE_RESERVED_WORD:
1098 case i::Token::FUTURE_STRICT_RESERVED_WORD: { 1127 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1099 bool is_getter = false; 1128 bool is_getter = false;
1100 bool is_setter = false; 1129 bool is_setter = false;
1101 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); 1130 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1102 if ((is_getter || is_setter) && peek() != i::Token::COLON) { 1131 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1103 i::Token::Value name = Next(); 1132 i::Token::Value name = Next();
1104 bool is_keyword = i::Token::IsKeyword(name); 1133 bool is_keyword = i::Token::IsKeyword(name);
1105 if (name != i::Token::IDENTIFIER && 1134 if (name != i::Token::IDENTIFIER &&
1106 name != i::Token::FUTURE_RESERVED_WORD && 1135 name != i::Token::FUTURE_RESERVED_WORD &&
1107 name != i::Token::FUTURE_STRICT_RESERVED_WORD && 1136 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1108 name != i::Token::NUMBER && 1137 name != i::Token::NUMBER &&
1109 name != i::Token::STRING && 1138 name != i::Token::STRING &&
1110 !is_keyword) { 1139 !is_keyword) {
1111 *ok = false; 1140 *ok = false;
1112 return Expression::Default(); 1141 return Expression::Default();
1113 } 1142 }
1114 if (!is_keyword) { 1143 if (!is_keyword) {
1115 LogSymbol(); 1144 LogSymbol();
1116 } 1145 }
1146 PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
1147 CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
1117 ParseFunctionLiteral(CHECK_OK); 1148 ParseFunctionLiteral(CHECK_OK);
1118 if (peek() != i::Token::RBRACE) { 1149 if (peek() != i::Token::RBRACE) {
1119 Expect(i::Token::COMMA, CHECK_OK); 1150 Expect(i::Token::COMMA, CHECK_OK);
1120 } 1151 }
1121 continue; // restart the while 1152 continue; // restart the while
1122 } 1153 }
1154 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1123 break; 1155 break;
1124 } 1156 }
1125 case i::Token::STRING: 1157 case i::Token::STRING:
1126 Consume(next); 1158 Consume(next);
1159 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1127 GetStringSymbol(); 1160 GetStringSymbol();
1128 break; 1161 break;
1129 case i::Token::NUMBER: 1162 case i::Token::NUMBER:
1130 Consume(next); 1163 Consume(next);
1164 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1131 break; 1165 break;
1132 default: 1166 default:
1133 if (i::Token::IsKeyword(next)) { 1167 if (i::Token::IsKeyword(next)) {
1134 Consume(next); 1168 Consume(next);
1169 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1135 } else { 1170 } else {
1136 // Unexpected token. 1171 // Unexpected token.
1137 *ok = false; 1172 *ok = false;
1138 return Expression::Default(); 1173 return Expression::Default();
1139 } 1174 }
1140 } 1175 }
1141 1176
1142 Expect(i::Token::COLON, CHECK_OK); 1177 Expect(i::Token::COLON, CHECK_OK);
1143 ParseAssignmentExpression(true, CHECK_OK); 1178 ParseAssignmentExpression(true, CHECK_OK);
1144 1179
1145 // TODO(1240767): Consider allowing trailing comma. 1180 // TODO(1240767): Consider allowing trailing comma.
1146 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK); 1181 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1147 } 1182 }
1148 Expect(i::Token::RBRACE, CHECK_OK); 1183 Expect(i::Token::RBRACE, CHECK_OK);
1149 1184
1150 scope_->NextMaterializedLiteralIndex(); 1185 scope_->NextMaterializedLiteralIndex();
1151 return Expression::Default(); 1186 return Expression::Default();
1152 } 1187 }
1153 1188
1154 1189
1155 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, 1190 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1156 bool* ok) { 1191 bool* ok) {
1157 if (!scanner_->ScanRegExpPattern(seen_equal)) { 1192 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1158 Next(); 1193 Next();
1159 i::JavaScriptScanner::Location location = scanner_->location(); 1194 ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
1160 ReportMessageAt(location.beg_pos, location.end_pos,
1161 "unterminated_regexp", NULL);
1162 *ok = false; 1195 *ok = false;
1163 return Expression::Default(); 1196 return Expression::Default();
1164 } 1197 }
1165 1198
1166 scope_->NextMaterializedLiteralIndex(); 1199 scope_->NextMaterializedLiteralIndex();
1167 1200
1168 if (!scanner_->ScanRegExpFlags()) { 1201 if (!scanner_->ScanRegExpFlags()) {
1169 Next(); 1202 Next();
1170 i::JavaScriptScanner::Location location = scanner_->location(); 1203 ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
1171 ReportMessageAt(location.beg_pos, location.end_pos,
1172 "invalid_regexp_flags", NULL);
1173 *ok = false; 1204 *ok = false;
1174 return Expression::Default(); 1205 return Expression::Default();
1175 } 1206 }
1176 Next(); 1207 Next();
1177 return Expression::Default(); 1208 return Expression::Default();
1178 } 1209 }
1179 1210
1180 1211
1181 PreParser::Arguments PreParser::ParseArguments(bool* ok) { 1212 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1182 // Arguments :: 1213 // Arguments ::
(...skipping 24 matching lines...) Expand all
1207 1238
1208 // Parse function body. 1239 // Parse function body.
1209 ScopeType outer_scope_type = scope_->type(); 1240 ScopeType outer_scope_type = scope_->type();
1210 bool inside_with = scope_->IsInsideWith(); 1241 bool inside_with = scope_->IsInsideWith();
1211 Scope function_scope(&scope_, kFunctionScope); 1242 Scope function_scope(&scope_, kFunctionScope);
1212 // FormalParameterList :: 1243 // FormalParameterList ::
1213 // '(' (Identifier)*[','] ')' 1244 // '(' (Identifier)*[','] ')'
1214 Expect(i::Token::LPAREN, CHECK_OK); 1245 Expect(i::Token::LPAREN, CHECK_OK);
1215 int start_position = scanner_->location().beg_pos; 1246 int start_position = scanner_->location().beg_pos;
1216 bool done = (peek() == i::Token::RPAREN); 1247 bool done = (peek() == i::Token::RPAREN);
1248 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1217 while (!done) { 1249 while (!done) {
1218 Identifier id = ParseIdentifier(CHECK_OK); 1250 Identifier id = ParseIdentifier(CHECK_OK);
1219 if (!id.IsValidStrictVariable()) { 1251 if (!id.IsValidStrictVariable()) {
1220 StrictModeIdentifierViolation(scanner_->location(), 1252 StrictModeIdentifierViolation(scanner_->location(),
1221 "strict_param_name", 1253 "strict_param_name",
1222 id, 1254 id,
1223 CHECK_OK); 1255 CHECK_OK);
1224 } 1256 }
1257 int prev_value;
1258 if (scanner_->is_literal_ascii()) {
1259 prev_value =
1260 duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1261 } else {
1262 prev_value =
1263 duplicate_finder.AddUC16Symbol(scanner_->literal_uc16_string(), 1);
1264 }
1265
1266 if (prev_value != 0) {
1267 SetStrictModeViolation(scanner_->location(),
1268 "strict_param_dupe",
1269 CHECK_OK);
1270 }
1225 done = (peek() == i::Token::RPAREN); 1271 done = (peek() == i::Token::RPAREN);
1226 if (!done) { 1272 if (!done) {
1227 Expect(i::Token::COMMA, CHECK_OK); 1273 Expect(i::Token::COMMA, CHECK_OK);
1228 } 1274 }
1229 } 1275 }
1230 Expect(i::Token::RPAREN, CHECK_OK); 1276 Expect(i::Token::RPAREN, CHECK_OK);
1231 1277
1232 Expect(i::Token::LBRACE, CHECK_OK); 1278 Expect(i::Token::LBRACE, CHECK_OK);
1233 int function_block_pos = scanner_->location().beg_pos; 1279 int function_block_pos = scanner_->location().beg_pos;
1234 1280
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1366 *ok = false; 1412 *ok = false;
1367 return Identifier::Default(); 1413 return Identifier::Default();
1368 } 1414 }
1369 } 1415 }
1370 1416
1371 1417
1372 void PreParser::SetStrictModeViolation(i::Scanner::Location location, 1418 void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1373 const char* type, 1419 const char* type,
1374 bool* ok) { 1420 bool* ok) {
1375 if (strict_mode()) { 1421 if (strict_mode()) {
1376 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 1422 ReportMessageAt(location, type, NULL);
1377 *ok = false; 1423 *ok = false;
1378 return; 1424 return;
1379 } 1425 }
1380 // Delay report in case this later turns out to be strict code 1426 // Delay report in case this later turns out to be strict code
1381 // (i.e., for function names and parameters prior to a "use strict" 1427 // (i.e., for function names and parameters prior to a "use strict"
1382 // directive). 1428 // directive).
1429 // It's safe to overwrite an existing violation.
1430 // It's either from a function that turned out to be non-strict,
1431 // or it's in the current function (and we just need to report
1432 // one error), or it's in a unclosed nesting function that wasn't
1433 // strict (otherwise we would already be in strict mode).
1383 strict_mode_violation_location_ = location; 1434 strict_mode_violation_location_ = location;
1384 strict_mode_violation_type_ = type; 1435 strict_mode_violation_type_ = type;
1385 } 1436 }
1386 1437
1387 1438
1388 void PreParser::CheckDelayedStrictModeViolation(int beg_pos, 1439 void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1389 int end_pos, 1440 int end_pos,
1390 bool* ok) { 1441 bool* ok) {
1391 i::Scanner::Location location = strict_mode_violation_location_; 1442 i::Scanner::Location location = strict_mode_violation_location_;
1392 if (location.IsValid() && 1443 if (location.IsValid() &&
1393 location.beg_pos > beg_pos && location.end_pos < end_pos) { 1444 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1394 ReportMessageAt(location.beg_pos, location.end_pos, 1445 ReportMessageAt(location, strict_mode_violation_type_, NULL);
1395 strict_mode_violation_type_, NULL);
1396 *ok = false; 1446 *ok = false;
1397 } 1447 }
1398 strict_mode_violation_location_ = i::Scanner::Location::invalid();
1399 } 1448 }
1400 1449
1401 1450
1402 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location, 1451 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1403 const char* eval_args_type, 1452 const char* eval_args_type,
1404 Identifier identifier, 1453 Identifier identifier,
1405 bool* ok) { 1454 bool* ok) {
1406 const char* type = eval_args_type; 1455 const char* type = eval_args_type;
1407 if (identifier.IsFutureReserved()) { 1456 if (identifier.IsFutureReserved()) {
1408 type = "reserved_word"; 1457 type = "reserved_word";
1409 } else if (identifier.IsFutureStrictReserved()) { 1458 } else if (identifier.IsFutureStrictReserved()) {
1410 type = "strict_reserved_word"; 1459 type = "strict_reserved_word";
1411 } 1460 }
1412 if (strict_mode()) { 1461 if (strict_mode()) {
1413 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 1462 ReportMessageAt(location, type, NULL);
1414 *ok = false; 1463 *ok = false;
1415 return; 1464 return;
1416 } 1465 }
1417 strict_mode_violation_location_ = location; 1466 strict_mode_violation_location_ = location;
1418 strict_mode_violation_type_ = type; 1467 strict_mode_violation_type_ = type;
1419 } 1468 }
1420 1469
1421 1470
1422 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { 1471 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1423 i::Token::Value next = Next(); 1472 i::Token::Value next = Next();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 } 1504 }
1456 return result; 1505 return result;
1457 } 1506 }
1458 1507
1459 bool PreParser::peek_any_identifier() { 1508 bool PreParser::peek_any_identifier() {
1460 i::Token::Value next = peek(); 1509 i::Token::Value next = peek();
1461 return next == i::Token::IDENTIFIER || 1510 return next == i::Token::IDENTIFIER ||
1462 next == i::Token::FUTURE_RESERVED_WORD || 1511 next == i::Token::FUTURE_RESERVED_WORD ||
1463 next == i::Token::FUTURE_STRICT_RESERVED_WORD; 1512 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
1464 } 1513 }
1514
1515
1516 int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1517 return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1518 }
1519
1520 int DuplicateFinder::AddUC16Symbol(i::Vector<const uint16_t> key, int value) {
1521 return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1522 }
1523
1524 int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1525 bool is_ascii,
1526 int value) {
1527 uint32_t hash = Hash(key, is_ascii);
1528 byte* encoding = BackupKey(key, is_ascii);
1529 i::HashMap::Entry* entry = map_->Lookup(encoding, hash, true);
1530 int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1531 entry->value =
1532 reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1533 return old_value;
1534 }
1535
1536
1537 int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
1538 ASSERT(key.length() > 0);
1539 // Quick check for already being in canonical form.
1540 if (IsNumberCanonical(key)) {
1541 return AddAsciiSymbol(key, value);
1542 }
1543
1544 int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
1545 double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1546 int length;
1547 const char* string;
1548 if (!isfinite(double_value)) {
1549 string = "Infinity";
1550 length = 8; // strlen("Infinity");
1551 } else {
1552 string = DoubleToCString(double_value,
1553 i::Vector<char>(number_buffer_, kBufferSize));
1554 length = i::StrLength(string);
1555 }
1556 return AddAsciiSymbol(i::Vector<const char>(string, length), value);
1557 }
1558
1559
1560 bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1561 // Test for a safe approximation of number literals that are already
1562 // in canonical form: max 15 digits, no leading zeroes, except an
1563 // integer part that is a single zero, and no trailing zeros below
1564 // the decimal point.
1565 int pos = 0;
1566 int length = number.length();
1567 if (number.length() > 15) return false;
1568 if (number[pos] == '0') {
1569 pos++;
1570 } else {
1571 while (pos < length &&
1572 static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1573 }
1574 if (length == pos) return true;
1575 if (number[pos] != '.') return false;
1576 pos++;
1577 bool invalid_last_digit = true;
1578 while (pos < length) {
1579 byte digit = number[pos] - '0';
1580 if (digit > '9' - '0') return false;
1581 invalid_last_digit = (digit == 0);
1582 pos++;
1583 }
1584 return !invalid_last_digit;
1585 }
1586
1587
1588 uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1589 // Primitive hash function, almost identical to the one used
1590 // for strings (except that it's seeded by the length and ASCII-ness).
1591 int length = key.length();
1592 uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1593 for (int i = 0; i < length; i++) {
1594 uint32_t c = key[i];
1595 hash = (hash + c) * 1025;
1596 hash ^= (hash >> 6);
1597 }
1598 return hash;
1599 }
1600
1601
1602 bool DuplicateFinder::Match(void* first, void* second) {
1603 // Decode lengths.
1604 // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1605 // with a 8th bit being non-zero while there are more heptets.
1606 // The value encodes the number of bytes following, and whether the original
1607 // was ASCII.
1608 byte* s1 = reinterpret_cast<byte*>(first);
1609 byte* s2 = reinterpret_cast<byte*>(second);
1610 uint32_t length_ascii_field = 0;
1611 byte c1;
1612 do {
1613 c1 = *s1;
1614 if (c1 != *s2) return false;
1615 length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1616 s1++;
1617 s2++;
1618 } while ((c1 & 0x80) != 0);
1619 int length = static_cast<int>(length_ascii_field >> 1);
1620 return memcmp(s1, s2, length) == 0;
1621 }
1622
1623
1624 byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1625 bool is_ascii) {
1626 uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1627 backing_store_.StartSequence();
1628 // Emit ascii_length as base-128 encoded number, with the 7th bit set
1629 // on the byte of every heptet except the last, least significant, one.
1630 if (ascii_length >= (1 << 7)) {
1631 if (ascii_length >= (1 << 14)) {
1632 if (ascii_length >= (1 << 21)) {
1633 if (ascii_length >= (1 << 28)) {
1634 backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1635 }
1636 backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1637 }
1638 backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1639 }
1640 backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1641 }
1642 backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1643
1644 backing_store_.AddBlock(bytes);
1645 return backing_store_.EndSequence().start();
1646 }
1465 } } // v8::preparser 1647 } } // v8::preparser
OLDNEW
« no previous file with comments | « src/preparser.h ('k') | src/preparser-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698