- Timestamp:
- 03/26/13 17:17:52 (12 years ago)
- Location:
- trunk/FACT++/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/InterpreterV8.cc
r15150 r15156 146 146 HandleScope handle_scope; 147 147 148 TryCatch exception;149 150 148 Handle<Function> func = Handle<Function>::Cast(args[1]); 151 149 … … 155 153 156 154 Time t; 157 while ( !exception.HasCaught())155 while (1) 158 156 { 159 157 const Handle<Value> rc = func->Call(func, args.Length()-2, argv); 160 if (!rc.IsEmpty() && !rc->IsUndefined()) 158 if (rc.IsEmpty()) 159 return Undefined(); 160 161 if (!rc->IsUndefined()) 161 162 return handle_scope.Close(rc); 162 163 … … 170 171 usleep(1000); 171 172 } 172 173 if (exception.HasCaught())174 return exception.ReThrow();175 173 176 174 if (timeout<0) … … 331 329 332 330 if (args.Length()==3 && !args[2]->IsInt32() && !args[2]->IsUndefined()) 333 return ThrowException(String::New("Argument 3 not an int32 and not null."));331 return ThrowException(String::New("Argument 3 not an int32 and not undefined.")); 334 332 335 333 // Using a Javascript function has the advantage that it is fully … … 692 690 const String::AsciiValue file(args[i]); 693 691 if (*file == NULL) 694 return ThrowException(String::New("File name missing")); 695 696 TryCatch exception; 697 const bool rc = ExecuteFile(*file); 698 if (exception.HasCaught()) 699 { 700 // If this is called from the main thread, re-throw 701 if (fThreadId==V8::GetCurrentThreadId()) 702 return exception.ReThrow(); 703 704 // Otherwise, handle the exception... 705 HandleException(exception, "include"); 706 } 707 if (!rc) 708 { 709 // ...and stop the thread immediately (if this is not done, 710 // the other threads might still proceed); 711 V8::TerminateExecution(fThreadId); 712 return ThrowException(Null()); 713 } 714 } 715 716 return Undefined();//Boolean::New(true); 692 return ThrowException(String::New("File name missing.")); 693 694 if (strlen(*file)==0) 695 return ThrowException(String::New("File name empty.")); 696 697 ifstream fin(*file); // izstream does not work: WHY? 698 if (!fin) 699 return ThrowException(String::New(errno!=0?strerror(errno):"Insufficient memory for decompression")); 700 701 string buffer; 702 getline(fin, buffer, '\0'); 703 704 if ((fin.fail() && !fin.eof()) || fin.bad()) 705 return ThrowException(String::New(strerror(errno))); 706 707 const Handle<Value> rc = ExecuteCode(buffer, *file); 708 if (rc.IsEmpty()) 709 return Undefined(); 710 } 711 712 return Undefined(); 717 713 } 718 714 … … 743 739 { 744 740 string buffer; 745 if (!getline(fin, buffer, '\0')) 741 getline(fin, buffer, '\0'); 742 if ((fin.fail() && !fin.eof()) || fin.bad()) 746 743 return ThrowException(String::New(strerror(errno))); 747 744 … … 767 764 768 765 return handle_scope.Close(arr); 766 } 767 768 // ========================================================================== 769 // Mail 770 // ========================================================================== 771 772 Handle<Value> InterpreterV8::ConstructorMail(const Arguments &args) 773 { 774 if (!args.IsConstructCall()) 775 return ThrowException(String::New("Mail must be called as constructor")); 776 777 HandleScope handle_scope; 778 779 Handle<Object> self = args.This(); 780 self->Set(String::New("send"), FunctionTemplate::New(WrapSendMail)->GetFunction(), ReadOnly); 781 return handle_scope.Close(self); 782 } 783 784 vector<string> InterpreterV8::ValueToArray(const Handle<Value> &val) 785 { 786 vector<string> rc; 787 if (val->IsString()) 788 { 789 rc.push_back(*String::AsciiValue(val->ToString())); 790 return rc; 791 } 792 793 if (val->IsArray()) 794 { 795 Handle<Array> arr = Handle<Array>::Cast(val); 796 for (uint32_t i=0; i<arr->Length(); i++) 797 { 798 Handle<Value> obj = arr->Get(i); 799 if (obj.IsEmpty()) 800 continue; 801 802 if (!obj->IsString()) 803 return vector<string>(); 804 805 rc.push_back(*String::AsciiValue(obj->ToString())); 806 } 807 } 808 809 return rc; 810 } 811 812 Handle<Value> InterpreterV8::FuncSendMail(const Arguments& args) 813 { 814 HandleScope handle_scope; 815 816 if (args.Length()>1) 817 return ThrowException(String::New("Only one argument allowed.")); 818 819 if (args.Length()==1 && !args[0]->IsBoolean()) 820 return ThrowException(String::New("Argument must be a boolean.")); 821 822 const bool block = args.Length()==0 || args[0]->BooleanValue(); 823 824 const Handle<Value> sub = args.This()->Get(String::New("subject")); 825 const Handle<Value> rec = args.This()->Get(String::New("recipient")); 826 const Handle<Value> txt = args.This()->Get(String::New("text")); 827 const Handle<Value> att = args.This()->Get(String::New("attachment")); 828 const Handle<Value> bcc = args.This()->Get(String::New("bcc")); 829 const Handle<Value> cc = args.This()->Get(String::New("cc")); 830 831 if (sub->IsUndefined()) 832 return ThrowException(String::New("Required property 'subject' missing.")); 833 834 const vector<string> vrec = ValueToArray(rec); 835 const vector<string> vtxt = ValueToArray(txt); 836 const vector<string> vatt = ValueToArray(att); 837 const vector<string> vbcc = ValueToArray(bcc); 838 const vector<string> vcc = ValueToArray(cc); 839 840 if (vrec.size()==0) 841 return ThrowException(String::New("Required property 'recipient' must be a string or an array of strings.")); 842 if (vtxt.size()==0) 843 return ThrowException(String::New("Required property 'text' must be a string or an array of strings.")); 844 if (vatt.size()==0 && !att->IsUndefined()) 845 return ThrowException(String::New("Property 'attachment' must be a string or an array of strings.")); 846 if (vbcc.size()==0 && !bcc->IsUndefined()) 847 return ThrowException(String::New("Property 'bcc' must be a string or an array of strings.")); 848 if (vcc.size()==0 && !cc->IsUndefined()) 849 return ThrowException(String::New("Property 'cc' must be a string or an array of strings.")); 850 851 if (!sub->IsString()) 852 return ThrowException(String::New("Property 'subject' must be a string.")); 853 854 const string subject = *String::AsciiValue(sub->ToString()); 855 856 857 FILE *pipe = popen(("from=no-reply@fact-project.org mailx -~ "+vrec[0]).c_str(), "w"); 858 if (!pipe) 859 return ThrowException(String::New(strerror(errno))); 860 861 fprintf(pipe, "%s", ("~s"+subject+"\n").c_str()); 862 for (auto it=vrec.begin()+1; it<vrec.end(); it++) 863 fprintf(pipe, "%s", ("~t"+*it+"\n").c_str()); 864 for (auto it=vbcc.begin(); it<vbcc.end(); it++) 865 fprintf(pipe, "%s", ("~b"+*it+"\n").c_str()); 866 for (auto it=vcc.begin(); it<vcc.end(); it++) 867 fprintf(pipe, "%s", ("~c"+*it+"\n").c_str()); 868 for (auto it=vatt.begin(); it<vatt.end(); it++) 869 fprintf(pipe, "%s", ("~@"+*it+"\n").c_str()); // Must not contain white spaces 870 871 for (auto it=vtxt.begin(); it<vtxt.end(); it++) 872 fwrite((*it+"\n").c_str(), it->length()+1, 1, pipe); 873 874 fprintf(pipe, "\n---\nsent by dimctrl"); 875 876 if (!block) 877 return Undefined(); 878 879 const int rc = pclose(pipe); 880 881 const Locker lock; 882 return handle_scope.Close(Integer::New(WEXITSTATUS(rc))); 769 883 } 770 884 … … 1275 1389 } 1276 1390 1391 // This hides the location of the exception, which is wanted. 1277 1392 if (exception.HasCaught()) 1278 1393 return exception.ReThrow(); … … 1972 2087 1973 2088 const Handle<Value> result = ExecuteCode(code); 2089 2090 // This hides the location of the exception in the internal code, 2091 // which is wanted. 1974 2092 if (exception.HasCaught()) 1975 2093 exception.ReThrow(); … … 1978 2096 } 1979 2097 1980 Handle<Value> InterpreterV8::ExecuteCode(const string &code, const string &file , bool main)2098 Handle<Value> InterpreterV8::ExecuteCode(const string &code, const string &file) 1981 2099 { 1982 2100 HandleScope handle_scope; … … 1985 2103 const Handle<String> origin = String::New(file.c_str()); 1986 2104 if (source.IsEmpty()) 1987 return Handle<Value>();2105 return Undefined(); 1988 2106 1989 2107 const Handle<Script> script = Script::Compile(source, origin); 1990 2108 if (script.IsEmpty()) 1991 return Handle<Value>(); 1992 1993 if (main && JsGetCurrentState().index!=3) 1994 JsSetState(3); 1995 1996 TryCatch exception; 1997 1998 const Handle<Value> result = script->Run(); 1999 if (exception.HasCaught()) 2000 { 2001 if (file=="internal" || (fThreadId==V8::GetCurrentThreadId() && !main)) 2002 return exception.ReThrow(); 2003 2004 HandleException(exception, "code"); 2005 return Handle<Value>(); 2006 } 2109 return Undefined(); 2110 2111 //if (main && JsGetCurrentState().index!=3) 2112 // JsSetState(3); 2113 2114 const Handle<Value> rc = script->Run(); 2115 if (rc.IsEmpty()) 2116 return Undefined(); 2007 2117 2008 2118 // If all went well and the result wasn't undefined then print 2009 2119 // the returned value. 2010 if (!result.IsEmpty() && !result->IsUndefined() && file!="internal") 2011 JsResult(*String::AsciiValue(result)); 2012 2013 return handle_scope.Close(result); 2014 } 2015 2016 bool InterpreterV8::ExecuteFile(const string &name, bool main) 2017 { 2018 ifstream fin(name.c_str()); 2019 if (!fin) 2020 { 2021 JsException("Error - Could not open file '"+name+"'"); 2022 return false; 2023 } 2024 2025 string buffer; 2026 if (!getline(fin, buffer, '\0')) 2027 return true; 2028 2029 if (fin.fail()) 2030 { 2031 JsException("Error - reading file."); 2032 return false; 2033 } 2034 2035 return !ExecuteCode(buffer, name, main).IsEmpty(); 2036 } 2037 2038 bool InterpreterV8::ExecuteConsole() 2039 { 2040 // Just necessray for the Handle<Script> 2041 const HandleScope handle_scope; 2042 2043 // A void script doing nothing than making sure that some JavaScript is executed 2044 const Handle<Script> catcher = Script::Compile(String::New(";"), String::New("")); 2045 2046 // Unlocking is necessary for the preemption to work 2047 const Unlocker global_unlock; 2048 2120 if (!rc->IsUndefined() && file!="internal") 2121 JsResult(*String::AsciiValue(rc)); 2122 2123 return handle_scope.Close(rc); 2124 } 2125 2126 void InterpreterV8::ExecuteConsole() 2127 { 2049 2128 JsSetState(3); 2050 2129 … … 2057 2136 while (1) 2058 2137 { 2138 // Create a local handle scope so that left-overs from single 2139 // console inputs will not fill up the memory 2140 const HandleScope handle_scope; 2141 2142 // Unlocking is necessary for the preemption to work 2143 const Unlocker global_unlock; 2144 2059 2145 const string buffer = Tools::Trim(Readline::StaticPrompt(command.empty() ? "JS> " : " \\> ")); 2060 2146 if (buffer==".q") … … 2082 2168 const Locker lock; 2083 2169 2084 // Dump all pending exceptions. This is mainly to catch the 'null' exception2085 // thrown if a running JavaScript should be terminated from somewhere.2086 while (1)2087 {2088 TryCatch exception;2089 catcher->Run();2090 if (!exception.HasCaught())2091 break;2092 }2093 2094 2170 // Catch exceptions during code compilation 2095 2171 TryCatch exception; 2096 2172 2097 2173 // Execute code which was entered 2098 bool rc = ExecuteCode(command, "console", true).IsEmpty(); 2099 if (exception.HasCaught()) 2100 { 2101 HandleException(exception, "compile"); 2102 rc = true; 2103 } 2174 ExecuteCode(command, "console"); 2175 if (!HandleException(exception, "console")) 2176 lout << endl; 2104 2177 2105 2178 // Stop all other threads … … 2114 2187 usleep(1000); 2115 2188 2116 // In case of an exception add an empty line to the output2117 if (rc)2118 lout << endl;2119 2120 2189 // command has been executed, collect new command 2121 2190 command = ""; … … 2125 2194 2126 2195 Readline::StaticPopHistory("java.his"); 2127 2128 return true;2129 2196 } 2130 2197 … … 2296 2363 global->Set(String::New("Subscription"), sub, ReadOnly); 2297 2364 2365 #ifdef HAVE_SQL 2298 2366 Handle<FunctionTemplate> db = FunctionTemplate::New(WrapDatabase); 2299 2367 db->SetClassName(String::New("Database")); 2300 2368 db->InstanceTemplate()->SetInternalFieldCount(1); 2301 2369 global->Set(String::New("Database"), db, ReadOnly); 2370 #endif 2302 2371 2303 2372 Handle<FunctionTemplate> thread = FunctionTemplate::New(WrapThread); … … 2319 2388 fTemplateEvent = evt; 2320 2389 fTemplateDescription = desc; 2390 2391 #ifdef HAVE_MAIL 2392 Handle<FunctionTemplate> mail = FunctionTemplate::New(ConstructorMail); 2393 mail->SetClassName(String::New("Mail")); 2394 global->Set(String::New("Mail"), mail, ReadOnly); 2395 #endif 2321 2396 2322 2397 #ifdef HAVE_NOVA … … 2372 2447 AddFormatToGlobal(); 2373 2448 2374 bool rc = true;2375 2449 if (!exception.HasCaught()) 2376 2450 { … … 2379 2453 Locker::StartPreemption(10); 2380 2454 2381 rc &= filename.empty() ? ExecuteConsole() : ExecuteFile(filename, true); 2455 if (filename.empty()) 2456 ExecuteConsole(); 2457 else 2458 { 2459 // We call script->Run because it is the only way to 2460 // catch exceptions. 2461 const Handle<String> source = String::New(("include('"+filename+"');").c_str()); 2462 const Handle<String> origin = String::New("main"); 2463 const Handle<Script> script = Script::Compile(source, origin); 2464 if (!script.IsEmpty()) 2465 { 2466 JsSetState(3); 2467 script->Run(); 2468 } 2469 } 2382 2470 2383 2471 Locker::StopPreemption(); … … 2390 2478 2391 2479 // Handle an exception 2392 rc &=HandleException(exception, "main");2480 /*const bool rc =*/ HandleException(exception, "main"); 2393 2481 2394 2482 // IsProfilerPaused() -
trunk/FACT++/src/InterpreterV8.h
r15101 r15156 58 58 #ifdef HAVE_V8 59 59 bool HandleException(v8::TryCatch &try_catch, const char *where); 60 bool ExecuteFile(const std::string &name, bool main=false); 61 bool ExecuteConsole(); 62 v8::Handle<v8::Value> ExecuteCode(const std::string &code, const std::string &file="internal", bool main=false); 60 void ExecuteConsole(); 61 v8::Handle<v8::Value> ExecuteCode(const std::string &code, const std::string &file="internal"); 63 62 v8::Handle<v8::Value> ExecuteInternal(const std::string &code); 64 63 65 64 void Thread(int &id, v8::Persistent<v8::Function> func, uint32_t ms); 65 66 std::vector<std::string> ValueToArray(const v8::Handle<v8::Value> &val); 66 67 67 68 v8::Handle<v8::Value> FuncWait(const v8::Arguments& args); … … 75 76 v8::Handle<v8::Value> FuncOut(const v8::Arguments& args); 76 77 v8::Handle<v8::Value> FuncFile(const v8::Arguments& args); 78 v8::Handle<v8::Value> FuncSendMail(const v8::Arguments& args); 77 79 v8::Handle<v8::Value> FuncInclude(const v8::Arguments& args); 78 80 v8::Handle<v8::Value> FuncExit(const v8::Arguments& args); … … 96 98 static v8::Handle<v8::Value> Constructor(const v8::Arguments &args); 97 99 100 static v8::Handle<v8::Value> ConstructorMail(const v8::Arguments &args); 101 98 102 #ifdef HAVE_NOVA 99 103 static double GetDataMember(const v8::Arguments &args, const char *name); … … 120 124 static v8::Handle<v8::Value> WrapInclude(const v8::Arguments &args) { if (This) return This->FuncInclude(args); else return v8::Undefined(); } 121 125 static v8::Handle<v8::Value> WrapFile(const v8::Arguments &args) { if (This) return This->FuncFile(args); else return v8::Undefined(); } 126 static v8::Handle<v8::Value> WrapSendMail(const v8::Arguments &args) { if (This) return This->FuncSendMail(args); else return v8::Undefined(); } 122 127 static v8::Handle<v8::Value> WrapLog(const v8::Arguments &args) { if (This) return This->FuncLog(args); else return v8::Undefined(); } 123 128 static v8::Handle<v8::Value> WrapAlarm(const v8::Arguments &args) { if (This) return This->FuncAlarm(args); else return v8::Undefined(); }
Note:
See TracChangeset
for help on using the changeset viewer.