18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <v8.h> 29e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <assert.h> 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <fcntl.h> 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <string.h> 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdio.h> 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h> 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#ifdef COMPRESS_STARTUP_DATA_BZ2 3669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#error Using compressed startup data is not supported for this sample 3744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 3844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch/** 4069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch * This sample program shows how to implement a simple javascript shell 4169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch * based on V8. This includes initializing V8 with command line options, 4269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch * creating global functions, compiling and executing strings. 4369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch * 4469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch * For a more sophisticated shell, consider using the debug shell D8. 4569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch */ 4669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockv8::Persistent<v8::Context> CreateShellContext(); 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RunShell(v8::Handle<v8::Context> context); 5069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochint RunMain(int argc, char* argv[]); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ExecuteString(v8::Handle<v8::String> source, 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Value> name, 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool print_result, 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool report_exceptions); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Print(const v8::Arguments& args); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Read(const v8::Arguments& args); 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Load(const v8::Arguments& args); 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Quit(const v8::Arguments& args); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Version(const v8::Arguments& args); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::String> ReadFile(const char* name); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ReportException(v8::TryCatch* handler); 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic bool run_shell; 6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochint main(int argc, char* argv[]) { 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::V8::SetFlagsFromCommandLine(&argc, argv, true); 6969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch run_shell = (argc == 1); 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope handle_scope; 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Persistent<v8::Context> context = CreateShellContext(); 7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (context.IsEmpty()) { 7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block printf("Error creating context\n"); 7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return 1; 7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 7669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context->Enter(); 7769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int result = RunMain(argc, argv); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (run_shell) RunShell(context); 7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block context->Exit(); 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context.Dispose(); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::V8::Dispose(); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Extracts a C string from a V8 Utf8Value. 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* ToCString(const v8::String::Utf8Value& value) { 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return *value ? *value : "<string conversion failed>"; 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Creates a new execution environment containing the built-in 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// functions. 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockv8::Persistent<v8::Context> CreateShellContext() { 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Create a template for the global object. 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bind the global 'print' function to the C++ Print callback. 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bind the global 'read' function to the C++ Read callback. 10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); 10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bind the global 'load' function to the C++ Load callback. 10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); 10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bind the 'quit' function 10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); 10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bind the 'version' function 10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); 1078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return v8::Context::New(NULL, global); 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The callback that is invoked by v8 whenever the JavaScript 'print' 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function is called. Prints its arguments on stdout separated by 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// spaces and ending with a newline. 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Print(const v8::Arguments& args) { 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool first = true; 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < args.Length(); i++) { 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope handle_scope; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (first) { 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block first = false; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf(" "); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::Utf8Value str(args[i]); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* cstr = ToCString(str); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s", cstr); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("\n"); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fflush(stdout); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::Undefined(); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The callback that is invoked by v8 whenever the JavaScript 'read' 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function is called. This function loads the content of the file named in 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the argument into a JavaScript string. 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Read(const v8::Arguments& args) { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (args.Length() != 1) { 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::ThrowException(v8::String::New("Bad parameters")); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::Utf8Value file(args[0]); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*file == NULL) { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::ThrowException(v8::String::New("Error loading file")); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::String> source = ReadFile(*file); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source.IsEmpty()) { 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::ThrowException(v8::String::New("Error loading file")); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return source; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The callback that is invoked by v8 whenever the JavaScript 'load' 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function is called. Loads, compiles and executes its argument 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JavaScript file. 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Load(const v8::Arguments& args) { 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < args.Length(); i++) { 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope handle_scope; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::Utf8Value file(args[i]); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*file == NULL) { 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::ThrowException(v8::String::New("Error loading file")); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::String> source = ReadFile(*file); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (source.IsEmpty()) { 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::ThrowException(v8::String::New("Error loading file")); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!ExecuteString(source, v8::String::New(*file), false, false)) { 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::ThrowException(v8::String::New("Error executing file")); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::Undefined(); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The callback that is invoked by v8 whenever the JavaScript 'quit' 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function is called. Quits. 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Quit(const v8::Arguments& args) { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If not arguments are given args[0] will yield undefined which 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // converts to the integer value 0. 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int exit_code = args[0]->Int32Value(); 18169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch fflush(stdout); 18269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch fflush(stderr); 18369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch exit(exit_code); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::Undefined(); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Value> Version(const v8::Arguments& args) { 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return v8::String::New(v8::V8::GetVersion()); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Reads a file into a v8 string. 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::String> ReadFile(const char* name) { 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file = fopen(name, "rb"); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (file == NULL) return v8::Handle<v8::String>(); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fseek(file, 0, SEEK_END); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = ftell(file); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rewind(file); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* chars = new char[size + 1]; 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block chars[size] = '\0'; 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < size;) { 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int read = fread(&chars[i], 1, size - i, file); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i += read; 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::String> result = v8::String::New(chars, size); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete[] chars; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Process remaining command line arguments and execute files 21669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochint RunMain(int argc, char* argv[]) { 21769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch for (int i = 1; i < argc; i++) { 21869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const char* str = argv[i]; 21969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (strcmp(str, "--shell") == 0) { 22069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch run_shell = true; 22169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (strcmp(str, "-f") == 0) { 22269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Ignore any -f flags for compatibility with the other stand- 22369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // alone JavaScript engines. 22469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch continue; 22569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (strncmp(str, "--", 2) == 0) { 22669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch printf("Warning: unknown flag %s.\nTry --help for options\n", str); 22769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { 22869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Execute argument given to -e option directly. 22969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch v8::Handle<v8::String> file_name = v8::String::New("unnamed"); 23069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch v8::Handle<v8::String> source = v8::String::New(argv[++i]); 23169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (!ExecuteString(source, file_name, false, true)) return 1; 23269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 23369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Use all other arguments as names of files to load and run. 23469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch v8::Handle<v8::String> file_name = v8::String::New(str); 23569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch v8::Handle<v8::String> source = ReadFile(str); 23669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (source.IsEmpty()) { 23769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch printf("Error reading '%s'\n", str); 23869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch continue; 23969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 24069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (!ExecuteString(source, file_name, false, true)) return 1; 24169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 24269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 24369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return 0; 24469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 24569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 24669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The read-eval-execute loop of the shell. 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RunShell(v8::Handle<v8::Context> context) { 24969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch printf("V8 version %s [sample shell]\n", v8::V8::GetVersion()); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kBufferSize = 256; 251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Enter the execution environment before evaluating any code. 252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::Context::Scope context_scope(context); 253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch v8::Local<v8::String> name(v8::String::New("(shell)")); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char buffer[kBufferSize]; 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("> "); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* str = fgets(buffer, kBufferSize, stdin); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (str == NULL) break; 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope handle_scope; 260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ExecuteString(v8::String::New(str), name, true, true); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("\n"); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Executes a string within the current v8 context. 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ExecuteString(v8::Handle<v8::String> source, 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Value> name, 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool print_result, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool report_exceptions) { 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope handle_scope; 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::TryCatch try_catch; 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Script> script = v8::Script::Compile(source, name); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (script.IsEmpty()) { 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print errors that happened during compilation. 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (report_exceptions) 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ReportException(&try_catch); 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Value> result = script->Run(); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result.IsEmpty()) { 282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch assert(try_catch.HasCaught()); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print errors that happened during execution. 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (report_exceptions) 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ReportException(&try_catch); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch assert(!try_catch.HasCaught()); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (print_result && !result->IsUndefined()) { 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If all went well and the result wasn't undefined then print 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the returned value. 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::Utf8Value str(result); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* cstr = ToCString(str); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s\n", cstr); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ReportException(v8::TryCatch* try_catch) { 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope handle_scope; 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::Utf8Value exception(try_catch->Exception()); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* exception_string = ToCString(exception); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Message> message = try_catch->Message(); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (message.IsEmpty()) { 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // V8 didn't provide any extra information about this error; just 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // print the exception. 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s\n", exception_string); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print (filename):(line number): (message). 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::Utf8Value filename(message->GetScriptResourceName()); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* filename_string = ToCString(filename); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int linenum = message->GetLineNumber(); 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s:%i: %s\n", filename_string, linenum, exception_string); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print line of source code. 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::String::Utf8Value sourceline(message->GetSourceLine()); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* sourceline_string = ToCString(sourceline); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s\n", sourceline_string); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print wavy underline (GetUnderline is deprecated). 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start = message->GetStartColumn(); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < start; i++) { 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf(" "); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int end = message->GetEndColumn(); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = start; i < end; i++) { 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("^"); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("\n"); 33125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen v8::String::Utf8Value stack_trace(try_catch->StackTrace()); 33225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (stack_trace.length() > 0) { 33325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen const char* stack_trace_string = ToCString(stack_trace); 33425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen printf("%s\n", stack_trace_string); 33525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 338