#include "CrossLang.hpp" #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Uuid.hpp" #include #include #include #include #include #include #include namespace Tesses::CrossLang { static void empty() {} bool InterperterThread::SetField(std::shared_ptr gc) { std::vector &cse = this->call_stack_entries; if (!cse.empty()) { auto stk = cse.back(); GCList ls(gc); TObject value = stk->Pop(ls); TObject _key = stk->Pop(ls); TObject instance = stk->Pop(ls); if (!std::holds_alternative(_key)) { stk->Push(gc, Undefined()); return false; } std::string key = std::get(_key); if (std::holds_alternative< std::shared_ptr>( instance)) { auto handle = std::get>( instance); if (handle) { int64_t ms; bool b; if (key == "Enabled" && GetObject(value, b)) { handle->SetEnabled(b); cse.back()->Push(gc, b); return false; } if (key == "Interval" && GetObject(value, ms)) { handle->SetIntervalFromMilliseconds(ms); cse.back()->Push(gc, ms); return false; } if (key == "Callback") { TCallable *callable; if (GetObjectHeap(value, callable)) { auto obj = CreateMarkedTObject(ls.GetGC(), callable); handle->SetCallback([obj]() -> void { TCallable *callable; if (GetObjectHeap(obj->GetObject(), callable)) { GCList ls(obj->GetGC()); callable->Call(ls, {}); } }); cse.back()->Push(gc, callable); return false; } else { handle->SetCallback(empty); cse.back()->Push(gc, nullptr); return false; } } } cse.back()->Push(gc, Undefined()); return false; } if (std::holds_alternative< std::shared_ptr>( instance)) { auto writer = std::get< std::shared_ptr>( instance); auto stringWriter = std::dynamic_pointer_cast< Tesses::Framework::TextStreams::StringWriter>(writer); if (stringWriter != nullptr) { if (key == "Text") { if (std::holds_alternative(value)) { stringWriter->GetString() = std::get(value); } cse.back()->Push(gc, stringWriter->GetString()); return false; } } if (key == "NewLine") { if (std::holds_alternative(value)) { writer->newline = std::get(value); } cse.back()->Push(gc, writer->newline); return false; } cse.back()->Push(gc, Undefined()); return false; } if (std::holds_alternative< std::shared_ptr>( instance)) { auto vfs = std::get>( instance); auto relative = std::dynamic_pointer_cast< Tesses::Framework::Filesystem::RelativeFilesystem>(vfs); if (relative) { if (key == "Working") { Tesses::Framework::Filesystem::VFSPath path; if (GetObjectAsPath(value, path)) { if (path.relative) { relative->SetWorking( path.MakeAbsolute(relative->GetWorking())); } else { relative->SetWorking(path); } } } } cse.back()->Push(gc, Undefined()); return false; } if (std::holds_alternative< std::shared_ptr>( instance)) { auto svr = std::get>( instance); auto bas = std::dynamic_pointer_cast< Tesses::Framework::Http::BasicAuthServer>(svr); auto cgi = std::dynamic_pointer_cast( svr); auto changable = std::dynamic_pointer_cast< Tesses::Framework::Http::ChangeableServer>(svr); if (changable != nullptr) { if (key == "Server") { bas->server = ToHttpServer(gc, value); stk->Push(gc, value); return false; } } if (bas != nullptr) { if (key == "Realm") { bool val; if (GetObject(value, val)) { bas->realm = val; stk->Push(gc, val); return false; } } if (key == "Server") { bas->server = ToHttpServer(gc, value); stk->Push(gc, value); return false; } if (key == "Authorization") { TCallable *val; if (GetObjectHeap(value, val)) { auto marked = CreateMarkedTObject(ls, val); bas->authorization = [marked](std::string user, std::string password) -> bool { GCList ls(marked->GetGC()); TCallable *callable; if (GetObjectHeap(marked->GetObject(), callable)) { return ToBool( callable->Call(ls, {user, password})); } return false; }; stk->Push(gc, val); return false; } } } if (cgi != nullptr) { if (key == "WorkingDirectory") { Tesses::Framework::Filesystem::VFSPath path; if (GetObjectAsPath(value, path)) { cgi->workingDirectory = path; stk->Push(gc, path); return false; } else { cgi->workingDirectory = std::nullopt; stk->Push(gc, nullptr); return false; } } if (key == "DocumentRoot") { Tesses::Framework::Filesystem::VFSPath path; if (GetObjectAsPath(value, path)) { cgi->document_root = path; stk->Push(gc, path); return false; } else { cgi->document_root = std::nullopt; stk->Push(gc, nullptr); return false; } } if (key == "AdminEmail") { std::string str; if (GetObject(value, str)) { cgi->adminEmail = str; stk->Push(gc, str); return false; } else { cgi->adminEmail = std::nullopt; stk->Push(gc, nullptr); return false; } } } stk->Push(gc, Undefined()); return false; } if (std::holds_alternative< std::shared_ptr>( instance)) { auto strm = std::get>( instance); auto netStrm = std::dynamic_pointer_cast< Tesses::Framework::Streams::NetworkStream>(strm); if (netStrm != nullptr) { int64_t n0; bool bc; if (key == "Broadcast" && GetObject(value, bc)) netStrm->SetBroadcast(bc); if (key == "NoDelay" && GetObject(value, bc)) netStrm->SetNoDelay(bc); if (key == "ReuseAddress" && GetObject(value, bc)) netStrm->SetReuseAddress(bc); if (key == "ReusePort" && GetObject(value, bc)) netStrm->SetReusePort(bc); if (key == "MulticastTTL" && GetObject(value, n0)) netStrm->SetMulticastTTL((uint8_t)n0); } stk->Push(gc, Undefined()); return false; } if (std::holds_alternative(instance)) { auto obj = std::get(instance).obj; auto dict = dynamic_cast(obj); auto dynDict = dynamic_cast(obj); auto natObj = dynamic_cast(obj); auto cls = dynamic_cast(obj); if (cls != nullptr) { gc->BarrierBegin(); auto obj = cls->GetValue(cse.back()->callable->className, "set" + key); gc->BarrierEnd(); TClosure *clos; TCallable *callable; if (GetObjectHeap(obj, clos)) { this->AddCallStackEntry(ls, clos, {value}); return true; } else if (GetObjectHeap(obj, callable)) { cse.back()->Push(gc, callable->Call(ls, {value})); return false; } gc->BarrierBegin(); cls->SetValue(cse.back()->callable->className, key, value); gc->BarrierEnd(); cse.back()->Push(gc, value); return false; } else if (natObj != nullptr) { cse.back()->Push(gc, natObj->CallMethod(ls, "set" + key, {value})); return false; } auto tcallable = dynamic_cast(obj); if (tcallable != nullptr) { if (key == "Tag") { gc->BarrierBegin(); tcallable->tag = value; gc->BarrierEnd(); cse.back()->Push(gc, nullptr); return false; } } if (dynDict != nullptr) { if (dynDict->MethodExists(ls, "set" + key)) { cse.back()->Push( gc, dynDict->CallMethod(ls, "set" + key, {value})); } else { dynDict->SetField(ls, key, value); cse.back()->Push(gc, value); } return false; } if (dict != nullptr) { gc->BarrierBegin(); TObject fn = dict->GetValue("set" + key); gc->BarrierEnd(); if (std::holds_alternative(fn) && dynamic_cast( std::get(fn).obj) != nullptr) { return InvokeTwo(ls, fn, dict, value); } else { gc->BarrierBegin(); dict->SetValue(key, value); stk->Push(gc, value); gc->BarrierEnd(); return false; } } } stk->Push(gc, Undefined()); } return false; } } // namespace Tesses::CrossLang