Luau - Alteration to `getfenv()` function to allow developers to easily grab the highest stack level

Hello

This feature request may not be a massively popular one, mainly due to the specific nature of what the feature is. Essentially, as far as I know, there is no way to easily get the highest stack level currently in use for functions such as getfenv() and setfenv().

The current implementation does not allow for negative numbers, but I would love if the team working on Luau would make an alteration to that, so that the use of -1 as an argument getfenv(-1) would return the highest stack level function environment.

Currently, the only way I believe this can be achieved is through a for loop, testing each call to getfenv until an error arises. My implementation is below.

--// int getHighestStackLevel()

-- this function loops through function environments until the highest stack level has been reached
function module.getHighestStackLevel()
	local stackLevel = 1
	
	-- Loop through stack levels until we reach the highest one
	while true do
		local success = (pcall(getfenv, stackLevel + 3)) -- +3 to test next stack level, plus the pcall function env, plus the getHighestStackLevel function env

		if success then
			stackLevel += 1
		else
			break
		end
	end
	
	return stackLevel
end

There probably aren’t a massive number of use cases for this on Roblox, especially as the getfenv and setfenv functions are not widely used either. I only ran into this because I was creating a custom logging system to improve the process of creating logs in the output. I found that in order to accurately describe the script in which the log came from, I needed to know the highest stack level as some calls would be nested in other functions.

This is all fine, but it would be great if we could get this information in a simpler, less rustic way.

Any and all feedback is greatly appreciated, I love to hear what you guys think!

Royal

2 Likes

Those functions are likely on their way to deprecation (RFC). It’s not only that there’s not many use cases for it but it’s not exactly good to use either (Importing global access chains).

If you’re creating a logging system, are you able to get any good use case out of debug.traceback? As the name implies, the function returns a traceback - a “How did I get here?” string - that you can use as information (but should not parse directly). In my own codebase, I have a service dedicated to processing logs and each script can, on their own, send tracebacks along with other debug information as desired.

-- Example of my deployment
self:DebugLog(debug.traceback("There was a problem here!"), "warn")
5 Likes

That’s a good point. I should look into debug.traceback more!

1 Like

debug.info would be more useful as Roblox has said not to rely on the format of the return from traceback, since its undefined

1 Like