Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
174 lines (149 sloc) 5.13 KB
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "v8/include/v8.h"
namespace {
const char kPrompt[] = "> ";
// Converts a V8 value to a C string.
const char* ToCString(const v8::String::Utf8Value& value) {
return *value ? *value : "<string conversion failed>";
}
v8::Handle<v8::Value> Version(const v8::Arguments& args) {
return v8::String::New(v8::V8::GetVersion());
}
v8::Handle<v8::Value> Quit(const v8::Arguments& args) {
int exit_code = args[0]->Int32Value();
exit(exit_code);
return v8::Undefined();
}
v8::Handle<v8::Value> Print(const v8::Arguments& args) {
for (int i = 0; i < args.Length(); ++i) {
v8::HandleScope handle_scope;
if (i != 0) printf(" ");
v8::String::Utf8Value str(args[i]);
printf("%s", ToCString(str));
}
printf("\n");
fflush(stdout);
return v8::Undefined();
}
v8::Persistent<v8::Context> CreateShellContext() {
// Create a template for the global object.
v8::Handle<v8::ObjectTemplate> global(v8::ObjectTemplate::New());
// Bind the 'version' function to the C++ Version function.
global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));
// Bind the 'quit' function to the C++ Quit function.
global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit));
// Bind the 'print' function to the C++ Print function.
global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
return v8::Context::New(NULL, global);
}
void ReportException(v8::TryCatch* try_catch) {
v8::HandleScope handle_scope;
v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = ToCString(exception);
v8::Handle<v8::Message> message = try_catch->Message();
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
printf("%s\n", exception_string);
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(message->GetScriptResourceName());
const char* filename_string = ToCString(filename);
int linenum = message->GetLineNumber();
printf("%s:%i: %s\n", filename_string, linenum, exception_string);
// Print line of source code.
v8::String::Utf8Value sourceline(message->GetSourceLine());
const char* sourceline_string = ToCString(sourceline);
printf("%s\n", sourceline_string);
// Print wavy underline (GetUnderline is deprecated).
int start = message->GetStartColumn();
for (int i = 0; i < start; i++) {
printf(" ");
}
int end = message->GetEndColumn();
for (int i = start; i < end; i++) {
printf("^");
}
printf("\n");
v8::String::Utf8Value stack_trace(try_catch->StackTrace());
if (stack_trace.length() > 0) {
const char* stack_trace_string = ToCString(stack_trace);
printf("%s\n", stack_trace_string);
}
}
}
void ExecuteString(v8::Handle<v8::String> source,
v8::Handle<v8::Value> name,
bool print_result,
bool report_exceptions) {
v8::TryCatch try_catch;
v8::Handle<v8::Script> script(v8::Script::Compile(source, name));
if (script.IsEmpty()) {
// Print errors that happened during compilation.
if (report_exceptions)
ReportException(&try_catch);
return;
} else {
v8::Handle<v8::Value> result(script->Run());
if (result.IsEmpty()) {
assert(try_catch.HasCaught());
// Print errors that happened during execution.
if (report_exceptions)
ReportException(&try_catch);
return;
} else {
assert(!try_catch.HasCaught());
if (print_result && !result->IsUndefined()) {
// If all went well and the result wasn't undefined then print the
// returned value.
v8::String::Utf8Value str(result);
fwrite(*str, sizeof(**str), str.length(), stdout);
printf("\n");
}
}
}
}
v8::Handle<v8::String> ReadFile(const char* filename) {
FILE* file = fopen(filename, "rb");
if (!file) return v8::Handle<v8::String>();
fseek(file, 0, SEEK_END);
long size = ftell(file);
rewind(file);
char* chars = new char[size + 1]; // + 1 for NULL terminator.
chars[size] = '\0';
for (long i = 0; i < size; ) {
int read = fread(&chars[i], 1, size - 1, file);
i += read;
}
fclose(file);
v8::Handle<v8::String> result(v8::String::New(chars, size));
delete[] chars;
return result;
}
} // namespace
int main(int argc, char** argv) {
v8::HandleScope outer_scope;
v8::Persistent<v8::Context> context(CreateShellContext());
if (context.IsEmpty()) {
printf("Error when creating v8 context.\n");
return 1;
}
context->Enter();
// Enter the execution environment before evaluating any code.
v8::Context::Scope context_scope(context);
v8::Local<v8::String> name(v8::String::New("(shell)"));
printf("V8 version %s [console shell]\n", v8::V8::GetVersion());
static const int kBufferSize = 256;
while (true) {
char buffer[kBufferSize];
printf("%s", kPrompt);
if (!fgets(buffer, sizeof(buffer), stdin)) break;
v8::HandleScope inner_scope;
ExecuteString(v8::String::New(buffer), name, true, true);
}
printf("\n");
context.Dispose();
return 0;
}
Something went wrong with that request. Please try again.