evaera / roblox-lua-promise

Promise implementation for Roblox
https://eryn.io/roblox-lua-promise/
MIT License
281 stars 78 forks source link

support tables with __call metamethod in handlers #64

Closed matthargett closed 2 years ago

matthargett commented 3 years ago

The library currently checks for:

    assert(
        successHandler == nil or type(successHandler) == "function",
        string.format(ERROR_NON_FUNCTION, "Promise:andThen")
    )
    assert(
        failureHandler == nil or type(failureHandler) == "function",
        string.format(ERROR_NON_FUNCTION, "Promise:andThen")
    )

which will fail for callable tables that use the __call metamethod, so this code fails the assertion above:

        local wrapped = {}
        setmetatable(wrapped, {
            __call = _wrapped,
        })
        wrapped.cancel = _cancel

                Promise.new():andThen(wrapped, wrapped)

a helper method that could be used in the library might look like:

local function isCallable(value)
  if typeof(value) == "function" then
    return true
  end
  if typeof(value) == "table" then
    local mt = getmetatable(value)
    if mt and rawget(mt, "__call") then
      return true
    end
  end
  return false
end
evaera commented 3 years ago

Supporting callable tables sounds good to me. We should make sure that we update this behavior everywhere we check for things that are functions.