Skip to content

Commit

Permalink
Fix issue with property definitions on valid tables
Browse files Browse the repository at this point in the history
  • Loading branch information
kunitoki committed Jan 3, 2024
1 parent eb3a9c3 commit fbc1eea
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 28 deletions.
81 changes: 58 additions & 23 deletions Source/LuaBridge/detail/Namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -1670,13 +1670,6 @@ class Namespace : public detail::Registrar
template <class T>
Namespace& addVariable(const char* name, const T& value)
{
if (m_stackSize == 1)
{
throw_or_assert<std::logic_error>("addVariable() called on global namespace");

return *this;
}

LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

Expand Down Expand Up @@ -1713,16 +1706,16 @@ class Namespace : public detail::Registrar
template <class T, class = std::enable_if_t<std::is_base_of_v<T, LuaRef> || !std::is_invocable_v<T>>>
Namespace& addProperty(const char* name, T* value, bool isWritable = true)
{
if (m_stackSize == 1)
LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

if (! checkTableHasPropertyGetter())
{
throw_or_assert<std::logic_error>("addProperty() called on global namespace");

return *this;
}

LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

lua_pushlightuserdata(L, value); // Stack: ns, pointer
lua_pushcclosure_x(L, &detail::property_getter<T>::call, 1); // Stack: ns, getter
detail::add_property_getter(L, name, -2); // Stack: ns
Expand Down Expand Up @@ -1755,16 +1748,16 @@ class Namespace : public detail::Registrar
template <class T, class = std::enable_if_t<std::is_base_of_v<T, LuaRef> || !std::is_invocable_v<T>>>
Namespace& addProperty(const char* name, const T* value)
{
if (m_stackSize == 1)
LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

if (! checkTableHasPropertyGetter())
{
throw_or_assert<std::logic_error>("addProperty() called on global namespace");

return *this;
}

LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

lua_pushlightuserdata(L, const_cast<T*>(value)); // Stack: ns, pointer
lua_pushcclosure_x(L, &detail::property_getter<T>::call, 1); // Stack: ns, getter
detail::add_property_getter(L, name, -2); // Stack: ns
Expand Down Expand Up @@ -1792,16 +1785,16 @@ class Namespace : public detail::Registrar
template <class TG, class TS = TG>
Namespace& addProperty(const char* name, TG (*get)(), void (*set)(TS) = nullptr)
{
if (m_stackSize == 1)
LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

if (! checkTableHasPropertyGetter())
{
throw_or_assert<std::logic_error>("addProperty() called on global namespace");

return *this;
}

LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

lua_pushlightuserdata(L, reinterpret_cast<void*>(get)); // Stack: ns, function ptr
lua_pushcclosure_x(L, &detail::invoke_proxy_function<TG (*)()>, 1); // Stack: ns, getter
detail::add_property_getter(L, name, -2);
Expand All @@ -1825,16 +1818,16 @@ class Namespace : public detail::Registrar
template <class TG, class TS = TG>
Namespace& addProperty(const char* name, TG (*get)() noexcept, void (*set)(TS) noexcept = nullptr)
{
if (m_stackSize == 1)
LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

if (! checkTableHasPropertyGetter())
{
throw_or_assert<std::logic_error>("addProperty() called on global namespace");

return *this;
}

LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

lua_pushlightuserdata(L, reinterpret_cast<void*>(get)); // Stack: ns, function ptr
lua_pushcclosure_x(L, &detail::invoke_proxy_function<TG (*)() noexcept>, 1); // Stack: ns, getter
detail::add_property_getter(L, name, -2);
Expand Down Expand Up @@ -1870,6 +1863,13 @@ class Namespace : public detail::Registrar
LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

if (! checkTableHasPropertyGetter())
{
throw_or_assert<std::logic_error>("addProperty() called on global namespace");

return *this;
}

using GetType = decltype(get);
lua_newuserdata_aligned<GetType>(L, std::move(get)); // Stack: ns, function userdata (ud)
lua_pushcclosure_x(L, &detail::invoke_proxy_functor<GetType>, 1); // Stack: ns, ud, getter
Expand Down Expand Up @@ -1902,6 +1902,13 @@ class Namespace : public detail::Registrar
LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

if (! checkTableHasPropertyGetter())
{
throw_or_assert<std::logic_error>("addProperty() called on global namespace");

return *this;
}

addProperty<Getter>(name, std::move(get));

using SetType = decltype(set);
Expand Down Expand Up @@ -1930,6 +1937,13 @@ class Namespace : public detail::Registrar
LUABRIDGE_ASSERT(name != nullptr);
LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns)

if (! checkTableHasPropertyGetter())
{
throw_or_assert<std::logic_error>("addProperty() called on global namespace");

return *this;
}

lua_pushcfunction_x(L, get); // Stack: ns, getter
detail::add_property_getter(L, name, -2); // Stack: ns

Expand Down Expand Up @@ -2006,6 +2020,9 @@ class Namespace : public detail::Registrar
}

//=============================================================================================
/**
* @brief
*/
Table beginTable(const char* name)
{
assertIsActive();
Expand Down Expand Up @@ -2045,6 +2062,24 @@ class Namespace : public detail::Registrar
assertIsActive();
return Class<Derived>(name, std::move(*this), detail::getStaticRegistryKey<Base>(), options);
}

private:
/**
* @brief Checks if the table has a property getter metatable.
*/
bool checkTableHasPropertyGetter() const
{
if (m_stackSize == 1 && lua_istable(L, -1))
{
lua_rawgetp(L, -1, detail::getPropgetKey());
const bool propertyGetterTableIsValid = lua_istable(L, -1);
lua_pop(L, 1);

return propertyGetterTableIsValid;
}

return true;
}
};

//=================================================================================================
Expand Down
10 changes: 5 additions & 5 deletions Tests/Source/NamespaceTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,12 @@ TEST_F(NamespaceTests, AddVariable)

enum class A { a, b, c, d };

#if LUABRIDGE_HAS_EXCEPTIONS
ASSERT_THROW(luabridge::getGlobalNamespace(L).addVariable("int", &int_), std::logic_error);
#endif

luabridge::getGlobalNamespace(L)
.addVariable("int", &int_);

runLua("result = int");
ASSERT_TRUE(result().isNil());
ASSERT_TRUE(result().isNumber());
EXPECT_EQ(int_, result<int>());

luabridge::getGlobalNamespace(L)
.beginNamespace("ns")
Expand Down

0 comments on commit fbc1eea

Please sign in to comment.