OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1078 } | 1078 } |
1079 | 1079 |
1080 | 1080 |
1081 enum ParserFlag { | 1081 enum ParserFlag { |
1082 kAllowLazy, | 1082 kAllowLazy, |
1083 kAllowNativesSyntax, | 1083 kAllowNativesSyntax, |
1084 kAllowHarmonyScoping, | 1084 kAllowHarmonyScoping, |
1085 kAllowModules, | 1085 kAllowModules, |
1086 kAllowGenerators, | 1086 kAllowGenerators, |
1087 kAllowForOf, | 1087 kAllowForOf, |
1088 kAllowHarmonyNumericLiterals, | 1088 kAllowHarmonyNumericLiterals |
1089 kParserFlagCount | |
1090 }; | 1089 }; |
1091 | 1090 |
1092 | 1091 |
1093 static bool checkParserFlag(unsigned flags, ParserFlag flag) { | 1092 template <class T> |
1094 return flags & (1 << flag); | 1093 void SetParserFlags(T* parser, i::EnumSet<ParserFlag> flags) { |
Michael Starzinger
2013/10/24 17:00:34
Just use ParserBase instead of a template paramete
| |
1094 parser->set_allow_lazy(flags.Contains(kAllowLazy)); | |
1095 parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax)); | |
1096 parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping)); | |
1097 parser->set_allow_modules(flags.Contains(kAllowModules)); | |
1098 parser->set_allow_generators(flags.Contains(kAllowGenerators)); | |
1099 parser->set_allow_for_of(flags.Contains(kAllowForOf)); | |
1100 parser->set_allow_harmony_numeric_literals( | |
1101 flags.Contains(kAllowHarmonyNumericLiterals)); | |
1095 } | 1102 } |
1096 | 1103 |
1097 | 1104 |
1098 #define SET_PARSER_FLAGS(parser, flags) \ | 1105 void TestParserSyncWithFlags(i::Handle<i::String> source, |
1099 parser.set_allow_lazy(checkParserFlag(flags, kAllowLazy)); \ | 1106 i::EnumSet<ParserFlag> flags) { |
1100 parser.set_allow_natives_syntax(checkParserFlag(flags, \ | |
1101 kAllowNativesSyntax)); \ | |
1102 parser.set_allow_harmony_scoping(checkParserFlag(flags, \ | |
1103 kAllowHarmonyScoping)); \ | |
1104 parser.set_allow_modules(checkParserFlag(flags, kAllowModules)); \ | |
1105 parser.set_allow_generators(checkParserFlag(flags, kAllowGenerators)); \ | |
1106 parser.set_allow_for_of(checkParserFlag(flags, kAllowForOf)); \ | |
1107 parser.set_allow_harmony_numeric_literals( \ | |
1108 checkParserFlag(flags, kAllowHarmonyNumericLiterals)); | |
1109 | |
1110 void TestParserSyncWithFlags(i::Handle<i::String> source, unsigned flags) { | |
1111 i::Isolate* isolate = CcTest::i_isolate(); | 1107 i::Isolate* isolate = CcTest::i_isolate(); |
1112 i::Factory* factory = isolate->factory(); | 1108 i::Factory* factory = isolate->factory(); |
1113 | 1109 |
1114 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); | 1110 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); |
1115 | 1111 |
1116 // Preparse the data. | 1112 // Preparse the data. |
1117 i::CompleteParserRecorder log; | 1113 i::CompleteParserRecorder log; |
1118 { | 1114 { |
1119 i::Scanner scanner(isolate->unicode_cache()); | 1115 i::Scanner scanner(isolate->unicode_cache()); |
1120 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); | 1116 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); |
1121 i::PreParser preparser(&scanner, &log, stack_limit); | 1117 i::PreParser preparser(&scanner, &log, stack_limit); |
1122 SET_PARSER_FLAGS(preparser, flags); | 1118 SetParserFlags(&preparser, flags); |
1123 scanner.Initialize(&stream); | 1119 scanner.Initialize(&stream); |
1124 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | 1120 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
1125 CHECK_EQ(i::PreParser::kPreParseSuccess, result); | 1121 CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
1126 } | 1122 } |
1127 i::ScriptDataImpl data(log.ExtractData()); | 1123 i::ScriptDataImpl data(log.ExtractData()); |
1128 | 1124 |
1129 // Parse the data | 1125 // Parse the data |
1130 i::FunctionLiteral* function; | 1126 i::FunctionLiteral* function; |
1131 { | 1127 { |
1132 i::Handle<i::Script> script = factory->NewScript(source); | 1128 i::Handle<i::Script> script = factory->NewScript(source); |
1133 i::CompilationInfoWithZone info(script); | 1129 i::CompilationInfoWithZone info(script); |
1134 i::Parser parser(&info); | 1130 i::Parser parser(&info); |
1135 SET_PARSER_FLAGS(parser, flags); | 1131 SetParserFlags(&parser, flags); |
1136 info.MarkAsGlobal(); | 1132 info.MarkAsGlobal(); |
1137 parser.Parse(); | 1133 parser.Parse(); |
1138 function = info.function(); | 1134 function = info.function(); |
1139 } | 1135 } |
1140 | 1136 |
1141 // Check that preparsing fails iff parsing fails. | 1137 // Check that preparsing fails iff parsing fails. |
1142 if (function == NULL) { | 1138 if (function == NULL) { |
1143 // Extract exception from the parser. | 1139 // Extract exception from the parser. |
1144 CHECK(isolate->has_pending_exception()); | 1140 CHECK(isolate->has_pending_exception()); |
1145 i::MaybeObject* maybe_object = isolate->pending_exception(); | 1141 i::MaybeObject* maybe_object = isolate->pending_exception(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1179 "\t%s\n" | 1175 "\t%s\n" |
1180 "with error:\n" | 1176 "with error:\n" |
1181 "\t%s\n" | 1177 "\t%s\n" |
1182 "However, the parser succeeded", | 1178 "However, the parser succeeded", |
1183 *source->ToCString(), *FormatMessage(&data)->ToCString()); | 1179 *source->ToCString(), *FormatMessage(&data)->ToCString()); |
1184 CHECK(false); | 1180 CHECK(false); |
1185 } | 1181 } |
1186 } | 1182 } |
1187 | 1183 |
1188 | 1184 |
1189 void TestParserSync(i::Handle<i::String> source) { | 1185 void TestParserSync(const char* source, |
1190 for (unsigned flags = 0; flags < (1 << kParserFlagCount); ++flags) { | 1186 const ParserFlag* flag_list, |
1191 TestParserSyncWithFlags(source, flags); | 1187 size_t flag_list_length) { |
1188 i::Handle<i::String> str = | |
1189 CcTest::i_isolate()->factory()->NewStringFromAscii(i::CStrVector(source)); | |
1190 for (int bits = 0; bits < (1 << flag_list_length); bits++) { | |
1191 i::EnumSet<ParserFlag> flags; | |
1192 for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) { | |
1193 if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]); | |
1194 } | |
1195 TestParserSyncWithFlags(str, flags); | |
1192 } | 1196 } |
1193 } | 1197 } |
1194 | 1198 |
1195 | 1199 |
1196 TEST(ParserSync) { | 1200 TEST(ParserSync) { |
1197 const char* context_data[][2] = { | 1201 const char* context_data[][2] = { |
1198 { "", "" }, | 1202 { "", "" }, |
1199 { "{", "}" }, | 1203 { "{", "}" }, |
1200 { "if (true) ", " else {}" }, | 1204 { "if (true) ", " else {}" }, |
1201 { "if (true) {} else ", "" }, | 1205 { "if (true) {} else ", "" }, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1255 | 1259 |
1256 const char* termination_data[] = { | 1260 const char* termination_data[] = { |
1257 "", | 1261 "", |
1258 ";", | 1262 ";", |
1259 "\n", | 1263 "\n", |
1260 ";\n", | 1264 ";\n", |
1261 "\n;", | 1265 "\n;", |
1262 NULL | 1266 NULL |
1263 }; | 1267 }; |
1264 | 1268 |
1265 i::Isolate* isolate = CcTest::i_isolate(); | |
1266 i::Factory* factory = isolate->factory(); | |
1267 | |
1268 v8::HandleScope handles(CcTest::isolate()); | 1269 v8::HandleScope handles(CcTest::isolate()); |
1269 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate()); | 1270 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate()); |
1270 v8::Context::Scope context_scope(context); | 1271 v8::Context::Scope context_scope(context); |
1271 | 1272 |
1272 int marker; | 1273 int marker; |
1273 isolate->stack_guard()->SetStackLimit( | 1274 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
1274 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 1275 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
1275 | 1276 |
1277 static const ParserFlag flags1[] = { | |
1278 kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators, | |
1279 kAllowForOf | |
1280 }; | |
1276 for (int i = 0; context_data[i][0] != NULL; ++i) { | 1281 for (int i = 0; context_data[i][0] != NULL; ++i) { |
1277 for (int j = 0; statement_data[j] != NULL; ++j) { | 1282 for (int j = 0; statement_data[j] != NULL; ++j) { |
1278 for (int k = 0; termination_data[k] != NULL; ++k) { | 1283 for (int k = 0; termination_data[k] != NULL; ++k) { |
1279 int kPrefixLen = i::StrLength(context_data[i][0]); | 1284 int kPrefixLen = i::StrLength(context_data[i][0]); |
1280 int kStatementLen = i::StrLength(statement_data[j]); | 1285 int kStatementLen = i::StrLength(statement_data[j]); |
1281 int kTerminationLen = i::StrLength(termination_data[k]); | 1286 int kTerminationLen = i::StrLength(termination_data[k]); |
1282 int kSuffixLen = i::StrLength(context_data[i][1]); | 1287 int kSuffixLen = i::StrLength(context_data[i][1]); |
1283 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen | 1288 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen |
1284 + kSuffixLen + i::StrLength("label: for (;;) { }"); | 1289 + kSuffixLen + i::StrLength("label: for (;;) { }"); |
1285 | 1290 |
1286 // Plug the source code pieces together. | 1291 // Plug the source code pieces together. |
1287 i::ScopedVector<char> program(kProgramSize + 1); | 1292 i::ScopedVector<char> program(kProgramSize + 1); |
1288 int length = i::OS::SNPrintF(program, | 1293 int length = i::OS::SNPrintF(program, |
1289 "label: for (;;) { %s%s%s%s }", | 1294 "label: for (;;) { %s%s%s%s }", |
1290 context_data[i][0], | 1295 context_data[i][0], |
1291 statement_data[j], | 1296 statement_data[j], |
1292 termination_data[k], | 1297 termination_data[k], |
1293 context_data[i][1]); | 1298 context_data[i][1]); |
1294 CHECK(length == kProgramSize); | 1299 CHECK(length == kProgramSize); |
1295 i::Handle<i::String> source = | 1300 TestParserSync(program.start(), flags1, ARRAY_SIZE(flags1)); |
1296 factory->NewStringFromAscii(i::CStrVector(program.start())); | |
1297 TestParserSync(source); | |
1298 } | 1301 } |
1299 } | 1302 } |
1300 } | 1303 } |
1304 | |
1305 // Neither Harmony numeric literals nor our natives syntax have any | |
1306 // interaction with the flags above, so test these separately to reduce | |
1307 // the combinatorial explosion. | |
1308 static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals }; | |
1309 TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2)); | |
1310 TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2)); | |
1311 | |
1312 static const ParserFlag flags3[] = { kAllowNativesSyntax }; | |
1313 TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3)); | |
1301 } | 1314 } |
1302 | 1315 |
1303 | 1316 |
1304 TEST(PreparserStrictOctal) { | 1317 TEST(PreparserStrictOctal) { |
1305 // Test that syntax error caused by octal literal is reported correctly as | 1318 // Test that syntax error caused by octal literal is reported correctly as |
1306 // such (issue 2220). | 1319 // such (issue 2220). |
1307 v8::internal::FLAG_min_preparse_length = 1; // Force preparsing. | 1320 v8::internal::FLAG_min_preparse_length = 1; // Force preparsing. |
1308 v8::V8::Initialize(); | 1321 v8::V8::Initialize(); |
1309 v8::HandleScope scope(CcTest::isolate()); | 1322 v8::HandleScope scope(CcTest::isolate()); |
1310 v8::Context::Scope context_scope( | 1323 v8::Context::Scope context_scope( |
1311 v8::Context::New(CcTest::isolate())); | 1324 v8::Context::New(CcTest::isolate())); |
1312 v8::TryCatch try_catch; | 1325 v8::TryCatch try_catch; |
1313 const char* script = | 1326 const char* script = |
1314 "\"use strict\"; \n" | 1327 "\"use strict\"; \n" |
1315 "a = function() { \n" | 1328 "a = function() { \n" |
1316 " b = function() { \n" | 1329 " b = function() { \n" |
1317 " 01; \n" | 1330 " 01; \n" |
1318 " }; \n" | 1331 " }; \n" |
1319 "}; \n"; | 1332 "}; \n"; |
1320 v8::Script::Compile(v8::String::New(script)); | 1333 v8::Script::Compile(v8::String::New(script)); |
1321 CHECK(try_catch.HasCaught()); | 1334 CHECK(try_catch.HasCaught()); |
1322 v8::String::Utf8Value exception(try_catch.Exception()); | 1335 v8::String::Utf8Value exception(try_catch.Exception()); |
1323 CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.", | 1336 CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.", |
1324 *exception); | 1337 *exception); |
1325 } | 1338 } |
OLD | NEW |