-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathxpcall.lua
More file actions
61 lines (57 loc) · 1.71 KB
/
xpcall.lua
File metadata and controls
61 lines (57 loc) · 1.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
--[[
shim layer for xpcall if it doesn't support ... forwarding
used by ext.load
xpcall doesn't forward extra args in vanilla lua 5.1, and in luajit without 5.2 compat (I think?)
while I'm here I will insert a default error handler, since 99% of my xpcall functions do nothing more than
`function(err) return err..'\n'..debug.traceback() end`
so that it will always capture the stack trace at the error by default.
--]]
local function defaultErrorHandler(err)
return tostring(err)..'\n'..debug.traceback()
end
return function(env)
env = env or _G
local oldxpcall = env.xpcall or _G.xpcall
local xpcallCanFwdArgs = select(2,
oldxpcall(
function(x) return x end,
function() end,
true
)
)
-- perform an xpcall without an error handler
-- see if it errors
local xpcallHasDefaultErrorHandler = xpcall(function()
xpcall(function() end)
end, function() end)
if xpcallCanFwdArgs then
if not xpcallHasDefaultErrorHandler then
-- xpcall arg forwarding works
-- just replace xpcall with a default error handler
local newxpcall = function(f, err, ...)
err = err or defaultErrorHandler
return oldxpcall(f, err, ...)
end
env.xpcall = newxpcall
else
-- no changes necessary to xpcall's behavior
-- write .xpcall if it's not already there
if not env.xpcall then
env.xpcall = oldxpcall
end
end
else
-- xpcall arg forwarding doesn't work
-- replace it with an xpcall that does arg forwarding
local unpack = env.unpack or table.unpack
local newxpcall = function(f, err, ...)
err = err or defaultErrorHandler
local args = {...}
args.n = select('#', ...)
return oldxpcall(function()
return f(unpack(args, 1, args.n))
end, err)
end
env.xpcall = newxpcall
end
end