Skip to content

Commit b11e6ca

Browse files
authored
Fix __index fallback/getter priority and cross-class member pointer registration (#255)
1 parent 0782a94 commit b11e6ca

5 files changed

Lines changed: 698 additions & 92 deletions

File tree

‎.github/workflows/build_linux.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ concurrency:
1717
cancel-in-progress: true
1818

1919
env:
20-
BUILD_TYPE: Release
20+
BUILD_TYPE: RelWithDebInfo
2121

2222
jobs:
2323
lua:

‎Distribution/LuaBridge/LuaBridge.h‎

Lines changed: 125 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7638,7 +7638,7 @@ inline std::optional<int> try_call_index_extensible(lua_State* L, const char* ke
76387638
}
76397639

76407640
template <bool IsObject>
7641-
inline std::optional<int> try_call_parent_index_fallback(lua_State* L, const char* key)
7641+
inline std::optional<int> try_call_parent_index_extensibles(lua_State* L, const char* key)
76427642
{
76437643
LUABRIDGE_ASSERT(lua_istable(L, -1));
76447644

@@ -7675,6 +7675,40 @@ inline std::optional<int> try_call_parent_index_fallback(lua_State* L, const cha
76757675
}
76767676
}
76777677

7678+
lua_pop(L, 1);
7679+
}
7680+
7681+
lua_pop(L, 1);
7682+
return std::nullopt;
7683+
}
7684+
7685+
template <bool IsObject>
7686+
inline std::optional<int> try_call_parent_index_fallbacks(lua_State* L, const char* key)
7687+
{
7688+
LUABRIDGE_ASSERT(lua_istable(L, -1));
7689+
7690+
if (key == nullptr)
7691+
return std::nullopt;
7692+
7693+
lua_rawgetp_x(L, -1, getParentKey());
7694+
if (! lua_istable(L, -1))
7695+
{
7696+
lua_pop(L, 1);
7697+
return std::nullopt;
7698+
}
7699+
7700+
const int parentListIndex = lua_absindex(L, -1);
7701+
const int parentCount = get_length(L, parentListIndex);
7702+
7703+
for (int i = 1; i <= parentCount; ++i)
7704+
{
7705+
lua_rawgeti(L, parentListIndex, i);
7706+
if (! lua_istable(L, -1))
7707+
{
7708+
lua_pop(L, 1);
7709+
continue;
7710+
}
7711+
76787712
lua_rawgetp_x(L, -1, getIndexFallbackKey());
76797713
if (lua_iscfunction(L, -1))
76807714
{
@@ -7725,15 +7759,18 @@ inline int index_metamethod(lua_State* L)
77257759

77267760
for (;;)
77277761
{
7762+
const Options options = get_class_options(L, -1);
7763+
77287764
if constexpr (IsObject)
77297765
{
7730-
7731-
if (auto result = try_call_index_fallback(L))
7732-
return *result;
7766+
if (options.test(extensibleClass | allowOverridingMethods))
7767+
{
7768+
if (auto result = try_call_index_fallback(L))
7769+
return *result;
7770+
}
77337771
}
77347772
else
77357773
{
7736-
77377774
if (auto result = try_call_static_index_fallback(L))
77387775
return *result;
77397776
}
@@ -7771,7 +7808,6 @@ inline int index_metamethod(lua_State* L)
77717808
LUABRIDGE_ASSERT(lua_isnil(L, -1));
77727809
lua_pop(L, 1);
77737810

7774-
const Options options = get_class_options(L, -1);
77757811
if (options.test(extensibleClass | allowOverridingMethods))
77767812
{
77777813
if (auto result = try_call_index_extensible<IsObject>(L, key))
@@ -7864,7 +7900,21 @@ inline int index_metamethod(lua_State* L)
78647900
return *result;
78657901
}
78667902

7867-
if (auto result = try_call_parent_index_fallback<IsObject>(L, key))
7903+
if (auto result = try_call_parent_index_extensibles<IsObject>(L, key))
7904+
return *result;
7905+
7906+
if constexpr (IsObject)
7907+
{
7908+
if (auto result = try_call_index_fallback(L))
7909+
return *result;
7910+
}
7911+
else
7912+
{
7913+
if (auto result = try_call_static_index_fallback(L))
7914+
return *result;
7915+
}
7916+
7917+
if (auto result = try_call_parent_index_fallbacks<IsObject>(L, key))
78687918
return *result;
78697919

78707920
lua_pop(L, 1);
@@ -8260,7 +8310,7 @@ inline std::optional<int> try_call_newindex_extensible(lua_State* L, const char*
82608310
}
82618311

82628312
template <bool IsObject>
8263-
inline std::optional<int> try_call_parent_newindex(lua_State* L)
8313+
inline std::optional<int> try_call_parent_newindex_setters(lua_State* L)
82648314
{
82658315
LUABRIDGE_ASSERT(lua_istable(L, -1));
82668316

@@ -8310,6 +8360,37 @@ inline std::optional<int> try_call_parent_newindex(lua_State* L)
83108360
lua_pop(L, 1);
83118361
}
83128362

8363+
lua_pop(L, 1);
8364+
}
8365+
8366+
lua_pop(L, 1);
8367+
return std::nullopt;
8368+
}
8369+
8370+
template <bool IsObject>
8371+
inline std::optional<int> try_call_parent_newindex_fallbacks(lua_State* L)
8372+
{
8373+
LUABRIDGE_ASSERT(lua_istable(L, -1));
8374+
8375+
lua_rawgetp_x(L, -1, getParentKey());
8376+
if (! lua_istable(L, -1))
8377+
{
8378+
lua_pop(L, 1);
8379+
return std::nullopt;
8380+
}
8381+
8382+
const int parentListIndex = lua_absindex(L, -1);
8383+
const int parentCount = get_length(L, parentListIndex);
8384+
8385+
for (int i = 1; i <= parentCount; ++i)
8386+
{
8387+
lua_rawgeti(L, parentListIndex, i);
8388+
if (! lua_istable(L, -1))
8389+
{
8390+
lua_pop(L, 1);
8391+
continue;
8392+
}
8393+
83138394
lua_rawgetp_x(L, -1, getNewIndexFallbackKey());
83148395
if (lua_iscfunction(L, -1))
83158396
{
@@ -8365,6 +8446,9 @@ inline int newindex_metamethod(lua_State* L)
83658446

83668447
lua_pop(L, 1);
83678448

8449+
if (auto result = try_call_parent_newindex_setters<IsObject>(L))
8450+
return *result;
8451+
83688452
if constexpr (IsObject)
83698453
{
83708454
if (auto result = try_call_newindex_fallback(L))
@@ -8390,27 +8474,7 @@ inline int newindex_metamethod(lua_State* L)
83908474
}
83918475
}
83928476

8393-
lua_rawgetp_x(L, -1, getPropsetKey());
8394-
if (lua_istable(L, -1))
8395-
{
8396-
lua_pushvalue(L, 2);
8397-
lua_rawget(L, -2);
8398-
lua_remove(L, -2);
8399-
8400-
if (lua_iscfunction(L, -1))
8401-
{
8402-
lua_remove(L, -2);
8403-
if constexpr (IsObject)
8404-
lua_pushvalue(L, 1);
8405-
lua_pushvalue(L, 3);
8406-
lua_call(L, IsObject ? 2 : 1, 0);
8407-
return 0;
8408-
}
8409-
}
8410-
8411-
lua_pop(L, 1);
8412-
8413-
if (auto result = try_call_parent_newindex<IsObject>(L))
8477+
if (auto result = try_call_parent_newindex_fallbacks<IsObject>(L))
84148478
return *result;
84158479

84168480
if constexpr (IsObject)
@@ -9452,36 +9516,44 @@ void push_class_property_getter(lua_State* L, T (U::*value), const char* debugna
94529516
lua_pushcclosure_x(L, &property_getter<T, C>::call, debugname, 1);
94539517
}
94549518

9455-
template <class C, class T>
9456-
void push_class_property_getter(lua_State* L, T (C::*getter)() const, const char* debugname)
9519+
template <class C, class B, class T>
9520+
void push_class_property_getter(lua_State* L, T (B::*getter)() const, const char* debugname)
94579521
{
9522+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9523+
94589524
using GetType = decltype(getter);
94599525

94609526
new (lua_newuserdata_x<GetType>(L, sizeof(GetType))) GetType(getter);
94619527
lua_pushcclosure_x(L, &invoke_const_member_function<GetType, C>, debugname, 1);
94629528
}
94639529

9464-
template <class C, class T>
9465-
void push_class_property_getter(lua_State* L, T (C::*getter)() const noexcept, const char* debugname)
9530+
template <class C, class B, class T>
9531+
void push_class_property_getter(lua_State* L, T (B::*getter)() const noexcept, const char* debugname)
94669532
{
9533+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9534+
94679535
using GetType = decltype(getter);
94689536

94699537
new (lua_newuserdata_x<GetType>(L, sizeof(GetType))) GetType(getter);
94709538
lua_pushcclosure_x(L, &invoke_const_member_function<GetType, C>, debugname, 1);
94719539
}
94729540

9473-
template <class C, class T>
9474-
void push_class_property_getter(lua_State* L, T (C::*getter)(lua_State*) const, const char* debugname)
9541+
template <class C, class B, class T>
9542+
void push_class_property_getter(lua_State* L, T (B::*getter)(lua_State*) const, const char* debugname)
94759543
{
9544+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9545+
94769546
using GetType = decltype(getter);
94779547

94789548
new (lua_newuserdata_x<GetType>(L, sizeof(GetType))) GetType(getter);
94799549
lua_pushcclosure_x(L, &invoke_const_member_function<GetType, C>, debugname, 1);
94809550
}
94819551

9482-
template <class C, class T>
9483-
void push_class_property_getter(lua_State* L, T (C::*getter)(lua_State*) const noexcept, const char* debugname)
9552+
template <class C, class B, class T>
9553+
void push_class_property_getter(lua_State* L, T (B::*getter)(lua_State*) const noexcept, const char* debugname)
94849554
{
9555+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9556+
94859557
using GetType = decltype(getter);
94869558

94879559
new (lua_newuserdata_x<GetType>(L, sizeof(GetType))) GetType(getter);
@@ -9607,36 +9679,44 @@ void push_class_property_setter(lua_State* L, T U::*value, const char* debugname
96079679
lua_pushcclosure_x(L, &property_setter<T, C>::call, debugname, 1);
96089680
}
96099681

9610-
template <class C, class T>
9611-
void push_class_property_setter(lua_State* L, void (C::*setter)(T), const char* debugname)
9682+
template <class C, class B, class T>
9683+
void push_class_property_setter(lua_State* L, void (B::*setter)(T), const char* debugname)
96129684
{
9685+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9686+
96139687
using SetType = decltype(setter);
96149688

96159689
new (lua_newuserdata_x<SetType>(L, sizeof(SetType))) SetType(setter);
96169690
lua_pushcclosure_x(L, &invoke_member_function<SetType, C>, debugname, 1);
96179691
}
96189692

9619-
template <class C, class T>
9620-
void push_class_property_setter(lua_State* L, void (C::*setter)(T) noexcept, const char* debugname)
9693+
template <class C, class B, class T>
9694+
void push_class_property_setter(lua_State* L, void (B::*setter)(T) noexcept, const char* debugname)
96219695
{
9696+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9697+
96229698
using SetType = decltype(setter);
96239699

96249700
new (lua_newuserdata_x<SetType>(L, sizeof(SetType))) SetType(setter);
96259701
lua_pushcclosure_x(L, &invoke_member_function<SetType, C>, debugname, 1);
96269702
}
96279703

9628-
template <class C, class T>
9629-
void push_class_property_setter(lua_State* L, void (C::*setter)(T, lua_State*), const char* debugname)
9704+
template <class C, class B, class T>
9705+
void push_class_property_setter(lua_State* L, void (B::*setter)(T, lua_State*), const char* debugname)
96309706
{
9707+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9708+
96319709
using SetType = decltype(setter);
96329710

96339711
new (lua_newuserdata_x<SetType>(L, sizeof(SetType))) SetType(setter);
96349712
lua_pushcclosure_x(L, &invoke_member_function<SetType, C>, debugname, 1);
96359713
}
96369714

9637-
template <class C, class T>
9638-
void push_class_property_setter(lua_State* L, void (C::*setter)(T, lua_State*) noexcept, const char* debugname)
9715+
template <class C, class B, class T>
9716+
void push_class_property_setter(lua_State* L, void (B::*setter)(T, lua_State*) noexcept, const char* debugname)
96399717
{
9718+
static_assert(std::is_same_v<C, B> || std::is_base_of_v<B, C>);
9719+
96409720
using SetType = decltype(setter);
96419721

96429722
new (lua_newuserdata_x<SetType>(L, sizeof(SetType))) SetType(setter);

0 commit comments

Comments
 (0)