This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
EveryOS's profile picture

Backup for getfenv

Started by EveryOS, 02 May 2018 - 05:12 PM
EveryOS #1
Posted 02 May 2018 - 07:12 PM
I noticed this line in the BIOs.

Is there an alternative to the getfenv function, which I use alot?
SquidDev #2
Posted 02 May 2018 - 07:32 PM
Whilst it's only disabled when the disable_lua51_features config option is enabled, it's generally better to use _ENV and the environment arguments to load/loadfile instead of using getfenv and setfenv. As it ensures compatibility into the future. You can always do _ENV or getfenv() if you want to handle pre-1.74 versions, though I don't personally think it's worth the issue.

For more information, see this section of the manual.
EveryOS #3
Posted 02 May 2018 - 08:04 PM
But what if I had an already-defined function that I won't to know the _ENV of? Is there like a metatable or something to help?
SquidDev #4
Posted 02 May 2018 - 08:24 PM
But what if I had an already-defined function that I won't to know the _ENV of? Is there like a metatable or something to help?
Nope.* You'll sadly have to find other ways to do whatever you are planning/needing to do.

*It's technically possible to do it with the debug API, but CC doesn't have that either.
Sewbacca #5
Posted 03 May 2018 - 09:07 AM
I think setfenv and getfenv are removed for security reasons, but you can keep track of all environments, if you need to.
Example (keeping track of all env of a custom application starter):


local tRunningPrograms = {}

local function createCustomEnv(path)
  local tEnv = { __runningProgram = path }
  local tMetatable = { __index = _G }
  setmetatable(tEnv, tMetatable)
  return tEnv, tMetatable
end

function run(sPath, ...)
  local tEnv, tMetatable = createCustomEnv(sPath)
  tRunningPrograms[#tRunningPrograms + 1] = {
	path = sPath,
	env = tEnv,
	metatable = tMetatable
  }
  os.run(tEnv, sPath, ...)
end

function prohibit(nID, sAPI)
  -- Note: This prohibition can be easily broken, if the program says: <sAPI> = nil,
  -- Then it have to know what proxy you are using -> it must be designed for your proxy
  -- There are some workarrounds, but this is just a demonstration of accessing environments.
  tRunningPrograms[nID].env[sAPI] = false
end


That is the way, how you could keep track of environments. If your program is structured like this, then write a simple getEnv(nID) [nID is not the level, but the running program] method and replace it with your getfenv method.
Edited on 03 May 2018 - 08:50 AM
SquidDev #6
Posted 03 May 2018 - 09:24 AM
-snip-
One very minor thing worth mentioning is that setmetatable returns the first table (except in a couple of edge cases, but that's a LuaJ quirk). This means tEnv and tMetatable are the same value.
Sewbacca #7
Posted 03 May 2018 - 10:52 AM
One very minor thing worth mentioning is that setmetatable returns the first table (except in a couple of edge cases, but that's a LuaJ quirk). This means tEnv and tMetatable are the same value.

Oh, just forgot it, thank you for mentioning. Edited. Please explain in which edge cases LuaJ quirks!
SquidDev #8
Posted 03 May 2018 - 11:11 AM
Please explain in which edge cases LuaJ quirks!
Setting the __mode key on a metatable will return a copy of the table instead of modifying the original one. This is a bug and is fixed in CC:Tweaked (and I believe in later versions of LuaJ).