#include #include #include "V8Instance.hpp" #include "../APIHelper.hpp" #include "../Logger.hpp" V8Instance::V8Instance(std::string guild_id, std::shared_ptr ah, std::map *guilds, std::map *channels, std::map *users, std::map *roles) { this->guild_id = guild_id; this->ah = ah; this->guilds = guilds; this->channels = channels; this->users = users; this->roles = roles; create(); } V8Instance::~V8Instance() { clean_up(); } void V8Instance::create() { Isolate::CreateParams create_params; create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator(); isolate = Isolate::New(create_params); isolate->Enter(); Logger::write("[v8] Created isolate", Logger::LogLevel::Debug); Isolate::Scope isolate_scope(isolate); HandleScope handle_scope(isolate); // set global context Local context = create_context(); context->Enter(); Context::Scope context_scope(context); Logger::write("[v8] Created context and context scope", Logger::LogLevel::Debug); } v8::Local V8Instance::create_context() { Local global = ObjectTemplate::New(isolate); // bind print() function Local self = External::New(isolate, (void *) this); global->Set( String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print, self) ); global->SetAccessor( String::NewFromUtf8(isolate, "server", NewStringType::kNormal).ToLocalChecked(), V8Instance::js_get_server, (AccessorSetterCallback) 0, self ); global->SetAccessor( String::NewFromUtf8(isolate, "channel", NewStringType::kNormal).ToLocalChecked(), V8Instance::js_get_channel, (AccessorSetterCallback) 0, self ); global->SetAccessor( String::NewFromUtf8(isolate, "user", NewStringType::kNormal).ToLocalChecked(), V8Instance::js_get_user, (AccessorSetterCallback) 0, self ); global->SetAccessor( String::NewFromUtf8(isolate, "input", NewStringType::kNormal).ToLocalChecked(), V8Instance::js_get_input, (AccessorSetterCallback) 0, self ); Logger::write("[v8] Created global obj, linked data and functions", Logger::LogLevel::Debug); return Context::New(isolate, NULL, global); } void V8Instance::js_get_server(Local property, const PropertyCallbackInfo &info) { auto data = info.Data().As(); V8Instance *self = static_cast(data->Value()); Local obj = Object::New(info.GetIsolate()); self->add_to_obj(obj, (*self->guilds)[self->guild_id]); info.GetReturnValue().Set(obj); } void V8Instance::js_get_channel(Local property, const PropertyCallbackInfo &info) { auto data = info.Data().As(); V8Instance *self = static_cast(data->Value()); if (!self->current_channel) { Logger::write("[v8] current_channel is null pointer", Logger::LogLevel::Severe); info.GetReturnValue().SetNull(); return; } Local obj = Object::New(info.GetIsolate()); self->add_to_obj(obj, (*self->current_channel)); info.GetReturnValue().Set(obj); } void V8Instance::js_get_user(Local property, const PropertyCallbackInfo &info) { auto data = info.Data().As(); V8Instance *self = static_cast(data->Value()); if (!self->current_sender) { Logger::write("[v8] current_sender is null pointer", Logger::LogLevel::Severe); info.GetReturnValue().SetNull(); return; } Local obj = Object::New(info.GetIsolate()); self->add_to_obj(obj, (*self->current_sender)); info.GetReturnValue().Set(obj); } void V8Instance::js_get_input(Local property, const PropertyCallbackInfo &info) { auto data = info.Data().As(); V8Instance *self = static_cast(data->Value()); info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), self->current_input.c_str(), NewStringType::kNormal).ToLocalChecked()); } void V8Instance::clean_up() { Logger::write("[v8] Cleaning up", Logger::LogLevel::Debug); isolate->Exit(); isolate->Dispose(); } void V8Instance::reload() { clean_up(); create(); } void V8Instance::exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args) { HandleScope handle_scope(isolate); Local context(isolate->GetCurrentContext()); current_sender = sender; current_channel = channel; current_input = args; Logger::write("[v8] Preparing JS: " + js, Logger::LogLevel::Debug); Local source = String::NewFromUtf8(isolate, js.c_str(), NewStringType::kNormal).ToLocalChecked(); // compile Logger::write("[v8] Isolate nullptr? " + std::to_string(isolate == nullptr) + " Context empty? " + std::to_string(context.IsEmpty()), Logger::LogLevel::Debug); TryCatch compile_try_catch(isolate); Local