debug.getupvalues
Returns all upvalues of a function as a table.
function debug.getupvalues(func: function | number): {any}Synopsis
How it works
Returns all upvaluesUpvalueA variable captured from an enclosing scope. When a function references a local variable from an outer function, that variable becomes an upvalue — stored in an UpVal struct that persists even after the outer function returns. of a closureClosureA function value that captures its lexical environment. In Luau, closures come in two types: LClosure (Luau bytecode + Proto + upvalues) and CClosure (native C function pointer + upvalues). as a table keyed by 1-based index. Each entry maps to an
UpVal struct. Open upvalues (still on the stack) are read through UpVal->v pointer indirection; closed upvalues contain the value directly in UpVal->u.value.Practical use
Upvalues capture the lexical environment of a closureClosureA function value that captures its lexical environment. In Luau, closures come in two types: LClosure (Luau bytecode + Proto + upvalues) and CClosure (native C function pointer + upvalues).. Dumping them reveals the closure's external state: imported modules, configuration values, cached references. Example:
debug.getupvalues(remoteHandler) exposes the upvalueUpvalueA variable captured from an enclosing scope. When a function references a local variable from an outer function, that variable becomes an upvalue — stored in an UpVal struct that persists even after the outer function returns. table used by an obfuscatedObfuscationDeliberately making code harder to understand. Common Luau obfuscation techniques: renaming variables to random strings, inserting dead code, encoding string literals, and wrapping logic in opaque function chains. remote handler.Usage
Dump upvalues
local u1, u2 = function() end, function() end
local function foo() print(u1, u2) end
for k, v in pairs(debug.getupvalues(foo)) do
print(k, v)
endParameters
func function | number A Luau function or stack level.
Returns
{any} Sparse table of upvalues.