Consider using xpcall in try block · Issue #1478 · TypeScriptToLua/TypeScriptToLua · GitHub
Skip to content

Consider using xpcall in try block #1478

Open

Description

@pilaoda

Error message from pcall only include the first line that error happened but not the full stack traceback, but this can be done by compiling to using xpcall and pass debug.traceback as second arg:

local result
local function ____catch(err)
    print("catch:", err)
end
local ____try, ____hasReturned = xpcall(
    function()
        result = dosomething(args)
    end,
    debug.traceback
)
if not ____try then
    ____catch(____hasReturned)
end

Although custom plugin can implement this feature, but plugin can not rewrite lualib such as pcall in Promise.lua

Activity

  1. lolleko commented on Sep 10, 2023

    @lolleko
    Member

    Unfortunately, it is not as simple as replacing pcall with xpcall & debug.traceback.
    Because using xpcall & debug.traceback will break our throw implementation.

    e.g.

          try {
              throw "Hello, I am an Error!";
          } catch (error) {
              return error;
          }
    

    would return:

    Hello, I am an Error!
        stack traceback:
            [C]: in function 'error'
            [string \"...\"]:17: in function <[string \"...\"]:16>
            [C]: in function 'xpcall'
            [string \"...\"]:15: in function <[string \"...\"]:6>
            (...tail calls...)
            [string \"...\"]:3: in main chunk
    

    instead of the correct/JS behavior

    Hello, I am an Error!
    

    This can possibly be solved by changing the way we throw string literals. Another solution might be to create a custom/adapted implementation of debug.tracepack.

  2. BribeFromTheHive commented on Feb 9, 2024

    @BribeFromTheHive

    Likely the best middle ground is that an empty catch block can compile to an xpcall, and a non-empty one can compile as-is. Same with un-caught rejected promise objects, if they don't already work that way.

  3. pilaoda commented on Mar 27, 2024

    @pilaoda
    ContributorAuthor


    coroutine.resume also lack of stack trace, the asyncCoroutine should pass into debug.traceback as the first argument to get the error trace in coroutine context.

  4. fadabaerobe6 commented on Apr 27, 2024

    @fadabaerobe6
    -- Reimplemented pcall function
    _G.pcall = function(func, ...)
        local results = table.pack(
            xpcall(func, function(err)
                -- Do nothing here, just return the error object
                return err..'\n'..debug.traceback()
            end, ...)
        )
        local status = table.remove(results, 1)
        if not status then
            -- When an error occurs, err is the error message, mimicking the behavior of pcall
            return false, table.unpack(results)
        else
            -- No error occurred, return all the additional parameters returned by xpcall
            return true, table.unpack(results)
        end
    end

    We can use xpcall to override pcall method to find the origin trackback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions