New typeof() global function

They probably don’t want something else to surface with the weekend coming up.

Rip all of Guardian’s code. It was using this :frowning:

Roblox still uses Lua 5.1 where newproxy is a thing. Also I think only newproxy is able to use __len. The primary use that comes to mind is making type return “userdata” instead of “table”.

2 Likes

what if I told you there was a 3rd thegamer101

2 Likes

3 of them? Illuminati confirmed?

Yeah, and the part about type(newproxy(true)) returning “userdata” is also true (and why it’s liked).
You can’t use rawget/rawset on userdata, so you can force people to (new)index, firing the metamethods.
Unlike the official Lua one, we can’t use newproxy(userdata) to get a userdata with the same metatable.
(which is to be expected, as newproxy(game) doesn’t seem very… good…)
Would be nice if we could use newproxy(newproxy(true)) to share one metatable between several stuff.
Seems cleaner than creating (and filling) a metatable for each newproxy instance you make.
(security risk? you can easily make your metamethods check stuff… not that security is a big issue)

1 Like

half-life 3 confirmed

Can’t use rawset/rawget on Userdata, meaning you can make a secure sandbox of the global environment. Useful for stuff like Script Builders, which is admittedly a very narrow use case.

The major reason is: Lua 5.1 has it naturally, and there is zero reason to remove it, as it poses no security or functionality concern.

When is this coming back? I have a very important use case for detecting instances, and hate causing errors to find the actual type :stuck_out_tongue:

1 Like

Until TheGamer101 is able to fix the bug, have this nice alternative hack:

-- Environment Localization
local type          = type
local pcall         = pcall
local string_dump   = string.dump
local string_find   = string.find
local string_match  = string.match

-- string Utilities.TypeOf(anyvalue Anyvalue)
-- Returns the type of its only argument, coded as a string. Includes support for ROBLOX types.
function TypeOf(Anyvalue)
  local AnyvalueType = type(Anyvalue)
  local Ran, Error = pcall(string.dump, Anyvalue)
  if not (Ran) then
    if (string.find(Error, "got (%w+)")) then
      AnyvalueType = string.match(Error, "got (%w+)")
    end
  end

  if not (AnyvalueType) then
    AnyvalueType = type(AnyvalueType)
  end

  if (AnyvalueType == "Object") then
    AnyvalueType = "Instance"
  end
  return AnyvalueType
end

Should work just like typeof, except hacky

[102216] below showed me a stupid. i fixed my stupid. 100% works
[102216a] changed function name to “typeof” so it makes more sense
[102316] realized another flaw in my function. if the passed argument was an “function”, the result would have been nil as string.dump only accepts functions. #fixedtho (also fixed formatting)
[102416] why am i making a changelog for this?
[102416a] fixed not returning “function” for calling typeof(Instance.GetFullName) functions. aka, wasn’t handling “C Lua Functions” correctly
[102416b] due to its rather slow nature, i optimized it a bit. it will also switch over to the real “typeof” when released once again.
[102416c] rip forgot typeof compatibility again. also, it seems you can only do so much with formatting. god it looks ugly here :frowning:
[102416d] fixed a grammar error in post. why am i noting this.
[102516] i rewrote it again. last time i doing it. this one works and works well, and i gotta stop this madness.

12 Likes

Why do you use the same identifier for the function name and a variable in your code? It obfuscates your code because I have to read your entire code to understand that ‘return Type’ is not returning the function itself but rather a variable. Just call the function “typeof”, then the change later on just means you have to delete some code.

1 Like

That’s… pretty good right there. Smart.

1 Like

I have submitted a fix for the bug, so hopefully it will be back soon :slight_smile:

1 Like

… what. That’s clever.

1 Like

Yeah, this is basically the best ROBLOX update in a long time. I just wish it would be un-broken sooner so I can make serialization not lag.

6 Likes

that’s really smart.
I tried implementing your hack differently and the result is pretty small.

local typeof = getfenv(0).typeof -- keeps intellisense from flipping out
if not typeof then
	local type        = type
	local pcall       = pcall
	local string_dump = string.dump
	local string_sub  = string.sub

	function typeof(val)
		local rtype = type(val)
		if rtype == 'userdata' then
			local _, err = pcall(string_dump, val)
			rtype = string_sub(err, 48, -2)
			if rtype == 'Object' then
				return 'Instance'
			end
		end
		return rtype
	end
end
3 Likes

yea … There’s bound to be better ways than mine (aka yours)

1 Like

This should improve your code’s performance and also prevent warnings (without getfenv) :smiley:

typeof = typeof

if not typeof then
	local type = type
	local pcall = pcall
	local string_dump = string.dump
	local string_sub = string.sub
	
	local lookup = setmetatable({}, {
		__index = function(lookup, result)
			local rtype = string_sub(result, 48, -2)
			rtype = (rtype == 'Object' and 'Instance') or rtype
			lookup[result] = rtype
			return rtype
		end
	})
	
	function typeof(val)
		local rtype = type(val)
		if rtype ~= 'userdata' then
			return rtype
		end
		local _, result = pcall(string_dump, val)
		return lookup[result]
	end
end

Even when new API’s are added, some people still manage to play using outdated clients :stuck_out_tongue:

1 Like

Nice! I forgot about negative string indices.
Only reason the getfenv was there was to get around writing typeof=typeof so that intellisense doesn’t complain.

I mean:

local typeof = typeof -- complains
typeof = typeof -- doesn't complain

Whoa, really? That’s a pretty old change by now. I wonder if there’s not some bug in loading the flag that enables it.