'load' reader function doesn't need to preserve stack

This commit is contained in:
Roberto I
2026-04-23 17:58:55 -03:00
parent 3228a97c6a
commit 4c5d5063a5

View File

@@ -366,33 +366,24 @@ static int luaB_loadfile (lua_State *L) {
/* /*
** reserved slot, above all arguments, to hold a copy of the returned ** Reader for generic 'load' function.
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/*
** Reader for generic 'load' function: 'lua_load' uses the
** stack for internal stuff, so the reader cannot change the
** stack top. Instead, it keeps its resulting string in a
** reserved slot inside the stack.
*/ */
static const char *generic_reader (lua_State *L, void *ud, size_t *size) { static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
(void)(ud); /* not used */ int *firstcall = cast(int *, ud);
luaL_checkstack(L, 2, "too many nested functions"); luaL_checkstack(L, 2, "too many nested functions");
if (*firstcall)
*firstcall = 0;
else
lua_pop(L, 1); /* remove previous result */
lua_pushvalue(L, 1); /* get function */ lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */ lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) { if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* pop result */
*size = 0; *size = 0;
return NULL; return NULL;
} }
else if (l_unlikely(!lua_isstring(L, -1))) else if (l_unlikely(!lua_isstring(L, -1)))
luaL_error(L, "reader function must return a string"); luaL_error(L, "reader function must return a string");
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ return lua_tolstring(L, -1, size);
return lua_tolstring(L, RESERVEDSLOT, size);
} }
@@ -407,10 +398,10 @@ static int luaB_load (lua_State *L) {
status = luaL_loadbufferx(L, s, l, chunkname, mode); status = luaL_loadbufferx(L, s, l, chunkname, mode);
} }
else { /* loading from a reader function */ else { /* loading from a reader function */
int firstcall = 1; /* userdata for generic_reader */
const char *chunkname = luaL_optstring(L, 2, "=(load)"); const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION); luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */ status = lua_load(L, generic_reader, &firstcall, chunkname, mode);
status = lua_load(L, generic_reader, NULL, chunkname, mode);
} }
return load_aux(L, status, env); return load_aux(L, status, env);
} }