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 cf5d8dc39..8eede398e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -1013,6 +1013,9 @@ public class Graph { } for (Loop l : loops) { + if (l.phase == 2) { + continue; + } if (l.loopContinue == part) { return (new ContinueItem(null, firstIns, l.id)); } @@ -1419,12 +1422,22 @@ public class Graph { found = null; loopcand: - for (GraphPart cand : currentLoop.breakCandidates) { - for (GraphPart cand2 : currentLoop.breakCandidates) { + for (int c1 = 0; c1 < currentLoop.breakCandidates.size(); c1++) { + GraphPart cand = currentLoop.breakCandidates.get(c1); + for (int c2 = 0; c2 < currentLoop.breakCandidates.size(); c2++) { + GraphPart cand2 = currentLoop.breakCandidates.get(c2); if (cand == cand2) { continue; } if (cand.leadsTo(localData, this, code, cand2, loops, throwStates, true)) { + + int curLevl = currentLoop.breakCandidatesLevels.get(c1); + int curLev2 = currentLoop.breakCandidatesLevels.get(c2); + /* + found = cand; + int lev2 = currentLoop.breakCandidatesLevels.get(c2); + currentLoop.breakCandidates.set(c1, cand2); + currentLoop.breakCandidatesLevels.set(c1, lev2);*/ int lev1 = Integer.MAX_VALUE; int lev2 = Integer.MAX_VALUE; for (int i = 0; i < currentLoop.breakCandidates.size(); i++) { @@ -1440,11 +1453,21 @@ public class Graph { } } // + GraphPart other; + int curLev; if (lev1 <= lev2) { found = cand2; + other = cand; + curLev = curLevl; } else { found = cand; + other = cand2; + curLev = curLev2; } + + currentLoop.breakCandidates.add(other); + currentLoop.breakCandidatesLevels.add(curLev); + break loopcand; } } @@ -2743,8 +2766,6 @@ public class Graph { List> caseCommands = new ArrayList<>(); GraphPart next = breakPart; - GraphTargetItem ti = checkLoop(new ArrayList<>() /*??*/, next, stopPart, loops, throwStates); - //create switch as new loop break command detection to work Loop currentLoop = new Loop(loops.size(), null, next); currentLoop.phase = 1; @@ -2848,8 +2869,11 @@ public class Graph { } } nextRef.setVal(next); - tiRef.setVal(ti); + currentLoop.phase = 2; + GraphTargetItem ti = checkLoop(new ArrayList<>() /*??*/, next, stopPart, loops, throwStates); + tiRef.setVal(ti); + return new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValuesMap, caseCommands, valuesMapping); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java index ef8cfe1d0..1c31de7c8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java @@ -106,8 +106,26 @@ public class GraphPrecontinueDetector { boolean wholeLoop = false; boolean inTryTarget = false; boolean hasMoreNexts = false; + boolean usePreNode = false; + if (node.parentNode == null) { + if (node.prev.size() == 1) { + Node prev = node.prev.get(0); + if (prev.next.size() == 2) { + Node other = null; + if (prev.next.get(0) == node) { + other = prev.next.get(1); + } else { + other = prev.next.get(0); + } + if (other.graphPart == el.loopBreak) { + node = prev; + usePreNode = true; + } + } + } + } - if (node.next.size() > 1) { + if (!usePreNode && node.next.size() > 1) { if (node.next.size() == 2) { Node other = null; if (node.next.get(0).graphPart == el.loopContinue) { @@ -142,6 +160,7 @@ public class GraphPrecontinueDetector { } if (!wholeLoop && !inTryTarget && !hasMoreNexts) { el.loopPreContinue = node.graphPart; + //System.err.println("set precontinue of loop " + el.loopContinue + " to " + el.loopPreContinue); } } } 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 d45f92b27..ac94edaee 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 @@ -278,6 +278,28 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testDoWhile4() { + decompileMethod("classic_air", "testDoWhile4", "var k:int = 8;\r\n" + + "do\r\n" + + "{\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"h\");\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"f\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"b\");\r\n" + + "}\r\n" + + "trace(\"gg\");\r\n" + + "}\r\n" + + "while(k < 10);\r\n" + + "trace(\"ss\");\r\n", + false); + } + @Test public void testDotParent() { decompileMethod("classic_air", "testDotParent", "var d:* = new TestClass1();\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 3a539954f..79dd7b673 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 @@ -276,6 +276,28 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testDoWhile4() { + decompileMethod("classic", "testDoWhile4", "var k:int = 8;\r\n" + + "do\r\n" + + "{\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"h\");\r\n" + + "if(k == 9)\r\n" + + "{\r\n" + + "trace(\"f\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"b\");\r\n" + + "}\r\n" + + "trace(\"gg\");\r\n" + + "}\r\n" + + "while(k < 10);\r\n" + + "trace(\"ss\");\r\n", + false); + } + @Test public void testDotParent() { decompileMethod("classic", "testDotParent", "var d:* = undefined;\r\n" @@ -1351,23 +1373,19 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes @Test public void testWhileBreak() { decompileMethod("classic", "testWhileBreak", "var a:int = 0;\r\n" - + "while(true)\r\n" - + "{\r\n" - + "if(a < 10)\r\n" + + "while(a < 10)\r\n" + "{\r\n" + "if(a > 1 && a > 2 && a > 3 && a > 4 && a > 5)\r\n" + "{\r\n" - + "break;\r\n" + + "return \"A\";\r\n" + "}\r\n" + "trace(\"middle\");\r\n" - + "if(a != 5)\r\n" + + "if(a == 5)\r\n" + "{\r\n" - + "continue;\r\n" + + "break;\r\n" + "}\r\n" + "}\r\n" - + "return \"B\";\r\n" - + "}\r\n" - + "return \"A\";\r\n", + + "return \"B\";\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 0db197db2..5ce622dad 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 cddd52ade..4899d5129 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 d2d726fc6..237141a4f 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as @@ -27,6 +27,7 @@ package TestDoWhile; TestDoWhile2; TestDoWhile3; + TestDoWhile4; TestExpressions; TestFinallyZeroJump; TestFor; diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestDoWhile4.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestDoWhile4.as new file mode 100644 index 000000000..f88fe7f25 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestDoWhile4.as @@ -0,0 +1,26 @@ +package tests +{ + + public class TestDoWhile4 + { + public function run():* + { + var k:int = 8; + do + { + if (k == 9) + { + trace("h"); + if (k == 9) + { + trace("f"); + continue; + } + trace("b"); + } + trace("gg"); + } while (k < 10); + trace("ss"); + } + } +}