diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2018-08-22 11:40:40 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2018-08-22 13:44:37 +0100 |
commit | b4673e15b303e011d8d61e595f3f26abaeb1b7bb (patch) | |
tree | c03388cee9eb62ee8b4f58ca5faf50a94d430845 | |
parent | 0b9ce172a7cb8c076893de66b23a83066ff98102 (diff) |
igt/shell: Move the shell globals into the igt.toy namespace
-rw-r--r-- | shell/igt-shell.cc | 92 | ||||
-rw-r--r-- | shell/lib/igt-toy.cc | 201 | ||||
-rw-r--r-- | shell/meson.build | 1 | ||||
-rw-r--r-- | shell/samples/print.js | 4 |
4 files changed, 210 insertions, 88 deletions
diff --git a/shell/igt-shell.cc b/shell/igt-shell.cc index 5ebb30bc..0e542e4e 100644 --- a/shell/igt-shell.cc +++ b/shell/igt-shell.cc @@ -95,19 +95,6 @@ static bool ExecuteString(Isolate* iso, Local<String> source, return true; } -static void Print(const FunctionCallbackInfo<Value>& args) -{ - auto iso = args.GetIsolate(); - HandleScope handle_scope(iso); - - for (int i = 0; i < args.Length(); i++) { - String::Utf8Value str(iso, args[i]); - printf("%s%s", i ? " " : "", ToCString(str)); - } - printf("\n"); - fflush(stdout); -} - static MaybeLocal<String> ReadStream(Isolate* iso, std::istream &in) { std::stringstream out; @@ -117,8 +104,7 @@ static MaybeLocal<String> ReadStream(Isolate* iso, std::istream &in) str.length()); } - -MaybeLocal<String> ReadFile(Isolate* iso, const char* filename) +static MaybeLocal<String> ReadFile(Isolate* iso, const char* filename) { std::ifstream stream(filename); if (!stream) @@ -127,64 +113,6 @@ MaybeLocal<String> ReadFile(Isolate* iso, const char* filename) return ReadStream(iso, stream); } -static void Read(const FunctionCallbackInfo<Value>& args) -{ - auto iso = args.GetIsolate(); - - if (args.Length() != 1) { - iso->ThrowException(AsString(iso, "Bad parameters").ToLocalChecked()); - return; - } - - String::Utf8Value filename(iso, args[0]); - if (*filename == NULL) { - iso->ThrowException(AsString(iso, "Bad parameters").ToLocalChecked()); - return; - } - - Local<String> source; - if (!ReadFile(iso, *filename).ToLocal(&source)) { - iso->ThrowException(AsString(iso, "Error reading file").ToLocalChecked()); - return; - } - - args.GetReturnValue().Set(source); -} - -static void Load(const FunctionCallbackInfo<Value>& args) -{ - auto iso = args.GetIsolate(); - - for (int i = 0; i < args.Length(); i++) { - HandleScope handle_scope(iso); - String::Utf8Value filename(iso, args[i]); - if (*filename == NULL) { - iso->ThrowException(AsString(iso, "Bad parameters").ToLocalChecked()); - return; - } - - Local<String> source; - if (!ReadFile(iso, *filename).ToLocal(&source)) { - iso->ThrowException(AsString(iso, "Error loading file").ToLocalChecked()); - return; - } - - if (!ExecuteString(iso, source, args[i], false, false)) { - iso->ThrowException(AsString(iso, "Error executing file").ToLocalChecked()); - return; - } - } -} - -static void Quit(const FunctionCallbackInfo<Value>& args) -{ - int exit_code = - args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromMaybe(0); - fflush(stdout); - fflush(stderr); - exit(exit_code); -} - static struct igt_builtin *globals; void igt_register_global(struct igt_builtin *b) @@ -193,23 +121,10 @@ void igt_register_global(struct igt_builtin *b) globals = b; } -static void shell_template(Isolate *iso, Local<ObjectTemplate> global) -{ - static const v8_helper_fn funcs[] = { - { "print", Print }, - { "read", Read }, - { "load", Load }, - { "quit", Quit }, - { }, - }; - v8_helper_funcs(iso, global, funcs); -} - static Local<Context> ShellContext(Isolate* iso) { Local<ObjectTemplate> global = ObjectTemplate::New(iso); - shell_template(iso, global); /* XXX defer to shell */ for (auto *b = globals; b; b = b->next) b->ctor(iso, global); @@ -276,6 +191,11 @@ static int shell(Isolate *iso, Platform *p, int argc, char **argv) HandleScope outer(iso); Local<String> name(AsString(iso, "(shell)").ToLocalChecked()); + /* Make our toy implemenation (i.e. print) global for user convenience */ + ExecuteString(iso, + AsString(iso, "Object.assign(this, igt.toy)").ToLocalChecked(), + name, false, false); + while (true) { char buf[256]; diff --git a/shell/lib/igt-toy.cc b/shell/lib/igt-toy.cc new file mode 100644 index 00000000..dcbb228f --- /dev/null +++ b/shell/lib/igt-toy.cc @@ -0,0 +1,201 @@ +#include <iostream> +#include <fstream> +#include <sstream> + +#include "igt-shell.h" +#include "v8-helpers.h" + +using namespace v8; + +static const char* ToCString(const String::Utf8Value& value) { + return *value ? *value : "<invalid string>"; +} + +static void ReportException(Isolate* iso, TryCatch* try_catch) +{ + HandleScope handle_scope(iso); + String::Utf8Value exception(iso, try_catch->Exception()); + const char* exception_string = ToCString(exception); + + Local<Message> message = try_catch->Message(); + if (message.IsEmpty()) { + fprintf(stderr, "%s\n", exception_string); + } else { + String::Utf8Value filename(iso, + message->GetScriptOrigin().ResourceName()); + Local<Context> ctx(iso->GetCurrentContext()); + fprintf(stderr, "%s:%i: %s\n", + ToCString(filename), + message->GetLineNumber(ctx).FromJust(), + exception_string); + + String::Utf8Value sourceline(iso, + message->GetSourceLine(ctx).ToLocalChecked()); + fprintf(stderr, "%s\n", ToCString(sourceline)); + + int start = message->GetStartColumn(ctx).FromJust(); + for (int i = 0; i < start; i++) + fprintf(stderr, " "); + int end = message->GetEndColumn(ctx).FromJust(); + for (int i = start; i < end; i++) + fprintf(stderr, "^"); + fprintf(stderr, "\n"); + + Local<Value> stack_trace_string; + if (try_catch->StackTrace(ctx).ToLocal(&stack_trace_string) && + stack_trace_string->IsString() && + Local<String>::Cast(stack_trace_string)->Length() > 0) { + String::Utf8Value stack_trace(iso, stack_trace_string); + fprintf(stderr, "%s\n", ToCString(stack_trace)); + } + } +} + +static bool ExecuteString(Isolate* iso, Local<String> source, + Local<Value> name, bool print_result, + bool report_exceptions) +{ + HandleScope handle_scope(iso); + TryCatch try_catch(iso); + + ScriptOrigin origin(name); + Local<Context> ctx(iso->GetCurrentContext()); + Local<Script> script; + if (!Script::Compile(ctx, source, &origin).ToLocal(&script)) { + if (report_exceptions) + ReportException(iso, &try_catch); + return false; + } + + Local<Value> result; + if (!script->Run(ctx).ToLocal(&result)) { + if (report_exceptions) + ReportException(iso, &try_catch); + return false; + } + + if (print_result && !result->IsUndefined()) { + String::Utf8Value str(iso, result); + printf("%s\n", ToCString(str)); + } + + return true; +} + +static void Print(const FunctionCallbackInfo<Value>& args) +{ + auto iso = args.GetIsolate(); + HandleScope handle_scope(iso); + + for (int i = 0; i < args.Length(); i++) { + String::Utf8Value str(iso, args[i]); + printf("%s%s", i ? " " : "", ToCString(str)); + } + printf("\n"); + fflush(stdout); +} + +static MaybeLocal<String> ReadStream(Isolate* iso, std::istream &in) +{ + std::stringstream out; + out << in.rdbuf(); + std::string str = out.str(); + return String::NewFromUtf8(iso, str.c_str(), NewStringType::kNormal, + str.length()); +} + +static MaybeLocal<String> ReadFile(Isolate* iso, const char* filename) +{ + std::ifstream stream(filename); + if (!stream) + iso->ThrowException(AsString(iso, "Error opening file").ToLocalChecked()); + + return ReadStream(iso, stream); +} + +static void Read(const FunctionCallbackInfo<Value>& args) +{ + auto iso = args.GetIsolate(); + + if (args.Length() != 1) { + iso->ThrowException(AsString(iso, "Bad parameters").ToLocalChecked()); + return; + } + + String::Utf8Value filename(iso, args[0]); + if (*filename == NULL) { + iso->ThrowException(AsString(iso, "Bad parameters").ToLocalChecked()); + return; + } + + Local<String> source; + if (!ReadFile(iso, *filename).ToLocal(&source)) { + iso->ThrowException(AsString(iso, "Error reading file").ToLocalChecked()); + return; + } + + args.GetReturnValue().Set(source); +} + +static void Load(const FunctionCallbackInfo<Value>& args) +{ + auto iso = args.GetIsolate(); + + for (int i = 0; i < args.Length(); i++) { + HandleScope handle_scope(iso); + String::Utf8Value filename(iso, args[i]); + if (*filename == NULL) { + iso->ThrowException(AsString(iso, "Bad parameters").ToLocalChecked()); + return; + } + + Local<String> source; + if (!ReadFile(iso, *filename).ToLocal(&source)) { + iso->ThrowException(AsString(iso, "Error loading file").ToLocalChecked()); + return; + } + + if (!ExecuteString(iso, source, args[i], false, false)) { + iso->ThrowException(AsString(iso, "Error executing file").ToLocalChecked()); + return; + } + } +} + +static void Quit(const FunctionCallbackInfo<Value>& args) +{ + int exit_code = + args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromMaybe(0); + fflush(stdout); + fflush(stderr); + exit(exit_code); +} + +static void igt_toy_ctor(Isolate *iso, Local<ObjectTemplate> igt) +{ + HandleScope handle_scope(iso); + + auto tmpl = ObjectTemplate::New(iso); + + static const v8_helper_fn funcs[] = { + { "print", Print }, + { "read", Read }, + { "load", Load }, + { "quit", Quit }, + { }, + }; + v8_helper_funcs(iso, tmpl, funcs); + + igt->Set(iso, "toy", tmpl); +} + +static struct igt_builtin igt_toy = { + .name = "toy", + .ctor = igt_toy_ctor +}; + +__attribute__((constructor)) +void __igt_register_toy__(void) +{ + igt_register_builtin(&igt_toy); +} diff --git a/shell/meson.build b/shell/meson.build index ff4d870f..9868549e 100644 --- a/shell/meson.build +++ b/shell/meson.build @@ -1,6 +1,7 @@ executable('igt', [ 'igt-shell.cc', 'lib/igt.cc', + 'lib/igt-toy.cc', 'lib/v8-helpers.cc', ], objects: 'v8/libv8_monolith.a', diff --git a/shell/samples/print.js b/shell/samples/print.js index fa0f0bf4..dee56dda 100644 --- a/shell/samples/print.js +++ b/shell/samples/print.js @@ -1,2 +1,2 @@ -print('Hello World!'); -print('Hello', 'World!'); +igt.toy.print('Hello World!'); +igt.toy.print('Hello', 'World!'); |