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

[Lua 5."2"] [1.7.4] Applying an environment to a coroutine

Started by Geforce Fan, 17 July 2015 - 08:37 PM
Geforce Fan #1
Posted 17 July 2015 - 10:37 PM
With the 1.7.4 update, setfenv is sort of depreciated now, and lua 5.2 functions have been added, or at least some of them. Is there a way I can apply an environment to a coroutine, spawned from a pre-specified function? I'm not loading the function as a string, I'm receiving it from an untrusted source, and I want to set its environment. Once again, I am NOT loading it from a string.

~~Nobump: Thanks for the replies.
R.I.P. in peace setfenv. You will be dearly missed.

//offtopic Rest In Peace in peace makes no sense. Ugh… (sorry :P/>)
I know, that's why it's funny. It's making fun of people who do that.
Edited on 19 July 2015 - 04:46 PM
Lignum #2
Posted 17 July 2015 - 11:20 PM
There's no real way to do it anymore, I'm afraid. Your best bet would be to avoid the situation in the first place. However, you could try to use string.dump on the function to get its code and then load a new function from that code with the desired environment. This won't work if the function has upvalues, though! It's a very hacky and slow way to do it but, if it works, it's the best there is.

EDIT: I've just given it a try, and I was stopped by the error "Binary chunk loading prohibited". I suppose this is because the compatibility layer doesn't support them? If so, it should work when Lua 5.2 is actually implemented. Until then you could use the code at the end of this thread to allow loadstring to load chunks.
Edited on 17 July 2015 - 09:32 PM
Geforce Fan #3
Posted 18 July 2015 - 02:32 AM
There's no real way to do it anymore, I'm afraid. Your best bet would be to avoid the situation in the first place. However, you could try to use string.dump on the function to get its code and then load a new function from that code with the desired environment. This won't work if the function has upvalues, though! It's a very hacky and slow way to do it but, if it works, it's the best there is.

EDIT: I've just given it a try, and I was stopped by the error "Binary chunk loading prohibited". I suppose this is because the compatibility layer doesn't support them? If so, it should work when Lua 5.2 is actually implemented. Until then you could use the code at the end of this thread to allow loadstring to load chunks.
Sigh….
R.I.P. in peace setfenv. You will be dearly missed.

Re-looking at my code, I probably don't need to set the environment of coroutines, it just makes it a little bit harder for me since I have to do it manually every time I call the task creation function. Routines created from an outside source can't get into the protected environment I don't want foreign code running in anyway, so there's that.
KingofGamesYami #4
Posted 18 July 2015 - 03:13 AM
R.I.P. in peace setfenv. You will be dearly missed.

//offtopic Rest In Peace in peace makes no sense. Ugh… (sorry :P/>)
Exerro #5
Posted 18 July 2015 - 11:27 AM
Well, I'm not sure about this, you seemed pretty clear about the fact that the code/function was not being loaded from a file, but whether or not that's just because the code that loads the file is different to the sandbox, and therefore can't load the code in a sandboxed environment, was unclear. If so, you can use some fancy metatable magic to dynamically change the function's (and coroutine's) environment:


local environments = {}
function loadfile( file )
	 local content = readfile( file ) -- I'm assuming you can do this part yourself (' to fix forum syntax highlighting)
	 local f, err
	 local env = setmetatable( {}, { __index = function( t, k ) return environments[f][k] end, __newindex( t, k, v ) environments[f][k] = v end } )
	 f, err = load( content, fs.getName( file ), nil, env )
	 if not f then return false, err end
	 environments[f] = getfenv( 2 ) -- the caller's environment, because that's generally what you want?
	 return f
end
function setfenv( f, env )
	 environments[f] = env
end
function getfenv( f )
	 return environments[f]
end
Edited on 18 July 2015 - 09:29 AM
Bomb Bloke #6
Posted 19 July 2015 - 03:28 AM
There was a bit of discussion about this in the beta thread, starting here.

There's no real way to do it anymore, I'm afraid.

Or at least, there presumably won't be. But setfenv isn't gone yet! ;)/>