Improved tests.

Fixed try..catch..finally.
This commit is contained in:
Jindra Petřík
2021-01-31 15:52:22 +01:00
parent ed5fdc313d
commit adf153e13a
19 changed files with 1418 additions and 772 deletions

View File

@@ -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<GraphPart> 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<GraphPart> getRealRefs(GraphPart part) {
List<GraphPart> ret = new ArrayList<>();
for (GraphPart r : part.refs) {
if (r.start >= 0) {
ret.add(r);
}
}
return ret;
}
private GraphPart searchPart(int ip, Set<GraphPart> allParts) {
for (GraphPart p : allParts) {
if (ip >= p.start && ip <= p.end) {
return p;
}
}
return null;
}
private List<GraphTargetItem> checkTry(List<GraphTargetItem> currentRet, List<GraphTargetItem> output, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, AVM2LocalData localData, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, Set<GraphPart> 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<ABCException> catchedExceptions = new ArrayList<>();
ABCException finallyException = null;
int endIp = -1;
int finallyIndex = -1;
List<Integer> 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<GraphPart> 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<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(afterPart);
List<GraphTargetItem> 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<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(exAfterPart);
if (defaultPart != null) {
stopPart2.add(defaultPart);
}
List<GraphTargetItem> 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<GraphTargetItem> ret = new ArrayList<>();
if (catchedExceptions.isEmpty() && finallyCommands.isEmpty()) {
ret.addAll(tryCommands);
return ret;
}
List<GraphTargetItem> 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;
}
}

View File

@@ -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);
}
}

View File

@@ -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"
+ "}");
}
}

View File

@@ -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);
}
}

View File

@@ -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<String, SWF> 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<ABC> 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<Traits> 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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<ScriptPack> 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);
}
}

View File

@@ -14,11 +14,12 @@ package
TestTryCatchIfInTry;
TestTryCatchLoop;
TestTryCatchExceptionUsage
TestTryFinally;
TestTryFinally;
TestTryFinallyDirectReturnInFinally;
TestTryFinallyLoop;
TestTryFinallyLoopInFinally;
TestTryFinallyMultipleCatch;
TestTryFinallyNoCatch;
TestTryFinallyReturn;
TestTryFinallyReturnInFinally;
TestTryFinallyReturnNested;

View File

@@ -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");
}

View File

@@ -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++;
}
}

View File

@@ -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++
}
}

View File

@@ -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");
}
}
}

View File

@@ -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";

View File

@@ -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;