mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-08 21:18:37 +00:00
Fixed: AS3 with statement decompilation
This commit is contained in:
@@ -32,6 +32,7 @@ All notable changes to this project will be documented in this file.
|
||||
- #1159, #1608 Regexp syntax hilight when not a regexp (only division) again
|
||||
- Graphviz Graph not showing AS3 exception end
|
||||
- #1609 First frame missing in frame to PDF export
|
||||
- AS3 with statement decompilation
|
||||
|
||||
### Changed
|
||||
- #1565, #1407, #1350 On BinaryData SWF save, parent SWF is saved
|
||||
|
||||
@@ -71,6 +71,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.ThrowAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.WithEndAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.WithObjectAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.FilterAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item;
|
||||
@@ -243,7 +244,6 @@ public class AVM2Graph extends Graph {
|
||||
|
||||
List<GraphTargetItem> targetOutput = translatePart(localData2, finallyTryTargetPart, finallyTryTargetStack, 0 /*??*/, "try_target");
|
||||
|
||||
|
||||
int switchedReg = -1;
|
||||
int finallyKind = FINALLY_KIND_UNKNOWN;
|
||||
Integer finallyThrowPushByte = null;
|
||||
@@ -1018,7 +1018,7 @@ public class AVM2Graph extends Graph {
|
||||
localData2.scopeStack = new ScopeStack();
|
||||
|
||||
//We are assuming Finally target has only 1 part
|
||||
finallyTargetItems = translatePart(localData, finallyTryTargetPart, st2, staticOperation, path);//printGraph(foundGotos, partCodes, partCodePos, visited, localData2, st2, allParts, null, finallyTryTargetPart, finallyTargetStopPart, loops, throwStates, 0, path);
|
||||
finallyTargetItems = translatePart(localData2, finallyTryTargetPart, st2, staticOperation, path);//printGraph(foundGotos, partCodes, partCodePos, visited, localData2, st2, allParts, null, finallyTryTargetPart, finallyTargetStopPart, loops, throwStates, 0, path);
|
||||
//boolean targetHasThrow = false;
|
||||
if (!finallyTargetItems.isEmpty() && (finallyTargetItems.get(finallyTargetItems.size() - 1) instanceof ThrowAVM2Item)) {
|
||||
|
||||
@@ -1132,6 +1132,30 @@ public class AVM2Graph extends Graph {
|
||||
currentCatchCommands.remove(0);
|
||||
}
|
||||
}*/
|
||||
loopwith:
|
||||
while (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(0) instanceof WithAVM2Item)) {
|
||||
WithAVM2Item w = (WithAVM2Item) currentCatchCommands.get(0);
|
||||
if (w.scope instanceof LocalRegAVM2Item) {
|
||||
int regId = ((LocalRegAVM2Item) w.scope).regIndex;
|
||||
for (GraphTargetItem item : localData.scopeStack) {
|
||||
if (item instanceof WithObjectAVM2Item) {
|
||||
WithObjectAVM2Item wo = (WithObjectAVM2Item) item;
|
||||
|
||||
if (wo.scope instanceof SetLocalAVM2Item) {
|
||||
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) wo.scope;
|
||||
if (setLocal.regIndex == regId) {
|
||||
currentCatchCommands.remove(0);
|
||||
int setLocalIp = localData.code.adr2pos(setLocal.getSrc().getAddress());
|
||||
int getLocalIp = localData.code.adr2pos(w.scope.getSrc().getAddress());
|
||||
localData.setLocalPosToGetLocalPos.get(setLocalIp).remove(getLocalIp);
|
||||
continue loopwith;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break; //its a brand new with inside catch clause
|
||||
}
|
||||
if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(currentCatchCommands.size() - 1) instanceof SetLocalAVM2Item)) {
|
||||
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) currentCatchCommands.get(currentCatchCommands.size() - 1);
|
||||
if (setLocal.regIndex == switchedReg) {
|
||||
@@ -1160,21 +1184,18 @@ public class AVM2Graph extends Graph {
|
||||
&& (((SetLocalAVM2Item) currentRet.get(currentRet.size() - 1)).regIndex == switchedReg)) {
|
||||
currentRet.remove(currentRet.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!finallyAsUnnamedException && !inlinedFinally && catchedExceptions.isEmpty() && finallyCommands.isEmpty()) {
|
||||
currentRet.addAll(tryCommands);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (finallyAsUnnamedException)
|
||||
{
|
||||
if (finallyAsUnnamedException) {
|
||||
catchedExceptions.add(finallyException);
|
||||
catchCommands.add(finallyCommands);
|
||||
finallyCommands = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
TryAVM2Item tryItem = new TryAVM2Item(tryCommands, catchedExceptions, catchCommands, finallyCommands, "");
|
||||
if (inlinedFinally) {
|
||||
List<List<GraphTargetItem>> parentCatchCommands = new ArrayList<>();
|
||||
@@ -1871,6 +1892,26 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
|
||||
if (list.get(i) instanceof WithAVM2Item) {
|
||||
WithAVM2Item wa = (WithAVM2Item) list.get(i);
|
||||
if (wa.scope instanceof SetLocalAVM2Item) {
|
||||
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) wa.scope;
|
||||
int setLocalIp = avm2code.adr2pos(setLocal.getSrc().getAddress());
|
||||
if (localData.getRegisterUsage(setLocalIp).isEmpty()) {
|
||||
for (int j = i + 1; j < list.size(); j++) {
|
||||
if (list.get(j) instanceof WithEndAVM2Item) {
|
||||
WithEndAVM2Item we = (WithEndAVM2Item) list.get(j);
|
||||
if (we.scope == wa.scope) {
|
||||
wa.scope = we.scope = setLocal.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list.get(i) instanceof SetLocalAVM2Item) {
|
||||
SetLocalAVM2Item ri = (SetLocalAVM2Item) list.get(i);
|
||||
int setLocalIp = avm2code.adr2pos(ri.getSrc().getAddress());
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
@@ -77,6 +78,16 @@ public class WithAVM2Item extends AVM2Item {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsNewLine() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlesNewLine() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
|
||||
@@ -2585,7 +2585,10 @@ public class Graph {
|
||||
public static GraphTextWriter graphToString(List<GraphTargetItem> tree, GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
for (GraphTargetItem ti : tree) {
|
||||
if (!ti.isEmpty()) {
|
||||
ti.toStringSemicoloned(writer, localData).newLine();
|
||||
ti.toStringSemicoloned(writer, localData);
|
||||
if (!ti.handlesNewLine()) {
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
return writer;
|
||||
|
||||
@@ -433,6 +433,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean handlesNewLine() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
writer.startOffset(src, getLineStartItem(), getPos(), srcData);
|
||||
appendTry(writer, localData);
|
||||
|
||||
@@ -18,10 +18,8 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
|
||||
|
||||
@Test
|
||||
public void testDeclareReg() {
|
||||
decompileMethod("assembled", "testDeclareReg", "var _loc3_:*;\r\n"
|
||||
+ "with(_loc3_ = other)\r\n"
|
||||
decompileMethod("assembled", "testDeclareReg", "with(other)\r\n"
|
||||
+ "{\r\n"
|
||||
+ "\r\n"
|
||||
+ "trace(\"hey\");\r\n"
|
||||
+ "}\r\n",
|
||||
false);
|
||||
|
||||
@@ -513,6 +513,28 @@ public class ActionScript3CrossCompileDecompileTest extends ActionScript3Decompi
|
||||
false);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "swfNamesProvider")
|
||||
public void testTryCatchWith(String swfUsed) {
|
||||
decompileMethod(swfUsed, "testTryCatchWith", "var a:MyTest = new MyTest();\r\n"
|
||||
+ "trace(\"before with\");\r\n"
|
||||
+ "with(a)\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"
|
||||
+ "attrib = attrib + 1;\r\n"
|
||||
+ "trace(\"in catch\");\r\n"
|
||||
+ "}\r\n"
|
||||
+ "trace(\"after try\");\r\n"
|
||||
+ "}\r\n"
|
||||
+ "trace(\"after\");\r\n",
|
||||
false);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "swfNamesProvider")
|
||||
public void testTryFinally(String swfUsed) {
|
||||
decompileMethod(swfUsed, "testTryFinally", "trace(\"before try\");\r\n"
|
||||
|
||||
@@ -504,6 +504,32 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript
|
||||
false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryCatchWith() {
|
||||
decompileMethod("swftools", "testTryCatchWith", "var _loc1_:* = new MyTest();\r\n"
|
||||
+ "trace(\"before with\");\r\n"
|
||||
+ "var _loc2_:*;\r\n"
|
||||
+ "with(_loc2_ = _loc1_)\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"
|
||||
+ "with(_loc2_)\r\n"
|
||||
+ "{\r\n"
|
||||
+ "\r\n"
|
||||
+ "attrib = attrib + 1;\r\n"
|
||||
+ "trace(\"in catch\");\r\n"
|
||||
+ "}\r\n"
|
||||
+ "trace(\"after try\");\r\n"
|
||||
+ "}\r\n"
|
||||
+ "trace(\"after\");\r\n",
|
||||
false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryFinally() {
|
||||
decompileMethod("swftools", "testTryFinally", "trace(\"before try\");\r\n"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -28,6 +28,8 @@ package
|
||||
TestTryCatchLoopBreak6;
|
||||
TestTryCatchReturn;
|
||||
TestTryCatchExceptionUsage
|
||||
TestTryCatchTry;
|
||||
TestTryCatchWith;
|
||||
TestTryFinally;
|
||||
TestTryFinallyDirectReturnInFinally;
|
||||
TestTryFinallyLoop;
|
||||
@@ -38,8 +40,7 @@ package
|
||||
TestTryFinallyReturnInFinally;
|
||||
TestTryFinallyReturnNested;
|
||||
TestTryFinallyReturnNested2;
|
||||
TestTryFinallyReturnVoid;
|
||||
TestTryCatchTry;
|
||||
TestTryFinallyReturnVoid;
|
||||
|
||||
public function Main()
|
||||
{
|
||||
|
||||
39
libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchWith.as
vendored
Normal file
39
libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchWith.as
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryCatchWith
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
var a:MyTest = new MyTest();
|
||||
|
||||
trace("before with");
|
||||
with (a)
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
attrib = attrib + 1;
|
||||
trace("in catch");
|
||||
}
|
||||
trace("after try");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyTest
|
||||
{
|
||||
public var attrib:int = 5;
|
||||
}
|
||||
Reference in New Issue
Block a user