@@ -7638,7 +7638,7 @@ inline std::optional<int> try_call_index_extensible(lua_State* L, const char* ke
76387638}
76397639
76407640template <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
82628312template <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