mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-18 11:02:10 +00:00
config/lua: improve error handle-ability with Lua require (#14937)
* config/lua: make `require` throw an actual error for nonexistent modules `require` uses pcall to catch errors and display them to the user. This is usually okay, but it also hides errors if Lua tries to load a nonexistent module, which the Lua config might actually want to detect and handle on its own (e.g. by loading a different module, or disabling functionality). Ref #14534 * config/lua: make vanilla `require` available as `__require` If `safeLuaRequire()`'s error-catching behavior isn't wanted, this allows the user to call the original version directly, as `__require`. Or, they could bring it back as the default by doing e.g. `require = __require`, which might be desired to avoid breaking third-party modules that want to catch errors during module load.
This commit is contained in:
@ -128,6 +128,17 @@ static int safeLuaRequire(lua_State* L) {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// if we failed to resolve the require'd module, return that as an actual
|
||||
// error (so the user can catch it via pcall)
|
||||
{
|
||||
std::string moduleErrPrefix = std::format("module '{}' not found", moduleName);
|
||||
if (err.starts_with(moduleErrPrefix))
|
||||
return luaL_error(L, err.c_str());
|
||||
}
|
||||
|
||||
// otherwise, throw the error message into the config-errors list, and
|
||||
// return an empty table to Lua (weird from a Lua perspective, but
|
||||
// hopefully acceptable since the error is directly visible to the user)
|
||||
if (auto* mgr = CConfigManager::fromLuaState(L); mgr) {
|
||||
if (!moduleName.empty()) {
|
||||
trackRequiredLuaModulePath(L, mgr, moduleName);
|
||||
@ -138,7 +149,7 @@ static int safeLuaRequire(lua_State* L) {
|
||||
|
||||
lua_pop(L, 1); // error object
|
||||
|
||||
lua_newtable(L); // fallback module
|
||||
lua_newtable(L); // empty table as fallback return
|
||||
const int fallbackIdx = lua_gettop(L);
|
||||
|
||||
if (!moduleName.empty()) {
|
||||
@ -322,8 +333,10 @@ void CConfigManager::reinitLuaState() {
|
||||
|
||||
lua_getglobal(m_lua, "require");
|
||||
if (lua_isfunction(m_lua, -1)) {
|
||||
lua_pushvalue(m_lua, -1);
|
||||
lua_setglobal(m_lua, "__require"); // original `require` as `__require`
|
||||
lua_pushcclosure(m_lua, safeLuaRequire, 1);
|
||||
lua_setglobal(m_lua, "require");
|
||||
lua_setglobal(m_lua, "require"); // safe require as `require`
|
||||
} else
|
||||
lua_pop(m_lua, 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user