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 |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |