From 922cd4508481ee0b78cc68a7d01a4168ebe79b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 2 Aug 2025 19:19:28 +0200 Subject: [PATCH] Fixed tests. --- .../localregs/GetLocalTypeIns.java | 81 +++++++++++++++---- .../flash/abc/avm2/model/CallAVM2Item.java | 6 -- .../abc/avm2/model/CallMethodAVM2Item.java | 6 -- .../abc/avm2/model/CallPropertyAVM2Item.java | 6 -- .../abc/avm2/model/CallStaticAVM2Item.java | 6 -- .../abc/avm2/model/CallSuperAVM2Item.java | 6 -- .../abc/avm2/model/ConstructAVM2Item.java | 6 -- .../abc/avm2/model/ConstructPropAVM2Item.java | 6 -- .../avm2/model/ConstructSuperAVM2Item.java | 6 -- .../avm2/model/clauses/FilterAVM2Item.java | 2 +- .../avm2/model/operations/BitNotAVM2Item.java | 2 +- .../operations/BitwiseBinaryOpAVM2Item.java | 2 +- .../operations/BitwiseBinaryOpActionItem.java | 2 +- .../model/operations/SubtractActionItem.java | 4 +- .../src/com/jpexs/decompiler/graph/Graph.java | 1 + .../decompiler/graph/GraphTargetItem.java | 44 ++++++---- .../decompiler/graph/TranslateStack.java | 25 ++++-- .../decompiler/graph/model/BinaryOpItem.java | 2 +- .../graph/model/CommaExpressionItem.java | 13 +++ .../jpexs/decompiler/graph/model/NotItem.java | 15 ++-- .../graph/model/ParenthesisItem.java | 9 ++- .../decompiler/graph/model/SwitchItem.java | 2 +- .../decompiler/graph/model/TernarOpItem.java | 6 +- .../decompiler/graph/model/UnaryOpItem.java | 2 +- .../ActionScript3AssembledDecompileTest.java | 16 +--- .../ActionScript3ClassicAirDecompileTest.java | 8 +- .../ActionScript3ClassicDecompileTest.java | 8 +- 27 files changed, 168 insertions(+), 124 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java index 737f7e762..a46d33ee7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java @@ -45,6 +45,7 @@ import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.CommaExpressionItem; import com.jpexs.decompiler.graph.model.DuplicateItem; import java.util.List; @@ -107,10 +108,20 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { //computedValue = new NotCompileTimeItem(ins, localData.lineStartInstruction, computedValue); } + GraphTargetItem type = TypeItem.UNBOUNDED; + + if (localData.localRegTypes.containsKey(regId)) { + type = localData.localRegTypes.get(regId); + } else if (computedValue != null) { + type = computedValue.returnType(); + } + stack.push(new LocalRegAVM2Item(ins, localData.lineStartInstruction, regId, computedValue, type)); + //chained assignments and/or ASC post/pre increment - if (!output.isEmpty()) { - if ((output.get(output.size() - 1) instanceof SetTypeAVM2Item)) { - GraphTargetItem setItem = output.get(output.size() - 1); + if (stack.peek() instanceof CommaExpressionItem) { + CommaExpressionItem ce = (CommaExpressionItem) stack.peek(); + if (ce.commands.size() == 2 && ce.commands.get(0) instanceof SetTypeAVM2Item) { + GraphTargetItem setItem = ce.commands.get(0); if ((setItem instanceof SetPropertyAVM2Item) && ((setItem.value.getNotCoerced() instanceof DecrementAVM2Item) || (setItem.value.getNotCoerced() instanceof IncrementAVM2Item))) { @@ -133,9 +144,10 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { } else { result = new PostDecrementAVM2Item(setProp.getSrc(), localData.lineStartInstruction, getProp); } - output.remove(output.size() - 1); - stack.moveToStack(output); - stack.add(result); + //output.remove(output.size() - 1); + //stack.moveToStack(output); + stack.pop(); + stack.push(result); return; } } @@ -153,6 +165,53 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { setItem.value = setLocal.value; } + //output.remove(output.size() - 1); + //stack.moveToStack(output); + stack.pop(); + + if (setItem instanceof SetPropertyAVM2Item) { + if ((setItem.value instanceof IncrementAVM2Item) || (setItem.value instanceof DecrementAVM2Item)) { + boolean isIncrement = (setItem.value instanceof IncrementAVM2Item); + if (setItem.value.value instanceof GetPropertyAVM2Item) { + SetPropertyAVM2Item setProp = (SetPropertyAVM2Item) setItem; + GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) setItem.value.value; + if (getProp.object.getThroughDuplicate() == setProp.object) { + if (((FullMultinameAVM2Item) setProp.propertyName).compareSame((FullMultinameAVM2Item) getProp.propertyName)) { + if (getProp.object instanceof DuplicateItem) { + getProp.object = getProp.object.value; + } + if (isIncrement) { + setItem = new PreIncrementAVM2Item(setProp.getSrc(), localData.lineStartInstruction, getProp); + } else { + setItem = new PreDecrementAVM2Item(setProp.getSrc(), localData.lineStartInstruction, getProp); + } + } + } + } + } + } + + stack.push(setItem); + return; + } + } + } + } + } else if (!output.isEmpty()) { + if ((output.get(output.size() - 1) instanceof SetTypeAVM2Item)) { + GraphTargetItem setItem = output.get(output.size() - 1); + if (setItem.value.getNotCoerced() instanceof SetLocalAVM2Item) { + SetLocalAVM2Item setLocal = (SetLocalAVM2Item) setItem.value.getNotCoerced(); + if (setLocal.regIndex == regId) { + int setLocalIp = localData.code.adr2pos(setLocal.getSrc().getAddress()); + if (localData.getSetLocalUsages(setLocalIp).size() == 1) { + if ((setItem.value instanceof CoerceAVM2Item) || (setItem.value instanceof ConvertAVM2Item)) { + setItem.value.value = setLocal.value; + } else { + setItem.value = setLocal.value; + } + + stack.pop(); output.remove(output.size() - 1); stack.moveToStack(output); @@ -185,14 +244,8 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { } } } - GraphTargetItem type = TypeItem.UNBOUNDED; - - if (localData.localRegTypes.containsKey(regId)) { - type = localData.localRegTypes.get(regId); - } else if (computedValue != null) { - type = computedValue.returnType(); - } - stack.push(new LocalRegAVM2Item(ins, localData.lineStartInstruction, regId, computedValue, type)); + + } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallAVM2Item.java index 5e8a87bdb..e33c74bb8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallAVM2Item.java @@ -238,13 +238,7 @@ public class CallAVM2Item extends AVM2Item { if (a > 0) { writer.allowWrapHere().append(","); } - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } arguments.get(a).toString(writer, localData); - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java index 5fa3489ce..77abf38db 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallMethodAVM2Item.java @@ -85,13 +85,7 @@ public class CallMethodAVM2Item extends AVM2Item { if (a > 0) { writer.allowWrapHere().append(","); } - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } arguments.get(a).toString(writer, localData); - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallPropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallPropertyAVM2Item.java index a0a4cc78f..649aee226 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallPropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallPropertyAVM2Item.java @@ -104,13 +104,7 @@ public class CallPropertyAVM2Item extends AVM2Item { if (a > 0) { writer.allowWrapHere().append(","); } - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } arguments.get(a).toString(writer, localData); - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java index a1e438f9b..6458d811d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallStaticAVM2Item.java @@ -86,13 +86,7 @@ public class CallStaticAVM2Item extends AVM2Item { if (a > 0) { writer.append(","); } - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } arguments.get(a).toString(writer, localData); - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java index e773f0d4e..12827de71 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java @@ -91,13 +91,7 @@ public class CallSuperAVM2Item extends AVM2Item { if (a > 0) { writer.append(","); } - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } arguments.get(a).toString(writer, localData); - if (arguments.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructAVM2Item.java index 7bbb01ab1..55db0972d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructAVM2Item.java @@ -127,13 +127,7 @@ public class ConstructAVM2Item extends AVM2Item { if (a > 0) { writer.allowWrapHere().append(","); } - if (args.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } args.get(a).toString(writer, localData); - if (args.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java index 648adbe2f..0aa69d86f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java @@ -125,13 +125,7 @@ public class ConstructPropAVM2Item extends AVM2Item { if (a > 0) { writer.allowWrapHere().append(","); } - if (args.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } args.get(a).toString(writer, localData); - if (args.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java index 4e2a0a529..e43207891 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java @@ -79,13 +79,7 @@ public class ConstructSuperAVM2Item extends AVM2Item { if (a > 0) { writer.allowWrapHere().append(","); } - if (args.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append("("); - } args.get(a).toString(writer, localData); - if (args.get(a).getPrecedence() >= PRECEDENCE_COMMA) { - writer.append(")"); - } } return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/FilterAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/FilterAVM2Item.java index 9d8ac7f68..b0916208a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/FilterAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/FilterAVM2Item.java @@ -65,7 +65,7 @@ public class FilterAVM2Item extends AVM2Item { public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { collection.toString(writer, localData); writer.append(".("); - expression.toStringBoolean(writer, localData); + expression.toString(writer, localData, "Boolean", true); return writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitNotAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitNotAVM2Item.java index 18bd33982..168986ac6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitNotAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitNotAVM2Item.java @@ -79,6 +79,6 @@ public class BitNotAVM2Item extends UnaryOpItem { return; } } - operand.toString(writer, localData, ""); + operand.toString(writer, localData, "", false); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitwiseBinaryOpAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitwiseBinaryOpAVM2Item.java index 5fb7d24b1..f4ae77915 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitwiseBinaryOpAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/BitwiseBinaryOpAVM2Item.java @@ -61,6 +61,6 @@ public abstract class BitwiseBinaryOpAVM2Item extends BinaryOpItem implements Co return; } } - operand.toString(writer, localData, ""); + operand.toString(writer, localData, "", false); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/BitwiseBinaryOpActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/BitwiseBinaryOpActionItem.java index 7042e609b..7901f9c31 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/BitwiseBinaryOpActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/BitwiseBinaryOpActionItem.java @@ -61,6 +61,6 @@ public abstract class BitwiseBinaryOpActionItem extends BinaryOpItem implements return; } } - operand.toString(writer, localData, ""); + operand.toString(writer, localData, "", false); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/SubtractActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/SubtractActionItem.java index 047d55fdb..f0c1c40c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/SubtractActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/SubtractActionItem.java @@ -80,10 +80,10 @@ public class SubtractActionItem extends BinaryOpItem implements CompoundableBina int rightPrecedence = rightSide.getPrecedence(); if (rightPrecedence >= precedence && rightPrecedence != GraphTargetItem.NOPRECEDENCE) { writer.append("("); - rightSide.toString(writer, localData, coerceRight); + rightSide.toString(writer, localData, coerceRight, false); writer.append(")"); } else { - rightSide.toString(writer, localData, coerceRight); + rightSide.toString(writer, localData, coerceRight, false); } return writer; } else if (rightSide.getPrecedence() >= precedence) { // >= add or subtract too diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 7cc979bbe..71c3f6b17 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -2390,6 +2390,7 @@ public class Graph { */ protected final void translatePart(List output, BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { List sub = part.getSubParts(); + stack.setConnectedOutput(0, output); int end; for (GraphPart p : sub) { if (p.end == -1) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index cbd208fc2..95e2048b5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -384,8 +384,8 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toStringBoolean(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return toString(writer, localData, "Boolean"); + public final GraphTextWriter toStringBoolean(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return toString(writer, localData, "Boolean", false); } /** @@ -396,8 +396,8 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toStringString(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return toString(writer, localData, "String"); + public final GraphTextWriter toStringString(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return toString(writer, localData, "String", false); } /** @@ -408,8 +408,8 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toStringInt(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return toString(writer, localData, "int"); + public final GraphTextWriter toStringInt(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return toString(writer, localData, "int", false); } /** @@ -420,8 +420,8 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toStringNumber(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return toString(writer, localData, "Number"); + public final GraphTextWriter toStringNumber(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return toString(writer, localData, "Number", false); } /** @@ -440,16 +440,17 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @param writer Writer * @param localData Local data * @param implicitCoerce Implicit coerce + * @param noParenthesis Do not use parenthesis * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toString(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException { + public GraphTextWriter toString(GraphTextWriter writer, LocalData localData, String implicitCoerce, boolean noParenthesis) throws InterruptedException { if (CancellableWorker.isInterrupted()) { throw new InterruptedException(); } writer.startOffset(src, getLineStartItem(), getPos(), srcData); - appendTry(writer, localData, implicitCoerce); + appendTry(writer, localData, implicitCoerce, noParenthesis); writer.endOffset(); return writer; } @@ -463,7 +464,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @throws InterruptedException On interrupt */ public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return toString(writer, localData, ""); + return toString(writer, localData, "", false); } /** @@ -489,6 +490,18 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @throws InterruptedException On interrupt */ public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException; + + /** + * Append this to a writer, ignoring parenthesis (in CommaExpression and/or Parenthesis) + * + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException On interrupt + */ + public GraphTextWriter appendNoParenthesis(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return appendTo(writer, localData); + } /** * Append this to a writer. @@ -499,7 +512,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @throws InterruptedException On interrupt */ public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return appendTry(writer, localData, ""); + return appendTry(writer, localData, "", false); } /** @@ -511,7 +524,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException { + public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData, String implicitCoerce, boolean noParenthesis) throws InterruptedException { GraphTargetItem t = this; if (!implicitCoerce.isEmpty()) { //if implicit coerce equals explicit /*if (t instanceof ConvertAVM2Item) { @@ -535,6 +548,9 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { if (!implicitCoerce.isEmpty() && Configuration.simplifyExpressions.get()) { t = t.simplify(implicitCoerce); } + if (noParenthesis) { + return t.appendNoParenthesis(writer, localData); + } return t.appendTo(writer, localData); } @@ -1124,5 +1140,5 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { } } return o1.equals(o2); - } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index d449b3b3d..776df75ff 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.graph; +import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; import com.jpexs.decompiler.graph.model.BranchStackResistant; @@ -82,9 +83,13 @@ public class TranslateStack extends Stack { @Override public GraphTargetItem push(GraphTargetItem item) { if (!outputQueue.isEmpty()) { - outputQueue.add(item); - item = new CommaExpressionItem(item.dialect, null, item.lineStartItem, outputQueue); - outputQueue = new ArrayList<>(); + if (item instanceof FindPropertyAVM2Item) { + finishBlock(connectedOutput); + } else { + outputQueue.add(item); + item = new CommaExpressionItem(item.dialect, null, item.lineStartItem, outputQueue); + outputQueue = new ArrayList<>(); + } } if (connectedOutput != null && item != null) { item.outputPos = prevOutputSize + connectedOutput.size(); @@ -288,13 +293,14 @@ public class TranslateStack extends Stack { continue; } output.add(pos, beforeExit ? item : new PushItem(item)); - }*/ - - output.addAll(outputQueue); - outputQueue.clear(); + }*/ int clen = output.size(); boolean isExit = false; + + if (!outputQueue.isEmpty() && outputQueue.get(outputQueue.size() - 1) instanceof ExitItem) { + isExit = true; + } if (clen > 0) { if (output.get(clen - 1) instanceof ScriptEndItem) { clen--; @@ -337,7 +343,10 @@ public class TranslateStack extends Stack { output.add(clen, new PushItem(p)); } } - } + } + + output.addAll(outputQueue); + outputQueue.clear(); } public void allowSwap(List output) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java index 9777a864e..a8e53bfa8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java @@ -140,7 +140,7 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp { * @throws InterruptedException On interrupt */ protected void operandToString(GraphTargetItem operand, GraphTextWriter writer, LocalData localData) throws InterruptedException { - operand.toString(writer, localData, ""); + operand.toString(writer, localData, "", false); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/CommaExpressionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/CommaExpressionItem.java index 4268375e2..0f315ee5b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/CommaExpressionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/CommaExpressionItem.java @@ -59,6 +59,17 @@ public class CommaExpressionItem extends GraphTargetItem { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + if (commands.isEmpty()) { + return writer; + } + writer.append("("); + appendNoParenthesis(writer, localData); + writer.append(")"); + return writer; + } + + @Override + public GraphTextWriter appendNoParenthesis(GraphTextWriter writer, LocalData localData) throws InterruptedException { boolean first = true; for (GraphTargetItem t : commands) { if (t.isEmpty()) { @@ -72,6 +83,8 @@ public class CommaExpressionItem extends GraphTargetItem { } return writer; } + + @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java index 5805b9b0a..0c44f04f1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java @@ -98,13 +98,18 @@ public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted { } @Override - public GraphTextWriter toStringBoolean(GraphTextWriter writer, LocalData localData) throws InterruptedException { - //Skip explicit conversion to boolean, it is not needed, it is done implicitly - if (value instanceof NotItem) { - return value.value.toStringBoolean(writer, localData); + public GraphTextWriter toString(GraphTextWriter writer, LocalData localData, String implicitCoerce, boolean noParenthesis) throws InterruptedException { + if ("Boolean".equals(implicitCoerce)) { + //Skip explicit conversion to boolean, it is not needed, it is done implicitly + if (value instanceof NotItem) { + return value.value.toStringBoolean(writer, localData); + } } - return super.toStringBoolean(writer, localData); + + return super.toString(writer, localData, implicitCoerce, noParenthesis); } + + @Override public GraphTargetItem invert(GraphSourceItem src) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ParenthesisItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ParenthesisItem.java index b2ec272c8..4b1203443 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ParenthesisItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ParenthesisItem.java @@ -47,10 +47,17 @@ public class ParenthesisItem extends GraphTargetItem { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.append("("); - value.toString(writer, localData); + appendNoParenthesis(writer, localData); return writer.append(")"); } + @Override + public GraphTextWriter appendNoParenthesis(GraphTextWriter writer, LocalData localData) throws InterruptedException { + value.toString(writer, localData); + return writer; + } + + @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return value.toSource(localData, generator); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java index 3ae49d8e5..d1525b537 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java @@ -151,7 +151,7 @@ public class SwitchItem extends LoopItem implements Block { if (!(caseValues.get(k) instanceof DefaultItem)) { writer.append("case "); } - caseValues.get(k).toString(writer, localData); + caseValues.get(k).toString(writer, localData, "", true); writer.append(":").newLine(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TernarOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TernarOpItem.java index deb154360..cd700f620 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TernarOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/TernarOpItem.java @@ -79,7 +79,7 @@ public class TernarOpItem extends GraphTargetItem { if (expression.getPrecedence() >= precedence) { writer.append("("); } - expression.toStringBoolean(writer, localData); + expression.toString(writer, localData, "Boolean", true); if (expression.getPrecedence() >= precedence) { writer.append(")"); } @@ -88,7 +88,7 @@ public class TernarOpItem extends GraphTargetItem { if (onTrue.getPrecedence() >= precedence && onTrue.getPrecedence() != GraphTargetItem.NOPRECEDENCE) { // >= ternar in ternar better in parenthesis writer.append("("); } - onTrue.toString(writer, localData); + onTrue.toString(writer, localData, "", true); if (onTrue.getPrecedence() >= precedence && onTrue.getPrecedence() != GraphTargetItem.NOPRECEDENCE) { writer.append(")"); } @@ -96,7 +96,7 @@ public class TernarOpItem extends GraphTargetItem { if (onFalse.getPrecedence() >= precedence && onFalse.getPrecedence() != GraphTargetItem.NOPRECEDENCE) { writer.append("("); } - onFalse.toString(writer, localData); + onFalse.toString(writer, localData, "", true); if (onFalse.getPrecedence() >= precedence && onFalse.getPrecedence() != GraphTargetItem.NOPRECEDENCE) { writer.append(")"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java index 3f8f53b6e..082f5299b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java @@ -178,6 +178,6 @@ public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp { * @throws InterruptedException On interrupt */ protected void operandToString(GraphTargetItem operand, GraphTextWriter writer, LocalData localData) throws InterruptedException { - operand.toString(writer, localData, ""); + operand.toString(writer, localData, "", false); } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java index cf75b0913..877b523bb 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java @@ -325,8 +325,7 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT decompileMethod("assembled", "testPushPlacement", "var a:int = 1;\r\n" + "var b:* = 2;\r\n" + "§§push(a);\r\n" - + "a += 1;\r\n" - + "if(b >= 2)\r\n" + + "if(((a += 1,b)) >= 2)\r\n" + "{\r\n" + "b = §§pop() + 7;\r\n" + "trace(b);\r\n" @@ -341,24 +340,13 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testPushWhile() { decompileMethod("assembled", "testPushWhile", "var _loc3_:int = 5;\r\n" - + "§§push(new (getDefinitionByName(\"flash.utils\"+\".\"+\"ByteArray\"))());\r\n" - + "§§push(§§dup(new (getDefinitionByName(\"flash.utils\"+\".\"+\"ByteArray\"))()));\r\n" - + "§§push(obfuscated);\r\n" - + "§§swap();\r\n" - + "§§pop()[\"xxx\"] = §§pop();\r\n" + + "§§push(obfuscated[\"xxx\"] = new (getDefinitionByName(\"flash.utils\"+\".\"+\"ByteArray\"))());\r\n" + "§§push(50);\r\n" + "while(§§dup(§§pop()))\r\n" + "{\r\n" - + "§§push(§§pop());\r\n" + "§§push(§§pop() - 1);\r\n" - + "§§swap();\r\n" - + "§§push(§§pop());\r\n" + "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 0x29 ^ 0x6F;\r\n" - + "§§push(§§pop());\r\n" + "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 9 ^ 0x54;\r\n" - + "§§push(§§pop());\r\n" - + "§§push(§§pop());\r\n" - + "§§swap();\r\n" + "}\r\n" + "§§pop();\r\n" + "§§pop();\r\n", diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java index d2bad1cd4..c738af077 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java @@ -177,7 +177,7 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile public void testComma() { decompileMethod("classic_air", "testComma", "var a:int = 5;\r\n" + "var b:int = 0;\r\n" - + "trace(a > 4 ? (b = 5, a) : 35);\r\n", + + "trace(a > 4 ? (b = 5,a) : 35);\r\n", false); } @@ -529,9 +529,9 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile public void testDotParent() { decompileMethod("classic_air", "testDotParent", "var d:* = new TestClass1();\r\n" + "var k:* = null;\r\n" - + "k.(d.attrib++, false);\r\n" + + "k.(d.attrib++,false);\r\n" + "trace(\"between\");\r\n" - + "var g:* = k.(d.attrib++, false);\r\n" + + "var g:* = k.(d.attrib++,false);\r\n" + "trace(\"end\");\r\n", false); } @@ -2108,7 +2108,7 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile + "break;\r\n" + "case \"B\":\r\n" + "trace(\"is B\");\r\n" - + "case 7, \"C\":\r\n" + + "case 7,\"C\":\r\n" + "trace(\"is C\");\r\n" + "}\r\n", false); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java index 7bc243fcd..ddcdf6f46 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java @@ -177,7 +177,7 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes public void testComma() { decompileMethod("classic", "testComma", "var a:int = 5;\r\n" + "var b:int = 0;\r\n" - + "trace(a > 4 ? (b = 5, a) : 35);\r\n", + + "trace(a > 4 ? (b = 5,a) : 35);\r\n", false); } @@ -531,9 +531,9 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes + "var g:* = undefined;\r\n" + "d = new TestClass1();\r\n" + "k = null;\r\n" - + "k.(++d.attrib, 0);\r\n" + + "k.(++d.attrib,0);\r\n" + "trace(\"between\");\r\n" - + "g = k.(++d.attrib, 0);\r\n" + + "g = k.(++d.attrib,0);\r\n" + "trace(\"end\");\r\n", false); } @@ -2091,7 +2091,7 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes + "break;\r\n" + "case \"B\":\r\n" + "trace(\"is B\");\r\n" - + "case TestSwitchComma.X, \"C\":\r\n" + + "case TestSwitchComma.X,\"C\":\r\n" + "trace(\"is C\");\r\n" + "}\r\n", false);