Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions tests/unit/src/unit/issues/Issue7350.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package unit.issues;

class Issue7350 extends Test {
// Return null through try-catch: null must propagate correctly,
// not be confused with _hx_pcall_default sentinel (Lua-specific).
function returnNullFromTry():Dynamic {
try {
return null;
} catch (e:Dynamic) {
return "error";
}
}

// Return false through try-catch: falsy values must propagate.
function returnFalseFromTry():Bool {
try {
return false;
} catch (e:Dynamic) {
return true;
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For this function, haxe currently generates:

___Main_Main_Fields_.returnInTryCatch = function(x) 
  local _hx_status, _hx_result = pcall(function() 
  
      if (x > 0) then 
        do return x * 2 end;
      end;
    return _hx_pcall_default
  end)
  if not _hx_status then 
    local _g = _hx_result;
    return -1;
  elseif _hx_result ~= _hx_pcall_default then
    return _hx_result
  end;
  return 0
end

from what I can tell in this case the do end doesn't make much of a difference?


// Return zero through try-catch.
function returnZeroFromTry():Int {
try {
return 0;
} catch (e:Dynamic) {
return -1;
}
}

// Try body falls through without returning: code after try-catch
// must execute (pcall sentinel must NOT trigger a return).
function fallThroughTry():Int {
var x = 1;
try {
x = 2;
} catch (e:Dynamic) {
x = 3;
}
return x + 10;
}

// Exception in try: catch block should handle it and return.
function returnFromCatch():String {
try {
throw "boom";
} catch (e:Dynamic) {
return "caught";
}
}

// Nested try-catch: inner return must propagate through outer.
function nestedTryCatch():Int {
try {
try {
return 99;
} catch (e:Dynamic) {
return -1;
}
} catch (e:Dynamic) {
return -2;
}
}

// Try-catch in a loop: return exits the function, not just the loop.
function returnFromTryInLoop():Int {
for (i in 0...5) {
try {
if (i == 3)
return i;
} catch (e:Dynamic) {
return -1;
}
}
return -2;
}

// Try-catch where try falls through and catch is not entered:
// subsequent code must see side effects from the try body.
function sideEffectsInTry():String {
var buf = new StringBuf();
buf.add("a");
try {
buf.add("b");
} catch (e:Dynamic) {
buf.add("x");
}
buf.add("c");
return buf.toString();
}

function test() {
eq(null, returnNullFromTry());
eq(false, returnFalseFromTry());
eq(0, returnZeroFromTry());
eq(12, fallThroughTry());
eq("caught", returnFromCatch());
eq(99, nestedTryCatch());
eq(3, returnFromTryInLoop());
eq("abc", sideEffectsInTry());
}
}
Loading