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 a459a92f9..2a0580c0e 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 @@ -260,22 +260,45 @@ public class AVM2Graph extends Graph { localData.switchedRegs.put(e, switchedReg); if (switchPart != null) { for (GraphPart r : finallyPart.refs) { - for (int ip = r.end; ip >= r.start; ip--) { - AVM2Instruction ins = avm2code.code.get(ip); - if (ins.definition instanceof JumpIns) { - continue; - } else if (ins.definition instanceof PushByteIns) { - int val = ins.operands[0]; - if (val < 0 || val > switchPart.nextParts.size() - 2) { - localData.finallyJumps.put(r, switchPart.nextParts.get(0)); //default branch + GraphPart rr = r; + boolean needsPrev = true; + while (true) { + for (int ip = rr.end; ip >= rr.start; ip--) { + AVM2Instruction ins = avm2code.code.get(ip); + if (ins.definition instanceof JumpIns) { + continue; + } else if (ins.definition instanceof PushByteIns) { + int val = ins.operands[0]; + if (val < 0 || val > switchPart.nextParts.size() - 2) { + localData.finallyJumps.put(rr, switchPart.nextParts.get(0)); //default branch + } else { + localData.finallyJumps.put(rr, switchPart.nextParts.get(1 + val)); + } + needsPrev = false; + break; + } else if ((ins.definition instanceof SetLocalTypeIns) && (((SetLocalTypeIns) ins.definition).getRegisterId(ins) == switchedReg)) { + //ignore + } else if (ins.definition instanceof CoerceAIns) { + //ignore } else { - localData.finallyJumps.put(r, switchPart.nextParts.get(1 + val)); + needsPrev = false; + break; } - break; - } else if ((ins.definition instanceof SetLocalTypeIns) && (((SetLocalTypeIns) ins.definition).getRegisterId(ins) == switchedReg)) { - //ignore - } else if (ins.definition instanceof CoerceAIns) { - //ignore + } + if (needsPrev) { + List prevs = new ArrayList<>(); + for (GraphPart prevR : rr.refs) { + if (prevR.start >= 0) { + prevs.add(prevR); + } + } + + if (prevs.size() == 1) { + rr = prevs.get(0); + } else { + break; + } + } else { break; } @@ -542,6 +565,25 @@ public class AVM2Graph extends Graph { } } + private List getRealRefs(GraphPart part) { + List ret = new ArrayList<>(); + for (GraphPart r : part.refs) { + if (r.start >= 0) { + ret.add(r); + } + } + return ret; + } + + private GraphPart searchPart(int ip, Set allParts) { + for (GraphPart p : allParts) { + if (ip >= p.start && ip <= p.end) { + return p; + } + } + return null; + } + private List checkTry(List currentRet, List output, List foundGotos, Map> partCodes, Map partCodePos, AVM2LocalData localData, GraphPart part, List stopPart, List loops, Set allParts, TranslateStack stack, int staticOperation, String path) throws InterruptedException { if (localData.parsedExceptions == null) { localData.parsedExceptions = new ArrayList<>(); @@ -556,31 +598,82 @@ public class AVM2Graph extends Graph { long addr = avm2code.getAddrThroughJumpAndDebugLine(avm2code.pos2adr(part.start)); long maxEndAddr = -1; List catchedExceptions = new ArrayList<>(); - ABCException finallyException = null; + int endIp = -1; - int finallyIndex = -1; + List finnalysIndicesToBe = new ArrayList<>(); for (int e = 0; e < body.exceptions.length; e++) { if (addr == avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].start)) { - if (!parsedExceptions.contains(body.exceptions[e])) { - long endAddr = avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end); - if (endAddr > maxEndAddr) { - catchedExceptions.clear(); - finallyException = null; - finallyIndex = -1; - maxEndAddr = avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end); - endIp = avm2code.adr2pos(maxEndAddr); - catchedExceptions.add(body.exceptions[e]); - } else if (endAddr == maxEndAddr) { - catchedExceptions.add(body.exceptions[e]); - } - if (body.exceptions[e].isFinally()) { - finallyException = body.exceptions[e]; - finallyIndex = e; + ABCException ex = body.exceptions[e]; + if (!parsedExceptions.contains(ex)) { + if (ex.isFinally()) { + finnalysIndicesToBe.add(e); + } else { + long endAddr = avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end); + if (endAddr > maxEndAddr) { + catchedExceptions.clear(); + maxEndAddr = avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end); + endIp = avm2code.adr2pos(maxEndAddr); + catchedExceptions.add(body.exceptions[e]); + } else if (endAddr == maxEndAddr) { + catchedExceptions.add(body.exceptions[e]); + } } } } } + //GraphPart endPart = searchPart(endIp, allParts); + int finallyIndex = -1; + ABCException finallyException = null; + Integer defaultPushByte = null; + + for (int e : finnalysIndicesToBe) { + ABCException finallyExceptionToBe = body.exceptions[e]; + if (endIp == -1) { + /*there's no exception, finally only*/ + finallyIndex = e; + finallyException = finallyExceptionToBe; + break; + } + int finEndIp = avm2code.getIpThroughJumpAndDebugLine(avm2code.adr2pos(finallyExceptionToBe.end)); + if (finEndIp == endIp) { + finallyIndex = e; + finallyException = finallyExceptionToBe; + break; + } + GraphPart endPart = searchPart(endIp, allParts); + GraphPart finEndPart = searchPart(finEndIp, allParts); + + if (endPart.getHeight() == 1) { + if (avm2code.code.get(endPart.start).definition instanceof PushByteIns) { + /*defaultPushByte = avm2code.code.get(endPart.start).operands[0];*/ + int afterEndIp = avm2code.getIpThroughJumpAndDebugLine(endPart.nextParts.get(0).start); + int afterFinEndIp = avm2code.getIpThroughJumpAndDebugLine(finEndPart.start); + if (afterEndIp == afterFinEndIp) { + finallyIndex = e; + finallyException = finallyExceptionToBe; + break; + } + } + } + } + + if (finallyException != null) { + int finEndIp = avm2code.adr2pos(finallyException.end); + GraphPart finallyEndPart = searchPart(finEndIp, allParts); + List refs = getRealRefs(finallyEndPart); + if (refs.size() == 1) { + GraphPart prev = refs.get(0); + if (prev.getHeight() == 1) { + if (avm2code.code.get(prev.start).definition instanceof PushByteIns) { + defaultPushByte = avm2code.code.get(prev.start).operands[0]; + } + } + } + + catchedExceptions.add(finallyException); + } + int switchedReg = -1; if (finallyIndex != -1) { switchedReg = localData.switchedRegs.containsKey(finallyIndex) ? localData.switchedRegs.get(finallyIndex) : -1; @@ -605,38 +698,17 @@ public class AVM2Graph extends Graph { stack.clear(); //If the original code (before check()) had "if" in it, there would be something on stack - for (ABCException ex : catchedExceptions) { - - TranslateStack st2 = (TranslateStack) stack.clone(); - st2.clear(); - st2.add(new ExceptionAVM2Item(ex)); - - GraphPart catchPart = null; - for (GraphPart p : allParts) { - if (p.start == avm2code.adr2pos(ex.target)) { - catchPart = p; - break; - } - } - AVM2LocalData localData2 = new AVM2LocalData(localData); - localData2.scopeStack = new ScopeStack(); - - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(afterPart); - - List currentCatchCommands = printGraph(foundGotos, partCodes, partCodePos, localData2, st2, allParts, null, catchPart, stopPart2, loops, staticOperation, path); - if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(0) instanceof SetLocalAVM2Item)) { - if (currentCatchCommands.get(0).value.getNotCoerced() instanceof ExceptionAVM2Item) { - currentCatchCommands.remove(0); - } - } - if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(currentCatchCommands.size() - 1) instanceof SetLocalAVM2Item)) { - SetLocalAVM2Item setLocal = (SetLocalAVM2Item) currentCatchCommands.get(currentCatchCommands.size() - 1); + if (switchedReg > -1) { + //There is assignment to switched reg before entering try + if (!currentRet.isEmpty() && (currentRet.get(currentRet.size() - 1) instanceof SetLocalAVM2Item)) { + SetLocalAVM2Item setLocal = (SetLocalAVM2Item) currentRet.get(currentRet.size() - 1); if (setLocal.regIndex == switchedReg) { - currentCatchCommands.remove(currentCatchCommands.size() - 1); + if (setLocal.value.getNotCoerced() instanceof IntegerValueAVM2Item) { + defaultPushByte = (int) (long) ((IntegerValueAVM2Item) setLocal.value.getNotCoerced()).value; + } + currentRet.remove(currentRet.size() - 1); } } - catchCommands.add(currentCatchCommands); } if (finallyException == null) { @@ -644,8 +716,22 @@ public class AVM2Graph extends Graph { stopPart2.add(afterPart); tryCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, part, stopPart2, loops, staticOperation, path); } - + GraphPart exAfterPart = afterPart; + GraphPart defaultPart = null; if (finallyException != null) { + + if (defaultPushByte != null) { + GraphPart switchPart = localData.ignoredSwitches.get(finallyIndex); + if (switchPart != null) { + if (defaultPushByte < 0 || defaultPushByte > switchPart.nextParts.size() - 2) { + defaultPart = switchPart.nextParts.get(0); + } else { + defaultPart = switchPart.nextParts.get(1 + defaultPushByte); + } + localData.defaultWays.put(switchPart, defaultPushByte); + } + } + afterPart = null; GraphPart finallyTryTargetPart = null; int targetPos = avm2code.adr2pos(finallyException.target); @@ -662,6 +748,9 @@ public class AVM2Graph extends Graph { if (finallyPart != null) { tryStopPart.add(finallyPart); } + if (defaultPart != null) { + tryStopPart.add(defaultPart); + } tryCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, part, tryStopPart, loops, staticOperation, path); makeAllCommands(tryCommands, stack); processIfs(tryCommands); @@ -683,6 +772,7 @@ public class AVM2Graph extends Graph { } if (switchPart != null) { finallyCommands.addAll(translatePart(localData, switchPart, stack, staticOperation, path)); + stack.pop(); //value switched by lookupswitch if (localData.defaultWays.containsKey(switchPart)) { int defaultWay = localData.defaultWays.get(switchPart); if (defaultWay < 0 || defaultWay > switchPart.nextParts.size() - 2) { @@ -693,33 +783,66 @@ public class AVM2Graph extends Graph { } else { afterPart = switchPart.nextParts.get(0); //take the default branch. TODO: detect actual value } + exAfterPart = afterPart; } - stack.pop(); - - if (tryCommands.size() == 1 - && (tryCommands.get(0) instanceof TryAVM2Item) - && catchCommands.isEmpty() - && ((TryAVM2Item) tryCommands.get(0)).finallyCommands.isEmpty()) { - catchCommands = ((TryAVM2Item) tryCommands.get(0)).catchCommands; - catchedExceptions = ((TryAVM2Item) tryCommands.get(0)).catchExceptions; - tryCommands = ((TryAVM2Item) tryCommands.get(0)).tryCommands; - } + //stack.pop(); } + + for (ABCException ex : catchedExceptions) { + + TranslateStack st2 = (TranslateStack) stack.clone(); + st2.clear(); + st2.add(new ExceptionAVM2Item(ex)); + + GraphPart catchPart = null; + for (GraphPart p : allParts) { + if (p.start == avm2code.adr2pos(ex.target)) { + catchPart = p; + break; + } + } + AVM2LocalData localData2 = new AVM2LocalData(localData); + localData2.scopeStack = new ScopeStack(); + + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(exAfterPart); + if (defaultPart != null) { + stopPart2.add(defaultPart); + } + + List currentCatchCommands = printGraph(foundGotos, partCodes, partCodePos, localData2, st2, allParts, null, catchPart, stopPart2, loops, staticOperation, path); + if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(0) instanceof SetLocalAVM2Item)) { + if (currentCatchCommands.get(0).value.getNotCoerced() instanceof ExceptionAVM2Item) { + currentCatchCommands.remove(0); + } + } + if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(currentCatchCommands.size() - 1) instanceof SetLocalAVM2Item)) { + SetLocalAVM2Item setLocal = (SetLocalAVM2Item) currentCatchCommands.get(currentCatchCommands.size() - 1); + if (setLocal.regIndex == switchedReg) { + currentCatchCommands.remove(currentCatchCommands.size() - 1); + } + } + catchCommands.add(currentCatchCommands); + } + + /*if (tryCommands.size() == 1 + && (tryCommands.get(0) instanceof TryAVM2Item) + && catchCommands.isEmpty() + && ((TryAVM2Item) tryCommands.get(0)).finallyCommands.isEmpty()) { + catchCommands = ((TryAVM2Item) tryCommands.get(0)).catchCommands; + catchedExceptions = ((TryAVM2Item) tryCommands.get(0)).catchExceptions; + tryCommands = ((TryAVM2Item) tryCommands.get(0)).tryCommands; + }*/ if (catchCommands.isEmpty() && finallyCommands.isEmpty() && tryCommands.isEmpty()) { return null; } - if (switchedReg > -1) { - //There is assignment to switched reg before entering try - if (!currentRet.isEmpty() && (currentRet.get(currentRet.size() - 1) instanceof SetLocalAVM2Item)) { - SetLocalAVM2Item setLocal = (SetLocalAVM2Item) currentRet.get(currentRet.size() - 1); - if (setLocal.regIndex == switchedReg) { - currentRet.remove(currentRet.size() - 1); - } - } + List ret = new ArrayList<>(); + if (catchedExceptions.isEmpty() && finallyCommands.isEmpty()) { + ret.addAll(tryCommands); + return ret; } - List ret = new ArrayList<>(); ret.add(new TryAVM2Item(tryCommands, catchedExceptions, catchCommands, finallyCommands, "TODO")); if (afterPart != null) { @@ -886,7 +1009,7 @@ public class AVM2Graph extends Graph { switchPart = gp; switchedReg = aLocalData.switchedRegs.containsKey(finallyIndex) ? aLocalData.switchedRegs.get(finallyIndex) : -1; - + break; } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3AssembledDecompileTest.java new file mode 100644 index 000000000..0fdf5b366 --- /dev/null +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3AssembledDecompileTest.java @@ -0,0 +1,146 @@ +package com.jpexs.decompiler.flash; + +import java.io.IOException; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileTestBase { + + @BeforeClass + public void init() throws IOException, InterruptedException { + addSwf("assembled", "testdata/custom/bin/custom.swf"); + } + + @Test + public void testDoubleDup() { + decompileMethod("assembled", "testDoubleDup", "var _loc10_:Rectangle = myprop(_loc5_);\r\n" + + "_loc10_.mymethod(-_loc10_.width,-_loc10_.height);\r\n", + false); + } + + @Test + public void testDup() { + decompileMethod("assembled", "testDup", "return 1 - (var _loc1_:Number = 1 - _loc1_ / _loc4_) * _loc1_;\r\n", + false); + } + + @Test + public void testDupAssignment() { + decompileMethod("assembled", "testDupAssignment", "var _loc1_:int = 0;\r\n" + + "var _loc2_:int = 10;\r\n" + + "if(_loc1_ = _loc2_)\r\n" + + "{\r\n" + + "trace(_loc2_);\r\n" + + "}\r\n", + false); + } + + @Test + public void testForEach() { + decompileMethod("assembled", "testForEach", "var _loc5_:* = undefined;\r\n" + + "var _loc2_:* = 0;\r\n" + + "var _loc3_:int = 0;\r\n" + + "for each(var _loc4_ in _loc5_)\r\n" + + "{\r\n" + + "if(_loc4_ != null)\r\n" + + "{\r\n" + + "_loc2_ = _loc4_;\r\n" + + "}\r\n" + + "}\r\n" + + "_loc3_ = 0;\r\n", + false); + } + + @Test + public void testForEachCoerced() { + decompileMethod("assembled", "testForEachCoerced", "for each(var _loc6_ in someprop)\r\n" + + "{\r\n" + + "_loc6_.methodname(_loc1_,_loc2_,_loc5_);\r\n" + + "}\r\n", + false); + } + + @Test + public void testIncrement() { + decompileMethod("assembled", "testIncrement", "super();\r\n" + + "b = a++;\r\n", + false); + } + + @Test + public void testIncrement2() { + decompileMethod("assembled", "testIncrement2", "if(++loadCount == 2)\r\n" + + "{\r\n" + + "somemethod();\r\n" + + "}\r\n", + false); + } + + @Test + public void testIncrement3() { + decompileMethod("assembled", "testIncrement3", "_loc1_.length--;\r\n", + false); + } + + @Test + public void testSetSlotDup() { + decompileMethod("assembled", "testSetSlotDup", "var _loc5_:int = 5;\r\n" + + "myname.somemethod(\"okay\",myslot = _loc5_);\r\n" + + "myname.start();\r\n", + false); + } + + @Test + public void testSetSlotFindProperty() { + decompileMethod("assembled", "testSetSlotFindProperty", "return var myprop:int = 50;\r\n", + false); + } + + @Test + public void testSwitch() { + decompileMethod("assembled", "testSwitch", "switch(int(somevar))\r\n" + + "{\r\n" + + "case 0:\r\n" + + "var _loc2_:String = \"X\";\r\n" + + "return;\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "_loc2_ = \"A\";\r\n" + + "break;\r\n" + + "case 3:\r\n" + + "_loc2_ = \"B\";\r\n" + + "break;\r\n" + + "case 4:\r\n" + + "_loc2_ = \"C\";\r\n" + + "}\r\n" + + "_loc2_ = \"after\";\r\n", + false); + } + + @Test + public void testSwitchDefault() { + decompileMethod("assembled", "testSwitchDefault", "switch(5)\r\n" + + "{\r\n" + + "case 6:\r\n" + + "var _loc2_:int = 6;\r\n" + + "case 0:\r\n" + + "_loc2_ = 0;\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "_loc2_ = 1;\r\n" + + "case 5:\r\n" + + "_loc2_ = 5;\r\n" + + "break;\r\n" + + "case 3:\r\n" + + "_loc2_ = 3;\r\n" + + "break;\r\n" + + "default:\r\n" + + "_loc2_ = 100;\r\n" + + "}\r\n", + false); + } +} diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3ClassTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3ClassTest.java new file mode 100644 index 000000000..5226614b3 --- /dev/null +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3ClassTest.java @@ -0,0 +1,215 @@ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.tags.DoABC2Tag; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.IOException; +import java.util.Arrays; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript3ClassTest extends ActionScript3DecompileTestBase { + + @BeforeClass + public void init() throws IOException, InterruptedException { + addSwf("standard", "testdata/flashdevelop/bin/flashdevelop.swf"); + } + + private void decompileScriptPack(String path, String expectedResult) { + + DoABC2Tag tag = null; + ABC abc = null; + ScriptPack scriptPack = null; + for (Tag t : getSwf("standard").getTags()) { + if (t instanceof DoABC2Tag) { + tag = (DoABC2Tag) t; + abc = tag.getABC(); + scriptPack = abc.findScriptPackByPath(path, Arrays.asList(abc)); + if (scriptPack != null) { + break; + } + } + } + assertNotNull(abc); + assertNotNull(scriptPack); + HighlightedTextWriter writer = null; + try { + writer = new HighlightedTextWriter(new CodeFormatting(), false); + scriptPack.toSource(writer, abc.script_info.get(scriptPack.scriptIndex).traits.traits, new ConvertData(), ScriptExportMode.AS, false); + } catch (InterruptedException ex) { + fail(); + } + String actualResult = cleanPCode(writer.toString()); + expectedResult = cleanPCode(expectedResult); + assertEquals(actualResult, expectedResult); + } + @Test + public void testMyPackage1TestClass() { + decompileScriptPack("tests_classes.mypackage1.TestClass", "package tests_classes.mypackage1\n" + + "{\n" + + " public class TestClass implements tests_classes.mypackage1.TestInterface\n" + + " {\n" + + " \n" + + " public function TestClass()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : String\n" + + " {\n" + + " trace(\"pkg1hello\");\n" + + " return \"pkg1hello\";\n" + + " }\n" + + " \n" + + " public function testMethod1() : void\n" + + " {\n" + + " var a:tests_classes.mypackage1.TestInterface = this;\n" + + " a.testMethod1();\n" + + " var b:tests_classes.mypackage2.TestInterface = this;\n" + + " b = new tests_classes.mypackage2.TestClass();\n" + + " }\n" + + " \n" + + " public function testMethod2() : void\n" + + " {\n" + + " var a:tests_classes.mypackage1.TestInterface = this;\n" + + " a.testMethod1();\n" + + " var b:tests_classes.mypackage2.TestInterface = this;\n" + + " b = new tests_classes.mypackage2.TestClass();\n" + + " }\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage1TestClass2() { + decompileScriptPack("tests_classes.mypackage1.TestClass2", "package tests_classes.mypackage1\n" + + "{\n" + + " public class TestClass2\n" + + " {\n" + + " \n" + + " public function TestClass2()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : String\n" + + " {\n" + + " var a:tests_classes.mypackage1.TestClass = null;\n" + + " var b:tests_classes.mypackage2.TestClass = null;\n" + + " var c:tests_classes.mypackage3.TestClass = null;\n" + + " a = new tests_classes.mypackage1.TestClass();\n" + + " b = new tests_classes.mypackage2.TestClass();\n" + + " c = new tests_classes.mypackage3.TestClass();\n" + + " var res:String = a.testCall() + b.testCall() + c.testCall() + this.testCall2() + myNamespace::testCall3();\n" + + " trace(res);\n" + + " return res;\n" + + " }\n" + + " \n" + + " myNamespace function testCall2() : String\n" + + " {\n" + + " return \"1\";\n" + + " }\n" + + " \n" + + " myNamespace function testCall3() : String\n" + + " {\n" + + " return myNamespace::testCall2();\n" + + " }\n" + + " \n" + + " public function testCall2() : String\n" + + " {\n" + + " return \"2\";\n" + + " }\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage1TestInterface() { + decompileScriptPack("tests_classes.mypackage1.TestInterface", "package tests_classes.mypackage1\n" + + "{\n" + + " public interface TestInterface extends tests_classes.mypackage2.TestInterface\n" + + " {\n" + + " \n" + + " function testMethod1() : void;\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage1MyNamespace() { + decompileScriptPack("tests_classes.mypackage1.myNamespace", "package tests_classes.mypackage1\n" + + "{\n" + + " public namespace myNamespace = \"https://www.free-decompiler.com/flash/test/namespace\";\n" + + "}"); + } + + @Test + public void testMyPackage2TestClass() { + decompileScriptPack("tests_classes.mypackage2.TestClass", "package tests_classes.mypackage2\n" + + "{\n" + + " public class TestClass implements TestInterface\n" + + " {\n" + + " \n" + + " public function TestClass()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : String\n" + + " {\n" + + " trace(\"pkg2hello\");\n" + + " return \"pkg2hello\";\n" + + " }\n" + + " \n" + + " public function testMethod2() : void\n" + + " {\n" + + " }\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage2TestInterface() { + decompileScriptPack("tests_classes.mypackage2.TestInterface", "package tests_classes.mypackage2\n" + + "{\n" + + " public interface TestInterface\n" + + " {\n" + + " \n" + + " function testMethod2() : void;\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage3TestClass() { + decompileScriptPack("tests_classes.mypackage3.TestClass", "package tests_classes.mypackage3\n" + + "{\n" + + " public class TestClass\n" + + " {\n" + + " \n" + + " public function TestClass()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : String\n" + + " {\n" + + " trace(\"pkg3hello\");\n" + + " return \"pkg3hello\";\n" + + " }\n" + + " }\n" + + "}"); + } +} diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3ClassicDecompileTest.java similarity index 55% rename from libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java rename to libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3ClassicDecompileTest.java index a2a007374..14a9c26e0 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3ClassicDecompileTest.java @@ -1,165 +1,29 @@ -/* - * Copyright (C) 2010-2021 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ package com.jpexs.decompiler.flash; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.ScriptPack; -import com.jpexs.decompiler.flash.abc.types.ConvertData; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.CodeFormatting; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.decompiler.flash.tags.DoABC2Tag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.ScopeStack; -import java.io.BufferedInputStream; -import java.io.FileInputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * * @author JPEXS */ -public class ActionScript3Test extends ActionScriptTestBase { - - private Map swfMap = new HashMap<>(); +public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTestBase { @BeforeClass public void init() throws IOException, InterruptedException { - //Main.initLogging(false); - swfMap.put("standard", new SWF(new BufferedInputStream(new FileInputStream("testdata/flashdevelop/bin/flashdevelop_flex.swf")), false)); - swfMap.put("standard_asc2", new SWF(new BufferedInputStream(new FileInputStream("testdata/flashdevelop/bin/flashdevelop_asc2.swf")), false)); - swfMap.put("assembled", new SWF(new BufferedInputStream(new FileInputStream("testdata/custom/bin/custom.swf")), false)); - Configuration.autoDeobfuscate.set(false); - Configuration.simplifyExpressions.set(false); - - Configuration.decompile.set(true); - Configuration.registerNameFormat.set("_loc%d_"); - Configuration.showMethodBodyId.set(false); + addSwf("classic", "testdata/flashdevelop/bin/flashdevelop.swf"); } - private void decompileMethod(String swfIdentifier, String methodName, String expectedResult, boolean isStatic) { - String className = methodName.substring(0, 1).toUpperCase() + methodName.substring(1); - - int clsIndex = -1; - int scriptIndex = -1; - - ABC abc = null; - SWF swf = swfMap.get(swfIdentifier); - List abcs = new ArrayList<>(); - for (ABCContainerTag abcTag : swf.getAbcList()) { - abcs.add(abcTag.getABC()); - } - ScriptPack scriptPack = null; - for (ABC a : abcs) { - scriptPack = a.findScriptPackByPath("tests." + className, abcs); - if (scriptPack != null) { - break; - } - } - assertNotNull(scriptPack); - abc = scriptPack.abc; - scriptIndex = scriptPack.scriptIndex; - - clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className}, "")); - - assertTrue(clsIndex > -1); - assertTrue(scriptIndex > -1); - - int bodyIndex = abc.findMethodBodyByName(clsIndex, "run"); - - assertTrue(bodyIndex > -1); - HighlightedTextWriter writer; - try { - List ts = new ArrayList<>(); - ts.add(abc.instance_info.get(clsIndex).instance_traits); - abc.bodies.get(bodyIndex).convert(new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(scriptIndex), 0, new NulWriter(), new ArrayList<>(), ts, true); - writer = new HighlightedTextWriter(new CodeFormatting(), false); - abc.bodies.get(bodyIndex).toString("run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>()); - } catch (InterruptedException ex) { - fail(); - return; - } - String actualResult = cleanPCode(writer.toString()); - expectedResult = cleanPCode(expectedResult); - assertEquals(actualResult, expectedResult); - } - - private void decompileScriptPack(String path, String expectedResult) { - - DoABC2Tag tag = null; - ABC abc = null; - ScriptPack scriptPack = null; - for (Tag t : swfMap.get("standard").getTags()) { - if (t instanceof DoABC2Tag) { - tag = (DoABC2Tag) t; - abc = tag.getABC(); - scriptPack = abc.findScriptPackByPath(path, Arrays.asList(abc)); - if (scriptPack != null) { - break; - } - } - } - assertNotNull(abc); - assertNotNull(scriptPack); - HighlightedTextWriter writer = null; - try { - writer = new HighlightedTextWriter(new CodeFormatting(), false); - scriptPack.toSource(writer, abc.script_info.get(scriptPack.scriptIndex).traits.traits, new ConvertData(), ScriptExportMode.AS, false); - } catch (InterruptedException ex) { - fail(); - } - String actualResult = cleanPCode(writer.toString()); - expectedResult = cleanPCode(expectedResult); - assertEquals(actualResult, expectedResult); - } - - @DataProvider - private Object[][] standardSwfNamesProvider() { - return new Object[][]{ - {"standard"}, //{"standard_asc2"} - }; - } - - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardArguments(String swfUsed) { - decompileMethod(swfUsed, "testArguments", "return arguments[0];\r\n", + @Test + public void testArguments() { + decompileMethod("classic", "testArguments", "return arguments[0];\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardCatchFinally(String swfUsed) { - decompileMethod(swfUsed, "testCatchFinally", "var a:* = 5;\r\n" + @Test + public void testCatchFinally() { + decompileMethod("classic", "testCatchFinally", "var a:* = 5;\r\n" + "try\r\n" + "{\r\n" + "a = 9;\r\n" @@ -176,9 +40,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardChain2(String swfUsed) { - decompileMethod(swfUsed, "testChain2", "var g:Array = null;\r\n" + @Test + public void testChain2() { + decompileMethod("classic", "testChain2", "var g:Array = null;\r\n" + "var h:Boolean = false;\r\n" + "var extraLine:Boolean = false;\r\n" + "var r:int = 7;\r\n" @@ -196,9 +60,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardChainedAssignments(String swfUsed) { - decompileMethod(swfUsed, "testChainedAssignments", "var a:int = 0;\r\n" + @Test + public void testChainedAssignments() { + decompileMethod("classic", "testChainedAssignments", "var a:int = 0;\r\n" + "var b:int = 0;\r\n" + "var c:int = 0;\r\n" + "var d:int = 0;\r\n" @@ -209,17 +73,17 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardComplexExpressions(String swfUsed) { - decompileMethod(swfUsed, "testComplexExpressions", "var i:int = 0;\r\n" + @Test + public void testComplexExpressions() { + decompileMethod("classic", "testComplexExpressions", "var i:int = 0;\r\n" + "var j:int = 0;\r\n" + "j = i = i + (i = i + i++);\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardContinueLevels(String swfUsed) { - decompileMethod(swfUsed, "testContinueLevels", "var b:* = undefined;\r\n" + @Test + public void testContinueLevels() { + decompileMethod("classic", "testContinueLevels", "var b:* = undefined;\r\n" + "var c:* = undefined;\r\n" + "var d:* = undefined;\r\n" + "var e:* = undefined;\r\n" @@ -281,9 +145,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardDecl2(String swfUsed) { - decompileMethod(swfUsed, "testDecl2", "var k:int = 0;\r\n" + @Test + public void testDecl2() { + decompileMethod("classic", "testDecl2", "var k:int = 0;\r\n" + "var i:int = 5;\r\n" + "i = i + 7;\r\n" + "if(i == 5)\r\n" @@ -297,9 +161,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardDeclarations(String swfUsed) { - decompileMethod(swfUsed, "testDeclarations", "var vall:* = undefined;\r\n" + @Test + public void testDeclarations() { + decompileMethod("classic", "testDeclarations", "var vall:* = undefined;\r\n" + "var vstr:String = null;\r\n" + "var vint:int = 0;\r\n" + "var vuint:uint = 0;\r\n" @@ -317,9 +181,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardDefaultNotLastGrouped(String swfUsed) { - decompileMethod(swfUsed, "testDefaultNotLastGrouped", "var k:* = 10;\r\n" + @Test + public void testDefaultNotLastGrouped() { + decompileMethod("classic", "testDefaultNotLastGrouped", "var k:* = 10;\r\n" + "switch(k)\r\n" + "{\r\n" + "case \"six\":\r\n" @@ -335,9 +199,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardDoWhile(String swfUsed) { - decompileMethod(swfUsed, "testDoWhile", "var a:* = 8;\r\n" + @Test + public void testDoWhile() { + decompileMethod("classic", "testDoWhile", "var a:* = 8;\r\n" + "do\r\n" + "{\r\n" + "trace(\"a=\" + a);\r\n" @@ -347,9 +211,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardDoWhile2(String swfUsed) { - decompileMethod(swfUsed, "testDoWhile2", "var k:int = 5;\r\n" + @Test + public void testDoWhile2() { + decompileMethod("classic", "testDoWhile2", "var k:int = 5;\r\n" + "do\r\n" + "{\r\n" + "k++;\r\n" @@ -368,9 +232,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardExpressions(String swfUsed) { - decompileMethod(swfUsed, "testExpressions", "var arr:Array = null;\r\n" + @Test + public void testExpressions() { + decompileMethod("classic", "testExpressions", "var arr:Array = null;\r\n" + "var i:int = 5;\r\n" + "var j:int = 5;\r\n" + "if((i = i = i / 2) == 1 || i == 2)\r\n" @@ -389,9 +253,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardFinallyZeroJump(String swfUsed) { - decompileMethod(swfUsed, "testFinallyZeroJump", "var str:String = param1;\r\n" + @Test + public void testFinallyZeroJump() { + decompileMethod("classic", "testFinallyZeroJump", "var str:String = param1;\r\n" + "try\r\n" + "{\r\n" + "}\r\n" @@ -411,18 +275,18 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardFor(String swfUsed) { - decompileMethod(swfUsed, "testFor", "for(var a:* = 0; a < 10; a++)\r\n" + @Test + public void testFor() { + decompileMethod("classic", "testFor", "for(var a:* = 0; a < 10; a++)\r\n" + "{\r\n" + "trace(\"a=\" + a);\r\n" + "}\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForAnd(String swfUsed) { - decompileMethod(swfUsed, "testForAnd", "var x:Boolean = false;\r\n" + @Test + public void testForAnd() { + decompileMethod("classic", "testForAnd", "var x:Boolean = false;\r\n" + "var len:int = 5;\r\n" + "var a:int = 4;\r\n" + "var b:int = 7;\r\n" @@ -445,9 +309,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForBreak(String swfUsed) { - decompileMethod(swfUsed, "testForBreak", "for(var a:* = 0; a < 10; a++)\r\n" + @Test + public void testForBreak() { + decompileMethod("classic", "testForBreak", "for(var a:* = 0; a < 10; a++)\r\n" + "{\r\n" + "if(a == 5)\r\n" + "{\r\n" @@ -458,9 +322,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForContinue(String swfUsed) { - decompileMethod(swfUsed, "testForContinue", "for(var a:* = 0; a < 10; a = a + 1)\r\n" + @Test + public void testForContinue() { + decompileMethod("classic", "testForContinue", "for(var a:* = 0; a < 10; a = a + 1)\r\n" + "{\r\n" + "if(a == 9)\r\n" + "{\r\n" @@ -486,9 +350,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForEach(String swfUsed) { - decompileMethod(swfUsed, "testForEach", "var list:Array = null;\r\n" + @Test + public void testForEach() { + decompileMethod("classic", "testForEach", "var list:Array = null;\r\n" + "var item:* = undefined;\r\n" + "list = new Array();\r\n" + "list[0] = \"first\";\r\n" @@ -501,9 +365,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForEachObjectArray(String swfUsed) { - decompileMethod(swfUsed, "testForEachObjectArray", "var list:Array = null;\r\n" + @Test + public void testForEachObjectArray() { + decompileMethod("classic", "testForEachObjectArray", "var list:Array = null;\r\n" + "var test:Array = null;\r\n" + "list = new Array();\r\n" + "list[0] = \"first\";\r\n" @@ -518,9 +382,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForEachObjectAttribute(String swfUsed) { - decompileMethod(swfUsed, "testForEachObjectAttribute", "var list:Array = null;\r\n" + @Test + public void testForEachObjectAttribute() { + decompileMethod("classic", "testForEachObjectAttribute", "var list:Array = null;\r\n" + "list = new Array();\r\n" + "list[0] = \"first\";\r\n" + "list[1] = \"second\";\r\n" @@ -532,9 +396,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForGoto(String swfUsed) { - decompileMethod(swfUsed, "testForGoto", "var c:int = 0;\r\n" + @Test + public void testForGoto() { + decompileMethod("classic", "testForGoto", "var c:int = 0;\r\n" + "var len:int = 5;\r\n" + "for(var i:uint = 0; i < len; i++)\r\n" + "{\r\n" @@ -557,9 +421,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForIn(String swfUsed) { - decompileMethod(swfUsed, "testForIn", "var dic:Dictionary = null;\r\n" + @Test + public void testForIn() { + decompileMethod("classic", "testForIn", "var dic:Dictionary = null;\r\n" + "var item:* = null;\r\n" + "for(item in dic)\r\n" + "{\r\n" @@ -572,9 +436,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardForXml(String swfUsed) { - decompileMethod(swfUsed, "testForXml", "var c:int = 0;\r\n" + @Test + public void testForXml() { + decompileMethod("classic", "testForXml", "var c:int = 0;\r\n" + "var name:String = \"ahoj\";\r\n" + "var myXML:XML = \r\n" + "\r\n" @@ -605,9 +469,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardGotos(String swfUsed) { - decompileMethod(swfUsed, "testGotos", "var a:Boolean = true;\r\n" + @Test + public void testGotos() { + decompileMethod("classic", "testGotos", "var a:Boolean = true;\r\n" + "var b:Boolean = false;\r\n" + "if(a)\r\n" + "{\r\n" @@ -637,9 +501,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardGotos2(String swfUsed) { - decompileMethod(swfUsed, "testGotos2", "var a:Boolean = true;\r\n" + @Test + public void testGotos2() { + decompileMethod("classic", "testGotos2", "var a:Boolean = true;\r\n" + "var b:Boolean = false;\r\n" + "var c:Boolean = true;\r\n" + "if(a)\r\n" @@ -661,9 +525,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardGotos3(String swfUsed) { - decompileMethod(swfUsed, "testGotos3", "var i:int = 0;\r\n" + @Test + public void testGotos3() { + decompileMethod("classic", "testGotos3", "var i:int = 0;\r\n" + "var a:int = 5;\r\n" + "if(a > 5)\r\n" + "{\r\n" @@ -688,9 +552,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardGotos4(String swfUsed) { - decompileMethod(swfUsed, "testGotos4", "var a:int = 5;\r\n" + @Test + public void testGotos4() { + decompileMethod("classic", "testGotos4", "var a:int = 5;\r\n" + "if(a > 3)\r\n" + "{\r\n" + "if(a < 7)\r\n" @@ -709,9 +573,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardGotos5(String swfUsed) { - decompileMethod(swfUsed, "testGotos5", "var j:int = 0;\r\n" + @Test + public void testGotos5() { + decompileMethod("classic", "testGotos5", "var j:int = 0;\r\n" + "var s:String = \"A\";\r\n" + "for(var i:int = 0; i < 10; i++)\r\n" + "{\r\n" @@ -733,9 +597,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardGotos6(String swfUsed) { - decompileMethod(swfUsed, "testGotos6", "var a:Boolean = true;\r\n" + @Test + public void testGotos6() { + decompileMethod("classic", "testGotos6", "var a:Boolean = true;\r\n" + "var s:String = \"a\";\r\n" + "if(a)\r\n" + "{\r\n" @@ -758,9 +622,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardGotos7(String swfUsed) { - decompileMethod(swfUsed, "testGotos7", "for(var i:int = 0; i < 10; i++)\r\n" + @Test + public void testGotos7() { + decompileMethod("classic", "testGotos7", "for(var i:int = 0; i < 10; i++)\r\n" + "{\r\n" + "switch(i)\r\n" + "{\r\n" @@ -787,15 +651,15 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardHello(String swfUsed) { - decompileMethod(swfUsed, "testHello", "trace(\"hello\");\r\n", + @Test + public void testHello() { + decompileMethod("classic", "testHello", "trace(\"hello\");\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardIf(String swfUsed) { - decompileMethod(swfUsed, "testIf", "var a:* = 5;\r\n" + @Test + public void testIf() { + decompileMethod("classic", "testIf", "var a:* = 5;\r\n" + "if(a == 7)\r\n" + "{\r\n" + "trace(\"onTrue\");\r\n" @@ -803,9 +667,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardIfElse(String swfUsed) { - decompileMethod(swfUsed, "testIfElse", "var a:* = 5;\r\n" + @Test + public void testIfElse() { + decompileMethod("classic", "testIfElse", "var a:* = 5;\r\n" + "if(a == 7)\r\n" + "{\r\n" + "trace(\"onTrue\");\r\n" @@ -817,9 +681,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardIfInIf(String swfUsed) { - decompileMethod(swfUsed, "testIfInIf", "var k:int = 5;\r\n" + @Test + public void testIfInIf() { + decompileMethod("classic", "testIfInIf", "var k:int = 5;\r\n" + "if(k > 5 && k < 20)\r\n" + "{\r\n" + "trace(\"A\");\r\n" @@ -841,9 +705,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardInc2(String swfUsed) { - decompileMethod(swfUsed, "testInc2", "var a:* = [1];\r\n" + @Test + public void testInc2() { + decompileMethod("classic", "testInc2", "var a:* = [1];\r\n" + "a[this.getInt()]++;\r\n" + "var d:* = a[this.getInt()]++;\r\n" + "var e:* = ++a[this.getInt()];\r\n" @@ -854,9 +718,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardIncDec(String swfUsed) { - decompileMethod(swfUsed, "testIncDec", "var a:* = 5;\r\n" + @Test + public void testIncDec() { + decompileMethod("classic", "testIncDec", "var a:* = 5;\r\n" + "var b:* = 0;\r\n" + "trace(\"++var\");\r\n" + "b = ++a;\r\n" @@ -893,9 +757,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardInlineFunctions(String swfUsed) { - decompileMethod(swfUsed, "testInlineFunctions", "var first:String = null;\r\n" + @Test + public void testInlineFunctions() { + decompileMethod("classic", "testInlineFunctions", "var first:String = null;\r\n" + "first = \"value1\";\r\n" + "var traceParameter:Function = function(aParam:String):String\r\n" + "{\r\n" @@ -915,9 +779,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardInnerFunctions(String swfUsed) { - decompileMethod(swfUsed, "testInnerFunctions", "var s:int = 0;\r\n" + @Test + public void testInnerFunctions() { + decompileMethod("classic", "testInnerFunctions", "var s:int = 0;\r\n" + "var innerFunc:Function = function(b:String):*\r\n" + "{\r\n" + "trace(b);\r\n" @@ -931,9 +795,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardInnerIf(String swfUsed) { - decompileMethod(swfUsed, "testInnerIf", "var a:* = 5;\r\n" + @Test + public void testInnerIf() { + decompileMethod("classic", "testInnerIf", "var a:* = 5;\r\n" + "var b:* = 4;\r\n" + "if(a == 5)\r\n" + "{\r\n" @@ -958,9 +822,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardInnerTry(String swfUsed) { - decompileMethod(swfUsed, "testInnerTry", "try\r\n" + @Test + public void testInnerTry() { + decompileMethod("classic", "testInnerTry", "try\r\n" + "{\r\n" + "try\r\n" + "{\r\n" @@ -983,9 +847,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardLogicalComputing(String swfUsed) { - decompileMethod(swfUsed, "testLogicalComputing", "var b:Boolean = false;\r\n" + @Test + public void testLogicalComputing() { + decompileMethod("classic", "testLogicalComputing", "var b:Boolean = false;\r\n" + "var i:* = 5;\r\n" + "var j:* = 7;\r\n" + "if(i > j)\r\n" @@ -997,16 +861,16 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardManualConvert(String swfUsed) { - decompileMethod(swfUsed, "testManualConvert", "trace(\"String(this).length\");\r\n" + @Test + public void testManualConvert() { + decompileMethod("classic", "testManualConvert", "trace(\"String(this).length\");\r\n" + "trace(String(this).length);\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardMissingDefault(String swfUsed) { - decompileMethod(swfUsed, "testMissingDefault", "var jj:int = 1;\r\n" + @Test + public void testMissingDefault() { + decompileMethod("classic", "testMissingDefault", "var jj:int = 1;\r\n" + "switch(jj)\r\n" + "{\r\n" + "case 1:\r\n" @@ -1021,9 +885,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardMultipleCondition(String swfUsed) { - decompileMethod(swfUsed, "testMultipleCondition", "var a:* = 5;\r\n" + @Test + public void testMultipleCondition() { + decompileMethod("classic", "testMultipleCondition", "var a:* = 5;\r\n" + "var b:* = 8;\r\n" + "var c:* = 9;\r\n" + "if((a <= 4 || b <= 8) && c == 7)\r\n" @@ -1037,18 +901,18 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardNamedAnonFunctions(String swfUsed) { - decompileMethod(swfUsed, "testNamedAnonFunctions", "var test:* = new function testFunc(param1:*, param2:int, param3:Array):Boolean\r\n" + @Test + public void testNamedAnonFunctions() { + decompileMethod("classic", "testNamedAnonFunctions", "var test:* = new function testFunc(param1:*, param2:int, param3:Array):Boolean\r\n" + "{\r\n" + "return (param1 as TestClass2).attrib1 == 5;\r\n" + "};\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardNames(String swfUsed) { - decompileMethod(swfUsed, "testNames", "var ns:* = this.getNamespace();\r\n" + @Test + public void testNames() { + decompileMethod("classic", "testNames", "var ns:* = this.getNamespace();\r\n" + "var name:* = this.getName();\r\n" + "var a:* = ns::unnamespacedFunc();\r\n" + "var b:* = ns::[name];\r\n" @@ -1057,21 +921,21 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardParamNames(String swfUsed) { - decompileMethod(swfUsed, "testParamNames", "return firstp + secondp + thirdp;\r\n", + @Test + public void testParamNames() { + decompileMethod("classic", "testParamNames", "return firstp + secondp + thirdp;\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardParamsCount(String swfUsed) { - decompileMethod(swfUsed, "testParamsCount", "return firstp;\r\n", + @Test + public void testParamsCount() { + decompileMethod("classic", "testParamsCount", "return firstp;\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardPrecedence(String swfUsed) { - decompileMethod(swfUsed, "testPrecedence", "var a:* = 0;\r\n" + @Test + public void testPrecedence() { + decompileMethod("classic", "testPrecedence", "var a:* = 0;\r\n" + "a = (5 + 6) * 7;\r\n" + "a = 5 * (2 + 3);\r\n" + "a = 5 + 6 * 7;\r\n" @@ -1086,9 +950,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardPrecedenceX(String swfUsed) { - decompileMethod(swfUsed, "testPrecedenceX", "var a:* = 5;\r\n" + @Test + public void testPrecedenceX() { + decompileMethod("classic", "testPrecedenceX", "var a:* = 5;\r\n" + "var b:* = 2;\r\n" + "var c:* = 3;\r\n" + "var d:* = a << (b >>> c);\r\n" @@ -1096,9 +960,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardProperty(String swfUsed) { - decompileMethod(swfUsed, "testProperty", "var d:* = new TestClass1();\r\n" + @Test + public void testProperty() { + decompileMethod("classic", "testProperty", "var d:* = new TestClass1();\r\n" + "var k:* = 7 + 8;\r\n" + "if(k == 15)\r\n" + "{\r\n" @@ -1107,25 +971,25 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardRegExp(String swfUsed) { - decompileMethod(swfUsed, "testRegExp", "var a1:* = /[a-z\\r\\n0-9\\\\]+/i;\r\n" + @Test + public void testRegExp() { + decompileMethod("classic", "testRegExp", "var a1:* = /[a-z\\r\\n0-9\\\\]+/i;\r\n" + "var a2:* = /[a-z\\r\\n0-9\\\\]+/i;\r\n" + "var b1:* = /[0-9AB]+/;\r\n" + "var b2:* = /[0-9AB]+/;\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardRest(String swfUsed) { - decompileMethod(swfUsed, "testRest", "trace(\"firstRest:\" + restval[0]);\r\n" + @Test + public void testRest() { + decompileMethod("classic", "testRest", "trace(\"firstRest:\" + restval[0]);\r\n" + "return firstp;\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardStrictEquals(String swfUsed) { - decompileMethod(swfUsed, "testStrictEquals", "var k:int = 6;\r\n" + @Test + public void testStrictEquals() { + decompileMethod("classic", "testStrictEquals", "var k:int = 6;\r\n" + "if(this.f() !== this.f())\r\n" + "{\r\n" + "trace(\"is eight\");\r\n" @@ -1133,18 +997,18 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardStringConcat(String swfUsed) { - decompileMethod(swfUsed, "testStringConcat", "var k:int = 8;\r\n" + @Test + public void testStringConcat() { + decompileMethod("classic", "testStringConcat", "var k:int = 8;\r\n" + "this.traceIt(\"hello\" + 5 * 6);\r\n" + "this.traceIt(\"hello\" + (k - 1));\r\n" + "this.traceIt(\"hello\" + 5 + 6);\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardStrings(String swfUsed) { - decompileMethod(swfUsed, "testStrings", "trace(\"hello\");\r\n" + @Test + public void testStrings() { + decompileMethod("classic", "testStrings", "trace(\"hello\");\r\n" + "trace(\"quotes:\\\"hello!\\\"\");\r\n" + "trace(\"backslash: \\\\ \");\r\n" + "trace(\"single quotes: \\'hello!\\'\");\r\n" @@ -1152,9 +1016,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardSwitch(String swfUsed) { - decompileMethod(swfUsed, "testSwitch", "var a:* = 5;\r\n" + @Test + public void testSwitch() { + decompileMethod("classic", "testSwitch", "var a:* = 5;\r\n" + "switch(a)\r\n" + "{\r\n" + "case 57 * a:\r\n" @@ -1171,9 +1035,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardSwitchComma(String swfUsed) { - decompileMethod(swfUsed, "testSwitchComma", "var b:int = 5;\r\n" + @Test + public void testSwitchComma() { + decompileMethod("classic", "testSwitchComma", "var b:int = 5;\r\n" + "var a:String = \"A\";\r\n" + "switch(a)\r\n" + "{\r\n" @@ -1188,9 +1052,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardSwitchDefault(String swfUsed) { - decompileMethod(swfUsed, "testSwitchDefault", "var a:* = 5;\r\n" + @Test + public void testSwitchDefault() { + decompileMethod("classic", "testSwitchDefault", "var a:* = 5;\r\n" + "switch(a)\r\n" + "{\r\n" + "case 57 * a:\r\n" @@ -1210,9 +1074,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardTernarOperator(String swfUsed) { - decompileMethod(swfUsed, "testTernarOperator", "var a:* = 5;\r\n" + @Test + public void testTernarOperator() { + decompileMethod("classic", "testTernarOperator", "var a:* = 5;\r\n" + "var b:* = 4;\r\n" + "var c:* = 4;\r\n" + "var d:* = 78;\r\n" @@ -1221,9 +1085,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardTry(String swfUsed) { - decompileMethod(swfUsed, "testTry", "var i:int = 0;\r\n" + @Test + public void testTry() { + decompileMethod("classic", "testTry", "var i:int = 0;\r\n" + "i = 7;\r\n" + "try\r\n" + "{\r\n" @@ -1246,9 +1110,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardTryReturn(String swfUsed) { - decompileMethod(swfUsed, "testTryReturn", "var i:int = 0;\r\n" + @Test + public void testTryReturn() { + decompileMethod("classic", "testTryReturn", "var i:int = 0;\r\n" + "var b:Boolean = false;\r\n" + "try\r\n" + "{\r\n" @@ -1274,9 +1138,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardTryReturn2(String swfUsed) { - decompileMethod(swfUsed, "testTryReturn2", "var c:Boolean = false;\r\n" + @Test + public void testTryReturn2() { + decompileMethod("classic", "testTryReturn2", "var c:Boolean = false;\r\n" + "trace(\"before\");\r\n" + "var a:Boolean = true;\r\n" + "var b:Boolean = false;\r\n" @@ -1317,9 +1181,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardUsagesTry(String swfUsed) { - decompileMethod(swfUsed, "testUsagesTry", "var k:int = 5;\r\n" + @Test + public void testUsagesTry() { + decompileMethod("classic", "testUsagesTry", "var k:int = 5;\r\n" + "switch(k)\r\n" + "{\r\n" + "case 0:\r\n" @@ -1351,9 +1215,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardVector(String swfUsed) { - decompileMethod(swfUsed, "testVector", "var v:Vector. = new Vector.();\r\n" + @Test + public void testVector() { + decompileMethod("classic", "testVector", "var v:Vector. = new Vector.();\r\n" + "v.push(\"hello\");\r\n" + "v[0] = \"hi\";\r\n" + "var a:int = 5;\r\n" @@ -1362,16 +1226,16 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardVector2(String swfUsed) { - decompileMethod(swfUsed, "testVector2", "var a:Vector.> = new Vector.>();\r\n" + @Test + public void testVector2() { + decompileMethod("classic", "testVector2", "var a:Vector.> = new Vector.>();\r\n" + "var b:Vector. = new [10,20,30];\r\n", false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardWhileAnd(String swfUsed) { - decompileMethod(swfUsed, "testWhileAnd", "var a:int = 5;\r\n" + @Test + public void testWhileAnd() { + decompileMethod("classic", "testWhileAnd", "var a:int = 5;\r\n" + "var b:int = 10;\r\n" + "while(a < 10 && b > 1)\r\n" + "{\r\n" @@ -1383,9 +1247,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardWhileContinue(String swfUsed) { - decompileMethod(swfUsed, "testWhileContinue", "var a:* = 5;\r\n" + @Test + public void testWhileContinue() { + decompileMethod("classic", "testWhileContinue", "var a:* = 5;\r\n" + "while(true)\r\n" + "{\r\n" + "if(a == 9)\r\n" @@ -1405,9 +1269,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardWhileTry(String swfUsed) { - decompileMethod(swfUsed, "testWhileTry", "while(true)\r\n" + @Test + public void testWhileTry() { + decompileMethod("classic", "testWhileTry", "while(true)\r\n" + "{\r\n" + "try\r\n" + "{\r\n" @@ -1429,9 +1293,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardWhileTry2(String swfUsed) { - decompileMethod(swfUsed, "testWhileTry2", "var j:* = undefined;\r\n" + @Test + public void testWhileTry2() { + decompileMethod("classic", "testWhileTry2", "var j:* = undefined;\r\n" + "for(var i:* = 0; i < 100; i++)\r\n" + "{\r\n" + "try\r\n" @@ -1455,9 +1319,9 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } - @Test(dataProvider = "standardSwfNamesProvider") - public void testStandardXml(String swfUsed) { - decompileMethod(swfUsed, "testXml", "var g:XML = null;\r\n" + @Test + public void testXml() { + decompileMethod("classic", "testXml", "var g:XML = null;\r\n" + "var name:String = \"ahoj\";\r\n" + "var myXML:XML = \r\n" + "\r\n" @@ -1570,323 +1434,4 @@ public class ActionScript3Test extends ActionScriptTestBase { + ";\r\n", false); } - - @Test - public void testAssembledDoubleDup() { - decompileMethod("assembled", "testDoubleDup", "var _loc10_:Rectangle = myprop(_loc5_);\r\n" - + "_loc10_.mymethod(-_loc10_.width,-_loc10_.height);\r\n", - false); - } - - @Test - public void testAssembledDup() { - decompileMethod("assembled", "testDup", "return 1 - (var _loc1_:Number = 1 - _loc1_ / _loc4_) * _loc1_;\r\n", - false); - } - - @Test - public void testAssembledDupAssignment() { - decompileMethod("assembled", "testDupAssignment", "var _loc1_:int = 0;\r\n" - + "var _loc2_:int = 10;\r\n" - + "if(_loc1_ = _loc2_)\r\n" - + "{\r\n" - + "trace(_loc2_);\r\n" - + "}\r\n", - false); - } - - @Test - public void testAssembledForEach() { - decompileMethod("assembled", "testForEach", "var _loc5_:* = undefined;\r\n" - + "var _loc2_:* = 0;\r\n" - + "var _loc3_:int = 0;\r\n" - + "for each(var _loc4_ in _loc5_)\r\n" - + "{\r\n" - + "if(_loc4_ != null)\r\n" - + "{\r\n" - + "_loc2_ = _loc4_;\r\n" - + "}\r\n" - + "}\r\n" - + "_loc3_ = 0;\r\n", - false); - } - - @Test - public void testAssembledForEachCoerced() { - decompileMethod("assembled", "testForEachCoerced", "for each(var _loc6_ in someprop)\r\n" - + "{\r\n" - + "_loc6_.methodname(_loc1_,_loc2_,_loc5_);\r\n" - + "}\r\n", - false); - } - - @Test - public void testAssembledIncrement() { - decompileMethod("assembled", "testIncrement", "super();\r\n" - + "b = a++;\r\n", - false); - } - - @Test - public void testAssembledIncrement2() { - decompileMethod("assembled", "testIncrement2", "if(++loadCount == 2)\r\n" - + "{\r\n" - + "somemethod();\r\n" - + "}\r\n", - false); - } - - @Test - public void testAssembledIncrement3() { - decompileMethod("assembled", "testIncrement3", "_loc1_.length--;\r\n", - false); - } - - @Test - public void testAssembledSetSlotDup() { - decompileMethod("assembled", "testSetSlotDup", "var _loc5_:int = 5;\r\n" - + "myname.somemethod(\"okay\",myslot = _loc5_);\r\n" - + "myname.start();\r\n", - false); - } - - @Test - public void testAssembledSetSlotFindProperty() { - decompileMethod("assembled", "testSetSlotFindProperty", "return var myprop:int = 50;\r\n", - false); - } - - @Test - public void testAssembledSwitch() { - decompileMethod("assembled", "testSwitch", "switch(int(somevar))\r\n" - + "{\r\n" - + "case 0:\r\n" - + "var _loc2_:String = \"X\";\r\n" - + "return;\r\n" - + "break;\r\n" - + "case 1:\r\n" - + "_loc2_ = \"A\";\r\n" - + "break;\r\n" - + "case 3:\r\n" - + "_loc2_ = \"B\";\r\n" - + "break;\r\n" - + "case 4:\r\n" - + "_loc2_ = \"C\";\r\n" - + "}\r\n" - + "_loc2_ = \"after\";\r\n", - false); - } - - @Test - public void testAssembledSwitchDefault() { - decompileMethod("assembled", "testSwitchDefault", "switch(5)\r\n" - + "{\r\n" - + "case 6:\r\n" - + "var _loc2_:int = 6;\r\n" - + "case 0:\r\n" - + "_loc2_ = 0;\r\n" - + "break;\r\n" - + "case 1:\r\n" - + "_loc2_ = 1;\r\n" - + "case 5:\r\n" - + "_loc2_ = 5;\r\n" - + "break;\r\n" - + "case 3:\r\n" - + "_loc2_ = 3;\r\n" - + "break;\r\n" - + "default:\r\n" - + "_loc2_ = 100;\r\n" - + "}\r\n", - false); - } - - @Test - public void testOptionalParameters() { - String methodName = "testOptionalParameters"; - String className = methodName.substring(0, 1).toUpperCase() + methodName.substring(1); - - int clsIndex = -1; - DoABC2Tag tag = null; - ABC abc = null; - for (Tag t : swfMap.get("standard").getTags()) { - if (t instanceof DoABC2Tag) { - tag = (DoABC2Tag) t; - abc = tag.getABC(); - clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className}, "")); - if (clsIndex > -1) { - break; - } - } - } - assertTrue(clsIndex > -1); - - int methodInfo = abc.findMethodInfoByName(clsIndex, "run"); - int bodyIndex = abc.findMethodBodyByName(clsIndex, "run"); - assertTrue(methodInfo > -1); - assertTrue(bodyIndex > -1); - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - abc.method_info.get(methodInfo).getParamStr(writer, abc.constants, abc.bodies.get(bodyIndex), abc, new ArrayList<>()); - String actualResult = writer.toString().replaceAll("[ \r\n]", ""); - String expectedResult = "p1:Event=null,p2:Number=1,p3:Number=-1,p4:Number=-1.1,p5:Number=-1.1,p6:String=\"a\""; - expectedResult = expectedResult.replaceAll("[ \r\n]", ""); - assertEquals(actualResult, expectedResult); - } - - @Test - public void testMyPackage1TestClass() { - decompileScriptPack("tests_classes.mypackage1.TestClass", "package tests_classes.mypackage1\n" - + "{\n" - + " public class TestClass implements tests_classes.mypackage1.TestInterface\n" - + " {\n" - + " \n" - + " public function TestClass()\n" - + " {\n" - + " super();\n" - + " }\n" - + " \n" - + " public function testCall() : String\n" - + " {\n" - + " trace(\"pkg1hello\");\n" - + " return \"pkg1hello\";\n" - + " }\n" - + " \n" - + " public function testMethod1() : void\n" - + " {\n" - + " var a:tests_classes.mypackage1.TestInterface = this;\n" - + " a.testMethod1();\n" - + " var b:tests_classes.mypackage2.TestInterface = this;\n" - + " b = new tests_classes.mypackage2.TestClass();\n" - + " }\n" - + " \n" - + " public function testMethod2() : void\n" - + " {\n" - + " var a:tests_classes.mypackage1.TestInterface = this;\n" - + " a.testMethod1();\n" - + " var b:tests_classes.mypackage2.TestInterface = this;\n" - + " b = new tests_classes.mypackage2.TestClass();\n" - + " }\n" - + " }\n" - + "}"); - } - - @Test - public void testMyPackage1TestClass2() { - decompileScriptPack("tests_classes.mypackage1.TestClass2", "package tests_classes.mypackage1\n" - + "{\n" - + " public class TestClass2\n" - + " {\n" - + " \n" - + " public function TestClass2()\n" - + " {\n" - + " super();\n" - + " }\n" - + " \n" - + " public function testCall() : String\n" - + " {\n" - + " var a:tests_classes.mypackage1.TestClass = null;\n" - + " var b:tests_classes.mypackage2.TestClass = null;\n" - + " var c:tests_classes.mypackage3.TestClass = null;\n" - + " a = new tests_classes.mypackage1.TestClass();\n" - + " b = new tests_classes.mypackage2.TestClass();\n" - + " c = new tests_classes.mypackage3.TestClass();\n" - + " var res:String = a.testCall() + b.testCall() + c.testCall() + this.testCall2() + myNamespace::testCall3();\n" - + " trace(res);\n" - + " return res;\n" - + " }\n" - + " \n" - + " myNamespace function testCall2() : String\n" - + " {\n" - + " return \"1\";\n" - + " }\n" - + " \n" - + " myNamespace function testCall3() : String\n" - + " {\n" - + " return myNamespace::testCall2();\n" - + " }\n" - + " \n" - + " public function testCall2() : String\n" - + " {\n" - + " return \"2\";\n" - + " }\n" - + " }\n" - + "}"); - } - - @Test - public void testMyPackage1TestInterface() { - decompileScriptPack("tests_classes.mypackage1.TestInterface", "package tests_classes.mypackage1\n" - + "{\n" - + " public interface TestInterface extends tests_classes.mypackage2.TestInterface\n" - + " {\n" - + " \n" - + " function testMethod1() : void;\n" - + " }\n" - + "}"); - } - - @Test - public void testMyPackage1MyNamespace() { - decompileScriptPack("tests_classes.mypackage1.myNamespace", "package tests_classes.mypackage1\n" - + "{\n" - + " public namespace myNamespace = \"https://www.free-decompiler.com/flash/test/namespace\";\n" - + "}"); - } - - @Test - public void testMyPackage2TestClass() { - decompileScriptPack("tests_classes.mypackage2.TestClass", "package tests_classes.mypackage2\n" - + "{\n" - + " public class TestClass implements TestInterface\n" - + " {\n" - + " \n" - + " public function TestClass()\n" - + " {\n" - + " super();\n" - + " }\n" - + " \n" - + " public function testCall() : String\n" - + " {\n" - + " trace(\"pkg2hello\");\n" - + " return \"pkg2hello\";\n" - + " }\n" - + " \n" - + " public function testMethod2() : void\n" - + " {\n" - + " }\n" - + " }\n" - + "}"); - } - - @Test - public void testMyPackage2TestInterface() { - decompileScriptPack("tests_classes.mypackage2.TestInterface", "package tests_classes.mypackage2\n" - + "{\n" - + " public interface TestInterface\n" - + " {\n" - + " \n" - + " function testMethod2() : void;\n" - + " }\n" - + "}"); - } - - @Test - public void testMyPackage3TestClass() { - decompileScriptPack("tests_classes.mypackage3.TestClass", "package tests_classes.mypackage3\n" - + "{\n" - + " public class TestClass\n" - + " {\n" - + " \n" - + " public function TestClass()\n" - + " {\n" - + " super();\n" - + " }\n" - + " \n" - + " public function testCall() : String\n" - + " {\n" - + " trace(\"pkg3hello\");\n" - + " return \"pkg3hello\";\n" - + " }\n" - + " }\n" - + "}"); - } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3CrossCompileDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3CrossCompileDecompileTest.java new file mode 100644 index 000000000..f2208e7d7 --- /dev/null +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3CrossCompileDecompileTest.java @@ -0,0 +1,372 @@ +package com.jpexs.decompiler.flash; + +import java.io.IOException; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript3CrossCompileDecompileTest extends ActionScript3DecompileTestBase { + + @BeforeClass + public void init() throws IOException, InterruptedException { + addSwf("flex", "testdata/cross_compile/bin/Main.flex.swf"); + addSwf("air", "testdata/cross_compile/bin/Main.air.swf"); + } + + @DataProvider + public Object[][] swfNamesProvider() { + return new Object[][]{ + {"flex"}, + {"air"} + }; + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryCatch(String swfUsed) { + decompileMethod(swfUsed, "testTryCatch", "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryCatchExceptionUsage(String swfUsed) { + decompileMethod(swfUsed, "testTryCatchExceptionUsage", "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"catched exception: \" + e.message);\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryCatchIfInTry(String swfUsed) { + decompileMethod(swfUsed, "testTryCatchIfInTry", "var a:Boolean = true;\r\n" + + "trace(\"before\");\r\n" + + "try\r\n" + + "{\r\n" + + "if(a)\r\n" + + "{\r\n" + + "trace(\"ret\");\r\n" + + "return;\r\n" + + "}\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryCatchLoop(String swfUsed) { + decompileMethod(swfUsed, "testTryCatchLoop", "var j:int = 0;\r\n" + + "var i:int = 0;\r\n" + + "while(i < 100)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "j = 0;\r\n" + + "while(j < 20)\r\n" + + "{\r\n" + + "trace(\"a\");\r\n" + + "j++;\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e:EOFError)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"after_try\");\r\n" + + "i++;\r\n" + + "}\r\n" + + "trace(\"end\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinally(String swfUsed) { + decompileMethod(swfUsed, "testTryFinally", "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyDirectReturnInFinally(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyDirectReturnInFinally", "var str:String = \"xxx\";\r\n" + + "try\r\n" + + "{\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"error\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"hi \");\r\n" + + "if(str == \"check\")\r\n" + + "{\r\n" + + "return str;\r\n" + + "}\r\n" + + "return \"hu\" + str;\r\n" + + "}\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyLoop(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyLoop", "var i:int = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "if(i == 5)\r\n" + + "{\r\n" + + "i = i + 5;\r\n" + + "trace(\"continue while\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n" + + "i++;\r\n" + + "}\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyLoopInFinally(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyLoopInFinally", "var i:int = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "if(i == 5)\r\n" + + "{\r\n" + + "i = i + 7;\r\n" + + "trace(\"continue while\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n" + + "i++;\r\n" + + "}\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyMultipleCatch(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyMultipleCatch", "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch Error\");\r\n" + + "}\r\n" + + "catch(e:EOFError)\r\n" + + "{\r\n" + + "trace(\"in catch EOFError\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyNoCatch(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyNoCatch", "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyReturn(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyReturn", "var a:int = 0;\r\n" + + "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "a = 5;\r\n" + + "if(a > 4)\r\n" + + "{\r\n" + + "return \"RET\";\r\n" + + "}\r\n" + + "trace(\"between\");\r\n" + + "if(a < 3)\r\n" + + "{\r\n" + + "return \"RE2\";\r\n" + + "}\r\n" + + "trace(\"in try2\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n" + + "return \"RETFINAL\";\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyReturnInFinally(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyReturnInFinally", "var a:int = 0;\r\n" + + "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "a = 5;\r\n" + + "if(a > 4)\r\n" + + "{\r\n" + + "return \"RET\";\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "if(a > 6)\r\n" + + "{\r\n" + + "return \"FINRET1\";\r\n" + + "}\r\n" + + "trace(\"xx\");\r\n" + + "if(a > 5)\r\n" + + "{\r\n" + + "return \"FINRET2\";\r\n" + + "}\r\n" + + "trace(\"nofinret\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n" + + "return \"RETEXIT\";\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyReturnNested(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyReturnNested", "var a:int = Math.random() * 5;\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"before try2\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try2\");\r\n" + + "if(a > 4)\r\n" + + "{\r\n" + + "return \"RET\";\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally2\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally1\");\r\n" + + "}\r\n" + + "return \"RETFINAL\";\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryFinallyReturnVoid(String swfUsed) { + decompileMethod(swfUsed, "testTryFinallyReturnVoid", "var a:int = Math.random() * 5;\r\n" + + "trace(\"before try\");\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "if(a > 4)\r\n" + + "{\r\n" + + "return;\r\n" + + "}\r\n" + + "trace(\"in try2\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"in finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } +} diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java new file mode 100644 index 000000000..6ba944cc1 --- /dev/null +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java @@ -0,0 +1,105 @@ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.tags.DoABC2Tag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.graph.DottedChain; +import com.jpexs.decompiler.graph.ScopeStack; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import org.testng.annotations.BeforeClass; + +/** + * + * @author JPEXS + */ +public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBase { + + private final Map swfMap = new HashMap<>(); + + @BeforeClass + public void initConfiguration() throws IOException, InterruptedException { + Configuration.autoDeobfuscate.set(false); + Configuration.simplifyExpressions.set(false); + + Configuration.decompile.set(true); + Configuration.registerNameFormat.set("_loc%d_"); + Configuration.showMethodBodyId.set(false); + } + + protected void addSwf(String identifier, String path) throws FileNotFoundException, IOException, InterruptedException { + swfMap.put(identifier, new SWF(new BufferedInputStream(new FileInputStream(path)), false)); + } + + public SWF getSwf(String identifier) { + return swfMap.get(identifier); + } + + protected void decompileMethod(String swfIdentifier, String methodName, String expectedResult, boolean isStatic) { + String className = methodName.substring(0, 1).toUpperCase() + methodName.substring(1); + + int clsIndex = -1; + int scriptIndex = -1; + + ABC abc = null; + SWF swf = getSwf(swfIdentifier); + List abcs = new ArrayList<>(); + for (ABCContainerTag abcTag : swf.getAbcList()) { + abcs.add(abcTag.getABC()); + } + ScriptPack scriptPack = null; + for (ABC a : abcs) { + scriptPack = a.findScriptPackByPath("tests." + className, abcs); + if (scriptPack != null) { + break; + } + } + assertNotNull(scriptPack); + abc = scriptPack.abc; + scriptIndex = scriptPack.scriptIndex; + + clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className}, "")); + + assertTrue(clsIndex > -1); + assertTrue(scriptIndex > -1); + + int bodyIndex = abc.findMethodBodyByName(clsIndex, "run"); + + assertTrue(bodyIndex > -1); + HighlightedTextWriter writer; + try { + List ts = new ArrayList<>(); + ts.add(abc.instance_info.get(clsIndex).instance_traits); + abc.bodies.get(bodyIndex).convert(new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(scriptIndex), 0, new NulWriter(), new ArrayList<>(), ts, true); + writer = new HighlightedTextWriter(new CodeFormatting(), false); + abc.bodies.get(bodyIndex).toString("run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>()); + } catch (InterruptedException ex) { + fail(); + return; + } + String actualResult = cleanPCode(writer.toString()); + expectedResult = cleanPCode(expectedResult); + assertEquals(actualResult, expectedResult); + } + +} diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java new file mode 100644 index 000000000..43b7594c8 --- /dev/null +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java @@ -0,0 +1,57 @@ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.tags.DoABC2Tag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.graph.DottedChain; +import java.io.IOException; +import java.util.ArrayList; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript3OptinalParametersTest extends ActionScript3DecompileTestBase { + + @BeforeClass + public void init() throws IOException, InterruptedException { + addSwf("standard", "testdata/flashdevelop/bin/flashdevelop.swf"); + } + @Test + public void testOptionalParameters() { + String methodName = "testOptionalParameters"; + String className = methodName.substring(0, 1).toUpperCase() + methodName.substring(1); + + int clsIndex = -1; + DoABC2Tag tag = null; + ABC abc = null; + for (Tag t : getSwf("standard").getTags()) { + if (t instanceof DoABC2Tag) { + tag = (DoABC2Tag) t; + abc = tag.getABC(); + clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className}, "")); + if (clsIndex > -1) { + break; + } + } + } + assertTrue(clsIndex > -1); + + int methodInfo = abc.findMethodInfoByName(clsIndex, "run"); + int bodyIndex = abc.findMethodBodyByName(clsIndex, "run"); + assertTrue(methodInfo > -1); + assertTrue(bodyIndex > -1); + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + abc.method_info.get(methodInfo).getParamStr(writer, abc.constants, abc.bodies.get(bodyIndex), abc, new ArrayList<>()); + String actualResult = writer.toString().replaceAll("[ \r\n]", ""); + String expectedResult = "p1:Event=null,p2:Number=1,p3:Number=-1,p4:Number=-1.1,p5:Number=-1.1,p6:String=\"a\""; + expectedResult = expectedResult.replaceAll("[ \r\n]", ""); + assertEquals(actualResult, expectedResult); + } +} diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java index 5e84f4458..0acfabd45 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java @@ -50,7 +50,9 @@ import java.util.TreeMap; */ public class AS3Generator { - private static void useFile(StringBuilder s, File f, String identifier) throws FileNotFoundException, IOException, InterruptedException { + private static void useFile(String testClassName, String[][] swfAndIdentifierList, boolean multipleProviders) throws FileNotFoundException, IOException, InterruptedException { + StringBuilder s = new StringBuilder(); + File f = new File(swfAndIdentifierList[0][0]); SWF swf = new SWF(new BufferedInputStream(new FileInputStream(f)), false); DoABC2Tag tag = null; List scriptPacks = swf.getAS3Packs(); @@ -58,6 +60,46 @@ public class AS3Generator { for (ScriptPack pack : scriptPacks) { sortedPacks.put(pack.getClassPath().toRawString(), pack); } + s.append("package com.jpexs.decompiler.flash;\r\n"); + s.append("\r\n"); + s.append("import java.io.IOException;\r\n"); + s.append("import org.testng.annotations.BeforeClass;\r\n"); + if (multipleProviders) { + s.append("import org.testng.annotations.DataProvider;\r\n"); + } + s.append("import org.testng.annotations.Test;\r\n"); + + s.append("/**\r\n"); + s.append(" *\r\n"); + s.append(" * @author JPEXS\r\n"); + s.append(" */\r\n"); + s.append("public class ").append(testClassName).append(" extends ActionScript3DecompileTestBase {\r\n"); + + s.append("@BeforeClass\r\n"); + s.append("public void init() throws IOException, InterruptedException {\r\n"); + for (int i = 0; i < swfAndIdentifierList.length; i++) { + s.append("addSwf(\"").append(swfAndIdentifierList[i][1]).append("\", \"").append(swfAndIdentifierList[i][0].replace("\\", "\\\\")).append("\");\r\n"); + } + s.append("}\r\n"); + + if (multipleProviders) { + s.append("@DataProvider\r\n"); + s.append("public Object[][] swfNamesProvider() {\r\n"); + s.append("return new Object[][]{\r\n"); + + for (int i = 0; i < swfAndIdentifierList.length; i++) { + s.append("{\""); + s.append(swfAndIdentifierList[i][1]); + s.append("\"}"); + if (i < swfAndIdentifierList.length - 1) { + s.append(","); + } + s.append("\r\n"); + } + s.append("};\r\n"); + s.append("}\r\n"); + } + for (String packClassName : sortedPacks.keySet()) { ScriptPack pack = sortedPacks.get(packClassName); ABC abc = pack.abc; @@ -71,20 +113,20 @@ public class AS3Generator { String name = t.getName(abc).getName(abc.constants, null, true, true); String clsName = pack.getClassPath().className; String lower = clsName.substring(0, 1).toLowerCase() + clsName.substring(1); - String idUpper = identifier.substring(0, 1).toUpperCase() + identifier.substring(1); - String testMethodName = lower.replaceAll("^test", "test" + idUpper); + String identifier = swfAndIdentifierList[0][1]; + String testMethodName = lower; //lower.replaceAll("^test", "test" + idUpper); if (lower.equals("testOptionalParameters")) { //SPECIAL: ignored continue; } if (name.equals("run")) { - if (identifier.equals("standard")) { - s.append("@Test(dataProvider = \"standardSwfNamesProvider\")\r\n"); + if (multipleProviders) { + s.append("@Test(dataProvider = \"swfNamesProvider\")\r\n"); } else { s.append("@Test\r\n"); } s.append("public void "); s.append(testMethodName); - if (identifier.equals("standard")) { + if (multipleProviders) { s.append("(String swfUsed){\r\ndecompileMethod(swfUsed"); } else { s.append("(){\r\ndecompileMethod(\""); @@ -118,18 +160,23 @@ public class AS3Generator { } } } + + s.append("}\r\n"); + String testPath = "test/com/jpexs/decompiler/flash/"; + Helper.writeFile(testPath + testClassName + ".java", s.toString().getBytes("UTF-8")); } public static void main(String[] args) throws Exception { Configuration.autoDeobfuscate.set(false); - StringBuilder s = new StringBuilder(); + useFile("ActionScript3ClassicDecompileTest", new String[][]{{"testdata/flashdevelop/bin/flashdevelop.swf", "classic"}}, false); + useFile("ActionScript3CrossCompileDecompileTest", new String[][]{ + {"testdata/cross_compile/bin/Main.flex.swf", "flex"}, + {"testdata/cross_compile/bin/Main.air.swf", "air"} + }, true); + useFile("ActionScript3AssembledDecompileTest", new String[][]{{"testdata/custom/bin/custom.swf", "assembled"}}, false); - useFile(s, new File("testdata/flashdevelop/bin/flashdevelop.swf"), "standard"); - useFile(s, new File("testdata/custom/bin/custom.swf"), "assembled"); - - Helper.writeFile("as3_teststub.java", s.toString().getBytes("UTF-8")); System.exit(0); } } diff --git a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.air.swf b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.air.swf index 2ada6378d..1e837d9a9 100644 Binary files a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.air.swf and b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex.swf b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex.swf index 948424409..cfb3f5cee 100644 Binary files a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex.swf and b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex_apache.swf b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex_apache.swf index 6742e0bc5..573709054 100644 Binary files a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex_apache.swf and b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex_apache.swf differ diff --git a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.swftools.swf b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.swftools.swf index 866fe6d15..1fceba1de 100644 Binary files a/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.swftools.swf and b/libsrc/ffdec_lib/testdata/cross_compile/bin/Main.swftools.swf differ diff --git a/libsrc/ffdec_lib/testdata/cross_compile/src/Main.as b/libsrc/ffdec_lib/testdata/cross_compile/src/Main.as index 257c1c562..d980c14da 100644 --- a/libsrc/ffdec_lib/testdata/cross_compile/src/Main.as +++ b/libsrc/ffdec_lib/testdata/cross_compile/src/Main.as @@ -14,11 +14,12 @@ package TestTryCatchIfInTry; TestTryCatchLoop; TestTryCatchExceptionUsage - TestTryFinally; + TestTryFinally; TestTryFinallyDirectReturnInFinally; TestTryFinallyLoop; TestTryFinallyLoopInFinally; TestTryFinallyMultipleCatch; + TestTryFinallyNoCatch; TestTryFinallyReturn; TestTryFinallyReturnInFinally; TestTryFinallyReturnNested; diff --git a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchLoop.as b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchLoop.as index 1d7cad3af..71ab4cf35 100644 --- a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchLoop.as +++ b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchLoop.as @@ -11,14 +11,16 @@ package tests public function run() : void { - var j:* = undefined; - for (var i:* = 0; i < 100; i++) + var i:int = 0; + while (i < 100) { try { - for (j = 0; j < 20; j++) + var j:int = 0; + while (j < 20) { trace("a"); + j++; } } catch (e:EOFError) @@ -30,6 +32,7 @@ package tests continue; } trace("after_try"); + i++; } trace("end"); } diff --git a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoop.as b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoop.as index 06a3d7056..a6ab6fcc8 100644 --- a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoop.as +++ b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoop.as @@ -9,7 +9,8 @@ package tests public function run() : void { - for (var i:int = 0; i < 10; i++) + var i:int = 0; + while (i < 10) { trace("before try"); try @@ -17,7 +18,8 @@ package tests trace("in try"); if (i == 5) { - trace("continue for"); + i += 5; + trace("continue while"); continue; } } @@ -30,6 +32,7 @@ package tests trace("in finally"); } trace("after"); + i++; } } diff --git a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoopInFinally.as b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoopInFinally.as index 4c3342857..8144d81cd 100644 --- a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoopInFinally.as +++ b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoopInFinally.as @@ -9,7 +9,8 @@ package tests public function run() : void { - for (var i:int = 0; i < 10; i++) + var i:int = 0; + while (i < 10) { trace("before try"); try @@ -24,12 +25,14 @@ package tests { if (i == 5) { - trace("continue for"); + i += 7; + trace("continue while"); continue; } trace("in finally"); } trace("after"); + i++ } } diff --git a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyNoCatch.as b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyNoCatch.as new file mode 100644 index 000000000..2a4eed5cd --- /dev/null +++ b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyNoCatch.as @@ -0,0 +1,26 @@ +package tests +{ + /** + * ... + * @author JPEXS + */ + public class TestTryFinallyNoCatch + { + + public function run() : void + { + trace("before try"); + try + { + trace("in try"); + } + finally + { + trace("in finally"); + } + trace("after"); + } + + } + +} \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnNested.as b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnNested.as index dc9d6d4da..baf378ca0 100644 --- a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnNested.as +++ b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnNested.as @@ -9,13 +9,13 @@ package tests public function run() : String { + var a:int = Math.random() * 5; try { trace("before try2"); try { trace("in try2"); - var a:int = 5; if (a > 4) { return "RET"; diff --git a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnVoid.as b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnVoid.as index c18fb4b7e..b5f57ccb9 100644 --- a/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnVoid.as +++ b/libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnVoid.as @@ -9,11 +9,11 @@ package tests public function run() : void { + var a:int = Math.random() * 5; trace("before try"); try { trace("in try"); - var a:int = 5; if (a > 4) { return;