Add RouteServer, TextReader/TextWriter and file locks

This commit is contained in:
2026-01-12 13:56:49 -06:00
parent a49b61c532
commit e6ce053c2e
15 changed files with 493 additions and 44 deletions

View File

@@ -170,6 +170,7 @@ src/types/vfsheapobject.cpp
src/types/streamheapobject.cpp
src/types/class.cpp
src/types/classenvironment.cpp
src/types/random.cpp
src/vm/filereader.cpp
src/vm/gc.cpp
src/vm/gclist.cpp

View File

@@ -4,6 +4,8 @@ using namespace Tesses::CrossLang;
int main(int argc, char** argv)
{
TF_InitWithConsole();
if(argc > 0)
TF_AllowPortable(argv[0]);
std::string name = argv[0];
Tesses::Framework::Filesystem::VFSPath exePath=Tesses::Framework::Filesystem::LocalFS->SystemToVFSPath(name);
exePath.MakeAbsolute();

View File

@@ -3,10 +3,10 @@ mkdir build-x86_64-tar
cd build-x86_64-tar
cmake -S ../../.. -B . -DTESSESFRAMEWORK_ENABLE_SHARED=ON -DTESSESFRAMEWORK_ENABLE_STATIC=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON
make -j`nproc`
make install DESTDIR=./crosslang
mkdir -p crosslang/share/Tesses/CrossLang
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
tar cvzf ../../../artifacts/crosslang-linux-x86_64.tar.gz crosslang
make install DESTDIR=./crosslang-x86_64
mkdir -p crosslang-x86_64/share/Tesses/CrossLang
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang-x86_64/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
tar cvzf ../../../artifacts/crosslang-linux-x86_64.tar.gz crosslang-x86_64
cd ..
foreign() {
@@ -14,10 +14,10 @@ mkdir build-$1\-tar
cd build-$1\-tar
cmake -S ../../.. -B . -DTESSESFRAMEWORK_ENABLE_SHARED=ON -DTESSESFRAMEWORK_ENABLE_STATIC=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/$1\.cmake
make -j`nproc`
make install DESTDIR=./crosslang
mkdir -p crosslang/share/Tesses/CrossLang
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
tar cvzf ../../../artifacts/crosslang-linux-$1\.tar.gz crosslang
make install DESTDIR=./crosslang-$1
mkdir -p crosslang-$1\/share/Tesses/CrossLang
cp ../build/jammy/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm crosslang-$1\/share/Tesses/CrossLang/Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm
tar cvzf ../../../artifacts/crosslang-linux-$1\.tar.gz crosslang-$1
cd ..
}
foreign arm64

View File

@@ -1687,6 +1687,8 @@ class GC {
virtual TObject Call(GCList& ls,std::vector<TObject> args)=0;
TObject CallWithFatalError(GCList& ls, std::vector<TObject> args);
virtual void Mark();
Tesses::Framework::Http::ServerRequestHandler ToRouteServerRequestHandler(GC* gc);
};
void ThrowFatalError(std::exception& ex);
@@ -2045,6 +2047,9 @@ class GC {
void CreateHardlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath newName);
bool DirectoryExists(Tesses::Framework::Filesystem::VFSPath path);
void DeleteFile(Tesses::Framework::Filesystem::VFSPath path);
void Lock(Tesses::Framework::Filesystem::VFSPath path);
void Unlock(Tesses::Framework::Filesystem::VFSPath path);
void DeleteDirectoryRecurse(Tesses::Framework::Filesystem::VFSPath path);
Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path);
void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest);
@@ -2370,6 +2375,16 @@ class GC {
virtual bool Equals(GC* gc, TObject right);
virtual ~TNativeObject();
};
class TRandom : public TNativeObject
{
public:
Tesses::Framework::Random random;
TRandom();
TRandom(uint64_t seed);
std::string TypeName();
TObject CallMethod(GCList& ls,std::string name, std::vector<TObject> args);
};
class TNative : public THeapObject
{
std::atomic<bool> destroyed;
@@ -2387,7 +2402,7 @@ class GC {
~TNative();
};
class ThreadHandle : public THeapObject {
public:
@@ -2604,4 +2619,6 @@ class GC {
std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path);
Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path);
};
};

View File

@@ -49,6 +49,8 @@ bool Download(Tesses::Framework::Filesystem::VFSPath filename,std::shared_ptr<Te
int main(int argc, char** argv)
{
TF_InitWithConsole();
if(argc > 0)
TF_AllowPortable(argv[0]);

View File

@@ -9,6 +9,8 @@ using namespace Tesses::Framework::Filesystem;
int main(int argc, char** argv)
{
TF_InitWithConsole();
if(argc > 0)
TF_AllowPortable(argv[0]);
GC gc;
gc.Start();
GCList ls(gc);

View File

@@ -4,11 +4,14 @@ using namespace Tesses::CrossLang;
int main(int argc, char** argv)
{
TF_InitWithConsole();
if(argc < 2)
{
printf("USAGE: %s <filename.crvm> <args...>\n",argv[0]);
return 1;
}
if(argc > 0)
TF_AllowPortable(argv[0]);
GC gc;
gc.Start();

View File

@@ -320,6 +320,15 @@ namespace Tesses::CrossLang {
dict->DeclareFunction(gc, "getSize", "Get console size",{},Console_getSize);
gc->BarrierBegin();
env->DeclareVariable("Console", dict);
auto _new = env->EnsureDictionary(gc,"New");
_new->DeclareFunction(gc,"ConsoleReader","Read from console",{},[](GCList& ls,std::vector<TObject> args)->TObject {
return std::make_shared<Tesses::Framework::TextStreams::ConsoleReader>();
});
_new->DeclareFunction(gc,"ConsoleWriter","Write to console",{"$isStderr"},[](GCList& ls,std::vector<TObject> args)->TObject {
bool err;
if(GetArgument(args,0,err)) return std::make_shared<Tesses::Framework::TextStreams::ConsoleWriter>(err);
return std::make_shared<Tesses::Framework::TextStreams::ConsoleWriter>();
});
gc->BarrierEnd();
}
}

View File

@@ -118,6 +118,19 @@ namespace Tesses::CrossLang
}
return Tesses::Framework::Filesystem::VFSPath();
}
static TObject Env_GetAll(GCList& ls, std::vector<TObject> args)
{
ls.GetGC()->BarrierBegin();
TList* list = TList::Create(ls);
std::vector<std::pair<std::string, std::string>> env;
Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env);
for(auto& item : env)
{
list->Add(TDictionary::Create(ls,{TDItem("Key",item.first),TDItem("Value",item.second)}));
}
ls.GetGC()->BarrierEnd();
return list;
}
void TStd::RegisterEnv(GC* gc, TRootEnvironment* env)
{
@@ -126,8 +139,9 @@ namespace Tesses::CrossLang
TDictionary* dict = TDictionary::Create(ls);
dict->DeclareFunction(gc,"GetAt","Get environment variable", {"key"}, Env_GetAt);
dict->DeclareFunction(gc,"SetAt","Set environment variable", {"key","value"}, Env_SetAt);
dict->DeclareFunction(gc,"GetAll","Get all of the environment variables",{},Env_GetAll);
dict->DeclareFunction(gc,"getDesktop","Get downloads folder",{},Env_getDownloads);
dict->DeclareFunction(gc,"getDesktop","Get desktop folder",{},Env_getDesktop);
dict->DeclareFunction(gc,"getDownloads","Get downloads folder",{},Env_getDownloads);
dict->DeclareFunction(gc,"getDocuments","Get documents folder",{},Env_getDocuments);
dict->DeclareFunction(gc,"getMusic","Get music folder",{},Env_getMusic);

View File

@@ -578,6 +578,7 @@ namespace Tesses::CrossLang
}
}
return Undefined();
}
@@ -897,7 +898,8 @@ namespace Tesses::CrossLang
~THttpResponse()
{
Close();
delete this->response;
this->response = nullptr;
}
std::string TypeName()
{
@@ -1478,9 +1480,14 @@ namespace Tesses::CrossLang
}
static TObject New_MountableServer(GCList& ls, std::vector<TObject> args)
{
if(args.empty()) return Undefined();
if(args.empty()) return std::make_shared<MountableServer>();
return std::make_shared<MountableServer>(ToHttpServer(ls.GetGC(),args[0]));
}
static TObject New_RouteServer(GCList& ls, std::vector<TObject> args)
{
if(args.empty()) return std::make_shared<RouteServer>();
return std::make_shared<RouteServer>(ToHttpServer(ls.GetGC(),args[0]));
}
static TObject New_StreamHttpRequestBody(GCList& ls, std::vector<TObject> args)
{
std::shared_ptr<Stream> strm;
@@ -1530,6 +1537,8 @@ namespace Tesses::CrossLang
_new->DeclareFunction(gc, "HttpServer", "Create a http server (allows multiple)",{"server","portOrUnixPath","$printIPs"},[env](GCList& ls, std::vector<TObject> args)->TObject{
return New_HttpServer(ls,args,env);
});
_new->DeclareFunction(gc, "RouteServer","Create a routeserver",{"$root"}, New_RouteServer);
_new->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer);
_new->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer);
_new->DeclareFunction(gc, "MountableServer","Create a server you can mount to, must mount parents before child",{"root"}, New_MountableServer);
@@ -1564,6 +1573,8 @@ namespace Tesses::CrossLang
http->DeclareFunction(gc, "ListenSimpleWithLoop", "Listen (creates application loop)", {"server","port"},Net_Http_ListenSimpleWithLoop);
http->DeclareFunction(gc, "ListenOnUnusedPort","Listen on unused localhost port and print Port: theport",{"server"},Net_Http_ListenOnUnusedPort);
//FileServer svr()
http->DeclareFunction(gc, "RouteServer","Create a routeserver",{"$root"}, New_RouteServer);
http->DeclareFunction(gc, "FileServer","Create a file server",{"vfs","allowlisting","spa"}, New_FileServer);
http->DeclareFunction(gc, "BasicAuthServer", "Create a basic auth server", {"$server","$auth","$realm"},New_BasicAuthServer);
http->DeclareFunction(gc, "BasicAuthGetCreds","Get creds from str",{"ctx"},[](GCList& ls, std::vector<TObject> args)->TObject {
@@ -1604,4 +1615,25 @@ namespace Tesses::CrossLang
dict->SetValue("Smtp", smtp);
gc->BarrierEnd();
}
Tesses::Framework::Http::ServerRequestHandler TCallable::ToRouteServerRequestHandler(GC* gc)
{
auto value = CreateMarkedTObject(gc,this);
return [value,this](ServerContext& ctx)->bool {
auto v=value;
auto gc = v->GetGC();
GCList ls(gc);
auto res = TNativeObject::Create<TServerContext>(ls, &ctx);
bool result;
auto out = this->Call(ls,{res});
if(GetObject(out,result))
{
res->Finish();
return result;
}
res->Finish();
return false;
};
}
}

View File

@@ -556,6 +556,18 @@ namespace Tesses::CrossLang
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
return GetArgument(args,0,strm);
}
static TObject TypeIsTextReader(GCList& ls, std::vector<TObject> args)
{
if(args.empty()) return nullptr;
std::shared_ptr<Tesses::Framework::TextStreams::TextReader> strm;
return GetArgument(args,0,strm);
}
static TObject TypeIsTextWriter(GCList& ls, std::vector<TObject> args)
{
if(args.empty()) return nullptr;
std::shared_ptr<Tesses::Framework::TextStreams::TextWriter> strm;
return GetArgument(args,0,strm);
}
static TObject TypeIsVFS(GCList& ls, std::vector<TObject> args)
{
if(args.empty()) return nullptr;
@@ -752,6 +764,7 @@ namespace Tesses::CrossLang
{
auto fileServer = std::dynamic_pointer_cast<Tesses::Framework::Http::FileServer>(svr);
auto mountableServer = std::dynamic_pointer_cast<Tesses::Framework::Http::MountableServer>(svr);
auto routableServer = std::dynamic_pointer_cast<Tesses::Framework::Http::RouteServer>(svr);
if(fileServer != nullptr)
{
return "FileServer";
@@ -760,10 +773,63 @@ namespace Tesses::CrossLang
{
return "MountableServer";
}
if(routableServer != nullptr)
{
return "RoutableServer";
}
}
return "HttpServer";
}
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextReader>>(_obj))
{
auto textReader = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextReader>>(_obj);
if(textReader != nullptr)
{
auto stringReader = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringReader>(textReader);
auto streamReader = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StreamReader>(textReader);
auto consoleReader = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::ConsoleReader>(textReader);
if(stringReader != nullptr)
{
return "StringReader";
}
if(streamReader != nullptr)
{
return "StreamReader";
}
if(consoleReader != nullptr)
{
return "ConsoleReader";
}
}
return "TextReader";
}
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(_obj))
{
auto textWriter = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(_obj);
if(textWriter != nullptr)
{
auto stringWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringWriter>(textWriter);
auto streamWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StreamWriter>(textWriter);
auto consoleWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::ConsoleReader>(textWriter);
if(stringWriter != nullptr)
{
return "StringWriter";
}
if(streamWriter != nullptr)
{
return "StreamWriter";
}
if(consoleWriter != nullptr)
{
return "ConsoleWriter";
}
}
return "TextReader";
}
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(_obj))
{
@@ -997,9 +1063,48 @@ namespace Tesses::CrossLang
}
return nullptr;
}
static TObject New_Task(GCList& ls, std::vector<TObject> args)
static TObject New_Promise(GCList& ls, std::vector<TObject> args)
{
return TTask::Create(ls);
TCallable* call;
if(GetArgumentHeap(args,0,call))
{
TTask* task = TTask::Create(ls);
TExternalMethod* resolve = TExternalMethod::Create(ls, "fulfill the promise",{"arg"},[task](GCList& ls,std::vector<TObject> args)->TObject {
if(!args.empty())
{
task->SetSucceeded(args[0]);
}
return Undefined();
});
resolve->watch.push_back(task);
TExternalMethod* reject = TExternalMethod::Create(ls, "reject the promise",{"arg"},[task](GCList& ls,std::vector<TObject> args)->TObject {
if(!args.empty())
{
auto item = args[0];
if(!std::holds_alternative<Undefined>(item))
{
try {
VMByteCodeException ex(ls.GetGC(),item,nullptr);
throw ex;
}
catch(...)
{
task->SetFailed(std::current_exception());
}
}
}
return Undefined();
});
reject->watch.push_back(task);
call->Call(ls,{resolve,reject});
return task;
}
return nullptr;
}
static TObject TimeSpan_Parse(GCList& ls, std::vector<TObject> args)
{
@@ -1051,6 +1156,72 @@ namespace Tesses::CrossLang
}
return nullptr;
}
static TObject New_StreamReader(GCList& ls, std::vector<TObject> args)
{
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
Tesses::Framework::Filesystem::VFSPath path;
if(GetArgument(args,0,strm))
{
return std::make_shared<Tesses::Framework::TextStreams::StreamReader>(strm);
}
else if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path))
{
strm = vfs->OpenFile(path,"rb");
return std::make_shared<Tesses::Framework::TextStreams::StreamReader>(strm);
}
return nullptr;
}
static TObject New_StreamWriter(GCList& ls, std::vector<TObject> args)
{
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
Tesses::Framework::Filesystem::VFSPath path;
if(GetArgument(args,0,strm))
{
return std::make_shared<Tesses::Framework::TextStreams::StreamWriter>(strm);
}
else if(GetArgument(args,0,vfs) && GetArgumentAsPath(args,1,path))
{
bool append=false;
GetArgument(args,2,append);
strm = vfs->OpenFile(path,append ? "ab" : "wb");
return std::make_shared<Tesses::Framework::TextStreams::StreamWriter>(strm);
}
return nullptr;
}
static TObject New_StringReader(GCList& ls, std::vector<TObject> args)
{
std::string str;
if(GetArgument(args,0,str))
{
return std::make_shared<Tesses::Framework::TextStreams::StringReader>(str);
}
return nullptr;
}
static TObject New_StringWriter(GCList& ls, std::vector<TObject> args)
{
std::string str;
if(GetArgument(args,0,str))
{
return std::make_shared<Tesses::Framework::TextStreams::StringWriter>(str);
}
return std::make_shared<Tesses::Framework::TextStreams::StringWriter>();
}
static TObject Task_FromResult(GCList& ls, std::vector<TObject> args)
{
if(!args.empty())
{
return TTask::FromResult(ls,args[0]);
}
return nullptr;
}
void TStd::RegisterRoot(GC* gc, TRootEnvironment* env)
{
GCList ls(gc);
@@ -1095,10 +1266,11 @@ namespace Tesses::CrossLang
return TTask::Run(ls,closure);
return nullptr;
});
task->DeclareFunction(gc, "FromResult", "async from result", {"result"}, Task_FromResult);
TDictionary* newTypes = env->EnsureDictionary(gc, "New");
//newTypes->DeclareFunction(gc,)
newTypes->DeclareFunction(gc, "Promise", "Create an async object",{"resolve","reject"},New_Promise);
newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime);
newTypes->DeclareFunction(gc, "TimeSpan","Create a DateTime object, if only one arg is provided days is totalSeconds, if there are only three arguments days will be hours, hours will be minutes, minutes will be seconds (according to the argument documentation)",{"days","$hours","$minutes","$seconds"},New_TimeSpan);
@@ -1133,7 +1305,18 @@ namespace Tesses::CrossLang
return TVMVersion((uint8_t)major,(uint8_t)minor,(uint8_t)patch,(uint16_t)build,stage);
});
newTypes->DeclareFunction(gc,"Random","Create random number generator",{"$seed"}, [](GCList& ls,std::vector<TObject> args)->TObject{
int64_t seed;
if(GetArgument(args,0,seed))
{
return TNativeObject::Create<TRandom>(ls, (uint64_t)seed);
}
return TNativeObject::Create<TRandom>(ls);
});
newTypes->DeclareFunction(gc, "StreamReader","Create a StreamReader", {"strmOrVFS","$pathIfVFS"},New_StreamReader);
newTypes->DeclareFunction(gc, "StreamWriter","Create a StreamWriter", {"strmOrVFS","$pathIfVFS","$appendIfVFS"},New_StreamWriter);
newTypes->DeclareFunction(gc, "StringReader","Create a StringReader", {"str"},New_StringReader);
newTypes->DeclareFunction(gc, "StringWriter","Create a StringWriter", {"$str"},New_StringWriter);
env->DeclareFunction(gc, "ParseLong","Parse Long from String",{"arg","$base"},ParseLong);
env->DeclareFunction(gc, "ParseDouble","Parse Double from String",{"arg"},ParseDouble);
@@ -1154,6 +1337,8 @@ namespace Tesses::CrossLang
env->DeclareFunction(gc, "TypeIsVFS","Get whether object is a virtual filesystem",{"object"},TypeIsVFS);
env->DeclareFunction(gc, "TypeIsDateTime","Get whether object is a DateTime",{"object"},TypeIsDateTime);
env->DeclareFunction(gc, "TypeIsTimeSpan","Get whether object is a TimeSpan",{"object"},TypeIsTimeSpan);
env->DeclareFunction(gc, "TypeIsTextReader","Get whether object is a TextReader",{"object"},TypeIsTextReader);
env->DeclareFunction(gc, "TypeIsTextWriter","Get whether object is a TextWriter",{"object"},TypeIsTextWriter);
newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector<TObject> args)->TObject {
@@ -1200,7 +1385,6 @@ namespace Tesses::CrossLang
return TAssociativeArray::Create(ls);
});
newTypes->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray);
newTypes->DeclareFunction(gc,"Task","Create a task for async, to manually create an async object",{},New_Task);
env->DeclareVariable("Version", TDictionary::Create(ls,{
TDItem("Parse",TExternalMethod::Create(ls,"Parse version from string",{"versionStr"},[](GCList& ls, std::vector<TObject> args)->TObject{

47
src/types/random.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "CrossLang.hpp"
namespace Tesses::CrossLang
{
TRandom::TRandom() : random()
{
}
TRandom::TRandom(uint64_t seed) : random(seed)
{
}
std::string TRandom::TypeName()
{
return "Random";
}
TObject TRandom::CallMethod(GCList& ls,std::string name, std::vector<TObject> args)
{
if(name == "Next")
{
int64_t first;
int64_t second;
if(GetArgument(args,0,first))
{
if(GetArgument(args,1,second))
{
return (int64_t)random.Next((int32_t)first,(int32_t)second);
}
return (int64_t)random.Next((uint32_t)first);
}
return random.Next();
}
if(name == "NextByte")
{
return (int64_t)random.NextByte();
}
if(name == "ToString") {
return "";
}
return Undefined();
}
}

View File

@@ -210,7 +210,11 @@ namespace Tesses::CrossLang
}
TObjectStream::~TObjectStream()
{
Close();
TDictionary* dict;
if(GetObjectHeap(this->obj, dict))
{
dict->CallMethod(*ls,"Close",{});
}
delete this->ls;
}

View File

@@ -169,6 +169,26 @@ namespace Tesses::CrossLang {
}
}
void TObjectVFS::Lock(Tesses::Framework::Filesystem::VFSPath path)
{
TDictionary* dict;
if(GetObjectHeap(this->obj, dict))
{
GCList ls(this->ls->GetGC());
dict->CallMethod(ls, "Lock",{path});
}
}
void TObjectVFS::Unlock(Tesses::Framework::Filesystem::VFSPath path)
{
TDictionary* dict;
if(GetObjectHeap(this->obj, dict))
{
GCList ls(this->ls->GetGC());
dict->CallMethod(ls, "Unlock",{path});
}
}
bool TObjectVFS::RegularFileExists(Tesses::Framework::Filesystem::VFSPath path)
{
@@ -573,8 +593,12 @@ namespace Tesses::CrossLang {
}
TObjectVFS::~TObjectVFS()
{
Close();
TDictionary* dict;
if(GetObjectHeap(this->obj, dict))
{
GCList ls(this->ls->GetGC());
dict->CallMethod(ls,"Close",{});
}
delete this->ls;
}

View File

@@ -3411,6 +3411,17 @@ namespace Tesses::CrossLang {
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadLineHttp")
{
std::string line;
if(textReader->ReadLineHttp(line))
{
cse.back()->Push(gc, line);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadAllLines")
{
std::vector<std::string> lines;
@@ -3763,6 +3774,7 @@ namespace Tesses::CrossLang {
if(svr != nullptr)
{
auto mountable = std::dynamic_pointer_cast<Tesses::Framework::Http::MountableServer>(svr);
auto routable = std::dynamic_pointer_cast<Tesses::Framework::Http::RouteServer>(svr);
if(mountable != nullptr)
{
@@ -3793,6 +3805,82 @@ namespace Tesses::CrossLang {
}
}
}
if(routable != nullptr)
{
if(key == "Add")
{
std::string method;
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,method) && GetArgument(args,1,pattern) && GetArgumentHeap(args,2,callable))
{
routable->Add(method,pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Delete")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Delete(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Get")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Get(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Options")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Options(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Patch")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Patch(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Post")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Post(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Put")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Put(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Trace")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Trace(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
}
if(key == "Handle")
{
cse.back()->Push(gc,IHttpServer_Handle(svr,args));
@@ -4107,6 +4195,26 @@ namespace Tesses::CrossLang {
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Lock")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
vfs->Lock(filename);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Unlock")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
vfs->Unlock(filename);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "DeleteDirectoryRecurse")
{
Tesses::Framework::Filesystem::VFSPath dirname;
@@ -4223,28 +4331,6 @@ namespace Tesses::CrossLang {
if(ttask != nullptr)
{
if(key == "SetSucceeded")
{
if(args.size() > 0)
{
ttask->SetSucceeded(args[0]);
}
cse.back()->Push(gc, Undefined());
return false;
}
if(key == "SetFailed")
{
if(args.size() > 0)
{
try {
throw VMByteCodeException(gc,args[0],cse.back());
} catch(...) {
ttask->SetFailed(std::current_exception());
}
}
cse.back()->Push(gc, Undefined());
return false;
}
if(key == "ContinueWith")
{
TCallable* callable2;
@@ -5581,6 +5667,15 @@ namespace Tesses::CrossLang {
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
{
auto writer = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance);
auto stringWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringWriter>(writer);
if(stringWriter != nullptr)
{
if(key == "Text")
{
cse.back()->Push(gc, stringWriter->GetString());
return false;
}
}
if(key == "NewLine")
{
cse.back()->Push(gc,writer->newline);
@@ -6245,6 +6340,19 @@ namespace Tesses::CrossLang {
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
{
auto writer = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance);
auto stringWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringWriter>(writer);
if(stringWriter != nullptr)
{
if(key == "Text")
{
if(std::holds_alternative<std::string>(value))
{
stringWriter->GetString() = std::get<std::string>(value);
}
cse.back()->Push(gc, stringWriter->GetString());
return false;
}
}
if(key == "NewLine")
{
if(std::holds_alternative<std::string>(value))