Advertisement
Guest User

Untitled

a guest
Dec 15th, 2019
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.90 KB | None | 0 0
  1. #ifdef _DEBUG
  2. #pragma comment(lib, "v8_monolith.lib")
  3. #pragma comment(lib, "dbghelp.lib")
  4.  
  5. #else
  6. #pragma comment(lib, "v8_monolith.release.lib")
  7. #endif
  8.  
  9. #include <Windows.h>
  10. #include <cassert>
  11. #include <libplatform/libplatform.h>
  12. #include <v8.h>
  13. #include <v8pp/class.hpp>
  14. #include <v8pp/module.hpp>
  15. #include <thread>
  16.  
  17.  
  18. v8::Global<v8::Function> function_pre_run;
  19. v8::Global<v8::Function> function_post_run;
  20.  
  21. v8::Persistent<v8::Context> context;
  22. v8::Isolate * isolate = nullptr;
  23.  
  24. const char* c_string(v8::String::Utf8Value& value) {
  25. return *value ? *value : "<string conversion failed>";
  26. }
  27.  
  28. void report_exception(v8::TryCatch * try_catch)
  29. {
  30. // Setup context...
  31. v8::Locker locker(isolate);
  32. v8::Isolate::Scope isolate_scope(isolate);
  33. v8::HandleScope handle_scope(isolate);
  34. v8::Context::Scope context_scope(context.Get(isolate));
  35.  
  36. v8::String::Utf8Value exception(isolate, try_catch->Exception());
  37. const char* exception_string = c_string(exception);
  38. v8::Local<v8::Message> message = try_catch->Message();
  39.  
  40. if (message.IsEmpty()) {
  41. // V8 didn't provide any extra information about this error; just
  42. // print the exception.
  43. fprintf(stderr, "%s\n", exception_string);
  44. }
  45. else {
  46. // Print (filename):(line number): (message).
  47.  
  48. v8::Local<v8::Context> context(isolate->GetCurrentContext());
  49.  
  50. int linenum = message->GetLineNumber(context).FromJust();
  51.  
  52. fprintf(stderr, "%i: %s\n", linenum, exception_string);
  53. // Print line of source code.
  54. v8::String::Utf8Value sourceline(
  55. isolate, message->GetSourceLine(context).ToLocalChecked());
  56. const char* sourceline_string = c_string(sourceline);
  57. fprintf(stderr, "%s\n", sourceline_string);
  58. // Print wavy underline (GetUnderline is deprecated).
  59. int start = message->GetStartColumn(context).FromJust();
  60. for (int i = 0; i < start; i++) {
  61. fprintf(stderr, " ");
  62. }
  63. int end = message->GetEndColumn(context).FromJust();
  64. for (int i = start; i < end; i++) {
  65. fprintf(stderr, "^");
  66. }
  67. fprintf(stderr, "\n");
  68. v8::Local<v8::Value> stack_trace_string;
  69. if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
  70. stack_trace_string->IsString() &&
  71. v8::Local<v8::String>::Cast(stack_trace_string)->Length() > 0) {
  72. v8::String::Utf8Value stack_trace(isolate, stack_trace_string);
  73. const char* stack_trace_string = c_string(stack_trace);
  74. fprintf(stderr, "%s\n", stack_trace_string);
  75. }
  76. }
  77. }
  78.  
  79.  
  80. // Executes a string within the current v8 context.
  81. bool execute_string(char * str, bool print_result, bool report_exceptions)
  82. {
  83. // Setup context...
  84. v8::Locker locker(isolate);
  85. v8::Isolate::Scope isolate_scope(isolate);
  86. v8::HandleScope handle_scope(isolate);
  87. v8::Context::Scope context_scope(context.Get(isolate));
  88.  
  89. // Enter the execution environment before evaluating any code.
  90. v8::Local<v8::String> name(v8::String::NewFromUtf8(isolate, "(shell)", v8::NewStringType::kNormal).ToLocalChecked());
  91.  
  92. // Setup other related...
  93. v8::TryCatch try_catch(isolate);
  94. v8::ScriptOrigin origin(name);
  95. v8::Local<v8::Context> context(isolate->GetCurrentContext());
  96. v8::Local<v8::Script> script;
  97.  
  98. // Setup our source...
  99. auto source = v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal).ToLocalChecked();
  100.  
  101. // Empty out our function...
  102. function_pre_run.Empty();
  103. function_post_run.Empty();
  104.  
  105. if (!v8::Script::Compile(context, source, &origin).ToLocal(&script))
  106. {
  107. // Print errors that happened during compilation.
  108. if (report_exceptions) report_exception(&try_catch);
  109.  
  110. // Return false here...
  111. return false;
  112. }
  113.  
  114. //////////////////////////////////////////////////
  115.  
  116. v8::Local<v8::Value> result;
  117.  
  118. if (!script->Run(context).ToLocal(&result))
  119. {
  120. assert(try_catch.HasCaught());
  121.  
  122. // Print errors that happened during execution.
  123. if (report_exceptions) report_exception(&try_catch);
  124.  
  125. return false;
  126. }
  127.  
  128. //////////////////////////////////////////////////
  129.  
  130. assert(!try_catch.HasCaught());
  131. if (print_result && !result->IsUndefined()) {
  132. // If all went well and the result wasn't undefined then print
  133. // the returned value.
  134. v8::String::Utf8Value str(isolate, result);
  135. const char* cstr = c_string(str);
  136.  
  137. printf("%s\n", cstr);
  138. }
  139.  
  140. return true;
  141. }
  142.  
  143. void print(const v8::FunctionCallbackInfo<v8::Value>& args)
  144. {
  145. // Setup context...
  146. v8::Locker locker(isolate);
  147. v8::Isolate::Scope isolate_scope(isolate);
  148. v8::HandleScope handle_scope(isolate);
  149. v8::Context::Scope context_scope(context.Get(isolate));
  150.  
  151. bool first = true;
  152. for (int i = 0; i < args.Length(); i++)
  153. {
  154. v8::HandleScope handle_scope(isolate);
  155. if (first) {
  156. first = false;
  157. }
  158. else {
  159. fprintf(stderr, " ");
  160. }
  161. v8::String::Utf8Value str(isolate, args[i]);
  162. const char* cstr = c_string(str);
  163. fprintf(stderr, "%s", cstr);
  164. }
  165. fprintf(stderr, "\n");
  166. fflush(stdout);
  167. }
  168.  
  169. void register_pre_run(const v8::FunctionCallbackInfo<v8::Value>& args)
  170. {
  171. v8::Locker locker(isolate);
  172. v8::Isolate::Scope isolate_scope(isolate);
  173. v8::HandleScope handle_scope(isolate);
  174. v8::Context::Scope context_scope(context.Get(isolate));
  175.  
  176. // Check if args given...
  177. if (args.Length() < 1) return;
  178.  
  179. // Get our arguments...
  180. v8::Local<v8::Value> arg = args[0];
  181.  
  182. // Check if arg is a function...
  183. if (!arg->IsFunction())
  184. {
  185. return;
  186. }
  187.  
  188. // Reset our global function...
  189. function_pre_run.Reset(isolate, v8::Local<v8::Function>::Cast(arg));
  190. }
  191.  
  192. void register_post_run(const v8::FunctionCallbackInfo<v8::Value>& args)
  193. {
  194. v8::Locker locker(isolate);
  195. v8::Isolate::Scope isolate_scope(isolate);
  196. v8::HandleScope handle_scope(isolate);
  197. v8::Context::Scope context_scope(context.Get(isolate));
  198.  
  199. // Check if args given...
  200. if (args.Length() < 1) return;
  201.  
  202. // Get our arguments...
  203. v8::Local<v8::Value> arg = args[0];
  204.  
  205. // Check if arg is a function...
  206. if (!arg->IsFunction())
  207. {
  208. return;
  209. }
  210.  
  211. // Reset our global function...
  212. function_post_run.Reset(isolate, v8::Local<v8::Function>::Cast(arg));
  213. }
  214.  
  215. void read_file(const char* name)
  216. {
  217. v8::Locker locker(isolate);
  218. v8::Isolate::Scope isolate_scope(isolate);
  219. v8::HandleScope handle_scope(isolate);
  220. v8::Context::Scope context_scope(context.Get(isolate));
  221.  
  222. FILE* file = fopen(name, "rb");
  223. if (file == NULL) return;
  224.  
  225. fseek(file, 0, SEEK_END);
  226. size_t size = ftell(file);
  227. rewind(file);
  228.  
  229. char* chars = new char[size + 1];
  230. chars[size] = '\0';
  231. for (size_t i = 0; i < size;) {
  232. i += fread(&chars[i], 1, size - i, file);
  233. if (ferror(file)) {
  234. fclose(file);
  235. return;
  236. }
  237. }
  238. fclose(file);
  239.  
  240. if (!execute_string(chars, true, true)) {
  241. isolate->ThrowException(
  242. v8::String::NewFromUtf8(isolate, "Error executing file",
  243. v8::NewStringType::kNormal).ToLocalChecked());
  244.  
  245. }
  246. delete[] chars;
  247.  
  248. fprintf(stderr, "Loaded %s successfully...\n", name);
  249. fflush(stdout);
  250. }
  251.  
  252. void load(const v8::FunctionCallbackInfo<v8::Value>& args) {
  253. v8::HandleScope handle_scope(isolate);
  254.  
  255. for (int i = 0; i < args.Length(); i++)
  256. {
  257. v8::HandleScope handle_scope(isolate);
  258. v8::String::Utf8Value file(isolate, args[i]);
  259. if (*file == NULL) {
  260. isolate->ThrowException(
  261. v8::String::NewFromUtf8(isolate, "Error loading file",
  262. v8::NewStringType::kNormal).ToLocalChecked());
  263. return;
  264. }
  265.  
  266. read_file(*file);
  267. }
  268. }
  269.  
  270. v8::Local<v8::Context> create_shell_context()
  271. {
  272. // Setup isolate locker...
  273. v8::Locker locker(isolate);
  274. v8::Isolate::Scope isolate_scope(isolate);
  275.  
  276. // Create a template for the global object.
  277. v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
  278.  
  279. // Bind the global 'print' function to the C++ Print callback.
  280. global->Set(v8::String::NewFromUtf8(isolate, "print").ToLocalChecked(), v8::FunctionTemplate::New(isolate, print));
  281.  
  282. // Bind the global 'load' function to the C++ Load callback.
  283. global->Set(v8::String::NewFromUtf8(isolate, "load").ToLocalChecked(), v8::FunctionTemplate::New(isolate, load));
  284.  
  285. ////////////////////////////////
  286.  
  287. // Bind the 'registerDraw' function
  288. global->Set(v8::String::NewFromUtf8(isolate, "registerPreRun").ToLocalChecked(),
  289. v8::FunctionTemplate::New(isolate, register_pre_run));
  290.  
  291. // Bind the 'registerCreateMove' function
  292. global->Set(v8::String::NewFromUtf8(isolate, "registerPostRun").ToLocalChecked(),
  293. v8::FunctionTemplate::New(isolate, register_post_run));
  294.  
  295. return v8::Context::New(isolate, NULL, global);
  296. }
  297.  
  298. void run_shell()
  299. {
  300. // Buffer size...
  301. static const int kBufferSize = 256;
  302.  
  303. // While true loop...
  304. while (true)
  305. {
  306. char buffer[kBufferSize];
  307. fprintf(stderr, "> ");
  308. char* str = fgets(buffer, kBufferSize, stdin);
  309. if (str == NULL) break;
  310.  
  311. //////////////////////////////////////////////
  312.  
  313. // Execute string...
  314. execute_string(str, true, true);
  315. }
  316.  
  317. // Print a newline...
  318. fprintf(stderr, "\n");
  319. }
  320.  
  321.  
  322. struct RequestManaged
  323. {
  324. const char* uri;
  325. const char* ip;
  326. };
  327.  
  328. extern "C"
  329. {
  330. __declspec(dllimport) void call_pre_run(const char * serialized_request);
  331. __declspec(dllimport) void start_engine();
  332. }
  333.  
  334.  
  335. void call_pre_run(const char * serialized_request)
  336. {
  337. // Check that isolate and the callback function is set...
  338. if (isolate && !function_pre_run.IsEmpty())
  339. {
  340. // Setup our lockers, isolate scope, and handle scope...
  341. v8::Locker locker(isolate);
  342. v8::Isolate::Scope isolate_scope(isolate);
  343. v8::HandleScope handle_scope(isolate);
  344. v8::Context::Scope context_scope(context.Get(isolate));
  345.  
  346. // Parse our JSON string...
  347. auto request_object = v8::JSON::Parse(
  348. isolate->GetCurrentContext(),
  349. v8pp::to_v8(isolate, serialized_request, strlen(serialized_request))
  350. ).ToLocalChecked();
  351.  
  352. // Setup our arguments...
  353. v8::Local<v8::Value> argv[1] = { request_object };
  354.  
  355. ////////////////////////////////////////////////////
  356.  
  357. // Local function...
  358. auto local_func = function_pre_run.Get(isolate);
  359.  
  360. // Attempt to get our registered create move callback and call it...
  361. if (local_func->IsCallable())
  362. local_func->Call(isolate->GetCurrentContext(), v8::Null(isolate), 1, argv);
  363. }
  364. }
  365.  
  366. void start_engine()
  367. {
  368. std::thread engine([] {
  369. // Initialize...
  370. std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
  371.  
  372. v8::V8::InitializePlatform(platform.get());
  373. v8::V8::InitializeICU();
  374. v8::V8::Initialize();
  375.  
  376. // Setup create params...
  377. v8::Isolate::CreateParams create_params;
  378.  
  379. create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
  380.  
  381. // Setup our isolate...
  382. isolate = v8::Isolate::New(create_params);
  383.  
  384. {
  385. // Setup lockers...
  386. v8::Locker locker(isolate);
  387. v8::Isolate::Scope isolate_scope(isolate);
  388. v8::HandleScope handle_scope(isolate);
  389.  
  390. // Setup our context...
  391. context.Reset(isolate, create_shell_context());
  392. }
  393.  
  394. // Run our shell...
  395. run_shell();
  396.  
  397. // Dispose our isolate...
  398. isolate->Dispose();
  399.  
  400. // Dispose everything...
  401. v8::V8::Dispose();
  402. v8::V8::ShutdownPlatform();
  403.  
  404. // Delete...
  405. delete create_params.array_buffer_allocator;
  406. });
  407. engine.detach();
  408. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement