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