Merge branch 'master' into merge

This commit is contained in:
Vyacheslav Egorov 2023-04-14 15:06:24 +03:00
commit 70ef0fbc83
4 changed files with 20 additions and 6 deletions

View File

@ -313,7 +313,11 @@ LUA_API uintptr_t lua_encodepointer(lua_State* L, uintptr_t p);
LUA_API double lua_clock(); LUA_API double lua_clock();
LUA_API void lua_setuserdatatag(lua_State* L, int idx, int tag); LUA_API void lua_setuserdatatag(lua_State* L, int idx, int tag);
LUA_API void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*));
typedef void (*lua_Destructor)(lua_State* L, void* userdata);
LUA_API void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor);
LUA_API lua_Destructor lua_getuserdatadtor(lua_State* L, int tag);
LUA_API void lua_clonefunction(lua_State* L, int idx); LUA_API void lua_clonefunction(lua_State* L, int idx);

View File

@ -1378,12 +1378,18 @@ void lua_setuserdatatag(lua_State* L, int idx, int tag)
uvalue(o)->tag = uint8_t(tag); uvalue(o)->tag = uint8_t(tag);
} }
void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*)) void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor)
{ {
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT); api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
L->global->udatagc[tag] = dtor; L->global->udatagc[tag] = dtor;
} }
lua_Destructor lua_getuserdatadtor(lua_State* L, int tag)
{
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
return L->global->udatagc[tag];
}
void lua_clonefunction(lua_State* L, int idx) void lua_clonefunction(lua_State* L, int idx)
{ {
luaC_checkGC(L); luaC_checkGC(L);

View File

@ -24,8 +24,7 @@ void luaU_freeudata(lua_State* L, Udata* u, lua_Page* page)
{ {
if (u->tag < LUA_UTAG_LIMIT) if (u->tag < LUA_UTAG_LIMIT)
{ {
void (*dtor)(lua_State*, void*) = nullptr; lua_Destructor dtor = L->global->udatagc[u->tag];
dtor = L->global->udatagc[u->tag];
// TODO: access to L here is highly unsafe since this is called during internal GC traversal // TODO: access to L here is highly unsafe since this is called during internal GC traversal
// certain operations such as lua_getthreaddata are okay, but by and large this risks crashes on improper use // certain operations such as lua_getthreaddata are okay, but by and large this risks crashes on improper use
if (dtor) if (dtor)

View File

@ -1352,9 +1352,14 @@ TEST_CASE("UserdataApi")
lua_State* L = globalState.get(); lua_State* L = globalState.get();
// setup dtor for tag 42 (created later) // setup dtor for tag 42 (created later)
lua_setuserdatadtor(L, 42, [](lua_State* l, void* data) { auto dtor = [](lua_State* l, void* data) {
dtorhits += *(int*)data; dtorhits += *(int*)data;
}); };
bool dtorIsNull = lua_getuserdatadtor(L, 42) == nullptr;
CHECK(dtorIsNull);
lua_setuserdatadtor(L, 42, dtor);
bool dtorIsSet = lua_getuserdatadtor(L, 42) == dtor;
CHECK(dtorIsSet);
// light user data // light user data
int lud; int lud;