GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix try/catch/finally flow by SuperPaintman · Pull Request #1729 · TypeScriptToLua/TypeScriptToLua

Conversation

@SuperPaintman

@SuperPaintman SuperPaintman commented Jun 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

TL;DR

This PR fixes the issue described in #1137.

try/catch/finally blocks didn't behave correctly when the catch block threw (or re-threw) an error. The finally block would never execute because the error from catch propagated immediately.

Example:

InputOutput (-before, +after)
declare function compute(this: void): void

function foo() {
    try {
        compute()
    } catch (err) {
        print("Reporting the error ...")
        throw err;
    } finally {
        print("Cleaning up resources...")
    }
}
 function foo(self)
     do
         local function ____catch(err)
             print("Reporting the error ...")
             error(err, 0)
         end
         local ____try, ____hasReturned = pcall(function()
             compute()
         end)
+        local ____rethrow
         if not ____try then
-            ____catch(____hasReturned)
+            ____try, ____rethrow = pcall(function()
+                ____catch(____hasReturned)
+            end)
         end
         do
             print("Cleaning up resources...")
         end
+        if not ____try then
+            error(____rethrow, 0)
+        end
     end
 end

Logs (-before, +after)

 Reporting the error ...
+Cleaning up resources...
 stdin:8: attempt to call global 'compute' (a nil value)
 stack traceback:
 	[C]: in function 'error'
-	stdin:5: in function '____catch'
-	stdin:11: in function 'foo'
+	stdin:20: in function 'foo'
 	stdin:1: in main chunk

How the fix works

Note: This change only affects try/catch/finally blocks. try/catch and try/finally are unchanged.

We capture any errors from catch block into a ____rethrow variable, then let the finally execute, and only then re-throw the error.

A few more examples

From unit tests (was broken) ("re-throw (%p)")
--- ./testdata-old/testcase-0002.lua
+++ ./testdata/testcase-0002.lua
@@ -1,55 +1,67 @@
 local ____exports = {}
 function ____exports.__main(self)
     local innerTry = false
     local innerFinally = false
     local outerFinally = false
     local function foo(self)
         do
             local function ____catch(e)
                 error((e .. "->") .. "outer.catch", 0)
             end
             local ____try, ____hasReturned = pcall(function()
                 do
                     local function ____catch(e)
                         error((e .. "->") .. "inner.catch", 0)
                     end
                     local ____try, ____hasReturned = pcall(function()
                         if innerTry then
                             error("inner.try", 0)
                         end
                     end)
+                    local ____rethrow
                     if not ____try then
-                        ____catch(____hasReturned)
+                        ____try, ____rethrow = pcall(function()
+                            ____catch(____hasReturned)
+                        end)
                     end
                     do
                         if innerFinally then
                             error("inner.finally", 0)
                         end
                     end
+                    if not ____try then
+                        error(____rethrow, 0)
+                    end
                 end
             end)
+            local ____rethrow
             if not ____try then
-                ____catch(____hasReturned)
+                ____try, ____rethrow = pcall(function()
+                    ____catch(____hasReturned)
+                end)
             end
             do
                 if outerFinally then
                     error("outer.finally", 0)
                 end
             end
+            if not ____try then
+                error(____rethrow, 0)
+            end
         end
     end
     local result = "x"
     do
         local function ____catch(e)
             result = e
         end
         local ____try, ____hasReturned = pcall(function()
             foo(nil)
         end)
         if not ____try then
             ____catch(____hasReturned)
         end
     end
     return result
 end
 return ____exports
From unit tests ("return from catch->finally")
--- ./testdata-old/testcase-0020.lua
+++ ./testdata/testcase-0020.lua
@@ -1,29 +1,35 @@
 local ____exports = {}
 function ____exports.__main(self)
     local x = "unevaluated"
     local function evaluate(self, arg)
         x = "evaluated"
         return arg
     end
     local function foobar(self)
         do
             local function ____catch(e)
                 return true, evaluate(nil, e)
             end
             local ____try, ____hasReturned, ____returnValue = pcall(function()
                 error("foobar", 0)
             end)
+            local ____rethrow
             if not ____try then
-                ____hasReturned, ____returnValue = ____catch(____hasReturned)
+                ____try, ____rethrow = pcall(function()
+                    ____hasReturned, ____returnValue = ____catch(____hasReturned)
+                end)
             end
             do
                 return "finally"
             end
+            if not ____try then
+                error(____rethrow, 0)
+            end
             if ____hasReturned then
                 return ____returnValue
             end
         end
     end
     return (tostring(foobar(nil)) .. " ") .. x
 end
 return ____exports

Resources

Closes: #1137

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
SuperPaintman added 2 commits June 28, 2026 05:43
@SuperPaintman
Fix try/catch/finally flow
5238499
Closes: TypeScriptToLua#1137
@SuperPaintman
Fix comment
5f25852
@SuperPaintman
SuperPaintman marked this pull request as ready for review June 28, 2026 05:11
@SuperPaintman

SuperPaintman commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

CC: @Perryvw as the author of #1137

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Perryvw
Perryvw approved these changes Jun 28, 2026
View reviewed changes

@Perryvw Perryvw left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine, just needs a npm run fix:prettier

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@SuperPaintman
Run prettier
c8d8148
@SuperPaintman

SuperPaintman commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

@Perryvw should be formatted now

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Perryvw
Perryvw merged commit b248e41 into TypeScriptToLua:master Jun 30, 2026
5 checks passed

Uh oh!

There was an error while loading. Please reload this page.

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

Reviewers

@Perryvw Perryvw Perryvw approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

try/finally does not behave as expected when rethrowing

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@SuperPaintman @Perryvw
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.