diff --git a/CHANGELOG.md b/CHANGELOG.md index 284f22b98..f50672d73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,7 @@ All notable changes to this project will be documented in this file. - [#2162] Debugger - ignore (warn) invalid jumps when injecting debug info - AS3 - extra newlines on methods which use activation - [#2162] AS3 switch inside foreach +- [#2162] AS3 try inside foreach ### Changed - [#2120] Exported assets no longer take names from assigned classes if there is more than 1 assigned class diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 5e5aba102..97d84d1c9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -2048,48 +2048,59 @@ public class AVM2Graph extends Graph { } @Override - protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData, String path) { - super.finalProcessAfter(list, level, localData, path); - for (int i = 0; i < list.size(); i++) { - - //Remove continues from all branches of try...catch block if its continue to parent loop - if (list.get(i) instanceof LoopItem) { - LoopItem li = (LoopItem) list.get(i); - if (li.hasBaseBody()) { - List loopCommands = li.getBaseBodyCommands(); - if (!loopCommands.isEmpty()) { - if (loopCommands.get(loopCommands.size() - 1) instanceof TryAVM2Item) { - TryAVM2Item ta = (TryAVM2Item) loopCommands.get(loopCommands.size() - 1); - for (List cc : ta.catchCommands) { - if (!cc.isEmpty()) { - if (cc.get(cc.size() - 1) instanceof ContinueItem) { - ContinueItem ci = (ContinueItem) cc.get(cc.size() - 1); - if (ci.loopId == li.loop.id) { - cc.remove(cc.size() - 1); - } - } - } - } - if (!ta.tryCommands.isEmpty()) { - if (ta.tryCommands.get(ta.tryCommands.size() - 1) instanceof ContinueItem) { - ContinueItem ci = (ContinueItem) ta.tryCommands.get(ta.tryCommands.size() - 1); - if (ci.loopId == li.loop.id) { - ta.tryCommands.remove(ta.tryCommands.size() - 1); - } - } - } - if (!ta.finallyCommands.isEmpty()) { - if (ta.finallyCommands.get(ta.finallyCommands.size() - 1) instanceof ContinueItem) { - ContinueItem ci = (ContinueItem) ta.finallyCommands.get(ta.finallyCommands.size() - 1); - if (ci.loopId == li.loop.id) { - ta.finallyCommands.remove(ta.finallyCommands.size() - 1); - } - } - } + protected void processOther(List list, long lastLoopId) { + if (list.isEmpty()) { + return; + } + + int pos = list.size() - 1; + + if (list.get(pos) instanceof ContinueItem) { + if (((ContinueItem) list.get(pos)).loopId != lastLoopId) { + return; + } + pos--; + if (list.size() < 2) { + return; + } + } + + //Remove continues from all branches of try...catch block if its continue to parent loop + if (list.get(pos) instanceof TryAVM2Item) { + TryAVM2Item ta = (TryAVM2Item) list.get(pos); + for (List cc : ta.catchCommands) { + if (!cc.isEmpty()) { + if (cc.get(cc.size() - 1) instanceof ContinueItem) { + ContinueItem ci = (ContinueItem) cc.get(cc.size() - 1); + if (ci.loopId == lastLoopId) { + cc.remove(cc.size() - 1); } } } } + if (!ta.tryCommands.isEmpty()) { + if (ta.tryCommands.get(ta.tryCommands.size() - 1) instanceof ContinueItem) { + ContinueItem ci = (ContinueItem) ta.tryCommands.get(ta.tryCommands.size() - 1); + if (ci.loopId == lastLoopId) { + ta.tryCommands.remove(ta.tryCommands.size() - 1); + } + } + } + if (!ta.finallyCommands.isEmpty()) { + if (ta.finallyCommands.get(ta.finallyCommands.size() - 1) instanceof ContinueItem) { + ContinueItem ci = (ContinueItem) ta.finallyCommands.get(ta.finallyCommands.size() - 1); + if (ci.loopId == lastLoopId) { + ta.finallyCommands.remove(ta.finallyCommands.size() - 1); + } + } + } + } + } + + @Override + protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData, String path) { + super.finalProcessAfter(list, level, localData, path); + for (int i = 0; i < list.size(); i++) { if (list.get(i) instanceof SetTypeAVM2Item) { if (((SetTypeAVM2Item) list.get(i)).getValue().getThroughDuplicate() instanceof ExceptionAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 1881338b6..0bec3ac4a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -834,6 +834,11 @@ public class Graph { processSwitches(list, -1); } + + protected void processOther(List list, long lastLoopId) { + + } + /* while(something){ @@ -2891,6 +2896,7 @@ public class Graph { boolean hasContinue = false; processIfs(loopItem.commands); processSwitches(loopItem.commands, currentLoop.id); + processOther(loopItem.commands, currentLoop.id); checkContinueAtTheEnd(loopItem.commands, currentLoop); List continues = loopItem.getContinues(); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java index 0796c6277..dd2ab52e9 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java @@ -769,6 +769,33 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testForEachTry() { + decompileMethod("classic_air", "testForEachTry", "var list:* = {};\r\n" + + "var b:Boolean = true;\r\n" + + "for each(var name in list)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"xx\");\r\n" + + "if(b)\r\n" + + "{\r\n" + + "trace(\"A\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"B\");\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"C\");\r\n" + + "}\r\n" + + "trace(\"D\");\r\n" + + "}\r\n", + false); + } + @Test public void testForGoto() { decompileMethod("classic_air", "testForGoto", "var i:* = 0;\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java index 4276692c1..e2d0e840a 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java @@ -767,6 +767,34 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testForEachTry() { + decompileMethod("classic", "testForEachTry", "var name:* = undefined;\r\n" + + "var list:* = {};\r\n" + + "var b:* = true;\r\n" + + "for each(name in list)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"xx\");\r\n" + + "if(b)\r\n" + + "{\r\n" + + "trace(\"A\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"B\");\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"C\");\r\n" + + "}\r\n" + + "trace(\"D\");\r\n" + + "}\r\n", + false); + } + @Test public void testForGoto() { decompileMethod("classic", "testForGoto", "var c:int = 0;\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java index 02a2c744d..dfc3669d5 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java @@ -244,7 +244,7 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript + "_loc1_ = 0;\r\n" + "var _loc2_:int = 0;\r\n" + "_loc2_ = 5;\r\n" - + "for(; _loc1_ < 10; _loc1_++)\r\n" + + "while(_loc1_ < 10)\r\n" + "{\r\n" + "try\r\n" + "{\r\n" @@ -258,6 +258,7 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript + "throw new Error(\"Problem: \" + _loc3_);\r\n" + "}\r\n" + "}\r\n" + + "_loc1_++;\r\n" + "}\r\n" + "trace(\"after\");\r\n", false); diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf index 625bf09bf..fcc4ac129 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf index 79a683d3c..91e8a4de6 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as index 865a5ad33..72e7a75bf 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as @@ -53,6 +53,7 @@ package TestForEachSwitch; TestForEachReturn; TestForEachReturn2; + TestForEachTry; TestForGoto; TestForIn; TestForInIf; diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestForEachTry.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestForEachTry.as new file mode 100644 index 000000000..5a35192c3 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestForEachTry.as @@ -0,0 +1,31 @@ +package tests +{ + public class TestForEachTry + { + public function run():* + { + var list = {}; + var b = true; + for each(var name in list) + { + try + { + trace("xx"); + if(b) + { + trace("A"); + } + else + { + trace("B"); + } + } + catch(e:Error) + { + trace("C"); + } + trace("D"); + } + } + } +}