Skip to content

Commit ead3dcb

Browse files
committed
Fix LuaTable::try_get_value implementation
1 parent b6b13ad commit ead3dcb

File tree

3 files changed

+102
-6
lines changed

3 files changed

+102
-6
lines changed

src/LuaTable.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
#include "LuaTable.hpp"
2424

2525
#include "utils/convert_godot_lua.hpp"
26-
#include "utils/convert_godot_std.hpp"
2726
#include "utils/metatable.hpp"
27+
#include "utils/stack_top_checker.hpp"
2828

2929
#include <godot_cpp/core/error_macros.hpp>
3030

@@ -37,14 +37,17 @@ LuaTable::LuaTable(sol::table&& table) : LuaObjectSubclass(table) {}
3737
LuaTable::LuaTable(const sol::table& table) : LuaObjectSubclass(table) {}
3838

3939
sol::optional<Variant> LuaTable::try_get_value(const Variant& key) const {
40+
StackTopChecker topcheck(lua_object.lua_state());
4041
lua_State *L = lua_object.lua_state();
41-
auto lua_key = to_lua(L, key);
42-
sol::stack::pop_n(L, 1);
43-
if (auto lua_value = lua_object.get<sol::optional<sol::object>>(lua_key)) {
44-
return to_variant(*lua_value);
42+
sol::stack::push(L, lua_object);
43+
std::ignore = to_lua(L, key);
44+
lua_gettable(L, -2);
45+
auto _ = sol::stack::pop_n(L, 2);
46+
if (lua_isnoneornil(L, -1)) {
47+
return std::nullopt;
4548
}
4649
else {
47-
return {};
50+
return to_variant(L, -1);
4851
}
4952
}
5053

@@ -53,6 +56,7 @@ Variant LuaTable::get_value(const Variant& key, const Variant& default_value) co
5356
}
5457

5558
void LuaTable::set_value(const Variant& key, const Variant& value) {
59+
StackTopChecker topcheck(lua_object.lua_state());
5660
lua_State *L = lua_object.lua_state();
5761
auto table_popper = sol::stack::push_pop(L, lua_object);
5862
std::ignore = to_lua(L, key);
@@ -61,6 +65,7 @@ void LuaTable::set_value(const Variant& key, const Variant& value) {
6165
}
6266

6367
void LuaTable::clear() {
68+
StackTopChecker topcheck(lua_object.lua_state());
6469
for (auto [key, _] : lua_object) {
6570
lua_object[key] = sol::nil;
6671
}
@@ -79,6 +84,7 @@ Array LuaTable::to_array() const {
7984
}
8085

8186
bool LuaTable::_iter_init(const Variant& iter) const {
87+
StackTopChecker topcheck(lua_object.lua_state());
8288
lua_State *L = lua_object.lua_state();
8389
auto table_popper = sol::stack::push_pop(lua_object);
8490
lua_pushnil(L);
@@ -95,6 +101,7 @@ bool LuaTable::_iter_init(const Variant& iter) const {
95101
}
96102

97103
bool LuaTable::_iter_next(const Variant& iter) const {
104+
StackTopChecker topcheck(lua_object.lua_state());
98105
lua_State *L = lua_object.lua_state();
99106
Array arg = iter;
100107
auto table_popper = sol::stack::push_pop(lua_object);
@@ -138,11 +145,13 @@ void LuaTable::_bind_methods() {
138145
}
139146

140147
bool LuaTable::_get(const StringName& property_name, Variant& r_value) const {
148+
StackTopChecker topcheck(lua_object.lua_state());
141149
r_value = to_variant(lua_object[property_name].get<sol::object>());
142150
return true;
143151
}
144152

145153
bool LuaTable::_set(const StringName& property_name, const Variant& value) {
154+
StackTopChecker topcheck(lua_object.lua_state());
146155
lua_object[property_name] = to_lua(lua_object.lua_state(), value);
147156
return true;
148157
}

src/utils/stack_top_checker.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright (C) 2025 Gil Barbosa Reis.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
* this software and associated documentation files (the “Software”), to deal in
6+
* the Software without restriction, including without limitation the rights to
7+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8+
* of the Software, and to permit persons to whom the Software is furnished to do
9+
* so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
#include <godot_cpp/core/error_macros.hpp>
24+
25+
#include "custom_sol.hpp"
26+
#include "stack_top_checker.hpp"
27+
28+
namespace luagdextension {
29+
30+
StackTopChecker::StackTopChecker(lua_State *L)
31+
: L(L)
32+
, previous_top(lua_gettop(L))
33+
{
34+
}
35+
36+
StackTopChecker::~StackTopChecker() {
37+
#ifdef DEBUG_ENABLED
38+
int top = lua_gettop(L);
39+
if (top != previous_top) {
40+
ERR_PRINT(String("Invalid stack top, expected %d, found %d") % Array::make(previous_top, top));
41+
}
42+
#endif
43+
}
44+
45+
}

src/utils/stack_top_checker.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (C) 2025 Gil Barbosa Reis.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
* this software and associated documentation files (the “Software”), to deal in
6+
* the Software without restriction, including without limitation the rights to
7+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8+
* of the Software, and to permit persons to whom the Software is furnished to do
9+
* so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
#ifndef __UTILS_STACK_TOP_CHECKER_HPP__
24+
#define __UTILS_STACK_TOP_CHECKER_HPP__
25+
26+
typedef struct lua_State lua_State;
27+
28+
namespace luagdextension {
29+
30+
class StackTopChecker {
31+
public:
32+
StackTopChecker(lua_State *L);
33+
~StackTopChecker();
34+
35+
private:
36+
lua_State *L;
37+
int previous_top;
38+
};
39+
40+
}
41+
42+
#endif // __UTILS_STACK_TOP_CHECKER_HPP__

0 commit comments

Comments
 (0)