1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-21 09:09:43 +00:00

Merge branch 'lua_util' into 'master'

Move LuaState::makeReadOnly(sol::table) out of the class

See merge request OpenMW/openmw!1229
This commit is contained in:
Evil Eye 2021-09-21 15:14:09 +00:00
commit 786b6b7c9a
10 changed files with 44 additions and 41 deletions

View file

@ -7,7 +7,7 @@ namespace MWLua
{
sol::table api(context.mLua->sol(), sol::create);
// TODO
return context.mLua->makeReadOnly(api);
return LuaUtil::makeReadOnly(api);
}
}

View file

@ -48,7 +48,7 @@ namespace MWLua
api["getControlSwitch"] = [input](const std::string& key) { return input->getControlSwitch(key); };
api["setControlSwitch"] = [input](const std::string& key, bool v) { input->toggleControlSwitch(key, v); };
api["ACTION"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
api["ACTION"] = LuaUtil::makeReadOnly(context.mLua->sol().create_table_with(
"GameMenu", MWInput::A_GameMenu,
"Screenshot", MWInput::A_Screenshot,
"Inventory", MWInput::A_Inventory,
@ -102,7 +102,7 @@ namespace MWLua
"ZoomOut", MWInput::A_ZoomOut
));
api["CONTROL_SWITCH"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
api["CONTROL_SWITCH"] = LuaUtil::makeReadOnly(context.mLua->sol().create_table_with(
"Controls", "playercontrols",
"Fighting", "playerfighting",
"Jumping", "playerjumping",
@ -112,7 +112,7 @@ namespace MWLua
"VanityMode", "vanitymode"
));
api["CONTROLLER_BUTTON"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
api["CONTROLLER_BUTTON"] = LuaUtil::makeReadOnly(context.mLua->sol().create_table_with(
"A", SDL_CONTROLLER_BUTTON_A,
"B", SDL_CONTROLLER_BUTTON_B,
"X", SDL_CONTROLLER_BUTTON_X,
@ -130,7 +130,7 @@ namespace MWLua
"DPadRight", SDL_CONTROLLER_BUTTON_DPAD_RIGHT
));
api["CONTROLLER_AXIS"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
api["CONTROLLER_AXIS"] = LuaUtil::makeReadOnly(context.mLua->sol().create_table_with(
"LeftX", SDL_CONTROLLER_AXIS_LEFTX,
"LeftY", SDL_CONTROLLER_AXIS_LEFTY,
"RightX", SDL_CONTROLLER_AXIS_RIGHTX,
@ -144,7 +144,7 @@ namespace MWLua
"MoveLeftRight", SDL_CONTROLLER_AXIS_MAX + MWInput::A_MoveLeftRight
));
return context.mLua->makeReadOnly(api);
return LuaUtil::makeReadOnly(api);
}
}

View file

@ -18,7 +18,7 @@ namespace MWLua
sol::table res(lua.sol(), sol::create);
for (const std::string& v : values)
res[v] = v;
return lua.makeReadOnly(res);
return LuaUtil::makeReadOnly(res);
}
sol::table initCorePackage(const Context& context)
@ -43,7 +43,7 @@ namespace MWLua
"Activator", "Armor", "Book", "Clothing", "Creature", "Door", "Ingredient",
"Light", "Miscellaneous", "NPC", "Player", "Potion", "Static", "Weapon"
});
api["EQUIPMENT_SLOT"] = lua->makeReadOnly(lua->sol().create_table_with(
api["EQUIPMENT_SLOT"] = LuaUtil::makeReadOnly(lua->sol().create_table_with(
"Helmet", MWWorld::InventoryStore::Slot_Helmet,
"Cuirass", MWWorld::InventoryStore::Slot_Cuirass,
"Greaves", MWWorld::InventoryStore::Slot_Greaves,
@ -64,7 +64,7 @@ namespace MWLua
"CarriedLeft", MWWorld::InventoryStore::Slot_CarriedLeft,
"Ammunition", MWWorld::InventoryStore::Slot_Ammunition
));
return lua->makeReadOnly(api);
return LuaUtil::makeReadOnly(api);
}
sol::table initWorldPackage(const Context& context)
@ -107,7 +107,7 @@ namespace MWLua
// return GObjectList{worldView->selectObjects(query, false)};
};
// TODO: add world.placeNewObject(recordId, cell, pos, [rot])
return context.mLua->makeReadOnly(api);
return LuaUtil::makeReadOnly(api);
}
sol::table initNearbyPackage(const Context& context)
@ -137,7 +137,7 @@ namespace MWLua
// TODO: Maybe use sqlite
// return LObjectList{worldView->selectObjects(query, true)};
};
return context.mLua->makeReadOnly(api);
return LuaUtil::makeReadOnly(api);
}
sol::table initQueryPackage(const Context& context)
@ -148,7 +148,7 @@ namespace MWLua
query[t] = Queries::Query(std::string(t));
for (const QueryFieldGroup& group : getBasicQueryFieldGroups())
query[group.mName] = initFieldGroup(context, group);
return query; // makeReadonly is applied by LuaState::addCommonPackage
return query; // makeReadOnly is applied by LuaState::addCommonPackage
}
sol::table initFieldGroup(const Context& context, const QueryFieldGroup& group)
@ -163,12 +163,12 @@ namespace MWLua
{
const std::string& name = field->path()[i];
if (subgroup[name] == sol::nil)
subgroup[name] = context.mLua->makeReadOnly(context.mLua->newTable());
subgroup = context.mLua->getMutableFromReadOnly(subgroup[name]);
subgroup[name] = LuaUtil::makeReadOnly(context.mLua->newTable());
subgroup = LuaUtil::getMutableFromReadOnly(subgroup[name]);
}
subgroup[field->path().back()] = field;
}
return context.mLua->makeReadOnly(res);
return LuaUtil::makeReadOnly(res);
}
}

View file

@ -62,7 +62,7 @@ namespace MWLua
else
return sol::make_object<float>(lua->sol(), value.getFloat());
};
return lua->makeReadOnly(config);
return LuaUtil::makeReadOnly(config);
}
sol::table initGlobalSettingsPackage(const Context& context) { return initSettingsPackage(context, true, false); }

View file

@ -12,7 +12,7 @@ namespace MWLua
{
luaManager->addUIMessage(message);
};
return context.mLua->makeReadOnly(api);
return LuaUtil::makeReadOnly(api);
}
}

View file

@ -119,7 +119,7 @@ return {
EXPECT_ERROR(LuaUtil::call(script["rawsetSystemLib"]), "bad argument #1 to 'rawset' (table expected, got userdata)");
EXPECT_ERROR(LuaUtil::call(script["modifySystemLib"]), "a userdata value");
EXPECT_EQ(mLua.getMutableFromReadOnly(mLua.makeReadOnly(script)), script);
EXPECT_EQ(LuaUtil::getMutableFromReadOnly(LuaUtil::makeReadOnly(script)), script);
}
TEST_F(LuaStateTest, Print)
@ -150,8 +150,8 @@ return {
{
LuaUtil::LuaState lua(mVFS.get());
sol::table api1 = lua.makeReadOnly(lua.sol().create_table_with("name", "api1"));
sol::table api2 = lua.makeReadOnly(lua.sol().create_table_with("name", "api2"));
sol::table api1 = LuaUtil::makeReadOnly(lua.sol().create_table_with("name", "api1"));
sol::table api2 = LuaUtil::makeReadOnly(lua.sol().create_table_with("name", "api2"));
sol::table script1 = lua.runInNewSandbox("bbb/tests.lua", "", {{"test.api", api1}});

View file

@ -67,27 +67,31 @@ namespace LuaUtil
mSandboxEnv = sol::nil;
}
sol::table LuaState::makeReadOnly(sol::table table)
sol::table makeReadOnly(sol::table table)
{
if (table == sol::nil)
return table;
if (table.is<sol::userdata>())
return table; // it is already userdata, no sense to wrap it again
lua_State* lua = table.lua_state();
table[sol::meta_function::index] = table;
sol::stack::push(mLua, std::move(table));
lua_newuserdata(mLua, 0);
lua_pushvalue(mLua, -2);
lua_setmetatable(mLua, -2);
return sol::stack::pop<sol::table>(mLua);
sol::stack::push(lua, std::move(table));
lua_newuserdata(lua, 0);
lua_pushvalue(lua, -2);
lua_setmetatable(lua, -2);
return sol::stack::pop<sol::table>(lua);
}
sol::table LuaState::getMutableFromReadOnly(const sol::userdata& ro)
sol::table getMutableFromReadOnly(const sol::userdata& ro)
{
sol::stack::push(mLua, ro);
int ok = lua_getmetatable(mLua, -1);
lua_State* lua = ro.lua_state();
sol::stack::push(lua, ro);
int ok = lua_getmetatable(lua, -1);
assert(ok);
(void)ok;
sol::table res = sol::stack::pop<sol::table>(mLua);
lua_pop(mLua, 1);
sol::table res = sol::stack::pop<sol::table>(lua);
lua_pop(lua, 1);
return res;
}

View file

@ -3,7 +3,6 @@
#include <map>
#include <limits> // missing from sol/sol.hpp
#include <sol/sol.hpp>
#include <components/vfs/manager.hpp>
@ -37,11 +36,6 @@ namespace LuaUtil
// A shortcut to create a new Lua table.
sol::table newTable() { return sol::table(mLua, sol::create); }
// Makes a table read only (when accessed from Lua) by wrapping it with an empty userdata.
// Needed to forbid any changes in common resources that can accessed from different sandboxes.
sol::table makeReadOnly(sol::table);
sol::table getMutableFromReadOnly(const sol::userdata&);
// Registers a package that will be available from every sandbox via `require(name)`.
// The package can be either a sol::table with an API or a sol::function. If it is a function,
// it will be evaluated (once per sandbox) the first time when requested. If the package
@ -106,6 +100,11 @@ namespace LuaUtil
// String representation of a Lua object. Should be used for debugging/logging purposes only.
std::string toString(const sol::object&);
// Makes a table read only (when accessed from Lua) by wrapping it with an empty userdata.
// Needed to forbid any changes in common resources that can accessed from different sandboxes.
sol::table makeReadOnly(sol::table);
sol::table getMutableFromReadOnly(const sol::userdata&);
}
#endif // COMPONENTS_LUA_LUASTATE_H

View file

@ -25,7 +25,7 @@ namespace LuaUtil
void ScriptsContainer::addPackage(const std::string& packageName, sol::object package)
{
API[packageName] = mLua.makeReadOnly(std::move(package));
API[packageName] = makeReadOnly(std::move(package));
}
bool ScriptsContainer::addNewScript(const std::string& path)
@ -63,7 +63,7 @@ namespace LuaUtil
if (interfaceName.empty() != (publicInterface == sol::nil))
Log(Debug::Error) << mNamePrefix << "[" << path << "]: 'interfaceName' should always be used together with 'interface'";
else if (!interfaceName.empty())
script.as<sol::table>()[INTERFACE] = mPublicInterfaces[interfaceName] = mLua.makeReadOnly(publicInterface);
script.as<sol::table>()[INTERFACE] = mPublicInterfaces[interfaceName] = makeReadOnly(publicInterface);
mScriptOrder.push_back(path);
mScripts[path].mInterface = std::move(script);
return true;
@ -329,7 +329,7 @@ namespace LuaUtil
mHoursTimersQueue.clear();
mPublicInterfaces.clear();
// Assigned by mLua.makeReadOnly, but `clear` removes it, so we need to assign it again.
// Assigned by LuaUtil::makeReadOnly, but `clear` removes it, so we need to assign it again.
mPublicInterfaces[sol::meta_function::index] = mPublicInterfaces;
}

View file

@ -76,7 +76,7 @@ namespace LuaUtil
virtual ~ScriptsContainer() {}
// Adds package that will be available (via `require`) for all scripts in the container.
// Automatically applies LuaState::makeReadOnly to the package.
// Automatically applies LuaUtil::makeReadOnly to the package.
void addPackage(const std::string& packageName, sol::object package);
// Finds a file with given path in the virtual file system, starts as a new script, and adds it to the container.