Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

"setfenv" not setting the environment properly?

I've been playing around with environment manipulation, and ran into something that really stumbled me. When you try to index a nil value in an environment or table, it should invoke the __index metamethod (if one is set to it). However in my case, it's not doing that. Here's my code:

function Test(x)
	print(x) -- print's nil
end

setfenv(Test,setmetatable({},{
	__index=function(t,k)
		if(k=='x')then
			print("No '"..k.."' value exists, returning default...")
			return "Replaced with this string"
		else
			return getfenv()[k]
		end
	end
}))

Test() -- not assigning any parameters (so, "x" should be nil, therefore allowing "__index" to be invoked when the environment is indexed for "x", like in it's print function above).

Yet, the output still prints "nil". Can anyone help please? Is there any way I can use __index on this function without getting rid of it's argument?

1 answer

✓ Accepted answer

As far as I can tell, lua does not consider x to be undefined because it is receiving the variable as a parameter (even though x is still nil, it is being set to nil when Test runs). If you remove the x parameter from the function, the index metamethod is called:

function Test()
    print(x) -- prints "Replaced with this string"
end
 
setfenv(Test,setmetatable({},{
    __index=function(t,k)
        if(k=='x')then
            print("No '"..k.."' value exists, returning default...")
            return "Replaced with this string"
        else
            return getfenv()[k]
        end
    end
}))
 
Test()

If you want to look into this behaviour further, I would recommend looking into lua disassembling tools.

3 comments

1

fenv metatables don't register for indexing a local variable. function arguments count as local.

1

Shows how much I know about function environments. Your comment does make a perfect answer though.

0

Still helped clear my miss-understanding. Thank you both.

This discussion is preserved as it was. New answers, comments, and votes are closed.