Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifdef _DEBUG
- #pragma comment(lib, "v8_monolith.lib")
- #pragma comment(lib, "dbghelp.lib")
- #else
- #pragma comment(lib, "v8_monolith.release.lib")
- #endif
- #include <Windows.h>
- #include <cassert>
- #include <libplatform/libplatform.h>
- #include <v8.h>
- #include <v8pp/class.hpp>
- #include <v8pp/module.hpp>
- #include <thread>
- v8::Global<v8::Function> function_pre_run;
- v8::Global<v8::Function> function_post_run;
- v8::Persistent<v8::Context> context;
- v8::Isolate * isolate = nullptr;
- const char* c_string(v8::String::Utf8Value& value) {
- return *value ? *value : "<string conversion failed>";
- }
- void report_exception(v8::TryCatch * try_catch)
- {
- // Setup context...
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::Scope context_scope(context.Get(isolate));
- v8::String::Utf8Value exception(isolate, try_catch->Exception());
- const char* exception_string = c_string(exception);
- v8::Local<v8::Message> message = try_catch->Message();
- if (message.IsEmpty()) {
- // V8 didn't provide any extra information about this error; just
- // print the exception.
- fprintf(stderr, "%s\n", exception_string);
- }
- else {
- // Print (filename):(line number): (message).
- v8::Local<v8::Context> context(isolate->GetCurrentContext());
- int linenum = message->GetLineNumber(context).FromJust();
- fprintf(stderr, "%i: %s\n", linenum, exception_string);
- // Print line of source code.
- v8::String::Utf8Value sourceline(
- isolate, message->GetSourceLine(context).ToLocalChecked());
- const char* sourceline_string = c_string(sourceline);
- fprintf(stderr, "%s\n", sourceline_string);
- // Print wavy underline (GetUnderline is deprecated).
- int start = message->GetStartColumn(context).FromJust();
- for (int i = 0; i < start; i++) {
- fprintf(stderr, " ");
- }
- int end = message->GetEndColumn(context).FromJust();
- for (int i = start; i < end; i++) {
- fprintf(stderr, "^");
- }
- fprintf(stderr, "\n");
- v8::Local<v8::Value> stack_trace_string;
- if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
- stack_trace_string->IsString() &&
- v8::Local<v8::String>::Cast(stack_trace_string)->Length() > 0) {
- v8::String::Utf8Value stack_trace(isolate, stack_trace_string);
- const char* stack_trace_string = c_string(stack_trace);
- fprintf(stderr, "%s\n", stack_trace_string);
- }
- }
- }
- // Executes a string within the current v8 context.
- bool execute_string(char * str, bool print_result, bool report_exceptions)
- {
- // Setup context...
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::Scope context_scope(context.Get(isolate));
- // Enter the execution environment before evaluating any code.
- v8::Local<v8::String> name(v8::String::NewFromUtf8(isolate, "(shell)", v8::NewStringType::kNormal).ToLocalChecked());
- // Setup other related...
- v8::TryCatch try_catch(isolate);
- v8::ScriptOrigin origin(name);
- v8::Local<v8::Context> context(isolate->GetCurrentContext());
- v8::Local<v8::Script> script;
- // Setup our source...
- auto source = v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal).ToLocalChecked();
- // Empty out our function...
- function_pre_run.Empty();
- function_post_run.Empty();
- if (!v8::Script::Compile(context, source, &origin).ToLocal(&script))
- {
- // Print errors that happened during compilation.
- if (report_exceptions) report_exception(&try_catch);
- // Return false here...
- return false;
- }
- //////////////////////////////////////////////////
- v8::Local<v8::Value> result;
- if (!script->Run(context).ToLocal(&result))
- {
- assert(try_catch.HasCaught());
- // Print errors that happened during execution.
- if (report_exceptions) report_exception(&try_catch);
- return false;
- }
- //////////////////////////////////////////////////
- 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(isolate, result);
- const char* cstr = c_string(str);
- printf("%s\n", cstr);
- }
- return true;
- }
- void print(const v8::FunctionCallbackInfo<v8::Value>& args)
- {
- // Setup context...
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::Scope context_scope(context.Get(isolate));
- bool first = true;
- for (int i = 0; i < args.Length(); i++)
- {
- v8::HandleScope handle_scope(isolate);
- if (first) {
- first = false;
- }
- else {
- fprintf(stderr, " ");
- }
- v8::String::Utf8Value str(isolate, args[i]);
- const char* cstr = c_string(str);
- fprintf(stderr, "%s", cstr);
- }
- fprintf(stderr, "\n");
- fflush(stdout);
- }
- void register_pre_run(const v8::FunctionCallbackInfo<v8::Value>& args)
- {
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::Scope context_scope(context.Get(isolate));
- // Check if args given...
- if (args.Length() < 1) return;
- // Get our arguments...
- v8::Local<v8::Value> arg = args[0];
- // Check if arg is a function...
- if (!arg->IsFunction())
- {
- return;
- }
- // Reset our global function...
- function_pre_run.Reset(isolate, v8::Local<v8::Function>::Cast(arg));
- }
- void register_post_run(const v8::FunctionCallbackInfo<v8::Value>& args)
- {
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::Scope context_scope(context.Get(isolate));
- // Check if args given...
- if (args.Length() < 1) return;
- // Get our arguments...
- v8::Local<v8::Value> arg = args[0];
- // Check if arg is a function...
- if (!arg->IsFunction())
- {
- return;
- }
- // Reset our global function...
- function_post_run.Reset(isolate, v8::Local<v8::Function>::Cast(arg));
- }
- void read_file(const char* name)
- {
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::Scope context_scope(context.Get(isolate));
- FILE* file = fopen(name, "rb");
- if (file == NULL) return;
- fseek(file, 0, SEEK_END);
- size_t size = ftell(file);
- rewind(file);
- char* chars = new char[size + 1];
- chars[size] = '\0';
- for (size_t i = 0; i < size;) {
- i += fread(&chars[i], 1, size - i, file);
- if (ferror(file)) {
- fclose(file);
- return;
- }
- }
- fclose(file);
- if (!execute_string(chars, true, true)) {
- isolate->ThrowException(
- v8::String::NewFromUtf8(isolate, "Error executing file",
- v8::NewStringType::kNormal).ToLocalChecked());
- }
- delete[] chars;
- fprintf(stderr, "Loaded %s successfully...\n", name);
- fflush(stdout);
- }
- void load(const v8::FunctionCallbackInfo<v8::Value>& args) {
- v8::HandleScope handle_scope(isolate);
- for (int i = 0; i < args.Length(); i++)
- {
- v8::HandleScope handle_scope(isolate);
- v8::String::Utf8Value file(isolate, args[i]);
- if (*file == NULL) {
- isolate->ThrowException(
- v8::String::NewFromUtf8(isolate, "Error loading file",
- v8::NewStringType::kNormal).ToLocalChecked());
- return;
- }
- read_file(*file);
- }
- }
- v8::Local<v8::Context> create_shell_context()
- {
- // Setup isolate locker...
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- // Create a template for the global object.
- v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
- // Bind the global 'print' function to the C++ Print callback.
- global->Set(v8::String::NewFromUtf8(isolate, "print").ToLocalChecked(), v8::FunctionTemplate::New(isolate, print));
- // Bind the global 'load' function to the C++ Load callback.
- global->Set(v8::String::NewFromUtf8(isolate, "load").ToLocalChecked(), v8::FunctionTemplate::New(isolate, load));
- ////////////////////////////////
- // Bind the 'registerDraw' function
- global->Set(v8::String::NewFromUtf8(isolate, "registerPreRun").ToLocalChecked(),
- v8::FunctionTemplate::New(isolate, register_pre_run));
- // Bind the 'registerCreateMove' function
- global->Set(v8::String::NewFromUtf8(isolate, "registerPostRun").ToLocalChecked(),
- v8::FunctionTemplate::New(isolate, register_post_run));
- return v8::Context::New(isolate, NULL, global);
- }
- void run_shell()
- {
- // Buffer size...
- static const int kBufferSize = 256;
- // While true loop...
- while (true)
- {
- char buffer[kBufferSize];
- fprintf(stderr, "> ");
- char* str = fgets(buffer, kBufferSize, stdin);
- if (str == NULL) break;
- //////////////////////////////////////////////
- // Execute string...
- execute_string(str, true, true);
- }
- // Print a newline...
- fprintf(stderr, "\n");
- }
- struct RequestManaged
- {
- const char* uri;
- const char* ip;
- };
- extern "C"
- {
- __declspec(dllimport) void call_pre_run(const char * serialized_request);
- __declspec(dllimport) void start_engine();
- }
- void call_pre_run(const char * serialized_request)
- {
- // Check that isolate and the callback function is set...
- if (isolate && !function_pre_run.IsEmpty())
- {
- // Setup our lockers, isolate scope, and handle scope...
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::Scope context_scope(context.Get(isolate));
- // Parse our JSON string...
- auto request_object = v8::JSON::Parse(
- isolate->GetCurrentContext(),
- v8pp::to_v8(isolate, serialized_request, strlen(serialized_request))
- ).ToLocalChecked();
- // Setup our arguments...
- v8::Local<v8::Value> argv[1] = { request_object };
- ////////////////////////////////////////////////////
- // Local function...
- auto local_func = function_pre_run.Get(isolate);
- // Attempt to get our registered create move callback and call it...
- if (local_func->IsCallable())
- local_func->Call(isolate->GetCurrentContext(), v8::Null(isolate), 1, argv);
- }
- }
- void start_engine()
- {
- std::thread engine([] {
- // Initialize...
- std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
- v8::V8::InitializePlatform(platform.get());
- v8::V8::InitializeICU();
- v8::V8::Initialize();
- // Setup create params...
- v8::Isolate::CreateParams create_params;
- create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
- // Setup our isolate...
- isolate = v8::Isolate::New(create_params);
- {
- // Setup lockers...
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- // Setup our context...
- context.Reset(isolate, create_shell_context());
- }
- // Run our shell...
- run_shell();
- // Dispose our isolate...
- isolate->Dispose();
- // Dispose everything...
- v8::V8::Dispose();
- v8::V8::ShutdownPlatform();
- // Delete...
- delete create_params.array_buffer_allocator;
- });
- engine.detach();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement