Use normalized path in LuaState

This commit is contained in:
elsid 2024-08-18 19:57:21 +02:00
parent 090c65c017
commit 32ec92e71c
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625
4 changed files with 52 additions and 41 deletions

View file

@ -16,16 +16,16 @@
namespace LuaUtil
{
static std::string packageNameToVfsPath(std::string_view packageName, const VFS::Manager* vfs)
static VFS::Path::Normalized packageNameToVfsPath(std::string_view packageName, const VFS::Manager& vfs)
{
std::string path(packageName);
std::replace(path.begin(), path.end(), '.', '/');
std::string pathWithInit = path + "/init.lua";
path.append(".lua");
if (vfs->exists(path))
std::string pathValue(packageName);
std::replace(pathValue.begin(), pathValue.end(), '.', '/');
VFS::Path::Normalized pathWithInit(pathValue + "/init.lua");
pathValue.append(".lua");
VFS::Path::Normalized path(pathValue);
if (vfs.exists(path))
return path;
else if (vfs->exists(pathWithInit))
else if (vfs.exists(pathWithInit))
return pathWithInit;
else
throw std::runtime_error("module not found: " + std::string(packageName));
@ -202,7 +202,7 @@ namespace LuaUtil
sol["setEnvironment"]
= [](const sol::environment& env, const sol::function& fn) { sol::set_environment(env, fn); };
sol["loadFromVFS"] = [this](std::string_view packageName) {
return loadScriptAndCache(packageNameToVfsPath(packageName, mVFS));
return loadScriptAndCache(packageNameToVfsPath(packageName, *mVFS));
};
sol["loadInternalLib"] = [this](std::string_view packageName) { return loadInternalLib(packageName); };
@ -341,15 +341,14 @@ namespace LuaUtil
mCommonPackages.insert_or_assign(std::move(packageName), std::move(package));
}
sol::protected_function_result LuaState::runInNewSandbox(const std::string& path, const std::string& namePrefix,
const std::map<std::string, sol::object>& packages, const sol::object& hiddenData)
sol::protected_function_result LuaState::runInNewSandbox(const VFS::Path::Normalized& path,
const std::string& envName, const std::map<std::string, sol::object>& packages, const sol::object& hiddenData)
{
// TODO
sol::protected_function script = loadScriptAndCache(path);
sol::environment env(mSol, sol::create, mSandboxEnv);
std::string envName = namePrefix + "[" + path + "]:";
env["print"] = mSol["printGen"](envName);
env["print"] = mSol["printGen"](envName + ":");
env["_G"] = env;
env[sol::metatable_key]["__metatable"] = false;
@ -395,12 +394,12 @@ namespace LuaUtil
return std::move(res);
}
sol::function LuaState::loadScriptAndCache(const std::string& path)
sol::function LuaState::loadScriptAndCache(const VFS::Path::Normalized& path)
{
auto iter = mCompiledScripts.find(path);
if (iter != mCompiledScripts.end())
{
sol::load_result res = mSol.load(iter->second.as_string_view(), path, sol::load_mode::binary);
sol::load_result res = mSol.load(iter->second.as_string_view(), path.value(), sol::load_mode::binary);
// Unless we have memory corruption issues, the bytecode is valid at this point, but loading might still
// fail because we've hit our Lua memory cap
if (!res.valid())
@ -412,10 +411,10 @@ namespace LuaUtil
return res;
}
sol::function LuaState::loadFromVFS(const std::string& path)
sol::function LuaState::loadFromVFS(const VFS::Path::Normalized& path)
{
std::string fileContent(std::istreambuf_iterator<char>(*mVFS->get(path)), {});
sol::load_result res = mSol.load(fileContent, path, sol::load_mode::text);
sol::load_result res = mSol.load(fileContent, path.value(), sol::load_mode::text);
if (!res.valid())
throw std::runtime_error(std::string("Lua error: ") += res.get<sol::error>().what());
return res;

View file

@ -7,6 +7,8 @@
#include <sol/sol.hpp>
#include <components/vfs/pathutil.hpp>
#include "configuration.hpp"
namespace VFS
@ -141,13 +143,13 @@ namespace LuaUtil
// (the result is expected to be an interface of the script).
// Args:
// path: path to the script in the virtual filesystem;
// namePrefix: sandbox name will be "<namePrefix>[<filePath>]". Sandbox name
// will be added to every `print` output.
// envName: sandbox name.
// packages: additional packages that should be available from the sandbox via `require`. Each package
// should be either a sol::table or a sol::function. If it is a function, it will be evaluated
// (once per sandbox) with the argument 'hiddenData' the first time when requested.
sol::protected_function_result runInNewSandbox(const std::string& path, const std::string& namePrefix = "",
const std::map<std::string, sol::object>& packages = {}, const sol::object& hiddenData = sol::nil);
sol::protected_function_result runInNewSandbox(const VFS::Path::Normalized& path,
const std::string& envName = "unnamed", const std::map<std::string, sol::object>& packages = {},
const sol::object& hiddenData = sol::nil);
void dropScriptCache() { mCompiledScripts.clear(); }
@ -157,7 +159,7 @@ namespace LuaUtil
// directly.
void addInternalLibSearchPath(const std::filesystem::path& path) { mLibSearchPaths.push_back(path); }
sol::function loadInternalLib(std::string_view libName);
sol::function loadFromVFS(const std::string& path);
sol::function loadFromVFS(const VFS::Path::Normalized& path);
sol::environment newInternalLibEnvironment();
uint64_t getTotalMemoryUsage() const { return mSol.memory_used(); }
@ -182,7 +184,7 @@ namespace LuaUtil
friend sol::protected_function_result call(
ScriptId scriptId, const sol::protected_function& fn, Args&&... args);
sol::function loadScriptAndCache(const std::string& path);
sol::function loadScriptAndCache(const VFS::Path::Normalized& path);
static void countHook(lua_State* L, lua_Debug* ar);
static void* trackingAllocator(void* ud, void* ptr, size_t osize, size_t nsize);
@ -227,7 +229,7 @@ namespace LuaUtil
sol::state_view mSol;
const ScriptsConfiguration* mConf;
sol::table mSandboxEnv;
std::map<std::string, sol::bytecode> mCompiledScripts;
std::map<VFS::Path::Normalized, sol::bytecode> mCompiledScripts;
std::map<std::string, sol::object> mCommonPackages;
const VFS::Manager* mVFS;
std::vector<std::filesystem::path> mLibSearchPaths;

View file

@ -97,7 +97,7 @@ namespace LuaUtil
try
{
sol::object scriptOutput = mLua.runInNewSandbox(path, mNamePrefix, mAPI, script.mHiddenData);
sol::object scriptOutput = mLua.runInNewSandbox(path, debugName, mAPI, script.mHiddenData);
if (scriptOutput == sol::nil)
return true;
sol::object engineHandlers = sol::nil, eventHandlers = sol::nil;