| 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 |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]"); | 699 TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]"); |
| 700 TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]"); | 700 TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]"); |
| 701 // Escaped ']'s wont end the character class. | 701 // Escaped ']'s wont end the character class. |
| 702 TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]"); | 702 TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]"); |
| 703 // Escaped slashes are not terminating. | 703 // Escaped slashes are not terminating. |
| 704 TestScanRegExp("/\\//flipperwald", "\\/"); | 704 TestScanRegExp("/\\//flipperwald", "\\/"); |
| 705 // Starting with '=' works too. | 705 // Starting with '=' works too. |
| 706 TestScanRegExp("/=/", "="); | 706 TestScanRegExp("/=/", "="); |
| 707 TestScanRegExp("/=?/", "=?"); | 707 TestScanRegExp("/=?/", "=?"); |
| 708 } | 708 } |
| 709 |
| 710 |
| 711 void TestParserSync(i::Handle<i::String> source, bool allow_lazy) { |
| 712 uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); |
| 713 |
| 714 // Preparse the data. |
| 715 i::CompleteParserRecorder log; |
| 716 i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); |
| 717 i::GenericStringUC16CharacterStream stream(source, 0, source->length()); |
| 718 scanner.Initialize(&stream); |
| 719 v8::preparser::PreParser::PreParseResult result = |
| 720 v8::preparser::PreParser::PreParseProgram( |
| 721 &scanner, &log, allow_lazy, stack_limit); |
| 722 CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); |
| 723 i::ScriptDataImpl data(log.ExtractData()); |
| 724 |
| 725 // Parse the data |
| 726 i::Handle<i::Script> script = FACTORY->NewScript(source); |
| 727 i::Parser parser(script, false, NULL, NULL); |
| 728 i::FunctionLiteral* function = |
| 729 parser.ParseProgram(source, true, i::kNonStrictMode); |
| 730 |
| 731 i::String* type_string = NULL; |
| 732 if (function == NULL) { |
| 733 // Extract exception from the parser. |
| 734 i::Handle<i::String> type_symbol = FACTORY->LookupAsciiSymbol("type"); |
| 735 CHECK(i::Isolate::Current()->has_pending_exception()); |
| 736 i::MaybeObject* maybe_object = i::Isolate::Current()->pending_exception(); |
| 737 i::JSObject* exception = NULL; |
| 738 CHECK(maybe_object->To(&exception)); |
| 739 |
| 740 // Get the type string. |
| 741 maybe_object = exception->GetProperty(*type_symbol); |
| 742 CHECK(maybe_object->To(&type_string)); |
| 743 } |
| 744 |
| 745 // Check that preparsing fails iff parsing fails. |
| 746 if (data.has_error() && function != NULL) { |
| 747 i::OS::Print( |
| 748 "Preparser failed on:\n" |
| 749 "\t%s\n" |
| 750 "with error:\n" |
| 751 "\t%s\n" |
| 752 "However, the parser succeeded", |
| 753 *source->ToCString(), data.BuildMessage()); |
| 754 CHECK(false); |
| 755 } else if (!data.has_error() && function == NULL) { |
| 756 i::OS::Print( |
| 757 "Parser failed on:\n" |
| 758 "\t%s\n" |
| 759 "with error:\n" |
| 760 "\t%s\n" |
| 761 "However, the preparser succeeded", |
| 762 *source->ToCString(), *type_string->ToCString()); |
| 763 CHECK(false); |
| 764 } |
| 765 |
| 766 // Check that preparser and parser produce the same error. |
| 767 if (function == NULL) { |
| 768 if (!type_string->IsEqualTo(i::CStrVector(data.BuildMessage()))) { |
| 769 i::OS::Print( |
| 770 "Expected parser and preparser to produce the same error on:\n" |
| 771 "\t%s\n" |
| 772 "However, found the following error messages\n" |
| 773 "\tparser: %s\n" |
| 774 "\tpreparser: %s\n", |
| 775 *source->ToCString(), *type_string->ToCString(), data.BuildMessage()); |
| 776 CHECK(false); |
| 777 } |
| 778 } |
| 779 } |
| 780 |
| 781 |
| 782 TEST(ParserSync) { |
| 783 const char* context_data[][2] = { |
| 784 { "", "" }, |
| 785 { "{", "}" }, |
| 786 { "if (true) ", " else {}" }, |
| 787 { "if (true) {} else ", "" }, |
| 788 { "if (true) ", "" }, |
| 789 { "do ", " while (false)" }, |
| 790 { "while (false) ", "" }, |
| 791 { "for (;;) ", "" }, |
| 792 { "with ({})", "" }, |
| 793 { "switch (12) { case 12: ", "}" }, |
| 794 { "switch (12) { default: ", "}" }, |
| 795 { "label2: ", "" }, |
| 796 { NULL, NULL } |
| 797 }; |
| 798 |
| 799 const char* statement_data[] = { |
| 800 "{}", |
| 801 "var x", |
| 802 "var x = 1", |
| 803 "const x", |
| 804 "const x = 1", |
| 805 ";", |
| 806 "12", |
| 807 "if (false) {} else ;", |
| 808 "if (false) {} else {}", |
| 809 "if (false) {} else 12", |
| 810 "if (false) ;" |
| 811 "if (false) {}", |
| 812 "if (false) 12", |
| 813 "do {} while (false)", |
| 814 "for (;;) ;", |
| 815 "for (;;) {}", |
| 816 "for (;;) 12", |
| 817 "continue", |
| 818 "continue label", |
| 819 "continue\nlabel", |
| 820 "break", |
| 821 "break label", |
| 822 "break\nlabel", |
| 823 "return", |
| 824 "return 12", |
| 825 "return\n12", |
| 826 "with ({}) ;", |
| 827 "with ({}) {}", |
| 828 "with ({}) 12", |
| 829 "switch ({}) { default: }" |
| 830 "label3: " |
| 831 "throw", |
| 832 "throw 12", |
| 833 "throw\n12", |
| 834 "try {} catch(e) {}", |
| 835 "try {} finally {}", |
| 836 "try {} catch(e) {} finally {}", |
| 837 "debugger", |
| 838 NULL |
| 839 }; |
| 840 |
| 841 const char* termination_data[] = { |
| 842 "", |
| 843 ";", |
| 844 "\n", |
| 845 ";\n", |
| 846 "\n;", |
| 847 NULL |
| 848 }; |
| 849 |
| 850 v8::HandleScope handles; |
| 851 v8::Persistent<v8::Context> context = v8::Context::New(); |
| 852 v8::Context::Scope context_scope(context); |
| 853 |
| 854 int marker; |
| 855 i::Isolate::Current()->stack_guard()->SetStackLimit( |
| 856 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 857 |
| 858 for (int i = 0; context_data[i][0] != NULL; ++i) { |
| 859 for (int j = 0; statement_data[j] != NULL; ++j) { |
| 860 for (int k = 0; termination_data[k] != NULL; ++k) { |
| 861 int kPrefixLen = i::StrLength(context_data[i][0]); |
| 862 int kStatementLen = i::StrLength(statement_data[j]); |
| 863 int kTerminationLen = i::StrLength(termination_data[k]); |
| 864 int kSuffixLen = i::StrLength(context_data[i][1]); |
| 865 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen |
| 866 + kSuffixLen + i::StrLength("label: for (;;) { }"); |
| 867 |
| 868 // Plug the source code pieces together. |
| 869 i::Vector<char> program = i::Vector<char>::New(kProgramSize + 1); |
| 870 int length = i::OS::SNPrintF(program, |
| 871 "label: for (;;) { %s%s%s%s }", |
| 872 context_data[i][0], |
| 873 statement_data[j], |
| 874 termination_data[k], |
| 875 context_data[i][1]); |
| 876 CHECK(length == kProgramSize); |
| 877 i::Handle<i::String> source = |
| 878 FACTORY->NewStringFromAscii(i::CStrVector(program.start())); |
| 879 TestParserSync(source, true); |
| 880 TestParserSync(source, false); |
| 881 } |
| 882 } |
| 883 } |
| 884 } |
| OLD | NEW |