The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / samples / shell.cc @ f230a1cf

History | View | Annotate | Download (12.5 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27

    
28
#include <v8.h>
29
#include <assert.h>
30
#include <fcntl.h>
31
#include <string.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34

    
35
#ifdef COMPRESS_STARTUP_DATA_BZ2
36
#error Using compressed startup data is not supported for this sample
37
#endif
38

    
39
/**
40
 * This sample program shows how to implement a simple javascript shell
41
 * based on V8.  This includes initializing V8 with command line options,
42
 * creating global functions, compiling and executing strings.
43
 *
44
 * For a more sophisticated shell, consider using the debug shell D8.
45
 */
46

    
47

    
48
v8::Handle<v8::Context> CreateShellContext(v8::Isolate* isolate);
49
void RunShell(v8::Handle<v8::Context> context);
50
int RunMain(v8::Isolate* isolate, int argc, char* argv[]);
51
bool ExecuteString(v8::Isolate* isolate,
52
                   v8::Handle<v8::String> source,
53
                   v8::Handle<v8::Value> name,
54
                   bool print_result,
55
                   bool report_exceptions);
56
void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
57
void Read(const v8::FunctionCallbackInfo<v8::Value>& args);
58
void Load(const v8::FunctionCallbackInfo<v8::Value>& args);
59
void Quit(const v8::FunctionCallbackInfo<v8::Value>& args);
60
void Version(const v8::FunctionCallbackInfo<v8::Value>& args);
61
v8::Handle<v8::String> ReadFile(const char* name);
62
void ReportException(v8::Isolate* isolate, v8::TryCatch* handler);
63

    
64

    
65
static bool run_shell;
66

    
67

    
68
int main(int argc, char* argv[]) {
69
  v8::V8::InitializeICU();
70
  v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
71
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
72
  run_shell = (argc == 1);
73
  int result;
74
  {
75
    v8::HandleScope handle_scope(isolate);
76
    v8::Handle<v8::Context> context = CreateShellContext(isolate);
77
    if (context.IsEmpty()) {
78
      fprintf(stderr, "Error creating context\n");
79
      return 1;
80
    }
81
    context->Enter();
82
    result = RunMain(isolate, argc, argv);
83
    if (run_shell) RunShell(context);
84
    context->Exit();
85
  }
86
  v8::V8::Dispose();
87
  return result;
88
}
89

    
90

    
91
// Extracts a C string from a V8 Utf8Value.
92
const char* ToCString(const v8::String::Utf8Value& value) {
93
  return *value ? *value : "<string conversion failed>";
94
}
95

    
96

    
97
// Creates a new execution environment containing the built-in
98
// functions.
99
v8::Handle<v8::Context> CreateShellContext(v8::Isolate* isolate) {
100
  // Create a template for the global object.
101
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
102
  // Bind the global 'print' function to the C++ Print callback.
103
  global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
104
  // Bind the global 'read' function to the C++ Read callback.
105
  global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
106
  // Bind the global 'load' function to the C++ Load callback.
107
  global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
108
  // Bind the 'quit' function
109
  global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit));
110
  // Bind the 'version' function
111
  global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));
112

    
113
  return v8::Context::New(isolate, NULL, global);
114
}
115

    
116

    
117
// The callback that is invoked by v8 whenever the JavaScript 'print'
118
// function is called.  Prints its arguments on stdout separated by
119
// spaces and ending with a newline.
120
void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
121
  bool first = true;
122
  for (int i = 0; i < args.Length(); i++) {
123
    v8::HandleScope handle_scope(args.GetIsolate());
124
    if (first) {
125
      first = false;
126
    } else {
127
      printf(" ");
128
    }
129
    v8::String::Utf8Value str(args[i]);
130
    const char* cstr = ToCString(str);
131
    printf("%s", cstr);
132
  }
133
  printf("\n");
134
  fflush(stdout);
135
}
136

    
137

    
138
// The callback that is invoked by v8 whenever the JavaScript 'read'
139
// function is called.  This function loads the content of the file named in
140
// the argument into a JavaScript string.
141
void Read(const v8::FunctionCallbackInfo<v8::Value>& args) {
142
  if (args.Length() != 1) {
143
    args.GetIsolate()->ThrowException(
144
        v8::String::New("Bad parameters"));
145
    return;
146
  }
147
  v8::String::Utf8Value file(args[0]);
148
  if (*file == NULL) {
149
    args.GetIsolate()->ThrowException(
150
        v8::String::New("Error loading file"));
151
    return;
152
  }
153
  v8::Handle<v8::String> source = ReadFile(*file);
154
  if (source.IsEmpty()) {
155
    args.GetIsolate()->ThrowException(
156
        v8::String::New("Error loading file"));
157
    return;
158
  }
159
  args.GetReturnValue().Set(source);
160
}
161

    
162

    
163
// The callback that is invoked by v8 whenever the JavaScript 'load'
164
// function is called.  Loads, compiles and executes its argument
165
// JavaScript file.
166
void Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
167
  for (int i = 0; i < args.Length(); i++) {
168
    v8::HandleScope handle_scope(args.GetIsolate());
169
    v8::String::Utf8Value file(args[i]);
170
    if (*file == NULL) {
171
      args.GetIsolate()->ThrowException(
172
          v8::String::New("Error loading file"));
173
      return;
174
    }
175
    v8::Handle<v8::String> source = ReadFile(*file);
176
    if (source.IsEmpty()) {
177
      args.GetIsolate()->ThrowException(
178
           v8::String::New("Error loading file"));
179
      return;
180
    }
181
    if (!ExecuteString(args.GetIsolate(),
182
                       source,
183
                       v8::String::New(*file),
184
                       false,
185
                       false)) {
186
      args.GetIsolate()->ThrowException(
187
          v8::String::New("Error executing file"));
188
      return;
189
    }
190
  }
191
}
192

    
193

    
194
// The callback that is invoked by v8 whenever the JavaScript 'quit'
195
// function is called.  Quits.
196
void Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
197
  // If not arguments are given args[0] will yield undefined which
198
  // converts to the integer value 0.
199
  int exit_code = args[0]->Int32Value();
200
  fflush(stdout);
201
  fflush(stderr);
202
  exit(exit_code);
203
}
204

    
205

    
206
void Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
207
  args.GetReturnValue().Set(v8::String::New(v8::V8::GetVersion()));
208
}
209

    
210

    
211
// Reads a file into a v8 string.
212
v8::Handle<v8::String> ReadFile(const char* name) {
213
  FILE* file = fopen(name, "rb");
214
  if (file == NULL) return v8::Handle<v8::String>();
215

    
216
  fseek(file, 0, SEEK_END);
217
  int size = ftell(file);
218
  rewind(file);
219

    
220
  char* chars = new char[size + 1];
221
  chars[size] = '\0';
222
  for (int i = 0; i < size;) {
223
    int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
224
    i += read;
225
  }
226
  fclose(file);
227
  v8::Handle<v8::String> result = v8::String::New(chars, size);
228
  delete[] chars;
229
  return result;
230
}
231

    
232

    
233
// Process remaining command line arguments and execute files
234
int RunMain(v8::Isolate* isolate, int argc, char* argv[]) {
235
  for (int i = 1; i < argc; i++) {
236
    const char* str = argv[i];
237
    if (strcmp(str, "--shell") == 0) {
238
      run_shell = true;
239
    } else if (strcmp(str, "-f") == 0) {
240
      // Ignore any -f flags for compatibility with the other stand-
241
      // alone JavaScript engines.
242
      continue;
243
    } else if (strncmp(str, "--", 2) == 0) {
244
      fprintf(stderr,
245
              "Warning: unknown flag %s.\nTry --help for options\n", str);
246
    } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
247
      // Execute argument given to -e option directly.
248
      v8::Handle<v8::String> file_name = v8::String::New("unnamed");
249
      v8::Handle<v8::String> source = v8::String::New(argv[++i]);
250
      if (!ExecuteString(isolate, source, file_name, false, true)) return 1;
251
    } else {
252
      // Use all other arguments as names of files to load and run.
253
      v8::Handle<v8::String> file_name = v8::String::New(str);
254
      v8::Handle<v8::String> source = ReadFile(str);
255
      if (source.IsEmpty()) {
256
        fprintf(stderr, "Error reading '%s'\n", str);
257
        continue;
258
      }
259
      if (!ExecuteString(isolate, source, file_name, false, true)) return 1;
260
    }
261
  }
262
  return 0;
263
}
264

    
265

    
266
// The read-eval-execute loop of the shell.
267
void RunShell(v8::Handle<v8::Context> context) {
268
  fprintf(stderr, "V8 version %s [sample shell]\n", v8::V8::GetVersion());
269
  static const int kBufferSize = 256;
270
  // Enter the execution environment before evaluating any code.
271
  v8::Context::Scope context_scope(context);
272
  v8::Local<v8::String> name(v8::String::New("(shell)"));
273
  while (true) {
274
    char buffer[kBufferSize];
275
    fprintf(stderr, "> ");
276
    char* str = fgets(buffer, kBufferSize, stdin);
277
    if (str == NULL) break;
278
    v8::HandleScope handle_scope(context->GetIsolate());
279
    ExecuteString(context->GetIsolate(),
280
                  v8::String::New(str),
281
                  name,
282
                  true,
283
                  true);
284
  }
285
  fprintf(stderr, "\n");
286
}
287

    
288

    
289
// Executes a string within the current v8 context.
290
bool ExecuteString(v8::Isolate* isolate,
291
                   v8::Handle<v8::String> source,
292
                   v8::Handle<v8::Value> name,
293
                   bool print_result,
294
                   bool report_exceptions) {
295
  v8::HandleScope handle_scope(isolate);
296
  v8::TryCatch try_catch;
297
  v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
298
  if (script.IsEmpty()) {
299
    // Print errors that happened during compilation.
300
    if (report_exceptions)
301
      ReportException(isolate, &try_catch);
302
    return false;
303
  } else {
304
    v8::Handle<v8::Value> result = script->Run();
305
    if (result.IsEmpty()) {
306
      assert(try_catch.HasCaught());
307
      // Print errors that happened during execution.
308
      if (report_exceptions)
309
        ReportException(isolate, &try_catch);
310
      return false;
311
    } else {
312
      assert(!try_catch.HasCaught());
313
      if (print_result && !result->IsUndefined()) {
314
        // If all went well and the result wasn't undefined then print
315
        // the returned value.
316
        v8::String::Utf8Value str(result);
317
        const char* cstr = ToCString(str);
318
        printf("%s\n", cstr);
319
      }
320
      return true;
321
    }
322
  }
323
}
324

    
325

    
326
void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
327
  v8::HandleScope handle_scope(isolate);
328
  v8::String::Utf8Value exception(try_catch->Exception());
329
  const char* exception_string = ToCString(exception);
330
  v8::Handle<v8::Message> message = try_catch->Message();
331
  if (message.IsEmpty()) {
332
    // V8 didn't provide any extra information about this error; just
333
    // print the exception.
334
    fprintf(stderr, "%s\n", exception_string);
335
  } else {
336
    // Print (filename):(line number): (message).
337
    v8::String::Utf8Value filename(message->GetScriptResourceName());
338
    const char* filename_string = ToCString(filename);
339
    int linenum = message->GetLineNumber();
340
    fprintf(stderr, "%s:%i: %s\n", filename_string, linenum, exception_string);
341
    // Print line of source code.
342
    v8::String::Utf8Value sourceline(message->GetSourceLine());
343
    const char* sourceline_string = ToCString(sourceline);
344
    fprintf(stderr, "%s\n", sourceline_string);
345
    // Print wavy underline (GetUnderline is deprecated).
346
    int start = message->GetStartColumn();
347
    for (int i = 0; i < start; i++) {
348
      fprintf(stderr, " ");
349
    }
350
    int end = message->GetEndColumn();
351
    for (int i = start; i < end; i++) {
352
      fprintf(stderr, "^");
353
    }
354
    fprintf(stderr, "\n");
355
    v8::String::Utf8Value stack_trace(try_catch->StackTrace());
356
    if (stack_trace.length() > 0) {
357
      const char* stack_trace_string = ToCString(stack_trace);
358
      fprintf(stderr, "%s\n", stack_trace_string);
359
    }
360
  }
361
}