// ShellUtils.cpp #include "ShellUtils.h" #include #include #include #include using namespace std; using namespace v8; v8::Handle Print(const v8::Arguments& args) { bool first = true; for (int i = 0; i < args.Length(); i++) { v8::HandleScope handle_scope; if (first) { first = false; } else { printf(" "); } v8::String::Utf8Value str(args[i]); printf("%s", *str); } printf("\n"); return v8::Undefined(); } std::string toSTLString( const v8::Handle & o ){ v8::String::Utf8Value str(o); const char * foo = *str; std::string s(foo); return s; } std::ostream& operator<<( std::ostream &s, const v8::Handle & o ){ v8::String::Utf8Value str(o); s << *str; return s; } std::ostream& operator<<( std::ostream &s, const v8::TryCatch * try_catch ){ v8::HandleScope handle_scope; v8::String::Utf8Value exception(try_catch->Exception()); v8::Handle message = try_catch->Message(); if (message.IsEmpty()) { s << *exception << endl; } else { v8::String::Utf8Value filename(message->GetScriptResourceName()); int linenum = message->GetLineNumber(); cout << *filename << ":" << linenum << " " << *exception << endl; v8::String::Utf8Value sourceline(message->GetSourceLine()); cout << *sourceline << endl; int start = message->GetStartColumn(); for (int i = 0; i < start; i++) cout << " "; int end = message->GetEndColumn(); for (int i = start; i < end; i++) cout << "^"; cout << endl; } if ( try_catch->next_ ) s << try_catch->next_; return s; } v8::Handle Load(const v8::Arguments& args) { for (int i = 0; i < args.Length(); i++) { v8::HandleScope handle_scope; v8::String::Utf8Value file(args[i]); v8::Handle source = ReadFile(*file); if (source.IsEmpty()) { return v8::ThrowException(v8::String::New("Error loading file")); } if (!ExecuteString(source, v8::String::New(*file), false, false)) { return v8::ThrowException(v8::String::New("Error executing file")); } } return v8::Undefined(); } v8::Handle Quit(const v8::Arguments& args) { // If not arguments are given args[0] will yield undefined which // converts to the integer value 0. int exit_code = args[0]->Int32Value(); exit(exit_code); return v8::Undefined(); } v8::Handle Version(const v8::Arguments& args) { return v8::String::New(v8::V8::GetVersion()); } v8::Handle ReadFile(const char* name) { boost::filesystem::path p(name); if ( is_directory( p ) ){ cerr << "can't read directory [" << name << "]" << endl; return v8::String::New( "" ); } FILE* file = fopen(name, "rb"); if (file == NULL) return v8::Handle(); fseek(file, 0, SEEK_END); int size = ftell(file); rewind(file); char* chars = new char[size + 1]; chars[size] = '\0'; for (int i = 0; i < size;) { int read = fread(&chars[i], 1, size - i, file); i += read; } fclose(file); v8::Handle result = v8::String::New(chars, size); delete[] chars; return result; } bool ExecuteString(v8::Handle source, v8::Handle name, bool print_result, bool report_exceptions ){ v8::HandleScope handle_scope; v8::TryCatch try_catch; v8::Handle script = v8::Script::Compile(source, name); if (script.IsEmpty()) { if (report_exceptions) ReportException(&try_catch); return false; } v8::Handle result = script->Run(); if ( result.IsEmpty() ){ if (report_exceptions) ReportException(&try_catch); return false; } if ( print_result ){ Local current = Context::GetCurrent(); Local global = current->Global(); Local shellPrint = global->Get( String::New( "shellPrint" ) ); if ( shellPrint->IsFunction() ){ v8::Function * f = (v8::Function*)(*shellPrint); v8::Handle argv[1]; argv[0] = result; f->Call( global , 1 , argv ); } else if ( ! result->IsUndefined() ){ cout << result << endl; } } return true; } v8::Handle JSSleep(const v8::Arguments& args){ assert( args.Length() == 1 ); assert( args[0]->IsNumber() ); boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); xt.nsec += args[0]->ToNumber()->Value() * 1000000; boost::thread::sleep(xt); return v8::Undefined(); } void ReportException(v8::TryCatch* try_catch) { cout << try_catch << endl; } void installShellUtils( v8::Handle& global ){ global->Set(v8::String::New("sleep"), v8::FunctionTemplate::New(JSSleep)); global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); }