Index: test/cctest/test-parsing.cc |
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc |
index bd1e24e11529f977b65cfe069eafa5ad34b62d33..414bc29466452842030a97e9bc231faa4899267d 100755 |
--- a/test/cctest/test-parsing.cc |
+++ b/test/cctest/test-parsing.cc |
@@ -884,3 +884,201 @@ TEST(ScopePositions) { |
CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen); |
} |
} |
+ |
+ |
+void TestParserSync(i::Handle<i::String> source, int flags) { |
+ uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); |
+ bool harmony_scoping = ((i::kLanguageModeMask & flags) == i::EXTENDED_MODE); |
+ |
+ // Preparse the data. |
+ i::CompleteParserRecorder log; |
+ i::Scanner scanner(i::Isolate::Current()->unicode_cache()); |
+ i::GenericStringUC16CharacterStream stream(source, 0, source->length()); |
+ scanner.SetHarmonyScoping(harmony_scoping); |
+ scanner.Initialize(&stream); |
+ v8::preparser::PreParser::PreParseResult result = |
+ v8::preparser::PreParser::PreParseProgram( |
+ &scanner, &log, flags, stack_limit); |
+ CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); |
+ i::ScriptDataImpl data(log.ExtractData()); |
+ |
+ // Parse the data |
+ i::Handle<i::Script> script = FACTORY->NewScript(source); |
+ bool save_harmony_scoping = i::FLAG_harmony_scoping; |
+ i::FLAG_harmony_scoping = harmony_scoping; |
+ i::Parser parser(script, flags, NULL, NULL); |
+ i::CompilationInfo info(script); |
+ info.MarkAsGlobal(); |
+ i::FunctionLiteral* function = parser.ParseProgram(&info); |
+ i::FLAG_harmony_scoping = save_harmony_scoping; |
+ |
+ i::String* type_string = NULL; |
+ if (function == NULL) { |
+ // Extract exception from the parser. |
+ i::Handle<i::String> type_symbol = FACTORY->LookupAsciiSymbol("type"); |
+ CHECK(i::Isolate::Current()->has_pending_exception()); |
+ i::MaybeObject* maybe_object = i::Isolate::Current()->pending_exception(); |
+ i::JSObject* exception = NULL; |
+ CHECK(maybe_object->To(&exception)); |
+ |
+ // Get the type string. |
+ maybe_object = exception->GetProperty(*type_symbol); |
+ CHECK(maybe_object->To(&type_string)); |
+ } |
+ |
+ // Check that preparsing fails iff parsing fails. |
+ if (data.has_error() && function != NULL) { |
+ i::OS::Print( |
+ "Preparser failed on:\n" |
+ "\t%s\n" |
+ "with error:\n" |
+ "\t%s\n" |
+ "However, the parser succeeded", |
+ *source->ToCString(), data.BuildMessage()); |
+ CHECK(false); |
+ } else if (!data.has_error() && function == NULL) { |
+ i::OS::Print( |
+ "Parser failed on:\n" |
+ "\t%s\n" |
+ "with error:\n" |
+ "\t%s\n" |
+ "However, the preparser succeeded", |
+ *source->ToCString(), *type_string->ToCString()); |
+ CHECK(false); |
+ } |
+ |
+ // Check that preparser and parser produce the same error. |
+ if (function == NULL) { |
+ if (!type_string->IsEqualTo(i::CStrVector(data.BuildMessage()))) { |
+ i::OS::Print( |
+ "Expected parser and preparser to produce the same error on:\n" |
+ "\t%s\n" |
+ "However, found the following error messages\n" |
+ "\tparser: %s\n" |
+ "\tpreparser: %s\n", |
+ *source->ToCString(), *type_string->ToCString(), data.BuildMessage()); |
+ CHECK(false); |
+ } |
+ } |
+} |
+ |
+ |
+void TestParserSyncWithFlags(i::Handle<i::String> source) { |
+ const int flags[] = { |
+ i::kNoParsingFlags | i::CLASSIC_MODE, |
+ i::kNoParsingFlags | i::STRICT_MODE, |
+ i::kNoParsingFlags | i::EXTENDED_MODE, |
+ i::kAllowLazy | i::CLASSIC_MODE, |
+ i::kAllowLazy | i::STRICT_MODE, |
+ i::kAllowLazy | i::EXTENDED_MODE |
+ }; |
+ static const int kFlagsCount = sizeof(flags) / sizeof(int); |
+ |
Yang
2011/12/07 15:59:33
Presubmit check says
test/cctest/test-parsing.cc:
Steven
2011/12/07 16:03:08
Done.
|
+ for (int k = 0; k < kFlagsCount; ++k) { |
+ TestParserSync(source, flags[k]); |
+ } |
+} |
+ |
+ |
+TEST(ParserSync) { |
+ const char* context_data[][2] = { |
+ { "", "" }, |
+ { "{", "}" }, |
+ { "if (true) ", " else {}" }, |
+ { "if (true) {} else ", "" }, |
+ { "if (true) ", "" }, |
+ { "do ", " while (false)" }, |
+ { "while (false) ", "" }, |
+ { "for (;;) ", "" }, |
+ { "with ({})", "" }, |
+ { "switch (12) { case 12: ", "}" }, |
+ { "switch (12) { default: ", "}" }, |
+ { "label2: ", "" }, |
+ { NULL, NULL } |
+ }; |
+ |
+ const char* statement_data[] = { |
+ "{}", |
+ "var x", |
+ "var x = 1", |
+ "const x", |
+ "const x = 1", |
+ ";", |
+ "12", |
+ "if (false) {} else ;", |
+ "if (false) {} else {}", |
+ "if (false) {} else 12", |
+ "if (false) ;" |
+ "if (false) {}", |
+ "if (false) 12", |
+ "do {} while (false)", |
+ "for (;;) ;", |
+ "for (;;) {}", |
+ "for (;;) 12", |
+ "continue", |
+ "continue label", |
+ "continue\nlabel", |
+ "break", |
+ "break label", |
+ "break\nlabel", |
+ "return", |
+ "return 12", |
+ "return\n12", |
+ "with ({}) ;", |
+ "with ({}) {}", |
+ "with ({}) 12", |
+ "switch ({}) { default: }" |
+ "label3: " |
+ "throw", |
+ "throw 12", |
+ "throw\n12", |
+ "try {} catch(e) {}", |
+ "try {} finally {}", |
+ "try {} catch(e) {} finally {}", |
+ "debugger", |
+ NULL |
+ }; |
+ |
+ const char* termination_data[] = { |
+ "", |
+ ";", |
+ "\n", |
+ ";\n", |
+ "\n;", |
+ NULL |
+ }; |
+ |
+ v8::HandleScope handles; |
+ v8::Persistent<v8::Context> context = v8::Context::New(); |
+ v8::Context::Scope context_scope(context); |
+ |
+ int marker; |
+ i::Isolate::Current()->stack_guard()->SetStackLimit( |
+ reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
+ |
+ for (int i = 0; context_data[i][0] != NULL; ++i) { |
+ for (int j = 0; statement_data[j] != NULL; ++j) { |
+ for (int k = 0; termination_data[k] != NULL; ++k) { |
+ int kPrefixLen = i::StrLength(context_data[i][0]); |
+ int kStatementLen = i::StrLength(statement_data[j]); |
+ int kTerminationLen = i::StrLength(termination_data[k]); |
+ int kSuffixLen = i::StrLength(context_data[i][1]); |
+ int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen |
+ + kSuffixLen + i::StrLength("label: for (;;) { }"); |
+ |
+ // Plug the source code pieces together. |
+ i::Vector<char> program = i::Vector<char>::New(kProgramSize + 1); |
+ int length = i::OS::SNPrintF( program, |
Yang
2011/12/07 15:59:33
Presubmit says
test/cctest/test-parsing.cc:1071:
Steven
2011/12/07 16:03:08
Done.
|
+ "label: for (;;) { %s%s%s%s }", |
+ context_data[i][0], |
+ statement_data[j], |
+ termination_data[k], |
+ context_data[i][1]); |
+ CHECK(length == kProgramSize); |
+ i::Handle<i::String> source = |
+ FACTORY->NewStringFromAscii(i::CStrVector(program.start())); |
+ TestParserSyncWithFlags(source); |
+ } |
+ } |
+ } |
+} |