From 02194053f43e79cb7741012f21c53384e5b82fec Mon Sep 17 00:00:00 2001 From: xshady Date: Mon, 24 Jun 2024 03:16:40 +0300 Subject: [PATCH] chore: revert V8Helpers.cpp --- shared/V8Helpers.cpp | 830 +++++++++++++++++++++---------------------- 1 file changed, 415 insertions(+), 415 deletions(-) diff --git a/shared/V8Helpers.cpp b/shared/V8Helpers.cpp index ccc38049..4cfca3a4 100644 --- a/shared/V8Helpers.cpp +++ b/shared/V8Helpers.cpp @@ -1,416 +1,416 @@ - -#include "cpp-sdk/ICore.h" -#include "V8ResourceImpl.h" -#include "V8Helpers.h" -#ifdef ALT_CLIENT - #include "CV8Resource.h" -#endif - -#include -#include -#include -#include - -bool V8Helpers::TryCatch(const std::function& fn) -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Local context = isolate->GetEnteredOrMicrotaskContext(); - v8::TryCatch tryCatch(isolate); - - V8ResourceImpl* v8resource = V8ResourceImpl::Get(context); - alt::IResource* resource = v8resource->GetResource(); - - if(!fn()) - { - v8::Local exception = tryCatch.Exception(); - v8::Local message = tryCatch.Message(); - - if(!message.IsEmpty() && !context.IsEmpty()) - { - v8::MaybeLocal maybeSourceLine = message->GetSourceLine(context); - v8::Maybe line = message->GetLineNumber(context); - v8::ScriptOrigin origin = message->GetScriptOrigin(); - std::string name = *v8::String::Utf8Value(isolate, origin.ResourceName()); - - // Only relevant for client - bool isBytecodeFile = false; -#ifdef ALT_CLIENT - isBytecodeFile = static_cast(v8resource)->GetModuleData(name).isBytecode; -#endif - - if(!origin.ResourceName()->IsUndefined()) - { - if(line.IsNothing() || isBytecodeFile) - { - Log::Error << "[V8] Exception at " << resource->GetName() << ":" << name << Log::Endl; - } - else - Log::Error << "[V8] Exception at " << resource->GetName() << ":" << name << ":" << line.ToChecked() << Log::Endl; - } - else - { - Log::Error << "[V8] Exception at " << resource->GetName() << Log::Endl; - } - - if(!maybeSourceLine.IsEmpty() && !isBytecodeFile) - { - v8::Local sourceLine = maybeSourceLine.ToLocalChecked(); - - if(sourceLine->Length() <= 80) - { - Log::Error << " " << *v8::String::Utf8Value(isolate, sourceLine) << Log::Endl; - } - else - { - Log::Error << " " << std::string{ *v8::String::Utf8Value(isolate, sourceLine), 80 } << "..." << Log::Endl; - } - } - - std::string trace; - v8::MaybeLocal stackTrace = tryCatch.StackTrace(context); - if(!stackTrace.IsEmpty() && stackTrace.ToLocalChecked()->IsString()) - { - trace = *v8::String::Utf8Value(isolate, stackTrace.ToLocalChecked().As()); - Log::Error << " " << trace << Log::Endl; - } - - if(!exception.IsEmpty()) - { - Log::Error << *v8::String::Utf8Value(isolate, exception) << Log::Endl; - } - - std::string sourceFile = origin.ResourceName()->IsUndefined() ? "" : *v8::String::Utf8Value(isolate, origin.ResourceName()); - v8resource->DispatchErrorEvent(*v8::String::Utf8Value(isolate, message->Get()), sourceFile, line.IsNothing() ? -1 : line.ToChecked(), trace); - } - else if(!exception.IsEmpty()) - { - Log::Error << "[V8] Exception: " << *v8::String::Utf8Value(isolate, exception) << Log::Endl; - } - else - { - Log::Error << "[V8] Exception occured" << Log::Endl; - } - - return false; - } - - return true; -} - -v8::Local V8Helpers::Get(v8::Local ctx, v8::Local obj, const char* name) -{ - return obj->Get(ctx, v8::String::NewFromUtf8(ctx->GetIsolate(), name, v8::NewStringType::kInternalized).ToLocalChecked()).ToLocalChecked(); -} - -v8::Local V8Helpers::Get(v8::Local ctx, v8::Local obj, v8::Local name) -{ - return obj->Get(ctx, name).ToLocalChecked(); -} - -v8::Local V8Helpers::New(v8::Isolate* isolate, v8::Local ctx, v8::Local constructor, std::vector>& args) -{ - v8::Local obj; - - V8Helpers::TryCatch( - [&] - { - v8::MaybeLocal maybeObj = constructor->CallAsConstructor(ctx, args.size(), args.data()); - - if(maybeObj.IsEmpty()) return false; - - obj = maybeObj.ToLocalChecked(); - return true; - }); - - return obj; -} - -v8::Local V8Helpers::CreateCustomObject(v8::Isolate* isolate, - void* data, - v8::GenericNamedPropertyGetterCallback getter, - v8::GenericNamedPropertySetterCallback setter, - v8::GenericNamedPropertyDeleterCallback deleter, - v8::GenericNamedPropertyEnumeratorCallback enumerator, - v8::GenericNamedPropertyQueryCallback query) -{ - v8::Local objTemplate = v8::ObjectTemplate::New(isolate); - v8::NamedPropertyHandlerConfiguration config; - config.getter = getter; - config.setter = setter; - config.deleter = deleter; - config.query = query; - config.enumerator = enumerator; - config.data = v8::External::New(isolate, data); - config.flags = v8::PropertyHandlerFlags::kHasNoSideEffect; - objTemplate->SetHandler(config); - - v8::Local obj = objTemplate->NewInstance(isolate->GetEnteredOrMicrotaskContext()).ToLocalChecked(); - return obj; -} - -inline static std::string GetStackFrameScriptName(v8::Local frame) -{ - v8::Local name = frame->GetScriptName(); - if(!name.IsEmpty()) return *v8::String::Utf8Value(v8::Isolate::GetCurrent(), name); - else if(frame->IsEval()) - return "[eval]"; - else if(frame->IsWasm()) - return "[wasm]"; - else if(!frame->IsUserJavaScript()) - return "[internal]"; - else - return "[unknown]"; -} - -V8Helpers::SourceLocation V8Helpers::SourceLocation::GetCurrent(v8::Isolate* isolate, V8ResourceImpl* resource) -{ - v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 5); - auto ctx = isolate->GetEnteredOrMicrotaskContext(); - - for(int i = 0; i < stackTrace->GetFrameCount(); i++) - { - v8::Local frame = stackTrace->GetFrame(isolate, i); - if(frame->GetScriptName().IsEmpty() && !frame->IsEval() && !frame->IsWasm() && frame->IsUserJavaScript()) continue; - - std::string name = GetStackFrameScriptName(frame); - bool isBytecode = false; -#ifdef ALT_CLIENT_API - isBytecode = resource ? static_cast(resource)->GetModuleData(name).isBytecode : false; -#endif - int line = isBytecode ? 0 : frame->GetLineNumber(); - return SourceLocation{ std::move(name), line, ctx }; - } - - return SourceLocation{ "[unknown]", 0, ctx }; -} - -V8Helpers::SourceLocation::SourceLocation(std::string&& _fileName, int _line, v8::Local ctx) : fileName(_fileName), line(_line) -{ - context.Reset(ctx->GetIsolate(), ctx); -} - -std::string V8Helpers::SourceLocation::ToString(v8::Isolate* isolate) -{ - std::stringstream stream; - stream << "["; - - // Check if not inside a worker - bool* isWorker = static_cast(isolate->GetData(v8::Isolate::GetNumberOfDataSlots() - 1)); - if (!isWorker || !(*isWorker)) - { - stream << V8ResourceImpl::Get(context.Get(isolate))->GetResource()->GetName() << ":"; - } - - stream << fileName << ":" << line << "]"; - return stream.str(); -} - -V8Helpers::StackTrace V8Helpers::StackTrace::GetCurrent(v8::Isolate* isolate, V8ResourceImpl* resource) -{ - v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 5); - auto ctx = isolate->GetEnteredOrMicrotaskContext(); - std::vector frames; - for(int i = 0; i < stackTrace->GetFrameCount(); i++) - { - v8::Local frame = stackTrace->GetFrame(isolate, i); - Frame frameData; - frameData.file = GetStackFrameScriptName(frame); - bool isBytecode = false; -#ifdef ALT_CLIENT_API - isBytecode = resource ? static_cast(resource)->GetModuleData(frameData.file).isBytecode : false; -#endif - frameData.line = isBytecode ? 0 : frame->GetLineNumber(); - if(frame->GetFunctionName().IsEmpty()) frameData.function = "[anonymous]"; - else - frameData.function = *v8::String::Utf8Value(isolate, frame->GetFunctionName()); - - frames.push_back(std::move(frameData)); - } - - return StackTrace{ std::move(frames), ctx }; -} - -V8Helpers::StackTrace::StackTrace(std::vector&& frames, v8::Local ctx) : frames(frames), context(ctx->GetIsolate(), ctx) {} - -void V8Helpers::StackTrace::Print(uint32_t offset) const -{ - Log::Error << ToString() << Log::Endl; -} - -std::string V8Helpers::StackTrace::ToString(uint32_t offset) const -{ - std::stringstream stream; - auto& frames = GetFrames(); - size_t size = frames.size(); - - for(size_t i = offset; i < size; i++) - { - const Frame& frame = frames[i]; - stream << " at " << frame.function << " (" << frame.file << ":" << frame.line << ")" - << "\n"; - } - return stream.str(); -} - -void V8Helpers::StackTrace::Print(v8::Isolate* isolate) -{ - V8Helpers::StackTrace trace = V8Helpers::StackTrace::GetCurrent(isolate); - trace.Print(); -} - -std::vector V8Helpers::EventHandler::GetCallbacks(V8ResourceImpl* impl, const alt::CEvent* e) -{ - return callbacksGetter(impl, e); -} - -std::vector> V8Helpers::EventHandler::GetArgs(V8ResourceImpl* impl, const alt::CEvent* e) -{ - std::vector> args; - argsGetter(impl, e, args); - return args; -} - -V8Helpers::EventHandler* V8Helpers::EventHandler::Get(const alt::CEvent* e) -{ - auto& _all = all(); - auto it = _all.find(e->GetType()); - - return (it != _all.end()) ? it->second : nullptr; -} - -alt::CEvent::Type V8Helpers::EventHandler::GetTypeForEventName(const std::string& event) -{ - // TODO: Shitty temp workaround -#ifdef ALT_CLIENT_API - if(event == "keyup" || event == "keydown") return alt::CEvent::Type::KEYBOARD_EVENT; -#endif -#ifdef ALT_SERVER_API - if(event == "entityEnterColshape" || event == "entityLeaveColshape") return alt::CEvent::Type::COLSHAPE_EVENT; -#endif - auto result = eventNameToHandlerMap().find(event); - if(result == eventNameToHandlerMap().end()) return alt::CEvent::Type::NONE; - return result->second->GetType(); -} - -void V8Helpers::EventHandler::Register(alt::CEvent::Type type, EventHandler* handler) -{ - auto& _all = all(); - if(_all.count(type) == 0) - { - _all.insert({ type, handler }); - } - else - { - Log::Error << "Handler for " << (int)type << " already defined" << Log::Endl; - } -} - -V8Helpers::EventHandler::CallbacksGetter V8Helpers::LocalEventHandler::GetCallbacksGetter(const std::string& name) -{ - return [name](V8ResourceImpl* resource, const alt::CEvent*) -> std::vector { return resource->GetLocalHandlers(name); }; -} - -V8Helpers::EventHandler::EventHandler(alt::CEvent::Type type, CallbacksGetter&& _handlersGetter, ArgsGetter&& _argsGetter) - : callbacksGetter(std::move(_handlersGetter)), argsGetter(std::move(_argsGetter)), type(type) -{ - Register(type, this); -} - -// Temp issue fix for https://stackoverflow.com/questions/9459980/c-global-variable-not-initialized-when-linked-through-static-libraries-but-ok -void V8Helpers::EventHandler::Reference() -{ - // Log::Info << "[V8] Registered handler for " << std::to_string((int)type) << Log::Endl; - (void)type; -} - -std::string V8Helpers::Stringify(v8::Local ctx, v8::Local val) -{ - v8::Local str; - if(!val->ToString(ctx).ToLocal(&str)) return std::string(); - if(val->IsObject() && strcmp(*v8::String::Utf8Value(ctx->GetIsolate(), str), "[object Object]") == 0) - { - v8::MaybeLocal maybe = v8::JSON::Stringify(ctx, val); - v8::Local stringified; - if(maybe.ToLocal(&stringified)) str = stringified; - } - - if(str.IsEmpty()) return std::string(); - std::string result = *v8::String::Utf8Value(ctx->GetIsolate(), str); - return result; -} - -std::string V8Helpers::GetJSValueTypeName(v8::Local val) -{ - if(val->IsUndefined()) return "undefined"; - if(val->IsNull()) return "null"; - if(val->IsNumber()) return "number"; - if(val->IsString()) return "string"; - if(val->IsArray()) return "array"; - if(val->IsBoolean()) return "bool"; - if(val->IsBigInt()) return "bigint"; - if(val->IsArrayBuffer()) return "arraybuffer"; - if(val->IsArrayBufferView()) return "arraybufferview"; - if(val->IsDate()) return "date"; - if(val->IsArgumentsObject()) return "arguments"; - if(val->IsAsyncFunction()) return "asyncfunction"; - if(val->IsExternal()) return "external"; - if(val->IsDataView()) return "dataview"; - if(val->IsSymbol()) return "symbol"; - if(val->IsFunction()) return "function"; - if(val->IsRegExp()) return "regexp"; - if(val->IsGeneratorFunction()) return "generatorfunction"; - if(val->IsPromise()) return "promise"; - if(val->IsProxy()) return "proxy"; - if(val->IsMap()) return "map"; - if(val->IsSet()) return "set"; - if(val->IsWeakMap()) return "weakmap"; - if(val->IsWeakSet()) return "weakset"; - if(val->IsTypedArray()) return "typedarray"; - if(val->IsProxy()) return "proxy"; - if(val->IsModuleNamespaceObject()) return "modulenamespace"; - if(val->IsObject()) return "object"; - else - return "unknown"; -} - -void V8Helpers::SetObjectClass(v8::Isolate* isolate, v8::Local obj, V8Class::ObjectClass cls) -{ - obj->SetInternalField( - static_cast(V8Class::InternalFields::OBJECT_CLASS), v8::External::New(isolate, reinterpret_cast(cls)) - ); -} - -V8Class::ObjectClass V8Helpers::GetObjectClass(v8::Local obj) -{ - if(obj->InternalFieldCount() <= static_cast(V8Class::InternalFields::OBJECT_CLASS)) - return V8Class::ObjectClass::NONE; - - auto val = obj->GetInternalField(static_cast(V8Class::InternalFields::OBJECT_CLASS)); - if(!val->IsExternal()) + +#include "cpp-sdk/ICore.h" +#include "V8ResourceImpl.h" +#include "V8Helpers.h" +#ifdef ALT_CLIENT + #include "CV8Resource.h" +#endif + +#include +#include +#include +#include + +bool V8Helpers::TryCatch(const std::function& fn) +{ + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local context = isolate->GetEnteredOrMicrotaskContext(); + v8::TryCatch tryCatch(isolate); + + V8ResourceImpl* v8resource = V8ResourceImpl::Get(context); + alt::IResource* resource = v8resource->GetResource(); + + if(!fn()) + { + v8::Local exception = tryCatch.Exception(); + v8::Local message = tryCatch.Message(); + + if(!message.IsEmpty() && !context.IsEmpty()) + { + v8::MaybeLocal maybeSourceLine = message->GetSourceLine(context); + v8::Maybe line = message->GetLineNumber(context); + v8::ScriptOrigin origin = message->GetScriptOrigin(); + std::string name = *v8::String::Utf8Value(isolate, origin.ResourceName()); + + // Only relevant for client + bool isBytecodeFile = false; +#ifdef ALT_CLIENT + isBytecodeFile = static_cast(v8resource)->GetModuleData(name).isBytecode; +#endif + + if(!origin.ResourceName()->IsUndefined()) + { + if(line.IsNothing() || isBytecodeFile) + { + Log::Error << "[V8] Exception at " << resource->GetName() << ":" << name << Log::Endl; + } + else + Log::Error << "[V8] Exception at " << resource->GetName() << ":" << name << ":" << line.ToChecked() << Log::Endl; + } + else + { + Log::Error << "[V8] Exception at " << resource->GetName() << Log::Endl; + } + + if(!maybeSourceLine.IsEmpty() && !isBytecodeFile) + { + v8::Local sourceLine = maybeSourceLine.ToLocalChecked(); + + if(sourceLine->Length() <= 80) + { + Log::Error << " " << *v8::String::Utf8Value(isolate, sourceLine) << Log::Endl; + } + else + { + Log::Error << " " << std::string{ *v8::String::Utf8Value(isolate, sourceLine), 80 } << "..." << Log::Endl; + } + } + + std::string trace; + v8::MaybeLocal stackTrace = tryCatch.StackTrace(context); + if(!stackTrace.IsEmpty() && stackTrace.ToLocalChecked()->IsString()) + { + trace = *v8::String::Utf8Value(isolate, stackTrace.ToLocalChecked().As()); + Log::Error << " " << trace << Log::Endl; + } + + if(!exception.IsEmpty()) + { + Log::Error << *v8::String::Utf8Value(isolate, exception) << Log::Endl; + } + + std::string sourceFile = origin.ResourceName()->IsUndefined() ? "" : *v8::String::Utf8Value(isolate, origin.ResourceName()); + v8resource->DispatchErrorEvent(*v8::String::Utf8Value(isolate, message->Get()), sourceFile, line.IsNothing() ? -1 : line.ToChecked(), trace); + } + else if(!exception.IsEmpty()) + { + Log::Error << "[V8] Exception: " << *v8::String::Utf8Value(isolate, exception) << Log::Endl; + } + else + { + Log::Error << "[V8] Exception occured" << Log::Endl; + } + + return false; + } + + return true; +} + +v8::Local V8Helpers::Get(v8::Local ctx, v8::Local obj, const char* name) +{ + return obj->Get(ctx, v8::String::NewFromUtf8(ctx->GetIsolate(), name, v8::NewStringType::kInternalized).ToLocalChecked()).ToLocalChecked(); +} + +v8::Local V8Helpers::Get(v8::Local ctx, v8::Local obj, v8::Local name) +{ + return obj->Get(ctx, name).ToLocalChecked(); +} + +v8::Local V8Helpers::New(v8::Isolate* isolate, v8::Local ctx, v8::Local constructor, std::vector>& args) +{ + v8::Local obj; + + V8Helpers::TryCatch( + [&] + { + v8::MaybeLocal maybeObj = constructor->CallAsConstructor(ctx, args.size(), args.data()); + + if(maybeObj.IsEmpty()) return false; + + obj = maybeObj.ToLocalChecked(); + return true; + }); + + return obj; +} + +v8::Local V8Helpers::CreateCustomObject(v8::Isolate* isolate, + void* data, + v8::GenericNamedPropertyGetterCallback getter, + v8::GenericNamedPropertySetterCallback setter, + v8::GenericNamedPropertyDeleterCallback deleter, + v8::GenericNamedPropertyEnumeratorCallback enumerator, + v8::GenericNamedPropertyQueryCallback query) +{ + v8::Local objTemplate = v8::ObjectTemplate::New(isolate); + v8::NamedPropertyHandlerConfiguration config; + config.getter = getter; + config.setter = setter; + config.deleter = deleter; + config.query = query; + config.enumerator = enumerator; + config.data = v8::External::New(isolate, data); + config.flags = v8::PropertyHandlerFlags::kHasNoSideEffect; + objTemplate->SetHandler(config); + + v8::Local obj = objTemplate->NewInstance(isolate->GetEnteredOrMicrotaskContext()).ToLocalChecked(); + return obj; +} + +inline static std::string GetStackFrameScriptName(v8::Local frame) +{ + v8::Local name = frame->GetScriptName(); + if(!name.IsEmpty()) return *v8::String::Utf8Value(v8::Isolate::GetCurrent(), name); + else if(frame->IsEval()) + return "[eval]"; + else if(frame->IsWasm()) + return "[wasm]"; + else if(!frame->IsUserJavaScript()) + return "[internal]"; + else + return "[unknown]"; +} + +V8Helpers::SourceLocation V8Helpers::SourceLocation::GetCurrent(v8::Isolate* isolate, V8ResourceImpl* resource) +{ + v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 5); + auto ctx = isolate->GetEnteredOrMicrotaskContext(); + + for(int i = 0; i < stackTrace->GetFrameCount(); i++) + { + v8::Local frame = stackTrace->GetFrame(isolate, i); + if(frame->GetScriptName().IsEmpty() && !frame->IsEval() && !frame->IsWasm() && frame->IsUserJavaScript()) continue; + + std::string name = GetStackFrameScriptName(frame); + bool isBytecode = false; +#ifdef ALT_CLIENT_API + isBytecode = resource ? static_cast(resource)->GetModuleData(name).isBytecode : false; +#endif + int line = isBytecode ? 0 : frame->GetLineNumber(); + return SourceLocation{ std::move(name), line, ctx }; + } + + return SourceLocation{ "[unknown]", 0, ctx }; +} + +V8Helpers::SourceLocation::SourceLocation(std::string&& _fileName, int _line, v8::Local ctx) : fileName(_fileName), line(_line) +{ + context.Reset(ctx->GetIsolate(), ctx); +} + +std::string V8Helpers::SourceLocation::ToString(v8::Isolate* isolate) +{ + std::stringstream stream; + stream << "["; + + // Check if not inside a worker + bool* isWorker = static_cast(isolate->GetData(v8::Isolate::GetNumberOfDataSlots() - 1)); + if (!isWorker || !(*isWorker)) + { + stream << V8ResourceImpl::Get(context.Get(isolate))->GetResource()->GetName() << ":"; + } + + stream << fileName << ":" << line << "]"; + return stream.str(); +} + +V8Helpers::StackTrace V8Helpers::StackTrace::GetCurrent(v8::Isolate* isolate, V8ResourceImpl* resource) +{ + v8::Local stackTrace = v8::StackTrace::CurrentStackTrace(isolate, 5); + auto ctx = isolate->GetEnteredOrMicrotaskContext(); + std::vector frames; + for(int i = 0; i < stackTrace->GetFrameCount(); i++) + { + v8::Local frame = stackTrace->GetFrame(isolate, i); + Frame frameData; + frameData.file = GetStackFrameScriptName(frame); + bool isBytecode = false; +#ifdef ALT_CLIENT_API + isBytecode = resource ? static_cast(resource)->GetModuleData(frameData.file).isBytecode : false; +#endif + frameData.line = isBytecode ? 0 : frame->GetLineNumber(); + if(frame->GetFunctionName().IsEmpty()) frameData.function = "[anonymous]"; + else + frameData.function = *v8::String::Utf8Value(isolate, frame->GetFunctionName()); + + frames.push_back(std::move(frameData)); + } + + return StackTrace{ std::move(frames), ctx }; +} + +V8Helpers::StackTrace::StackTrace(std::vector&& frames, v8::Local ctx) : frames(frames), context(ctx->GetIsolate(), ctx) {} + +void V8Helpers::StackTrace::Print(uint32_t offset) const +{ + Log::Error << ToString() << Log::Endl; +} + +std::string V8Helpers::StackTrace::ToString(uint32_t offset) const +{ + std::stringstream stream; + auto& frames = GetFrames(); + size_t size = frames.size(); + + for(size_t i = offset; i < size; i++) + { + const Frame& frame = frames[i]; + stream << " at " << frame.function << " (" << frame.file << ":" << frame.line << ")" + << "\n"; + } + return stream.str(); +} + +void V8Helpers::StackTrace::Print(v8::Isolate* isolate) +{ + V8Helpers::StackTrace trace = V8Helpers::StackTrace::GetCurrent(isolate); + trace.Print(); +} + +std::vector V8Helpers::EventHandler::GetCallbacks(V8ResourceImpl* impl, const alt::CEvent* e) +{ + return callbacksGetter(impl, e); +} + +std::vector> V8Helpers::EventHandler::GetArgs(V8ResourceImpl* impl, const alt::CEvent* e) +{ + std::vector> args; + argsGetter(impl, e, args); + return args; +} + +V8Helpers::EventHandler* V8Helpers::EventHandler::Get(const alt::CEvent* e) +{ + auto& _all = all(); + auto it = _all.find(e->GetType()); + + return (it != _all.end()) ? it->second : nullptr; +} + +alt::CEvent::Type V8Helpers::EventHandler::GetTypeForEventName(const std::string& event) +{ + // TODO: Shitty temp workaround +#ifdef ALT_CLIENT_API + if(event == "keyup" || event == "keydown") return alt::CEvent::Type::KEYBOARD_EVENT; +#endif +#ifdef ALT_SERVER_API + if(event == "entityEnterColshape" || event == "entityLeaveColshape") return alt::CEvent::Type::COLSHAPE_EVENT; +#endif + auto result = eventNameToHandlerMap().find(event); + if(result == eventNameToHandlerMap().end()) return alt::CEvent::Type::NONE; + return result->second->GetType(); +} + +void V8Helpers::EventHandler::Register(alt::CEvent::Type type, EventHandler* handler) +{ + auto& _all = all(); + if(_all.count(type) == 0) + { + _all.insert({ type, handler }); + } + else + { + Log::Error << "Handler for " << (int)type << " already defined" << Log::Endl; + } +} + +V8Helpers::EventHandler::CallbacksGetter V8Helpers::LocalEventHandler::GetCallbacksGetter(const std::string& name) +{ + return [name](V8ResourceImpl* resource, const alt::CEvent*) -> std::vector { return resource->GetLocalHandlers(name); }; +} + +V8Helpers::EventHandler::EventHandler(alt::CEvent::Type type, CallbacksGetter&& _handlersGetter, ArgsGetter&& _argsGetter) + : callbacksGetter(std::move(_handlersGetter)), argsGetter(std::move(_argsGetter)), type(type) +{ + Register(type, this); +} + +// Temp issue fix for https://stackoverflow.com/questions/9459980/c-global-variable-not-initialized-when-linked-through-static-libraries-but-ok +void V8Helpers::EventHandler::Reference() +{ + // Log::Info << "[V8] Registered handler for " << std::to_string((int)type) << Log::Endl; + (void)type; +} + +std::string V8Helpers::Stringify(v8::Local ctx, v8::Local val) +{ + v8::Local str; + if(!val->ToString(ctx).ToLocal(&str)) return std::string(); + if(val->IsObject() && strcmp(*v8::String::Utf8Value(ctx->GetIsolate(), str), "[object Object]") == 0) + { + v8::MaybeLocal maybe = v8::JSON::Stringify(ctx, val); + v8::Local stringified; + if(maybe.ToLocal(&stringified)) str = stringified; + } + + if(str.IsEmpty()) return std::string(); + std::string result = *v8::String::Utf8Value(ctx->GetIsolate(), str); + return result; +} + +std::string V8Helpers::GetJSValueTypeName(v8::Local val) +{ + if(val->IsUndefined()) return "undefined"; + if(val->IsNull()) return "null"; + if(val->IsNumber()) return "number"; + if(val->IsString()) return "string"; + if(val->IsArray()) return "array"; + if(val->IsBoolean()) return "bool"; + if(val->IsBigInt()) return "bigint"; + if(val->IsArrayBuffer()) return "arraybuffer"; + if(val->IsArrayBufferView()) return "arraybufferview"; + if(val->IsDate()) return "date"; + if(val->IsArgumentsObject()) return "arguments"; + if(val->IsAsyncFunction()) return "asyncfunction"; + if(val->IsExternal()) return "external"; + if(val->IsDataView()) return "dataview"; + if(val->IsSymbol()) return "symbol"; + if(val->IsFunction()) return "function"; + if(val->IsRegExp()) return "regexp"; + if(val->IsGeneratorFunction()) return "generatorfunction"; + if(val->IsPromise()) return "promise"; + if(val->IsProxy()) return "proxy"; + if(val->IsMap()) return "map"; + if(val->IsSet()) return "set"; + if(val->IsWeakMap()) return "weakmap"; + if(val->IsWeakSet()) return "weakset"; + if(val->IsTypedArray()) return "typedarray"; + if(val->IsProxy()) return "proxy"; + if(val->IsModuleNamespaceObject()) return "modulenamespace"; + if(val->IsObject()) return "object"; + else + return "unknown"; +} + +void V8Helpers::SetObjectClass(v8::Isolate* isolate, v8::Local obj, V8Class::ObjectClass cls) +{ + obj->SetInternalField( + static_cast(V8Class::InternalFields::OBJECT_CLASS), v8::External::New(isolate, reinterpret_cast(cls)) + ); +} + +V8Class::ObjectClass V8Helpers::GetObjectClass(v8::Local obj) +{ + if(obj->InternalFieldCount() <= static_cast(V8Class::InternalFields::OBJECT_CLASS)) + return V8Class::ObjectClass::NONE; + + auto val = obj->GetInternalField(static_cast(V8Class::InternalFields::OBJECT_CLASS)); + if(!val->IsExternal()) return V8Class::ObjectClass::NONE; - - void* cls = val.As()->Value(); - return *reinterpret_cast(&cls); -} - -v8::MaybeLocal V8Helpers::CallFunctionWithTimeout(v8::Local fn, v8::Local ctx, std::vector>& args, uint32_t timeout) -{ - v8::Isolate* isolate = ctx->GetIsolate(); - /*std::shared_ptr hasTimedOut{ new bool(false) }; - std::shared_ptr hasFinished{ new bool(false) }; - std::thread([=]() { - std::this_thread::sleep_for(std::chrono::milliseconds(timeout)); - if(*hasFinished || isolate->IsExecutionTerminating()) return; - *hasTimedOut = true; - isolate->TerminateExecution(); - }).detach();*/ - - v8::MaybeLocal result = fn->Call(ctx, v8::Undefined(isolate), args.size(), args.data()); - /**hasFinished = true; - if(*hasTimedOut) - { - Log::Error << "[V8] Script execution timed out" << Log::Endl; - return v8::MaybeLocal(); - }*/ - return result; -} + + void* cls = val.As()->Value(); + return *reinterpret_cast(&cls); +} + +v8::MaybeLocal V8Helpers::CallFunctionWithTimeout(v8::Local fn, v8::Local ctx, std::vector>& args, uint32_t timeout) +{ + v8::Isolate* isolate = ctx->GetIsolate(); + /*std::shared_ptr hasTimedOut{ new bool(false) }; + std::shared_ptr hasFinished{ new bool(false) }; + std::thread([=]() { + std::this_thread::sleep_for(std::chrono::milliseconds(timeout)); + if(*hasFinished || isolate->IsExecutionTerminating()) return; + *hasTimedOut = true; + isolate->TerminateExecution(); + }).detach();*/ + + v8::MaybeLocal result = fn->Call(ctx, v8::Undefined(isolate), args.size(), args.data()); + /**hasFinished = true; + if(*hasTimedOut) + { + Log::Error << "[V8] Script execution timed out" << Log::Endl; + return v8::MaybeLocal(); + }*/ + return result; +}