mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-31 21:45:35 +00:00
Merge branch 'fix_6694' into 'master'
Fix #6694 and add a couple of utility functions Closes #6694 See merge request OpenMW/openmw!1775
This commit is contained in:
commit
934c637c30
3 changed files with 45 additions and 17 deletions
|
@ -46,7 +46,7 @@ namespace LuaUtil
|
||||||
|
|
||||||
static const std::string safeFunctions[] = {
|
static const std::string safeFunctions[] = {
|
||||||
"assert", "error", "ipairs", "next", "pairs", "pcall", "select", "tonumber", "tostring",
|
"assert", "error", "ipairs", "next", "pairs", "pcall", "select", "tonumber", "tostring",
|
||||||
"type", "unpack", "xpcall", "rawequal", "rawget", "rawset", "getmetatable", "setmetatable"};
|
"type", "unpack", "xpcall", "rawequal", "rawget", "rawset", "setmetatable"};
|
||||||
static const std::string safePackages[] = {"coroutine", "math", "string", "table"};
|
static const std::string safePackages[] = {"coroutine", "math", "string", "table"};
|
||||||
|
|
||||||
LuaState::LuaState(const VFS::Manager* vfs, const ScriptsConfiguration* conf) : mConf(conf), mVFS(vfs)
|
LuaState::LuaState(const VFS::Manager* vfs, const ScriptsConfiguration* conf) : mConf(conf), mVFS(vfs)
|
||||||
|
@ -58,7 +58,6 @@ namespace LuaUtil
|
||||||
mLua["math"]["randomseed"] = []{};
|
mLua["math"]["randomseed"] = []{};
|
||||||
|
|
||||||
mLua["writeToLog"] = [](std::string_view s) { Log(Debug::Level::Info) << s; };
|
mLua["writeToLog"] = [](std::string_view s) { Log(Debug::Level::Info) << s; };
|
||||||
mLua["cmetatable"] = [](const sol::table& v) -> sol::object { return v[sol::metatable_key]; };
|
|
||||||
|
|
||||||
// Some fixes for compatibility between different Lua versions
|
// Some fixes for compatibility between different Lua versions
|
||||||
if (mLua["unpack"] == sol::nil)
|
if (mLua["unpack"] == sol::nil)
|
||||||
|
@ -70,29 +69,35 @@ namespace LuaUtil
|
||||||
mLua.script(R"(
|
mLua.script(R"(
|
||||||
local _pairs = pairs
|
local _pairs = pairs
|
||||||
local _ipairs = ipairs
|
local _ipairs = ipairs
|
||||||
local _cmeta = cmetatable
|
pairs = function(v) return (rawget(getmetatable(v) or {}, '__pairs') or _pairs)(v) end
|
||||||
pairs = function(v) return ((_cmeta(v) or v).__pairs or _pairs)(v) end
|
ipairs = function(v) return (rawget(getmetatable(v) or {}, '__ipairs') or _ipairs)(v) end
|
||||||
ipairs = function(v) return ((_cmeta(v) or v).__ipairs or _ipairs)(v) end
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
mLua.script(R"(
|
mLua.script(R"(
|
||||||
local _pairs = pairs
|
local printToLog = function(...)
|
||||||
local _ipairs = ipairs
|
local strs = {}
|
||||||
local _tostring = tostring
|
for i = 1, select('#', ...) do
|
||||||
local _write = writeToLog
|
strs[i] = tostring(select(i, ...))
|
||||||
local printToLog = function(name, ...)
|
|
||||||
local msg = name
|
|
||||||
for _, v in _ipairs({...}) do
|
|
||||||
msg = msg .. '\t' .. _tostring(v)
|
|
||||||
end
|
end
|
||||||
return _write(msg)
|
return writeToLog(table.concat(strs, '\t'))
|
||||||
end
|
end
|
||||||
printGen = function(name) return function(...) return printToLog(name, ...) end end
|
printGen = function(name) return function(...) return printToLog(name, ...) end end
|
||||||
|
|
||||||
local _cmeta = cmetatable
|
function pairsForReadOnly(v)
|
||||||
function pairsForReadOnly(v) return _pairs(_cmeta(v).__index) end
|
local nextFn, t, firstKey = pairs(getmetatable(v).__index)
|
||||||
function ipairsForReadOnly(v) return _ipairs(_cmeta(v).__index) end
|
return function(_, k) return nextFn(t, k) end, v, firstKey
|
||||||
|
end
|
||||||
|
function ipairsForReadOnly(v)
|
||||||
|
local nextFn, t, firstKey = ipairs(getmetatable(v).__index)
|
||||||
|
return function(_, k) return nextFn(t, k) end, v, firstKey
|
||||||
|
end
|
||||||
|
|
||||||
|
getmetatable('').__metatable = false
|
||||||
|
getSafeMetatable = function(v)
|
||||||
|
if type(v) ~= 'table' then error('getmetatable is allowed only for tables', 2) end
|
||||||
|
return getmetatable(v)
|
||||||
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
mSandboxEnv = sol::table(mLua, sol::create);
|
mSandboxEnv = sol::table(mLua, sol::create);
|
||||||
|
@ -107,6 +112,7 @@ namespace LuaUtil
|
||||||
if (mLua[s] == sol::nil) throw std::logic_error("Lua package not found: " + s);
|
if (mLua[s] == sol::nil) throw std::logic_error("Lua package not found: " + s);
|
||||||
mCommonPackages[s] = mSandboxEnv[s] = makeReadOnly(mLua[s]);
|
mCommonPackages[s] = mSandboxEnv[s] = makeReadOnly(mLua[s]);
|
||||||
}
|
}
|
||||||
|
mSandboxEnv["getmetatable"] = mLua["getSafeMetatable"];
|
||||||
mCommonPackages["os"] = mSandboxEnv["os"] = makeReadOnly(tableFromPairs<std::string_view, sol::function>({
|
mCommonPackages["os"] = mSandboxEnv["os"] = makeReadOnly(tableFromPairs<std::string_view, sol::function>({
|
||||||
{"date", mLua["os"]["date"]},
|
{"date", mLua["os"]["date"]},
|
||||||
{"difftime", mLua["os"]["difftime"]},
|
{"difftime", mLua["os"]["difftime"]},
|
||||||
|
@ -162,6 +168,8 @@ namespace LuaUtil
|
||||||
sol::environment env(mLua, sol::create, mSandboxEnv);
|
sol::environment env(mLua, sol::create, mSandboxEnv);
|
||||||
std::string envName = namePrefix + "[" + path + "]:";
|
std::string envName = namePrefix + "[" + path + "]:";
|
||||||
env["print"] = mLua["printGen"](envName);
|
env["print"] = mLua["printGen"](envName);
|
||||||
|
env["_G"] = env;
|
||||||
|
env[sol::metatable_key]["__metatable"] = false;
|
||||||
|
|
||||||
auto maybeRunLoader = [&hiddenData](const sol::object& package) -> sol::object
|
auto maybeRunLoader = [&hiddenData](const sol::object& package) -> sol::object
|
||||||
{
|
{
|
||||||
|
|
|
@ -247,6 +247,19 @@ namespace LuaUtil
|
||||||
util["bitNot"] = [](unsigned a) { return ~a; };
|
util["bitNot"] = [](unsigned a) { return ~a; };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util["loadCode"] = [](const std::string& code, const sol::table& env, sol::this_state s)
|
||||||
|
{
|
||||||
|
sol::state_view lua(s);
|
||||||
|
sol::load_result res = lua.load(code, "", sol::load_mode::text);
|
||||||
|
if (!res.valid())
|
||||||
|
throw std::runtime_error("Lua error: " + res.get<std::string>());
|
||||||
|
sol::function fn = res;
|
||||||
|
sol::environment newEnv(lua, sol::create, env);
|
||||||
|
newEnv[sol::metatable_key][sol::meta_function::new_index] = env;
|
||||||
|
sol::set_environment(newEnv, fn);
|
||||||
|
return fn;
|
||||||
|
};
|
||||||
|
|
||||||
return util;
|
return util;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,13 @@
|
||||||
-- @param #table table Any table.
|
-- @param #table table Any table.
|
||||||
-- @return #table The same table wrapped with read only userdata.
|
-- @return #table The same table wrapped with read only userdata.
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Parses Lua code from string and returns as a function.
|
||||||
|
-- @function [parent=#util] loadCode
|
||||||
|
-- @param #string code Lua code.
|
||||||
|
-- @param #table table Environment to run the code in.
|
||||||
|
-- @return #function The loaded code.
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Bitwise And (supports any number of arguments).
|
-- Bitwise And (supports any number of arguments).
|
||||||
-- @function [parent=#util] bitAnd
|
-- @function [parent=#util] bitAnd
|
||||||
|
|
Loading…
Reference in a new issue