Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 13 matching lines...) Expand all Loading... | |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include <v8.h> | 28 #include <v8.h> |
| 29 #include <fcntl.h> | 29 #include <fcntl.h> |
| 30 #include <string.h> | 30 #include <string.h> |
| 31 #include <stdio.h> | 31 #include <stdio.h> |
| 32 #include <stdlib.h> | 32 #include <stdlib.h> |
| 33 | 33 |
| 34 // TODO(isolates): | |
| 35 // o Add thread implementation for more platforms. | |
| 36 // o Do not assume not WIN32 implies pthreads. | |
| 37 #ifndef WIN32 | |
| 38 #include <pthread.h> | |
| 39 #endif | |
| 34 | 40 |
| 41 v8::Handle<v8::Context> CreateShellContext(); | |
| 35 void RunShell(v8::Handle<v8::Context> context); | 42 void RunShell(v8::Handle<v8::Context> context); |
| 36 bool ExecuteString(v8::Handle<v8::String> source, | 43 bool ExecuteString(v8::Handle<v8::String> source, |
| 37 v8::Handle<v8::Value> name, | 44 v8::Handle<v8::Value> name, |
| 38 bool print_result, | 45 bool print_result, |
| 39 bool report_exceptions); | 46 bool report_exceptions); |
| 40 v8::Handle<v8::Value> Print(const v8::Arguments& args); | 47 v8::Handle<v8::Value> Print(const v8::Arguments& args); |
| 41 v8::Handle<v8::Value> Read(const v8::Arguments& args); | 48 v8::Handle<v8::Value> Read(const v8::Arguments& args); |
| 42 v8::Handle<v8::Value> Load(const v8::Arguments& args); | 49 v8::Handle<v8::Value> Load(const v8::Arguments& args); |
| 43 v8::Handle<v8::Value> Quit(const v8::Arguments& args); | 50 v8::Handle<v8::Value> Quit(const v8::Arguments& args); |
| 44 v8::Handle<v8::Value> Version(const v8::Arguments& args); | 51 v8::Handle<v8::Value> Version(const v8::Arguments& args); |
| 45 v8::Handle<v8::String> ReadFile(const char* name); | 52 v8::Handle<v8::String> ReadFile(const char* name); |
| 46 void ReportException(v8::TryCatch* handler); | 53 void ReportException(v8::TryCatch* handler); |
| 47 | 54 |
| 48 | 55 |
| 56 #ifndef WIN32 | |
| 57 void* IsolateThreadEntry(void* arg); | |
| 58 #endif | |
| 59 | |
| 60 class SourceGroup { | |
| 61 public: | |
| 62 SourceGroup() : argv_(NULL), begin_offset_(0), end_offset_(0) { | |
| 63 #ifndef WIN32 | |
| 64 thread_ = 0; | |
| 65 #endif | |
| 66 } | |
| 67 | |
| 68 void Begin(char** argv, int offset) { | |
| 69 argv_ = const_cast<const char**>(argv); | |
| 70 begin_offset_ = offset; | |
| 71 } | |
| 72 | |
| 73 void End(int offset) { end_offset_ = offset; } | |
| 74 | |
| 75 void Execute() { | |
| 76 for (int i = begin_offset_; i < end_offset_; ++i) { | |
| 77 const char* arg = argv_[i]; | |
| 78 if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) { | |
| 79 // Execute argument given to -e option directly. | |
| 80 v8::HandleScope handle_scope; | |
| 81 v8::Handle<v8::String> file_name = v8::String::New("unnamed"); | |
| 82 v8::Handle<v8::String> source = v8::String::New(argv_[i + 1]); | |
| 83 if (!ExecuteString(source, file_name, false, true)) { | |
| 84 exit(1); | |
| 85 return; | |
| 86 } | |
| 87 ++i; | |
| 88 } else if (arg[0] == '-') { | |
| 89 // Ignore other options. They have been parsed already. | |
| 90 } else { | |
| 91 // Use all other arguments as names of files to load and run. | |
| 92 v8::HandleScope handle_scope; | |
| 93 v8::Handle<v8::String> file_name = v8::String::New(arg); | |
| 94 v8::Handle<v8::String> source = ReadFile(arg); | |
| 95 if (source.IsEmpty()) { | |
| 96 printf("Error reading '%s'\n", arg); | |
| 97 } | |
| 98 if (!ExecuteString(source, file_name, false, true)) { | |
|
yurys
2010/10/06 14:52:58
This code can be extracted out of the if/else expr
| |
| 99 exit(1); | |
| 100 return; | |
| 101 } | |
| 102 } | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 #ifdef WIN32 | |
| 107 void StartExecuteInThread() { ExecuteInThread(); } | |
| 108 void WaitForThread() {} | |
| 109 | |
| 110 #else | |
| 111 void StartExecuteInThread() { | |
| 112 pthread_create(&thread_, NULL, &IsolateThreadEntry, this); | |
| 113 } | |
| 114 | |
| 115 void WaitForThread() { | |
| 116 if (thread_ == 0) return; | |
| 117 pthread_join(thread_, NULL); | |
| 118 thread_ = 0; | |
| 119 } | |
| 120 #endif // WIN32 | |
| 121 | |
| 122 private: | |
| 123 void ExecuteInThread() { | |
| 124 v8::Isolate* isolate = v8::Isolate::New(); | |
| 125 { | |
| 126 v8::Isolate::Scope iscope(isolate); | |
| 127 v8::HandleScope scope; | |
| 128 v8::Context::Scope cscope(CreateShellContext()); | |
| 129 Execute(); | |
| 130 } | |
| 131 isolate->Dispose(); | |
| 132 } | |
| 133 | |
| 134 const char** argv_; | |
| 135 int begin_offset_; | |
| 136 int end_offset_; | |
| 137 #ifndef WIN32 | |
| 138 pthread_t thread_; | |
| 139 #endif | |
| 140 | |
| 141 friend void* IsolateThreadEntry(void* arg); | |
| 142 }; | |
| 143 | |
| 144 #ifndef WIN32 | |
| 145 void* IsolateThreadEntry(void* arg) { | |
|
yurys
2010/10/06 14:52:58
This function can be made a private static method
| |
| 146 reinterpret_cast<SourceGroup*>(arg)->ExecuteInThread(); | |
| 147 return NULL; | |
| 148 } | |
| 149 #endif | |
| 150 | |
| 151 | |
| 49 int RunMain(int argc, char* argv[]) { | 152 int RunMain(int argc, char* argv[]) { |
| 50 v8::V8::SetFlagsFromCommandLine(&argc, argv, true); | 153 v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
| 51 v8::HandleScope handle_scope; | 154 v8::HandleScope handle_scope; |
| 52 // Create a template for the global object. | 155 v8::Handle<v8::Context> context = CreateShellContext(); |
| 53 v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); | |
| 54 // Bind the global 'print' function to the C++ Print callback. | |
| 55 global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); | |
| 56 // Bind the global 'read' function to the C++ Read callback. | |
| 57 global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); | |
| 58 // Bind the global 'load' function to the C++ Load callback. | |
| 59 global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); | |
| 60 // Bind the 'quit' function | |
| 61 global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); | |
| 62 // Bind the 'version' function | |
| 63 global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); | |
| 64 // Create a new execution environment containing the built-in | |
| 65 // functions | |
| 66 v8::Handle<v8::Context> context = v8::Context::New(NULL, global); | |
| 67 // Enter the newly created execution environment. | 156 // Enter the newly created execution environment. |
| 68 v8::Context::Scope context_scope(context); | 157 v8::Context::Scope context_scope(context); |
| 69 bool run_shell = (argc == 1); | 158 bool run_shell = (argc == 1); |
| 159 int num_isolates = 1; | |
| 160 for (int i = 1; i < argc; i++) { | |
| 161 if (strcmp(argv[i], "--isolate") == 0) ++num_isolates; | |
| 162 } | |
| 163 SourceGroup* isolate_sources = new SourceGroup[num_isolates]; | |
| 164 SourceGroup* current = isolate_sources; | |
| 165 current->Begin(argv, 1); | |
| 70 for (int i = 1; i < argc; i++) { | 166 for (int i = 1; i < argc; i++) { |
| 71 const char* str = argv[i]; | 167 const char* str = argv[i]; |
| 72 if (strcmp(str, "--shell") == 0) { | 168 if (strcmp(str, "--isolate") == 0) { |
| 169 current->End(i); | |
| 170 current++; | |
| 171 current->Begin(argv, i + 1); | |
| 172 } else if (strcmp(str, "--shell") == 0) { | |
| 73 run_shell = true; | 173 run_shell = true; |
| 74 } else if (strcmp(str, "-f") == 0) { | 174 } else if (strcmp(str, "-f") == 0) { |
| 75 // Ignore any -f flags for compatibility with the other stand- | 175 // Ignore any -f flags for compatibility with the other stand- |
| 76 // alone JavaScript engines. | 176 // alone JavaScript engines. |
| 77 continue; | 177 continue; |
| 78 } else if (strncmp(str, "--", 2) == 0) { | 178 } else if (strncmp(str, "--", 2) == 0) { |
| 79 printf("Warning: unknown flag %s.\nTry --help for options\n", str); | 179 printf("Warning: unknown flag %s.\nTry --help for options\n", str); |
| 80 } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { | |
| 81 // Execute argument given to -e option directly | |
| 82 v8::HandleScope handle_scope; | |
| 83 v8::Handle<v8::String> file_name = v8::String::New("unnamed"); | |
| 84 v8::Handle<v8::String> source = v8::String::New(argv[i + 1]); | |
| 85 if (!ExecuteString(source, file_name, false, true)) | |
| 86 return 1; | |
| 87 i++; | |
| 88 } else { | |
| 89 // Use all other arguments as names of files to load and run. | |
| 90 v8::HandleScope handle_scope; | |
| 91 v8::Handle<v8::String> file_name = v8::String::New(str); | |
| 92 v8::Handle<v8::String> source = ReadFile(str); | |
| 93 if (source.IsEmpty()) { | |
| 94 printf("Error reading '%s'\n", str); | |
| 95 return 1; | |
| 96 } | |
| 97 if (!ExecuteString(source, file_name, false, true)) | |
| 98 return 1; | |
| 99 } | 180 } |
| 100 } | 181 } |
| 182 current->End(argc); | |
| 183 for (int i = 1; i < num_isolates; ++i) { | |
| 184 isolate_sources[i].StartExecuteInThread(); | |
| 185 } | |
| 186 isolate_sources[0].Execute(); | |
| 101 if (run_shell) RunShell(context); | 187 if (run_shell) RunShell(context); |
| 188 for (int i = 1; i < num_isolates; ++i) { | |
| 189 isolate_sources[i].WaitForThread(); | |
| 190 } | |
|
yurys
2010/10/06 14:52:58
Should we delete isolate_sources before exit here?
| |
| 102 return 0; | 191 return 0; |
| 103 } | 192 } |
| 104 | 193 |
| 105 | 194 |
| 106 int main(int argc, char* argv[]) { | 195 int main(int argc, char* argv[]) { |
| 107 int result = RunMain(argc, argv); | 196 int result = RunMain(argc, argv); |
| 108 v8::V8::Dispose(); | 197 v8::V8::Dispose(); |
| 109 return result; | 198 return result; |
| 110 } | 199 } |
| 111 | 200 |
| 112 | 201 |
| 113 // Extracts a C string from a V8 Utf8Value. | 202 // Extracts a C string from a V8 Utf8Value. |
| 114 const char* ToCString(const v8::String::Utf8Value& value) { | 203 const char* ToCString(const v8::String::Utf8Value& value) { |
| 115 return *value ? *value : "<string conversion failed>"; | 204 return *value ? *value : "<string conversion failed>"; |
| 116 } | 205 } |
| 117 | 206 |
| 118 | 207 |
| 208 // Creates a new execution environment containing the built-in | |
| 209 // functions. | |
| 210 v8::Handle<v8::Context> CreateShellContext() { | |
| 211 // Create a template for the global object. | |
| 212 v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); | |
| 213 // Bind the global 'print' function to the C++ Print callback. | |
| 214 global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); | |
| 215 // Bind the global 'read' function to the C++ Read callback. | |
| 216 global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); | |
| 217 // Bind the global 'load' function to the C++ Load callback. | |
| 218 global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); | |
| 219 // Bind the 'quit' function | |
| 220 global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); | |
| 221 // Bind the 'version' function | |
| 222 global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); | |
| 223 return v8::Context::New(NULL, global); | |
| 224 } | |
| 225 | |
| 226 | |
| 119 // The callback that is invoked by v8 whenever the JavaScript 'print' | 227 // The callback that is invoked by v8 whenever the JavaScript 'print' |
| 120 // function is called. Prints its arguments on stdout separated by | 228 // function is called. Prints its arguments on stdout separated by |
| 121 // spaces and ending with a newline. | 229 // spaces and ending with a newline. |
| 122 v8::Handle<v8::Value> Print(const v8::Arguments& args) { | 230 v8::Handle<v8::Value> Print(const v8::Arguments& args) { |
| 123 bool first = true; | 231 bool first = true; |
| 124 for (int i = 0; i < args.Length(); i++) { | 232 for (int i = 0; i < args.Length(); i++) { |
| 125 v8::HandleScope handle_scope; | 233 v8::HandleScope handle_scope; |
| 126 if (first) { | 234 if (first) { |
| 127 first = false; | 235 first = false; |
| 128 } else { | 236 } else { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 printf("^"); | 407 printf("^"); |
| 300 } | 408 } |
| 301 printf("\n"); | 409 printf("\n"); |
| 302 v8::String::Utf8Value stack_trace(try_catch->StackTrace()); | 410 v8::String::Utf8Value stack_trace(try_catch->StackTrace()); |
| 303 if (stack_trace.length() > 0) { | 411 if (stack_trace.length() > 0) { |
| 304 const char* stack_trace_string = ToCString(stack_trace); | 412 const char* stack_trace_string = ToCString(stack_trace); |
| 305 printf("%s\n", stack_trace_string); | 413 printf("%s\n", stack_trace_string); |
| 306 } | 414 } |
| 307 } | 415 } |
| 308 } | 416 } |
| OLD | NEW |