diff --git a/src/logic/scripting/lua/libs/libinput.cpp b/src/logic/scripting/lua/libs/libinput.cpp index 5c85921e..bdd075ac 100644 --- a/src/logic/scripting/lua/libs/libinput.cpp +++ b/src/logic/scripting/lua/libs/libinput.cpp @@ -40,6 +40,7 @@ static int l_add_callback(lua::State* L) { throw std::runtime_error("on_hud_open is not called yet"); } auto key = input_util::keycode_from(bindname.substr(pos + 1)); + lua::pushvalue(L, 2); auto callback = lua::create_simple_handler(L); hud->keepAlive(Events::keyCallbacks[key].add(callback)); return 0; diff --git a/src/logic/scripting/lua/lua_util.cpp b/src/logic/scripting/lua/lua_util.cpp index 3dd51d90..8c3adaea 100644 --- a/src/logic/scripting/lua/lua_util.cpp +++ b/src/logic/scripting/lua/lua_util.cpp @@ -219,7 +219,7 @@ void lua::dump_stack(State* L) { static std::shared_ptr create_lambda_handler(State* L) { auto ptr = reinterpret_cast(topointer(L, -1)); auto name = util::mangleid(ptr); - getglobal(L, LAMBDAS_TABLE); + requireglobal(L, LAMBDAS_TABLE); pushvalue(L, -2); setfield(L, name); pop(L, 2); @@ -227,7 +227,7 @@ static std::shared_ptr create_lambda_handler(State* L) { return std::shared_ptr( new std::string(name), [=](std::string* name) { - getglobal(L, LAMBDAS_TABLE); + requireglobal(L, LAMBDAS_TABLE); pushnil(L); setfield(L, *name); pop(L); @@ -239,41 +239,48 @@ static std::shared_ptr create_lambda_handler(State* L) { runnable lua::create_runnable(State* L) { auto funcptr = create_lambda_handler(L); return [=]() { - getglobal(L, LAMBDAS_TABLE); - getfield(L, *funcptr); - if (call_nothrow(L, 0)) { - pop(L); - } + if (!get_from(L, LAMBDAS_TABLE, *funcptr, false)) + return; + call_nothrow(L, 0, 0); + pop(L); }; } KeyCallback lua::create_simple_handler(State* L) { auto funcptr = create_lambda_handler(L); return [=]() -> bool { - getglobal(L, LAMBDAS_TABLE); - getfield(L, *funcptr); - if (call_nothrow(L, 0)) { - bool result = toboolean(L, -1); - pop(L); - return result; - } else { + if (!get_from(L, LAMBDAS_TABLE, *funcptr, false)) return false; + int top = gettop(L) - 1; + if (call_nothrow(L, 0)) { + int nres = gettop(L) - top; + if (nres) { + bool result = toboolean(L, -1); + pop(L, 1 + nres); + return result; + } } + pop(L); + return false; }; } scripting::common_func lua::create_lambda(State* L) { auto funcptr = create_lambda_handler(L); return [=](const std::vector& args) -> dv::value { - getglobal(L, LAMBDAS_TABLE); - getfield(L, *funcptr); + int top = gettop(L) + 1; + if (!get_from(L, LAMBDAS_TABLE, *funcptr, false)) + return nullptr; for (const auto& arg : args) { pushvalue(L, arg); } if (call(L, args.size(), 1)) { - auto result = tovalue(L, -1); - pop(L, 2); - return result; + int nres = gettop(L) - top; + if (nres) { + auto result = tovalue(L, -1); + pop(L, 1 + nres); + return result; + } } pop(L); return nullptr; @@ -283,16 +290,21 @@ scripting::common_func lua::create_lambda(State* L) { scripting::common_func lua::create_lambda_nothrow(State* L) { auto funcptr = create_lambda_handler(L); return [=](const std::vector& args) -> dv::value { - getglobal(L, LAMBDAS_TABLE); - getfield(L, *funcptr); + int top = gettop(L) - 1; + if (!get_from(L, LAMBDAS_TABLE, *funcptr, false)) + return nullptr; for (const auto& arg : args) { pushvalue(L, arg); } if (call_nothrow(L, args.size(), 1)) { - auto result = tovalue(L, -1); - pop(L); - return result; + int nres = gettop(L) - top; + if (nres) { + auto result = tovalue(L, -1); + pop(L, 1 + nres); + return result; + } } + pop(L); return nullptr; }; } diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index 2748d175..9f3ac414 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -539,10 +539,12 @@ namespace lua { if (getfield(L, name)) { return 1; } else if (required) { + pop(L); throw std::runtime_error( "table " + tableName + " has no member " + name ); } + pop(L); return 0; } else { throw std::runtime_error("table " + tableName + " not found");