mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-02 20:04:37 +00:00
Fixed #2077 AS3 try..catch parts outside block
Fixed AS3 try..catch inside loop unneccessary continue
This commit is contained in:
@@ -101,6 +101,7 @@ import com.jpexs.decompiler.graph.model.AnyItem;
|
||||
import com.jpexs.decompiler.graph.model.BreakItem;
|
||||
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
|
||||
import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
import com.jpexs.decompiler.graph.model.DoWhileItem;
|
||||
import com.jpexs.decompiler.graph.model.ExitItem;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.GotoItem;
|
||||
@@ -934,6 +935,17 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
private GraphPart findNearestPartOutsideCatch(GraphPart tryTarget, Set<GraphPart> catchParts) {
|
||||
for (GraphPart p : catchParts) {
|
||||
for (GraphPart n : p.nextParts) {
|
||||
if (!catchParts.contains(n)) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean checkTry(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, AVM2LocalData localData, GraphPart part, List<GraphPart> stopPart, List<StopPartKind> stopPartKind, List<Loop> loops, List<ThrowState> throwStates, Set<GraphPart> allParts, TranslateStack stack, int staticOperation, String path, int recursionLevel) throws InterruptedException {
|
||||
if (localData.parsedExceptions == null) {
|
||||
localData.parsedExceptions = new ArrayList<>();
|
||||
@@ -1021,6 +1033,34 @@ public class AVM2Graph extends Graph {
|
||||
//System.err.println("oursidetrycatch: " + afterPart);
|
||||
}
|
||||
|
||||
//List<GraphPart> catchedExceptionsAfter = new ArrayList<>();
|
||||
|
||||
List<GraphPart> catchAfterParts = new ArrayList<>();
|
||||
|
||||
if (afterPart == null) {
|
||||
|
||||
loope:
|
||||
for (int e = 0; e < catchedExceptions.size(); e++) {
|
||||
ABCException ex = catchedExceptions.get(e);
|
||||
int eId = catchedExceptionIds.get(e);
|
||||
for (ThrowState ts : throwStates) {
|
||||
if (ts.exceptionId == eId) {
|
||||
GraphPart possibleAfter = findNearestPartOutsideCatch(ts.targetPart, ts.catchParts);
|
||||
if (possibleAfter != null) {
|
||||
if (!stopPart.contains(possibleAfter)) {
|
||||
catchAfterParts.add(possibleAfter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (catchAfterParts.size() == 1) {
|
||||
afterPart = catchAfterParts.iterator().next();
|
||||
} else if (catchAfterParts.size() > 1) {
|
||||
afterPart = getMostCommonPart(localData, catchAfterParts, loops, throwStates, stopPart);
|
||||
}
|
||||
}
|
||||
|
||||
GraphPart exAfterPart = afterPart;
|
||||
|
||||
if (finallyException == null) {
|
||||
@@ -1195,6 +1235,11 @@ public class AVM2Graph extends Graph {
|
||||
stopPart2.add(defaultPart);
|
||||
stopPartKind2.add(StopPartKind.OTHER);
|
||||
}
|
||||
|
||||
for (GraphPart p:catchAfterParts) {
|
||||
stopPart2.add(p);
|
||||
stopPartKind2.add(StopPartKind.OTHER);
|
||||
}
|
||||
|
||||
List<GraphTargetItem> currentCatchCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData2, st2, allParts, null, catchPart, stopPart2, stopPartKind2, loops, throwStates, staticOperation, path);
|
||||
/*if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(0) instanceof SetLocalAVM2Item)) {
|
||||
@@ -1422,13 +1467,30 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkPartOutput(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<StopPartKind> stopPartKind, List<Loop> loops, List<ThrowState> throwStates, Loop currentLoop, int staticOperation, String path, int recursionLevel) throws InterruptedException {
|
||||
protected boolean checkPartOutput(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos,
|
||||
Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos,
|
||||
Set<GraphPart> visited, GraphSource code,
|
||||
BaseLocalData localData, Set<GraphPart> allParts,
|
||||
TranslateStack stack, GraphPart parent,
|
||||
GraphPart part, List<GraphPart> stopPart,
|
||||
List<StopPartKind> stopPartKind, List<Loop> loops,
|
||||
List<ThrowState> throwStates, Loop currentLoop,
|
||||
int staticOperation, String path,
|
||||
int recursionLevel) throws InterruptedException {
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
return checkTry(currentRet, foundGotos, partCodes, partCodePos, visited, aLocalData, part, stopPart, stopPartKind, loops, throwStates, allParts, stack, staticOperation, path, recursionLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<StopPartKind> stopPartKind, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
|
||||
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos,
|
||||
Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos,
|
||||
Set<GraphPart> visited, GraphSource code,
|
||||
BaseLocalData localData, Set<GraphPart> allParts,
|
||||
TranslateStack stack, GraphPart parent,
|
||||
GraphPart part, List<GraphPart> stopPart,
|
||||
List<StopPartKind> stopPartKind, List<Loop> loops,
|
||||
List<ThrowState> throwStates, List<GraphTargetItem> output,
|
||||
Loop currentLoop, int staticOperation, String path) throws InterruptedException {
|
||||
List<GraphTargetItem> ret = null;
|
||||
|
||||
/*if (ret != null) {
|
||||
@@ -1557,7 +1619,10 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphPart checkPartWithOutput(List<GraphTargetItem> output, TranslateStack stack, BaseLocalData localData, GraphPart prev, GraphPart part, Set<GraphPart> allParts) {
|
||||
protected GraphPart checkPartWithOutput(List<GraphTargetItem> output, TranslateStack stack,
|
||||
BaseLocalData localData, GraphPart prev,
|
||||
GraphPart part, Set<GraphPart> allParts
|
||||
) {
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
if (aLocalData.finallyJumps == null) {
|
||||
aLocalData.finallyJumps = new HashMap<>();
|
||||
@@ -1986,6 +2051,45 @@ public class AVM2Graph extends Graph {
|
||||
protected void finalProcessAfter(List<GraphTargetItem> list, int level, FinalProcessLocalData localData, String path) {
|
||||
super.finalProcessAfter(list, level, localData, path);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
|
||||
//Remove continues from all branches of try...catch block if its continue to parent loop
|
||||
if (list.get(i) instanceof LoopItem) {
|
||||
LoopItem li = (LoopItem) list.get(i);
|
||||
if (li.hasBaseBody()) {
|
||||
List<GraphTargetItem> loopCommands = li.getBaseBodyCommands();
|
||||
if (!loopCommands.isEmpty()) {
|
||||
if (loopCommands.get(loopCommands.size() - 1) instanceof TryAVM2Item) {
|
||||
TryAVM2Item ta = (TryAVM2Item) loopCommands.get(loopCommands.size() - 1);
|
||||
for (List<GraphTargetItem> cc : ta.catchCommands) {
|
||||
if (!cc.isEmpty()) {
|
||||
if (cc.get(cc.size() - 1) instanceof ContinueItem) {
|
||||
ContinueItem ci = (ContinueItem) cc.get(cc.size() - 1);
|
||||
if (ci.loopId == li.loop.id) {
|
||||
cc.remove(cc.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ta.tryCommands.isEmpty()) {
|
||||
if (ta.tryCommands.get(ta.tryCommands.size() - 1) instanceof ContinueItem) {
|
||||
ContinueItem ci = (ContinueItem) ta.tryCommands.get(ta.tryCommands.size() - 1);
|
||||
if (ci.loopId == li.loop.id) {
|
||||
ta.tryCommands.remove(ta.tryCommands.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ta.finallyCommands.isEmpty()) {
|
||||
if (ta.finallyCommands.get(ta.finallyCommands.size() - 1) instanceof ContinueItem) {
|
||||
ContinueItem ci = (ContinueItem) ta.finallyCommands.get(ta.finallyCommands.size() - 1);
|
||||
if (ci.loopId == li.loop.id) {
|
||||
ta.finallyCommands.remove(ta.finallyCommands.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list.get(i) instanceof SetTypeAVM2Item) {
|
||||
if (((SetTypeAVM2Item) list.get(i)).getValue().getThroughDuplicate() instanceof ExceptionAVM2Item) {
|
||||
|
||||
@@ -2319,12 +2423,12 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isSetLocUsage) {
|
||||
nextReferencedRegisters.add(regIndex);
|
||||
foundGetLoc = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2440,7 +2544,7 @@ public class AVM2Graph extends Graph {
|
||||
|
||||
List<ThrowState> ret = new ArrayList<>();
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
ThrowState ts = new ThrowState();
|
||||
ThrowState ts = new ThrowState();
|
||||
ts.exceptionId = e;
|
||||
ts.state = 0;
|
||||
ts.targetPart = searchPart(code.adr2pos(body.exceptions[e].target), allParts);
|
||||
@@ -2477,7 +2581,7 @@ public class AVM2Graph extends Graph {
|
||||
//Search all parts which have same or greater scope level, these all belong to catch
|
||||
Set<GraphPart> catchParts = new HashSet<>();
|
||||
if (scopePos > -1) {
|
||||
walkCatchParts(avm2LocalData.codeStats, part, ip, catchParts, scopePos);
|
||||
walkCatchParts(avm2LocalData.codeStats, part, ip, catchParts, scopePos, allParts, body.exceptions[e].isFinally());
|
||||
} else {
|
||||
logger.fine("No newcatch..pushscope found in catch, probably swftools");
|
||||
part = ts.targetPart;
|
||||
@@ -2546,18 +2650,71 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
private void walkCatchParts(CodeStats stats, GraphPart part, int startIp, Set<GraphPart> catchParts, int scopePos) {
|
||||
private void walkCatchParts(CodeStats stats, GraphPart part, int startIp, Set<GraphPart> catchParts, int scopePos, Set<GraphPart> allParts, boolean isFinally) {
|
||||
if (catchParts.contains(part)) {
|
||||
return;
|
||||
}
|
||||
catchParts.add(part);
|
||||
for (int ip = startIp; ip <= part.end; ip++) {
|
||||
if (stats.instructionStats[ip].scopepos_after < scopePos) {
|
||||
|
||||
//popscope can be followed by jump (break/continue),
|
||||
//in such case, treat as single block
|
||||
if (ip >= 0 && ip < code.size()) {
|
||||
boolean onlyKillJump = true;
|
||||
for (int j = ip + 1; j <= part.end; j++) {
|
||||
AVM2Instruction ins = (AVM2Instruction) code.get(j);
|
||||
if (ins.definition instanceof KillIns) {
|
||||
continue;
|
||||
}
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
continue;
|
||||
}
|
||||
if (ins.definition instanceof DebugLineIns) {
|
||||
continue;
|
||||
}
|
||||
onlyKillJump = false;
|
||||
break;
|
||||
}
|
||||
if (onlyKillJump) {
|
||||
catchParts.add(part);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ip < part.end && !isFinally) {
|
||||
//split part into half
|
||||
GraphPart secondPart = new GraphPart(ip + 1, part.end);
|
||||
part.end = ip;
|
||||
for (GraphPart n : part.nextParts) {
|
||||
n.refs.remove(part);
|
||||
n.refs.add(secondPart);
|
||||
}
|
||||
secondPart.nextParts.addAll(part.nextParts);
|
||||
part.nextParts.clear();
|
||||
part.nextParts.add(secondPart);
|
||||
secondPart.refs.add(part);
|
||||
|
||||
secondPart.type = GraphPart.TYPE_NONE;
|
||||
secondPart.discoveredTime = part.discoveredTime;
|
||||
secondPart.closedTime = part.closedTime;
|
||||
secondPart.finishedTime = part.finishedTime;
|
||||
secondPart.iloop_header = part.iloop_header;
|
||||
secondPart.irreducible = part.irreducible;
|
||||
secondPart.level = part.level;
|
||||
secondPart.numBlocks = part.numBlocks;
|
||||
secondPart.order = part.order;
|
||||
secondPart.path = part.path;
|
||||
secondPart.posX = part.posX;
|
||||
secondPart.posY = part.posY;
|
||||
secondPart.traversed = true;
|
||||
allParts.add(secondPart);
|
||||
}
|
||||
catchParts.add(part);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catchParts.add(part);
|
||||
for (GraphPart n : part.nextParts) {
|
||||
walkCatchParts(stats, n, n.start, catchParts, scopePos);
|
||||
walkCatchParts(stats, n, n.start, catchParts, scopePos, allParts, isFinally);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,4 +166,14 @@ public class ForEachInAVM2Item extends LoopItem implements Block {
|
||||
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
|
||||
return ((AVM2SourceGenerator) generator).generate(localData, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBaseBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphTargetItem> getBaseBodyCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,4 +150,14 @@ public class ForInAVM2Item extends LoopItem implements Block {
|
||||
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
|
||||
return ((AVM2SourceGenerator) generator).generate(localData, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBaseBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphTargetItem> getBaseBodyCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,6 +643,10 @@ public class Graph {
|
||||
int ret = o.level - level;
|
||||
if (ret == 0) {
|
||||
ret = part.closedTime - o.part.closedTime;
|
||||
|
||||
if (ret == 0) { //some nodes may be split in half and thus have same closedTime - like in try..catch
|
||||
return part.start - o.part.start;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -64,9 +64,7 @@ public class GraphPart implements Serializable {
|
||||
public List<GraphPart> refs = new ArrayList<>();
|
||||
|
||||
public boolean ignored = false;
|
||||
|
||||
public List<Object> forContinues = new ArrayList<>();
|
||||
|
||||
|
||||
public int level;
|
||||
|
||||
public int discoveredTime;
|
||||
|
||||
@@ -154,4 +154,14 @@ public class DoWhileItem extends LoopItem implements Block {
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBaseBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphTargetItem> getBaseBodyCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,4 +171,14 @@ public class ForItem extends LoopItem implements Block {
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBaseBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphTargetItem> getBaseBodyCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.graph.model;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.Loop;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -32,4 +33,8 @@ public abstract class LoopItem extends GraphTargetItem {
|
||||
super(src, lineStartItem, NOPRECEDENCE);
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
public abstract boolean hasBaseBody();
|
||||
|
||||
public abstract List<GraphTargetItem> getBaseBodyCommands();
|
||||
}
|
||||
|
||||
@@ -175,4 +175,14 @@ public class SwitchItem extends LoopItem implements Block {
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBaseBody() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphTargetItem> getBaseBodyCommands() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,4 +150,14 @@ public class WhileItem extends LoopItem implements Block {
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBaseBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphTargetItem> getBaseBodyCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user