diff --git a/trunk/test/com/jpexs/decompiler/flash/TestABCStream.java b/trunk/test/com/jpexs/decompiler/flash/ABCStreamTest.java similarity index 84% rename from trunk/test/com/jpexs/decompiler/flash/TestABCStream.java rename to trunk/test/com/jpexs/decompiler/flash/ABCStreamTest.java index a75401297..058daff99 100644 --- a/trunk/test/com/jpexs/decompiler/flash/TestABCStream.java +++ b/trunk/test/com/jpexs/decompiler/flash/ABCStreamTest.java @@ -5,10 +5,14 @@ import com.jpexs.decompiler.flash.abc.ABCOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import junit.framework.TestCase; -import org.junit.Test; +import static org.testng.Assert.*; +import org.testng.annotations.Test; -public class TestABCStream extends TestCase { +/** + * + * @author JPEXS + */ +public class ABCStreamTest { @Test public void testU30() { try { diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionScript3Test.java b/trunk/test/com/jpexs/decompiler/flash/ActionScript3Test.java new file mode 100644 index 000000000..d6917b7e1 --- /dev/null +++ b/trunk/test/com/jpexs/decompiler/flash/ActionScript3Test.java @@ -0,0 +1,799 @@ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.graph.GraphTargetItem; +import com.jpexs.decompiler.flash.tags.DoABCTag; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Stack; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript3Test { + + private SWF swf; + private int clsIndex; + private ABC abc; + + @BeforeClass + public void init() throws IOException { + swf = new SWF(new FileInputStream("testdata/as3/TestMovie.swf")); + DoABCTag tag = null; + for (Tag t : swf.tags) { + if (t instanceof DoABCTag) { + tag = (DoABCTag) t; + break; + } + } + assertNotNull(tag); + clsIndex = tag.abc.findClassByName("classes.Test"); + assertTrue(clsIndex > -1); + this.abc = tag.abc; + } + + private void decompileMethod(String methodName, String expectedResult, boolean isStatic) { + int bodyIndex = abc.findMethodBodyByName(clsIndex, methodName); + assertTrue(bodyIndex > -1); + String actualResult = abc.bodies[bodyIndex].toString(methodName, false, isStatic, clsIndex, abc, abc.constants, abc.method_info, new Stack(), false, false, new ArrayList(), abc.instance_info[clsIndex].instance_traits); + actualResult = actualResult.replaceAll("[ \r\n]", ""); + expectedResult = expectedResult.replaceAll("[ \r\n]", ""); + assertEquals(expectedResult, actualResult); + } + + @Test + public void testHello() { + decompileMethod("testHello", "trace(\"hello\");\r\n", false); + } + + @Test + public void testIncDec() { + decompileMethod("testIncDec", "var a:* = 5;\r\n" + + "var b:* = 0;\r\n" + + "trace(\"++var\");\r\n" + + "b=++a;\r\n" + + "trace(\"var++\");\r\n" + + "b=a++;\r\n" + + "trace(\"--var\");\r\n" + + "b=--a;\r\n" + + "trace(\"var--\");\r\n" + + "b=a--;\r\n" + + "var c:* = [1,2,3,4,5];\r\n" + + "trace(\"++arr\");\r\n" + + "b=++c[2];\r\n" + + "trace(\"arr++\");\r\n" + + "b=c[2]++;\r\n" + + "trace(\"--arr\");\r\n" + + "b=--c[2];\r\n" + + "trace(\"arr--\");\r\n" + + "b=c[2]--;\r\n" + + "var d:* = new TestClass1();\r\n" + + "trace(\"++property\");\r\n" + + "trace(++d.attrib);\r\n" + + "trace(\"property++\");\r\n" + + "trace(d.attrib++);\r\n" + + "trace(\"--property\");\r\n" + + "trace(--d.attrib);\r\n" + + "trace(\"property--\");\r\n" + + "trace(d.attrib--);\r\n" + + "trace(\"arr[e++]\");\r\n" + + "var chars:Array = new Array(36);\r\n" + + "var index:uint = 0;\r\n" + + "chars[index++]=5;\r\n" + + "trace(\"arr[++e]\");\r\n" + + "chars[++index]=5;\r\n", false); + } + + @Test + public void testDoWhile() { + decompileMethod("testDoWhile", "var a:* = 8;\r\n" + + "do\r\n" + + "{\r\n" + + "trace(\"a=\"+a);\r\n" + + "a++;\r\n" + + "}\r\n" + + "while(a>=20);\r\n", false); + } + + @Test + public void testInnerTry() { + decompileMethod("testInnerTry", "try\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"try body 1\");\r\n" + + "}\r\n" + + "catch(e:DefinitionError)\r\n" + + "{\r\n" + + "trace(\"catched DefinitionError\");\r\n" + + "}\r\n" + + "trace(\"after try 1\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"catched Error\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"finally block\");\r\n" + + "}\r\n", false); + } + + @Test + public void testWhileContinue() { + decompileMethod("testWhileContinue", "var a:* = 5;\r\n" + + "while(true)\r\n" + + "{\r\n" + + "if(a==9)\r\n" + + "{\r\n" + + "if(a==8)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "if(a==9)\r\n" + + "{\r\n" + + "return;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"hello 1\");\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"hello2\");\r\n" + + "continue loop0;\r\n", false); + } + + @Test + public void testPrecedence() { + decompileMethod("testPrecedence", "var a:* = 0;\r\n" + + "a=(5+6)*7;\r\n" + + "a=5*(2+3);\r\n" + + "a=5+6*7;\r\n" + + "a=5*2+2;\r\n" + + "trace(\"a=\"+a);\r\n", false); + } + + @Test + public void testStrings() { + decompileMethod("testStrings", "trace(\"hello\");\r\n" + + "trace(\"quotes:\\\"hello!\\\"\");\r\n" + + "trace(\"backslash: \\\\ \");\r\n" + + "trace(\"single quotes: \\'hello!\\'\");\r\n" + + "trace(\"new line \\r\\n hello!\");\r\n", false); + } + + @Test + public void testContinueLevels() { + decompileMethod("testContinueLevels", "var b:* = undefined;\r\n" + + "var c:* = undefined;\r\n" + + "var d:* = undefined;\r\n" + + "var e:* = undefined;\r\n" + + "var a:* = 5;\r\n" + + "switch(a)\r\n" + + "{\r\n" + + "case 57*a:\r\n" + + "trace(\"fiftyseven multiply a\");\r\n" + + "b=0;\r\n" + + "while(b>=50)\r\n" + + "{\r\n" + + "if(b==10)\r\n" + + "{\r\n" + + "break;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "if(b==15)\r\n" + + "{\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "b=b+1;\r\n" + + "continue;\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "break;\r\n" + + "case 13:\r\n" + + "trace(\"thirteen\");\r\n" + + "case 14:\r\n" + + "trace(\"fourteen\");\r\n" + + "break;\r\n" + + "case 89:\r\n" + + "trace(\"eightynine\");\r\n" + + "break;\r\n" + + "default:\r\n" + + "trace(\"default clause\");\r\n" + + "}\r\n" + + "c=0;\r\n" + + "loop0:\r\n" + + "for(;c>=8;c=c+1)\r\n" + + "{\r\n" + + "d=0;\r\n" + + "while(d>=25)\r\n" + + "{\r\n" + + "e=0;\r\n" + + "if(e>=50)\r\n" + + "{\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "if(e==9)\r\n" + + "{\r\n" + + "break;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "if(e==20)\r\n" + + "{\r\n" + + "continue loop0;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "if(e==8)\r\n" + + "{\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "break loop0;\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "d++;\r\n" + + "}\r\n" + + "trace(\"hello\");\r\n" + + "}\r\n", false); + } + + @Test + public void testSwitchDefault() { + decompileMethod("testSwitchDefault", "var a:* = 5;\r\n" + + "switch(a)\r\n" + + "{\r\n" + + "case 57*a:\r\n" + + "trace(\"fiftyseven multiply a\");\r\n" + + "break;\r\n" + + "case 13:\r\n" + + "trace(\"thirteen\");\r\n" + + "case 14:\r\n" + + "trace(\"fourteen\");\r\n" + + "break;\r\n" + + "case 89:\r\n" + + "trace(\"eightynine\");\r\n" + + "break;\r\n" + + "default:\r\n" + + "trace(\"default clause\");\r\n" + + "}\r\n", false); + } + + @Test + public void testMultipleCondition() { + decompileMethod("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" + + "{\r\n" + + "trace(\"onTrue\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"onFalse\");\r\n" + + "}\r\n", false); + } + + @Test + public void testForBreak() { + decompileMethod("testForBreak", "var a:* = 0;\r\n" + + "while(a>=10)\r\n" + + "{\r\n" + + "if(a==5)\r\n" + + "{\r\n" + + "break;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"hello:\"+a);\r\n" + + "a++;\r\n" + + "continue;\r\n" + + "}\r\n" + + "}\r\n", false); + } + + @Test + public void testIf() { + decompileMethod("testIf", "var a:* = 5;\r\n" + + "if(a==7)\r\n" + + "{\r\n" + + "trace(\"onTrue\");\r\n" + + "}\r\n", false); + } + + @Test + public void testIfElse() { + decompileMethod("testIfElse", "var a:* = 5;\r\n" + + "if(a==7)\r\n" + + "{\r\n" + + "trace(\"onTrue\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"onFalse\");\r\n" + + "}\r\n", false); + } + + @Test + public void testFor() { + decompileMethod("testFor", "var a:* = 0;\r\n" + + "while(a>=10)\r\n" + + "{\r\n" + + "trace(\"a=\"+a);\r\n" + + "a++;\r\n" + + "}\r\n", false); + } + + @Test + public void testForContinue() { + decompileMethod("testForContinue", "var a:* = 0;\r\n" + + "for(;a>=10;a=a+1)\r\n" + + "{\r\n" + + "if(a==9)\r\n" + + "{\r\n" + + "if(a==5)\r\n" + + "{\r\n" + + "trace(\"part1\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"a=\"+a);\r\n" + + "if(a==7)\r\n" + + "{\r\n" + + "trace(\"part2\");\r\n" + + "continue;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"part3\");\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"part4\");\r\n" + + "}\r\n" + + "trace(\"part5\");\r\n" + + "}\r\n", false); + } + + @Test + public void testTry() { + decompileMethod("testTry", "var i:int = 0;\r\n" + + "i=7;\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"try body\");\r\n" + + "}\r\n" + + "catch(e:DefinitionError)\r\n" + + "{\r\n" + + "trace(\"catched DefinitionError\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"Error message:\"+e.message);\r\n" + + "trace(\"Stacktrace:\"+e.getStackTrace());\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"Finally part\");\r\n" + + "}\r\n", false); + } + + @Test + public void testSwitch() { + decompileMethod("testSwitch", "var a:* = 5;\r\n" + + "switch(a)\r\n" + + "{\r\n" + + "case 57*a:\r\n" + + "trace(\"fiftyseven multiply a\");\r\n" + + "break;\r\n" + + "case 13:\r\n" + + "trace(\"thirteen\");\r\n" + + "case 14:\r\n" + + "trace(\"fourteen\");\r\n" + + "break;\r\n" + + "case 89:\r\n" + + "trace(\"eightynine\");\r\n" + + "break;\r\n" + + "}\r\n", false); + } + + @Test + public void testTernarOperator() { + decompileMethod("testTernarOperator", "var a:* = 5;\r\n" + + "var b:* = 4;\r\n" + + "var c:* = 4;\r\n" + + "var d:* = 78;\r\n" + + "var e:* = a==b?true:3;\r\n" + + "trace(\"e=\"+e);\r\n", false); + } + + @Test + public void testInnerIf() { + decompileMethod("testInnerIf", "var a:* = 5;\r\n" + + "var b:* = 4;\r\n" + + "if(a==5)\r\n" + + "{\r\n" + + "if(b==6)\r\n" + + "{\r\n" + + "trace(\"b==6\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"b!=6\");\r\n" + + "}\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "if(b==7)\r\n" + + "{\r\n" + + "trace(\"b==7\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"b!=7\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"end\");\r\n", false); + } + + @Test + public void testVector() { + decompileMethod("testVector", "var v:Vector. = new Vector.();\r\n" + + "v.push(\"hello\");\r\n" + + "v[0]=\"hi\";\r\n" + + "v[5*8-39]=\"hi2\";\r\n" + + "trace(v[0]);\r\n", false); + } + + @Test + public void testProperty() { + decompileMethod("testProperty", "var d:* = new TestClass1();\r\n" + + "var k:* = 7+8;\r\n" + + "if(k==15)\r\n" + + "{\r\n" + + "d.method(d.attrib*5);\r\n" + + "}\r\n", false); + } + + @Test + public void testRest() { + decompileMethod("testRest", "trace(\"firstRest:\"+restval[0]);\r\n" + + "return firstp;\r\n", false); + } + + @Test + public void testParamNames() { + decompileMethod("testParamNames", "return firstp+secondp+thirdp;\r\n", false); + } + + @Test + public void testForEach() { + decompileMethod("testForEach", "var list:Array = null;\r\n" + + "var item:* = undefined;\r\n" + + "list=new Array();\r\n" + + "list[0]=\"first\";\r\n" + + "list[1]=\"second\";\r\n" + + "list[2]=\"third\";\r\n" + + "for each (item in list)\r\n" + + "{\r\n" + + "trace(\"item #\"+item);\r\n" + + "}\r\n", false); + } + + @Test + public void testForEachObjectArray() { + decompileMethod("testForEachObjectArray", "var list:Array = null;\r\n" + + "var test:Array = null;\r\n" + + "list=new Array();\r\n" + + "list[0]=\"first\";\r\n" + + "list[1]=\"second\";\r\n" + + "list[2]=\"third\";\r\n" + + "test=new Array();\r\n" + + "test[0]=0;\r\n" + + "for each (test[0] in list)\r\n" + + "{\r\n" + + "trace(\"item #\"+test[0]);\r\n" + + "}\r\n", false); + } + + @Test + public void testForEachObjectAttribute() { + decompileMethod("testForEachObjectAttribute", "var list:Array = null;\r\n" + + "list=new Array();\r\n" + + "list[0]=\"first\";\r\n" + + "list[1]=\"second\";\r\n" + + "list[2]=\"third\";\r\n" + + "for each (this.testPriv in list)\r\n" + + "{\r\n" + + "trace(\"item #\"+this.testPriv);\r\n" + + "}\r\n", false); + } + + @Test + public void testParamsCount() { + decompileMethod("testParamsCount", "return firstp;\r\n", false); + } + + @Test + public void testInlineFunctions() { + decompileMethod("testInlineFunctions", "var first:String = null;\r\n" + + "first=\"value1\";\r\n" + + "var traceParameter:Function = new function(aParam:String):String\r\n" + + "{\r\n" + + "var second:String = null;\r\n" + + "second=\"value2\";\r\n" + + "second=second+\"cc\";\r\n" + + "var traceParam2:Function = new function(bParam:String):String\r\n" + + "{\r\n" + + "trace(bParam+\",\"+aParam);\r\n" + + "return first+second+aParam+bParam;\r\n" + + "};\r\n" + + "trace(second);\r\n" + + "traceParam2(aParam);\r\n" + + "return first;\r\n" + + "};\r\n" + + "traceParameter(\"hello\");\r\n", false); + } + + @Test + public void testMissingDefault() { + decompileMethod("testMissingDefault", "var jj:* = 1;\r\n" + + "switch(jj)\r\n" + + "{\r\n" + + "case 1:\r\n" + + "jj=1;\r\n" + + "break;\r\n" + + "case 2:\r\n" + + "jj=2;\r\n" + + "break;\r\n" + + "default:\r\n" + + "jj=3;\r\n" + + "}\r\n", false); + } + + @Test + public void testChainedAssignments() { + decompileMethod("testChainedAssignments", "var a:* = 0;\r\n" + + "var b:* = 0;\r\n" + + "var c:* = 0;\r\n" + + "var d:* = 0;\r\n" + + "d=c=b=a=5;\r\n" + + "var e:TestClass2 = TestClass2.createMe(\"test\");\r\n" + + "e.attrib1=e.attrib2=e.attrib3=this.getCounter();\r\n" + + "this.traceIt(e.toString());\r\n", false); + } + + @Test + public void testFinallyZeroJump() { + decompileMethod("testFinallyZeroJump", "var str:String = param1;\r\n" + + "try\r\n" + + "{\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"error is :\"+e.message);\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"hi \");\r\n" + + "return \"hu\"+str;\r\n" + + "}\r\n", false); + } + + @Test + public void testInnerFunctions() { + decompileMethod("testInnerFunctions", "var s:int = 0;\r\n" + + "var innerFunc:Function = new function(b:String):*\r\n" + + "{\r\n" + + "trace(b);\r\n" + + "};\r\n" + + "var k:int = 5;\r\n" + + "if(k==6)\r\n" + + "{\r\n" + + "s=8;\r\n" + + "}\r\n" + + "innerFunc(a);\r\n", false); + } + + @Test + public void testDeclarations() { + decompileMethod("testDeclarations", "var vall:* = undefined;\r\n" + + "var vstr:String = null;\r\n" + + "var vint:* = 0;\r\n" + + "var vuint:uint = 0;\r\n" + + "var vclass:TestClass1 = null;\r\n" + + "var vnumber:* = NaN;\r\n" + + "var vobject:Object = null;\r\n" + + "vall=6;\r\n" + + "vstr=\"hello\";\r\n" + + "vuint=7;\r\n" + + "vint=-4;\r\n" + + "vclass=new TestClass1();\r\n" + + "vnumber=0.5;\r\n" + + "vnumber=6;\r\n" + + "vobject=vclass;\r\n", false); + } + + @Test + public void testForIn() { + decompileMethod("testForIn", "var dic:Dictionary = null;\r\n" + + "var item:Object = null;\r\n" + + "for (item in dic)\r\n" + + "{\r\n" + + "trace(item);\r\n" + + "}\r\n" + + "for each (item in dic)\r\n" + + "{\r\n" + + "trace(item);\r\n" + + "}\r\n", false); + } + + @Test + public void testNames() { + decompileMethod("testNames", "var ns:* = this.getNamespace();\r\n" + + "var name:* = this.getName();\r\n", false); + } + + @Test + public void testComplexExpressions() { + decompileMethod("testComplexExpressions", "var i:* = 0;\r\n" + + "var j:* = 0;\r\n" + + "j=i=i+(i=i+i++);\r\n", false); + } + + @Test + public void testExpressions() { + decompileMethod("testExpressions", "var arr:Array = null;\r\n" + + "var i:* = 5;\r\n" + + "var j:* = 5;\r\n" + + "if((i=i=i/2)==1||i==2)\r\n" + + "{\r\n" + + "arguments.concat(i);\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "if(i==0)\r\n" + + "{\r\n" + + "i=j++;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "arr[0]();\r\n" + + "}\r\n" + + "}\r\n" + + "return i==0;\r\n", false); + } + + @Test + public void testArguments() { + decompileMethod("testArguments", "return arguments[0];\r\n", false); + } + + @Test + public void testLogicalComputing() { + decompileMethod("testLogicalComputing", "var b:* = false;\r\n" + + "var i:* = 5;\r\n" + + "var j:* = 7;\r\n" + + "if(i>j)\r\n" + + "{\r\n" + + "j=9;\r\n" + + "b=true;\r\n" + + "}\r\n" + + "b=(i==0||i==1)&&j==0;\r\n", false); + } + + @Test + public void testInc2() { + decompileMethod("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" + + "var b:* = 1;\r\n" + + "b++;\r\n" + + "var c:* = 1;\r\n" + + "b=c++;\r\n", false); + } + + @Test + public void testDecl2() { + decompileMethod("testDecl2", "var k:* = 0;\r\n" + + "var i:* = 5;\r\n" + + "i=i+7;\r\n" + + "if(i==5)\r\n" + + "{\r\n" + + "if(i<8)\r\n" + + "{\r\n" + + "k=6;\r\n" + + "}\r\n" + + "}\r\n" + + "k=7;\r\n", false); + } + + @Test + public void testChain2() { + decompileMethod("testChain2", "var g:Array = null;\r\n" + + "var h:* = false;\r\n" + + "var extraLine:* = false;\r\n" + + "var r:* = 7;\r\n" + + "var t:* = 0;\r\n" + + "t=this.getInt();\r\n" + + "if(t+1=0)\r\n" + + "{\r\n" + + "trace(\"ch\");\r\n" + + "}\r\n", false); + } + + @Test + public void testDoWhile2() { + decompileMethod("testDoWhile2", "var k:* = 5;\r\n" + + "do\r\n" + + "{\r\n" + + "k++;\r\n" + + "if(k==7)\r\n" + + "{\r\n" + + "k=5*k;\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "k=5-k;\r\n" + + "}\r\n" + + "k--;\r\n" + + "}\r\n" + + "while(k>=9);\r\n" + + "return 2;\r\n", false); + } + + @Test + public void testWhileAnd() { + decompileMethod("testWhileAnd", "var a:* = 5;\r\n" + + "var b:* = 10;\r\n" + + "while(a>10&&b<1)\r\n" + + "{\r\n" + + "a++;\r\n" + + "b--;\r\n" + + "}\r\n" + + "a=7;\r\n" + + "b=9;\r\n", false); + } + + @Test + public void testNamedAnonFunctions() { + decompileMethod("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 + public void testStringConcat() { + decompileMethod("testStringConcat", "var k:* = 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); + } +} diff --git a/trunk/test/com/jpexs/decompiler/flash/Generator.java b/trunk/test/com/jpexs/decompiler/flash/Generator.java new file mode 100644 index 000000000..184072e26 --- /dev/null +++ b/trunk/test/com/jpexs/decompiler/flash/Generator.java @@ -0,0 +1,64 @@ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; +import com.jpexs.decompiler.flash.graph.GraphTargetItem; +import com.jpexs.decompiler.flash.tags.DoABCTag; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.FileInputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Stack; + +/** + * + * Generates stub for ActionScript3Test + * + * @author JPEXS + */ +public class Generator { + public static void main(String[] args) throws Exception { + SWF swf=new SWF(new FileInputStream("testdata/as3/TestMovie.swf")); + DoABCTag tag = null; + for (Tag t : swf.tags) { + if (t instanceof DoABCTag) { + tag = (DoABCTag) t; + break; + } + } + ABC abc=tag.abc; + int classId=abc.findClassByName("classes.Test"); + StringBuilder s=new StringBuilder(); + for(Trait t:abc.instance_info[classId].instance_traits.traits){ + if(t instanceof TraitMethodGetterSetter){ + String name=t.getName(abc).getName(abc.constants, new ArrayList()); + if(name.startsWith("test")){ + s.append("@Test\r\npublic void "); + s.append(name); + s.append("(){\r\ndecompileMethod(\""); + s.append(name); + s.append("\", "); + String src=abc.findBody(((TraitMethodGetterSetter)t).method_info).toString("", false, false, classId, abc, abc.constants, abc.method_info, new Stack(), false, false, new ArrayList(), abc.instance_info[classId].instance_traits); + String srcs[]=src.split("[\r\n]+"); + for(int i=0;i - - - - - -delete myXML.node1.* -trace(myXML); - - var t:Test=new Test(); + var t:Test = new Test(); t.testHello(); } + + public static var staticVariable:int = 5; + public static var staticVariable2:int = 5; + + public function testStatic2():int + { + return TestMovie.staticVariable + TestMovie.staticVariable2; + } + + public function testStatic():void + { + var testFunction:Function = function(name:String):* + { + return TestMovie[name]; + }; + trace(testFunction("staticVariable")); + } } } \ No newline at end of file diff --git a/trunk/testdata/as3/TestMovie.fla b/trunk/testdata/as3/TestMovie.fla new file mode 100644 index 000000000..f581ef8c8 Binary files /dev/null and b/trunk/testdata/as3/TestMovie.fla differ diff --git a/trunk/testdata/as3/TestMovie.swf b/trunk/testdata/as3/TestMovie.swf index f0d5acb2d..efe5dca3c 100644 Binary files a/trunk/testdata/as3/TestMovie.swf and b/trunk/testdata/as3/TestMovie.swf differ diff --git a/trunk/testdata/as3/classes/Test.as b/trunk/testdata/as3/classes/Test.as index f9bc3ed44..9d7304a46 100644 --- a/trunk/testdata/as3/classes/Test.as +++ b/trunk/testdata/as3/classes/Test.as @@ -1,422 +1,797 @@ -package classes { -public class Test { - private var testPriv:int=5; - protected var testProt:int=9; - public var vec:Vector.=new Vector.(); +package classes +{ + import flash.utils.Dictionary; + import classes.myInternal; - public function testHello(){ - trace("hello"); + public class Test + { + private var testPriv:int = 5; + protected var testProt:int = 9; + public var t3:TestClass3; + public static const p:int = 8; + + public function testHello() + { + trace("hello"); + } + + public function testIncDec() + { + var a = 5; + var b = 0; + trace("++var"); + b = ++a; + trace("var++"); + b = a++; + trace("--var"); + b = --a; + trace("var--"); + b = a--; + var c = [1, 2, 3, 4, 5]; + trace("++arr"); + b = ++c[2]; + trace("arr++"); + b = c[2]++; + trace("--arr"); + b = --c[2]; + trace("arr--"); + b = c[2]--; + + var d = new TestClass1(); + trace("++property"); + trace(++d.attrib); + trace("property++"); + trace(d.attrib++); + trace("--property"); + trace(--d.attrib); + trace("property--"); + trace(d.attrib--); + + trace("arr[e++]"); + + var chars:Array = new Array(36); + var index:uint = 0; + + chars[index++] = 5; + + trace("arr[++e]"); + chars[++index] = 5; + return; + } + + public function testDoWhile() + { + var a = 8; + do + { + trace("a=" + a); + a++; + } while (a < 20); + return; + } + + public function testInnerTry() + { + try + { + try + { + trace("try body 1"); + } + catch (e:DefinitionError) + { + trace("catched DefinitionError"); + } + trace("after try 1"); + } + catch (e:Error) + { + trace("catched Error"); + } + finally + { + trace("finally block"); + } + } + + public function testWhileContinue() + { + var a = 5; + while (true) + { + if (a == 9) + { + if (a == 8) + { + continue; + } + if (a == 9) + { + break; + } + trace("hello 1"); + } + trace("hello2"); + } + return; + } + + public function testPrecedence() + { + var a = 0; + a = (5 + 6) * 7; + a = 5 * (2 + 3); + a = 5 + 6 * 7; + a = 5 * 2 + 2; + trace("a=" + a); + return; + } + + public function testStrings() + { + trace("hello"); + trace("quotes:\"hello!\""); + trace("backslash: \\ "); + trace("single quotes: \'hello!\'"); + trace("new line \r\n hello!"); + } + + public function testContinueLevels() + { + var a = 5; + loop123: switch (a) + { + case 57 * a: + trace("fiftyseven multiply a"); + var b = 0; + while (b < 50) + { + if (b == 10) + { + break; + } + if (b == 15) + { + break loop123; + } + b = b + 1; + } + break; + case 13: + trace("thirteen"); + case 14: + trace("fourteen"); + break; + case 89: + trace("eightynine"); + break; + default: + trace("default clause"); + } + + loop182: for (var c = 0; c < 8; c = c + 1) + { + + loop165: for (var d = 0; d < 25; d++) + { + + for (var e = 0; e < 50; e++) + { + if (e == 9) + { + break loop165; + } + if (e == 20) + { + continue loop182; + } + if (e == 8) + { + break; + } + break loop182; + } + } + trace("hello"); + } + } + + public function testSwitchDefault() + { + var a = 5; + switch (a) + { + case 57 * a: + trace("fiftyseven multiply a"); + break; + case 13: + trace("thirteen"); + case 14: + trace("fourteen"); + break; + case 89: + trace("eightynine"); + break; + default: + trace("default clause"); + } + } + + public function testMultipleCondition() + { + var a = 5; + var b = 8; + var c = 9; + if ((a <= 4 || b <= 8) && c == 7) + { + trace("onTrue"); + } + else + { + trace("onFalse"); + } + } + + public function testForBreak() + { + for (var a = 0; a < 10; a++) + { + if (a == 5) + { + break; + } + trace("hello:" + a); + } + } + + public function testIf() + { + var a = 5; + if (a == 7) + { + trace("onTrue"); + } + } + + public function testIfElse() + { + var a = 5; + if (a == 7) + { + trace("onTrue"); + } + else + { + trace("onFalse"); + } + } + + public function testFor() + { + for (var a = 0; a < 10; a++) + { + trace("a=" + a); + } + } + + public function testForContinue() + { + for (var a = 0; a < 10; a = a + 1) + { + if (a == 9) + { + if (a == 5) + { + trace("part1"); + continue; + } + trace("a=" + a); + if (a == 7) + { + trace("part2"); + continue; + } + trace("part3"); + } + else + { + trace("part4"); + } + trace("part5"); + } + } + + public function testTry() + { + var i:int; + i = 7; + try + { + trace("try body"); + } + catch (e:DefinitionError) + { + trace("catched DefinitionError"); + } + catch (e:Error) + { + trace("Error message:" + e.message); + trace("Stacktrace:" + e.getStackTrace()); + } + finally + { + trace("Finally part"); + } + } + + public function testSwitch() + { + var a = 5; + switch (a) + { + case 57 * a: + trace("fiftyseven multiply a"); + break; + case 13: + trace("thirteen"); + case 14: + trace("fourteen"); + break; + case 89: + trace("eightynine"); + break; + } + } + + public function testTernarOperator() + { + var a = 5; + var b = 4; + var c = 4; + var d = 78; + var e = (a == b) ? ((c == d) ? 1 : 7) : 3; + trace("e=" + e); + } + + public function testInnerIf() + { + var a = 5; + var b = 4; + if (a == 5) + { + if (b == 6) + { + trace("b==6"); + } + else + { + trace("b!=6"); + } + } + else + { + if (b == 7) + { + trace("b==7"); + } + else + { + trace("b!=7"); + } + } + trace("end"); + } + + public function testVector() + { + var v:Vector. = new Vector.(); + v.push("hello"); + v[0] = "hi"; + v[5 * 8 - 39] = "hi2"; + trace(v[0]); + } + + public function testProperty() + { + var d = new TestClass1(); + var k = 7 + 8; + if (k == 15) + { + d.method(d.attrib * 5); + } + } + + public function testRest(firstp:int, ... restval):int + { + trace("firstRest:" + restval[0]); + return firstp; + } + + public function testParamNames(firstp:int, secondp:int, thirdp:int):int + { + return firstp + secondp + thirdp; + } + + public function testForEach() + { + var list:Array; + list = new Array(); + list[0] = "first"; + list[1] = "second"; + list[2] = "third"; + for each (var item in list) + { + trace("item #" + item); + } + } + + public function testForEachObjectArray() + { + var list:Array; + list = new Array(); + list[0] = "first"; + list[1] = "second"; + list[2] = "third"; + var test:Array; + test = new Array(); + test[0] = 0; + for each (test[0]in list) + { + trace("item #" + test[0]); + } + } + + public function testForEachObjectAttribute() + { + var list:Array; + list = new Array(); + list[0] = "first"; + list[1] = "second"; + list[2] = "third"; + for each (testPriv in list) + { + trace("item #" + testPriv); + } + } + + public function testParamsCount(firstp:int, secondp:int, thirdp:int):int + { + return firstp; + } + + public function testInlineFunctions() + { + var first:String = "value1"; + var traceParameter:Function = function(aParam:String):String + { + var second:String = "value2"; + second = second + "cc"; + var traceParam2:Function = function(bParam:String):String + { + trace(bParam + "," + aParam); + return first + second + aParam + bParam; + } + trace(second); + traceParam2(aParam); + return first; + }; + traceParameter("hello"); + } + + public function testMissingDefault() + { + var jj:int = 1; + switch (jj) + { + case 1: + jj = 1; + break; + case 2: + jj = 2; + break; + default: + jj = 3; + } + } + + private function traceIt(s:String) + { + trace(s); + } + + private static var counter:int; + + private function getCounter():int + { + counter++; + return counter; + } + + public function testChainedAssignments() + { + var a:int; + var b:int; + var c:int; + var d:int; + d = c = b = a = 5; + var e:TestClass2 = TestClass2.createMe("test"); + e.attrib1 = e.attrib2 = e.attrib3 = getCounter(); + traceIt(e.toString()); + } + + private function testFinallyZeroJump(param1:String):String + { + var str:String = param1; + try + { + return str; + } + catch (e:Error) + { + trace("error is :" + e.message); + } + finally + { + trace("hi "); + if (5 == 4) + { + return str; + } + else + { + return "hu" + str; + } + } + } + + public function testInnerFunctions(a:String) + { + var k:int = 5; + if (k == 6) + { + var s:int = 8; + } + function innerFunc(b:String) + { + trace(b); + } + innerFunc(a); + } + + public function testDeclarations() + { + var vall:*; + var vstr:String; + var vint:int; + var vuint:uint; + var vclass:TestClass1; + var vnumber:Number; + var vobject:Object; + + vall = 6; + vstr = "hello"; + vuint = 7; + vint = -4; + vclass = new TestClass1(); + vnumber = 0.5; + vnumber = 6; + vobject = vclass; + } + + public function testForIn() + { + var dic:Dictionary; + var item:Object; + for (item in dic) + { + trace(item); + } + for each (item in dic) + { + trace(item); + } + } + + myInternal function namespacedFunc() + { + trace("hello"); + } + + function unnamespacedFunc() + { + trace("hello2"); + } + + function getNamespace():Namespace + { + return null; //myInternal; + } + + function getName():String + { + return "unnamespacedFunc"; + } + + function testNames() + { + var ns = getNamespace(); + var name = getName(); + //var a=ns::unnamespacedFunc(); + //var b=ns::[name]; + //trace(b.c); + } + + function testComplexExpressions() + { + var i:int; + var j:int; + j = (i = i + (i += i++)); + } + + function testExpressions() + { + var i:int = 5; + var j:int = 5; + var arr:Array; + + if ((i = i /= 2) == 1 || i == 2) + { + arguments.concat(i); + } + else if (i == 0) + { + i = j++; + } + else + { + arr[0](); + } + + return i == 0; + } + + public function testArguments(a:int):String + { + return arguments[0]; + } + + public function println(str:String):void + { + trace(arguments.callee == this.println); + trace(arguments.length); + trace(arguments[0]); + trace(str); + } + + public function testLogicalComputing() + { + var i = 5; + var j = 7; + if (i > j) + { + j = 9; + var b:Boolean = true; + } + b = (i == 0 || i == 1) && j == 0; + } + + private function getInt():int + { + return counter++; + } + + public function testInc2() + { + var a = [1]; + a[getInt()]++; + var d = a[getInt()]++; + + var e = ++a[getInt()]; + var b = 1; + b++; + var c = 1; + b = c++; + } + + protected function testDecl2() + { + var i:int = 5; + i += 7; + if (i == 5) + { + if (i < 8) + { + var k:int = 6; + } + } + k = 7; + } + + public function testChain2() + { + var g:Array; + var h:Boolean; + var r:int = 7; + var t:int = 0; + t = this.getInt(); + var extraLine:Boolean; + if (t + 1 < g.length) + { + t++; + h = true; + } + if (t >= 0) + { + trace("ch"); + } + + } + + public function textXML() + { + var name = "ahoj"; + var myXML:XML = + + + {name} + + ; + + var k = myXML.@id; + var all = myXML.@*.toXMLString(); + k = myXML.book; + k = myXML.book.(@isbn = "12345"); + + var g:XML = new XML(""); + } + + public function testDoWhile2():int + { + var k:int = 5; + do + { + k++; + if (k == 7) + { + k = 5 * k; + } + else + { + k = 5 - k; + } + k-- + } while (k < 9); + return 2; + } + + public function testWhileAnd() + { + var a:int = 5; + var b:int = 10; + while ((a < 10) && (b > 1)) + { + a++; + b--; + } + a = 7; + b = 9; + } + + public function testNamedAnonFunctions() + { + var test=new function testFunc(param1:*, param2:int, param3:Array):Boolean + { + return (param1 as TestClass2).attrib1==5; + } + } + + public function testStringConcat() + { + var k:int = 8; + traceIt("hello"+5*6); + traceIt("hello"+(k-1)); + traceIt("hello"+5+6); + } } - - public function testIncDec() { - var a=5; - var b=0; - trace("++var"); - b=++a; - trace("var++"); - b=a++; - trace("--var"); - b=--a; - trace("var--"); - b=a--; - var c=[1,2,3,4,5]; - trace("++arr"); - b=++c[2]; - trace("arr++"); - b=c[2]++; - trace("--arr"); - b=--c[2]; - trace("arr--"); - b=c[2]--; - - var d=new TestClass1(); - trace("++property"); - trace(++d.attrib); - trace("property++"); - trace(d.attrib++); - trace("--property"); - trace(--d.attrib); - trace("property--"); - trace(d.attrib--); - return; - } - public function testDoWhile() { - var a=8; - do - { - trace("a="+a); - a++; - } - while(a<20); - return; - } - public function testInnerTry(){ - try - { - try - { - trace("try body 1"); - } - catch(e:DefinitionError) - { - trace("catched DefinitionError"); - } - trace("after try 1"); - } - catch(e:Error) - { - trace("catched Error"); - } - finally - { - trace("finally block"); - } - } - public function testWhileContinue() { - var a=5; - while(true) - { - if(a==9) - { - if(a==8) - { - continue; - } - if(a==9) - { - break; - } - trace("hello 1"); - } - trace("hello2"); - } - return; - } - public function testPrecedence() { - var a=0; - a=(5+6)*7; - a=5*(2+3); - a=5+6*7; - a=5*2+2; - trace("a="+a); - return; - } - public function testStrings() { - trace("hello"); - trace("quotes:\"hello!\""); - trace("backslash: \\ "); - trace("single quotes: \'hello!\'"); - trace("new line \r\n hello!"); - } - public function testContinueLevels() { - var a=5; - loop123: - switch(a) - { - case 57*a: - trace("fiftyseven multiply a"); - var b=0; - while(b<50) - { - if(b==10) - { - break; - } - if(b==15) - { - break loop123; - } - b=b+1; - } - break; - case 13: - trace("thirteen"); - case 14: - trace("fourteen"); - break; - case 89: - trace("eightynine"); - break; - default: - trace("default clause"); - } - - loop182: - for(var c=0;c<8;c=c+1) - { - - loop165: - for(var d=0;d<25;d++) - { - - for(var e=0;e<50;e++) - { - if(e==9) - { - break loop165; - } - if(e==20) - { - continue loop182; - } - if(e==8) - { - break; - } - break loop182; - } - } - trace("hello"); - } - } - public function testSwitchDefault(){ - var a=5; - switch(a) - { - case 57*a: - trace("fiftyseven multiply a"); - break; - case 13: - trace("thirteen"); - case 14: - trace("fourteen"); - break; - case 89: - trace("eightynine"); - break; - default: - trace("default clause"); - } - } - public function testMultipleCondition(){ - var a=5; - var b=8; - var c=9; - if((a<=4||b<=8)&&c==7) - { - trace("onTrue"); - } - else - { - trace("onFalse"); - } - } - public function testForBreak(){ - for(var a=0;a<10;a++) - { - if(a==5) - { - break; - } - trace("hello:"+a); - } - } - - public function testIf(){ - var a=5; - if(a==7) - { - trace("onTrue"); - } - } - - public function testIfElse(){ - var a=5; - if(a==7) - { - trace("onTrue"); - } - else - { - trace("onFalse"); - } - } - public function testFor() { - for(var a=0;a<10;a++) - { - trace("a="+a); - } - } - public function testForContinue() { - for(var a=0;a<10;a=a+1) - { - if(a==9) - { - if(a==5) - { - trace("part1"); - continue; - } - trace("a="+a); - if(a==7) - { - trace("part2"); - continue; - } - trace("part3"); - } - else - { - trace("part4"); - } - trace("part5"); - } - } - public function testTry() { - var i:int; - i=7; - try - { - trace("try body"); - } - catch(e:DefinitionError) - { - trace("catched DefinitionError"); - } - catch(e:Error) - { - trace("Error message:"+e.message); - trace("Stacktrace:"+e.getStackTrace()); - } - finally - { - trace("Finally part"); - } - } - public function testSwitch(){ - var a=5; - switch(a) - { - case 57*a: - trace("fiftyseven multiply a"); - break; - case 13: - trace("thirteen"); - case 14: - trace("fourteen"); - break; - case 89: - trace("eightynine"); - break; - } - } - public function testTernarOperator(){ - var a=5; - var b=4; - var c=4; - var d=78; - var e=(a==b) - ?((c==d)?1 - :7 - ): - 3; - trace("e="+e); - } - - public function testInnerIf(){ - var a=5; - var b=4; - if(a==5){ - if(b==6){ - trace("b==6"); - }else{ - trace("b!=6"); - } - }else{ - if(b==7){ - trace("b==7"); - }else{ - trace("b!=7"); - } - } - trace("end"); - } - - public function testVector(){ - var v:Vector. = new Vector.(); - v.push("hello"); - v[0]="hi"; - v[5*8-39]="hi2"; - trace(v[0]); - - vec.push("atributte hello"); - vec[2*6-11]="atributte hi"; - } - - public function testProperty(){ - var d=new TestClass1(); - var k=7+8; - if(k==15) - { - d.metoda(d.attrib*5); - } - } - - public function testRest(firstp:int,...restval):int{ - trace("firstRest:"+restval[0]); - return firstp; - } - - public function testParamNames(firstp:int,secondp:int,thirdp:int):int{ - return firstp+secondp+thirdp; - } - - public function testForEach(){ - var list:Array; - list=new Array(); - list[0]="first"; - list[1]="second"; - list[2]="third"; - for each(var item in list){ - trace("item #"+item); - } - } - - public function testForEachObjectArray(){ - var list:Array; - list=new Array(); - list[0]="first"; - list[1]="second"; - list[2]="third"; - var test:Array; - test=new Array(); - test[0]=0; - for each(test[0] in list){ - trace("item #"+test[0]); - } - } - - public function testForEachObjectAttribute(){ - var list:Array; - list=new Array(); - list[0]="first"; - list[1]="second"; - list[2]="third"; - for each(testPriv in list){ - trace("item #"+testPriv); - } - } - - public function testParamsCount(firstp:int,secondp:int,thirdp:int):int - { - return firstp; - } - - - public function testCalcStackSize() { - var a=[1]; - var b=[2]; - a[0]++; - b[0]++; - //b=c[2]++; - /*trace("--arr"); - b=--c[2]; - trace("arr--"); - b=c[2]--;*/ - - return; - } - - } } \ No newline at end of file diff --git a/trunk/testdata/as3/classes/TestClass1.as b/trunk/testdata/as3/classes/TestClass1.as index 18e5379a6..870ea7c4f 100644 --- a/trunk/testdata/as3/classes/TestClass1.as +++ b/trunk/testdata/as3/classes/TestClass1.as @@ -1,14 +1,19 @@ -package classes{ - public dynamic class TestClass1{ - public var attrib:int=5; - - public function testHello(){ +package classes +{ + + public dynamic class TestClass1 + { + public var attrib:int = 5; + public var sons:Array; + + public function testHello() + { trace("hello2"); } - public function metoda(i:int):int + public function method(i:int):int { - trace("metoda"); + trace("method"); return 7; } } diff --git a/trunk/testdata/as3/classes/TestClass2.as b/trunk/testdata/as3/classes/TestClass2.as new file mode 100644 index 000000000..f672c273a --- /dev/null +++ b/trunk/testdata/as3/classes/TestClass2.as @@ -0,0 +1,20 @@ +package classes +{ + + public dynamic class TestClass2 + { + public var attrib1:int; + public var attrib2:int; + public var attrib3:int; + + public function TestClass2(a1:String) + { + trace("Class2 construct"); + } + + public static function createMe(a1:String):TestClass2 + { + return new TestClass2(a1); + } + } +} \ No newline at end of file diff --git a/trunk/testdata/as3/classes/TestClass3.as b/trunk/testdata/as3/classes/TestClass3.as new file mode 100644 index 000000000..cc06b6f30 --- /dev/null +++ b/trunk/testdata/as3/classes/TestClass3.as @@ -0,0 +1,8 @@ +package classes +{ + + public class TestClass3 + { + + } +} diff --git a/trunk/testdata/as3/classes/myInternal.as b/trunk/testdata/as3/classes/myInternal.as new file mode 100644 index 000000000..65ab4e45f --- /dev/null +++ b/trunk/testdata/as3/classes/myInternal.as @@ -0,0 +1,4 @@ +package classes { + public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples"; +} + \ No newline at end of file