1414#include "graphics/graphics.h"
1515#endif
1616
17- typedef void voidFn (void );
18-
1917#ifdef _WIN32
2018#define LOVR_EXPORT __declspec(dllexport)
2119#else
@@ -47,6 +45,16 @@ static int luax_type(lua_State* L) {
4745 return 1 ;
4846}
4947
48+ #ifdef LOVR_USE_LUAU
49+ static void luax_destructor (lua_State * L , void * userdata ) {
50+ Object * object = userdata ;
51+ if (object -> pointer ) {
52+ lovrRelease (object -> pointer , lovrTypeInfo [object -> type ].destructor );
53+ object -> pointer = NULL ;
54+ }
55+ }
56+ #endif
57+
5058static int luax_release (lua_State * L ) {
5159 Object * object = lua_touserdata (L , 1 );
5260
@@ -68,17 +76,6 @@ static int luax_release(lua_State* L) {
6876 return 0 ;
6977}
7078
71- static int luax_runfinalizers (lua_State * L ) {
72- lua_getfield (L , LUA_REGISTRYINDEX , "_lovrfinalizers" );
73- for (int i = luax_len (L , 2 ); i >= 1 ; i -- ) {
74- lua_rawgeti (L , 2 , i );
75- voidFn * finalizer = (voidFn * ) lua_tocfunction (L , -1 );
76- finalizer ();
77- lua_pop (L , 1 );
78- }
79- return 0 ;
80- }
81-
8279void luax_preload (lua_State * L ) {
8380 static const luaL_Reg lovrModules [] = {
8481 { "lovr" , luaopen_lovr },
@@ -138,13 +135,19 @@ void _luax_registertype(lua_State* L, int type, const char* name, void (*destruc
138135 lua_pushvalue (L , -1 );
139136 lua_setfield (L , -1 , "__index" );
140137
138+ #ifdef LOVR_USE_LUAU
139+ lua_setuserdatadtor (L , type , luax_destructor );
140+ lua_pushvalue (L , -1 );
141+ lua_setuserdatametatable (L , type );
142+ #else
141143 // m.__gc = luax_release
142144 lua_pushcfunction (L , luax_release );
143145 lua_setfield (L , -2 , "__gc" );
144146
145147 // m.__close = gc
146148 lua_pushcfunction (L , luax_release );
147149 lua_setfield (L , -2 , "__close" );
150+ #endif
148151
149152 // m.__tostring
150153 lua_pushcfunction (L , luax_tostring );
@@ -168,13 +171,18 @@ void _luax_registertype(lua_State* L, int type, const char* name, void (*destruc
168171}
169172
170173void * _luax_totype (lua_State * L , int index , int type ) {
174+ #ifdef LOVR_USE_LUAU
175+ Object * object = lua_touserdatatagged (L , index , type );
176+ return object ? object -> pointer : NULL ;
177+ #else
171178 Object * object = lua_touserdata (L , index );
172179
173180 if (object && lua_type (L , index ) != LUA_TLIGHTUSERDATA && object -> type == type ) {
174181 return object -> pointer ;
175182 }
176183
177184 return NULL ;
185+ #endif
178186}
179187
180188void * _luax_checktype (lua_State * L , int index , int type ) {
@@ -240,9 +248,13 @@ void _luax_pushtype(lua_State* L, int type, void* pointer) {
240248 }
241249
242250 // Allocate userdata
251+ #ifdef LOVR_USE_LUAU
252+ Object * object = (Object * ) lua_newuserdatataggedwithmetatable (L , sizeof (Object ), type );
253+ #else
243254 Object * object = (Object * ) lua_newuserdata (L , sizeof (Object ));
244255 luaL_newmetatable (L , lovrTypeInfo [type ].name );
245256 lua_setmetatable (L , -2 );
257+ #endif
246258 lovrRetain (pointer );
247259 object -> pointer = pointer ;
248260 object -> type = type ;
@@ -428,30 +440,35 @@ void luax_setmainthread(lua_State *L) {
428440#endif
429441}
430442
431- void luax_atexit (lua_State * L , voidFn * finalizer ) {
443+ typedef struct Finalizer {
444+ struct Finalizer * next ;
445+ void (* fn )(void );
446+ } Finalizer ;
447+
448+ void luax_atexit (lua_State * L , void (* fn )(void )) {
449+ Finalizer * finalizer = lovrMalloc (sizeof (Finalizer ));
450+ finalizer -> fn = fn ;
451+
432452 lua_getfield (L , LUA_REGISTRYINDEX , "_lovrfinalizers" );
453+ finalizer -> next = lua_touserdata (L , -1 );
454+ lua_pop (L , 1 );
433455
434- if ( lua_isnil ( L , -1 )) {
435- lua_newtable ( L );
436- lua_replace ( L , -2 );
456+ lua_pushlightuserdata ( L , finalizer );
457+ lua_setfield ( L , LUA_REGISTRYINDEX , "_lovrfinalizers" );
458+ }
437459
438- // Userdata sentinel since tables don't have __gc (yet)
439- lua_newuserdata (L , sizeof (void * ));
440- lua_createtable (L , 0 , 1 );
441- lua_pushcfunction (L , luax_runfinalizers );
442- lua_setfield (L , -2 , "__gc" );
443- lua_setmetatable (L , -2 );
444- lua_setfield (L , -2 , "" );
460+ void luax_close (lua_State * L ) {
461+ lua_getfield (L , LUA_REGISTRYINDEX , "_lovrfinalizers" );
462+ Finalizer * finalizer = lua_touserdata (L , -1 );
445463
446- // Write to the registry
447- lua_pushvalue (L , -1 );
448- lua_setfield (L , LUA_REGISTRYINDEX , "_lovrfinalizers" );
449- }
464+ lua_close (L );
450465
451- int length = luax_len (L , -1 );
452- lua_pushcfunction (L , (lua_CFunction ) finalizer );
453- lua_rawseti (L , -2 , length + 1 );
454- lua_pop (L , 1 );
466+ while (finalizer ) {
467+ finalizer -> fn ();
468+ Finalizer * next = finalizer -> next ;
469+ lovrFree (finalizer );
470+ finalizer = next ;
471+ }
455472}
456473
457474uint32_t _luax_checku32 (lua_State * L , int index ) {
0 commit comments