summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-08-22 11:40:40 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2018-08-22 13:44:37 +0100
commitb4673e15b303e011d8d61e595f3f26abaeb1b7bb (patch)
treec03388cee9eb62ee8b4f58ca5faf50a94d430845
parent0b9ce172a7cb8c076893de66b23a83066ff98102 (diff)
igt/shell: Move the shell globals into the igt.toy namespace
-rw-r--r--shell/igt-shell.cc92
-rw-r--r--shell/lib/igt-toy.cc201
-rw-r--r--shell/meson.build1
-rw-r--r--shell/samples/print.js4
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!');