__newindex, __namecall, and how to differentiate the two

I am working on my own library. When new members are added to the table, it does some sorting of its own in the __newindex function. What I am trying to know, is how to differentiate:
function object:Create()
end
from
function object.Create()
end

1 Like

You should read Programming in Lua : 16. The linked page talks about this syntax, but the whole chapter is gold.

2 Likes

__namecall is no longer a metamethod you can use, I believe.

__namecall is a Roblox specific metamethod that’s used exclusively on Instances. You can only use it by adding it to a userdata (with newproxy(true)), and, it doesn’t give you any information about the actual call, that information is only accessible from C code.

The : function notation is completely identical to the following cases:

function object:Abc(a, b, c)

end
function object.Abc(self, a, b, c)

end
object:Abc(a, b, c)
object.Abc(object, a, b, c) -- Actually a little slower in luau due to optimizations with the above

There isn’t actually a way to differentiate between these, and, in fact, you can use functions on instances like this:

local Destroy = game.Destroy

Destroy(script) -- This works because game.Destroy, script.Destroy, etc are all the same function, they actually use the instance you pass to them as the target on what to destroy. If you print out the functions you can see they are the same function.

The way that Roblox outputs the error message when you don’t use : is by checking if the first argument is an instance. Really the only way to differentiate is by checking the first argument, there isn’t another way to do this.

2 Likes

That’s not name calling, that’s just a clear call

This is a namecall: workspace("FindFirstChild", "Model")

We can no longer do this, and shouldn’t

Yeah, I am aware that’s not a namecall, sorry if that seemed misleading. My first paragraph at the top is not related to the last part of my message, I was mostly responding to the discussion of the metamethod above, and, I didn’t make it clear my reply was not about the metamethod or namecalling.

If I remember correctly that specific quirk was a bug, I don’t recall all of the details, but, it was removed with one of the initial luau releases and I vaguely remember zeuxg mentioning it.

When you use the : notation on an instance the __namecall metamethod is invoked to make function calls faster for instances. This metamethod used to pass the name of the method being called but in luau this was changed, and now only the self variable and function arguments are passed to the metamethod. The name of the method is no longer passed for performance reasons, it can only be accessed in C code.

@RuizuKun_Dev:

This is a namecall: workspace("FindFirstChild", "Model")

__namecall is a metamethod which fires when you call a function of an object via :, it’s just an internal optimization. What you showed doesn’t invoke the metamethod.

The metamethod is only accessible to proxies as Hexcede stated, but for exploiters its not limited.

Additional Info

Exploiters can easily bypass metatable locks simply doing debug.getmetatable or, getrawmetatable. which is available to them via custom script executors like Synpase. game has a metatable, but its locked. Exploiters bypass this and then simply hook up the __namecall, and can use it to their own advantages. They might even use it for remote methods like FireServer returning something else than expected!

Here’s an example:

local game_meta = getrawmetatable(game)
local game_namecall = game_meta.__namecall

function game_meta.__namecall(self, ...)
    local args = {...}
    local method = args[args]

    if method == "FireServer" or method == "InvokeServer" then
          return "hehe get rekt"
    end
    
    -- idk what should i return
end

__newindex is a metamethod which fires when you append a new key to a table or you update a certain key which already exists.

The difference of these 2 functions down below is that, the one declared with :, will allow you to access self, which refers to the object you call the function from. The function declared with . is just a normal function of the object, nothing fancy.

function object:Create()
end
from
function object.Create()
end

1 Like

I believe you can do it with __call now…
Luaquack used it in his Ascensionist script inside one of the ModuleScripts that are required for Ascensionist

local m=setmetatable({}, {
	__call=function(self, method, ...)
		if method~=nil then
			if string.lower(tostring(method))=="getservice" then
				warn("NOOO YOU CALLED A TABLE NOOOOOOOOOOOOO:"..[[
				
				]]..(...))
				return game:GetService(...)
			else
				return error("You can't call a table, broo its a table not a function bruhh your so bad at scripting if you think tables can be like functions (this is a joke) ", 0)
			end
		end
	end,
})
m("getSErviCE", "Workspace").Name="Wow I JUST CALLED A TABLE LOLZ"

heres the Ascensionist script just incase you wanna check it out.