aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/lua/vim/shared.lua2
-rw-r--r--test/functional/lua/vim_spec.lua54
2 files changed, 55 insertions, 1 deletions
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 621de2b1c2..99530bf72e 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -997,7 +997,7 @@ function vim.is_callable(f)
if m == nil then
return false
end
- return type(m.__call) == 'function'
+ return type(rawget(m, '__call')) == 'function'
end
--- Creates a table whose missing keys are provided by {createfn} (like Python's "defaultdict").
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 23bb9f0a2e..03c743c9ae 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -1495,6 +1495,60 @@ describe('lua stdlib', function()
]])
)
+ eq(
+ { false, false },
+ exec_lua([[
+ local meta = { __call = {} }
+ assert(meta.__call)
+ local function new()
+ return setmetatable({}, meta)
+ end
+ local not_callable = new()
+ return { pcall(function() not_callable() end), vim.is_callable(not_callable) }
+ ]])
+ )
+ eq(
+ { false, false },
+ exec_lua([[
+ local function new()
+ return { __call = function()end }
+ end
+ local not_callable = new()
+ assert(not_callable.__call)
+ return { pcall(function() not_callable() end), vim.is_callable(not_callable) }
+ ]])
+ )
+ eq(
+ { false, false },
+ exec_lua([[
+ local meta = setmetatable(
+ { __index = { __call = function() end } },
+ { __index = { __call = function() end } }
+ )
+ assert(meta.__call)
+ local not_callable = setmetatable({}, meta)
+ assert(not_callable.__call)
+ return { pcall(function() not_callable() end), vim.is_callable(not_callable) }
+ ]])
+ )
+ eq(
+ { false, false },
+ exec_lua([[
+ local meta = setmetatable({
+ __index = function()
+ return function() end
+ end,
+ }, {
+ __index = function()
+ return function() end
+ end,
+ })
+ assert(meta.__call)
+ local not_callable = setmetatable({}, meta)
+ assert(not_callable.__call)
+ return { pcall(function() not_callable() end), vim.is_callable(not_callable) }
+ ]])
+ )
eq(false, exec_lua('return vim.is_callable(1)'))
eq(false, exec_lua("return vim.is_callable('foo')"))
eq(false, exec_lua('return vim.is_callable({})'))