diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java index 898c7bb3f..952e49d84 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java @@ -43,6 +43,11 @@ public abstract class BaseLocalData { * Second pass data */ public SecondPassData secondPassData = null; + + /** + * SWF version + */ + public int swfVersion = -1; /** * Constructor. diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index a4de7c88e..481083024 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -5916,7 +5916,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { try { List callStack = new ArrayList<>(); callStack.add(documentPack.abc.findBody(mi)); - documentPack.abc.findBody(mi).convert(callStack, getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + int swfVersion = -1; + if (documentPack.getOpenable() instanceof SWF) { + swfVersion = ((SWF) documentPack.getOpenable()).version; + } + documentPack.abc.findBody(mi).convert(swfVersion, callStack, getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); List infos = documentPack.abc.findBody(mi).convertedItems; if (!infos.isEmpty()) { if (infos.get(0) instanceof IfItem) { @@ -5994,7 +5998,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { int cinit = p.abc.class_info.get(ci).cinit_index; callStack = new ArrayList<>(); callStack.add(p.abc.findBody(cinit)); - p.abc.findBody(cinit).convert(callStack, getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + p.abc.findBody(cinit).convert(swfVersion, callStack, getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); List cinitBody = p.abc.findBody(cinit).convertedItems; for (GraphTargetItem cit : cinitBody) { if (cit instanceof SetPropertyAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java index 73141dcb8..3acc0dfe7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java @@ -296,6 +296,7 @@ public class AVM2LocalData extends BaseLocalData { finallyKinds = localData.finallyKinds; seenMethods = localData.seenMethods; bottomSetLocals = localData.bottomSetLocals; + swfVersion = localData.swfVersion; } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 593bd92a1..b03885998 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -257,6 +257,11 @@ public class ScriptPack extends AS3ClassTreeItem { */ public void convert(AbcIndexing abcIndex, final NulWriter writer, final List traits, final ConvertData convertData, final ScriptExportMode exportMode, final boolean parallel) throws InterruptedException { + int swfVersion = -1; + if (getOpenable() instanceof SWF) { + swfVersion = ((SWF) getOpenable()).version; + } + int sinit_index = abc.script_info.get(scriptIndex).init_index; int sinit_bodyIndex = abc.findBodyIndex(sinit_index); if (sinit_bodyIndex != -1 && (isSimple || traitIndices.isEmpty())) { @@ -269,21 +274,21 @@ public class ScriptPack extends AS3ClassTreeItem { writer.mark(); List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(sinit_bodyIndex)); - abc.bodies.get(sinit_bodyIndex).convert(callStack, abcIndex, convertData, path + "/.scriptinitializer", exportMode, true, sinit_index, scriptIndex, -1, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, writer, new ArrayList<>(), abc.script_info.get(scriptIndex).traits, true, new HashSet<>()); + abc.bodies.get(sinit_bodyIndex).convert(swfVersion, callStack, abcIndex, convertData, path + "/.scriptinitializer", exportMode, true, sinit_index, scriptIndex, -1, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, writer, new ArrayList<>(), abc.script_info.get(scriptIndex).traits, true, new HashSet<>()); scriptInitializerIsEmpty = !writer.getMark(); } ScopeStack scopeStack = new ScopeStack(); scopeStack.push(new GlobalAVM2Item(null, null)); - + for (int t : traitIndices) { Trait trait = traits.get(t); Multiname name = trait.getName(abc); int nskind = name.getSimpleNamespaceKind(abc.constants); if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { - trait.convertPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack); + trait.convertPackaged(swfVersion, abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack); } else { - trait.convert(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack); + trait.convert(swfVersion, abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack); } } } @@ -302,6 +307,12 @@ public class ScriptPack extends AS3ClassTreeItem { * @throws InterruptedException On interrupt */ private void appendTo(AbcIndexing abcIndex, GraphTextWriter writer, List traits, ConvertData convertData, ScriptExportMode exportMode, boolean parallel, boolean exportAllClasses) throws InterruptedException { + + int swfVersion = -1; + if (getOpenable() instanceof SWF) { + swfVersion = ((SWF) getOpenable()).version; + } + boolean first = true; //script initializer int script_init = abc.script_info.get(scriptIndex).init_index; @@ -344,7 +355,7 @@ public class ScriptPack extends AS3ClassTreeItem { writer.newLine(); } writer.startTrait(traitIndicesList.get(t)); - trait.toStringPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, fullyQualifiedNames, parallel, false); + trait.toStringPackaged(swfVersion, abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, fullyQualifiedNames, parallel, false); if (!(trait instanceof TraitClass)) { writer.endTrait(); @@ -375,7 +386,7 @@ public class ScriptPack extends AS3ClassTreeItem { writer.newLine(); } writer.startTrait(traitIndicesList.get(t)); - trait.toString(abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); + trait.toString(swfVersion, abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); if (!(trait instanceof TraitClass)) { writer.endTrait(); @@ -406,9 +417,9 @@ public class ScriptPack extends AS3ClassTreeItem { Multiname name = trait.getName(abc); int nskind = name.getSimpleNamespaceKind(abc.constants); if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { - trait.toStringPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); + trait.toStringPackaged(swfVersion, abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); } else { - trait.toString(abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); + trait.toString(swfVersion, abcIndex, pkg, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); } writer.endTrait(); first = false; @@ -425,7 +436,7 @@ public class ScriptPack extends AS3ClassTreeItem { if (!first) { writer.newLine(); } - abc.bodies.get(bodyIndex).toString(callStack, abcIndex, path + "/.scriptinitializer", exportMode, abc, null, writer, fullyQualifiedNames, new HashSet<>()); + abc.bodies.get(bodyIndex).toString(swfVersion, callStack, abcIndex, path + "/.scriptinitializer", exportMode, abc, null, writer, fullyQualifiedNames, new HashSet<>()); } else { writer.append(""); } @@ -452,6 +463,7 @@ public class ScriptPack extends AS3ClassTreeItem { /** * Converts the script pack to source. * + * @param swfVersion SWF version * @param abcIndex Abc indexing * @param writer Writer * @param traits Traits diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 9cb4a689e..d68b8c2d9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1826,6 +1826,7 @@ public class AVM2Code implements Cloneable { /** * Converts to source output. * + * @param swfVersion SWF version * @param switchParts Switch parts * @param callStack Call stack * @param abcIndex ABC indexing @@ -1856,7 +1857,7 @@ public class AVM2Code implements Cloneable { * @throws ConvertException On convert error * @throws InterruptedException On interrupt */ - public ConvertOutput toSourceOutput(Set switchParts, List callStack, AbcIndexing abcIndex, Map> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssignmentIps, LinkedIdentityHashSet bottomStackSetLocals) throws ConvertException, InterruptedException { + public ConvertOutput toSourceOutput(int swfVersion, Set switchParts, List callStack, AbcIndexing abcIndex, Map> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssignmentIps, LinkedIdentityHashSet bottomStackSetLocals) throws ConvertException, InterruptedException { boolean debugMode = DEBUG_MODE; if (debugMode) { System.err.println("OPEN SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString()); @@ -1976,7 +1977,7 @@ public class AVM2Code implements Cloneable { } else */ if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) { - ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssignmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals); + ins.definition.translate(swfVersion, switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssignmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals); //ip = end + 1; break; } else if (ins.definition instanceof NewFunctionIns) { @@ -2012,13 +2013,13 @@ public class AVM2Code implements Cloneable { } } // What to do when hasDup is false? - ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssignmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals); + ins.definition.translate(swfVersion, switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssignmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals); NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek(); nft.functionName = functionName; ip++; } else { try { - ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssignmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals); + ins.definition.translate(swfVersion, switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssignmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals); if (stack.size() == 1 && (stack.peek() instanceof SetLocalAVM2Item)) { bottomStackSetLocals.add((SetLocalAVM2Item) stack.peek()); @@ -2522,6 +2523,7 @@ public class AVM2Code implements Cloneable { /** * Converts code to source - list of GraphTargetItems. * + * @param swfVersion SWF version * @param callStack Call stack * @param abcIndex ABC indexing * @param thisHasDefaultToPrimitive True if this has default to primitive @@ -2543,7 +2545,7 @@ public class AVM2Code implements Cloneable { * @return List of GraphTargetItems * @throws InterruptedException On interrupt */ - public List toGraphTargetItems(List callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssignmentIps) throws InterruptedException { + public List toGraphTargetItems(int swfVersion, List callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssignmentIps) throws InterruptedException { initToSource(); List list; HashMap localRegs = new HashMap<>(); @@ -2558,9 +2560,9 @@ public class AVM2Code implements Cloneable { } try { - list = AVM2Graph.translateViaGraph(null, callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssignmentIps, thisHasDefaultToPrimitive); + list = AVM2Graph.translateViaGraph(swfVersion, null, callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssignmentIps, thisHasDefaultToPrimitive); } catch (SecondPassException spe) { - list = AVM2Graph.translateViaGraph(spe.getData(), callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssignmentIps, thisHasDefaultToPrimitive); + list = AVM2Graph.translateViaGraph(swfVersion, spe.getData(), callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssignmentIps, thisHasDefaultToPrimitive); } if (initTraits != null) { loopi: diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java index b6ed09353..79d484129 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java @@ -84,7 +84,7 @@ public class CodeStats { if (stats.stackpos > ms) { ms = stats.stackpos; } - writer.appendNoHilight(i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(writer, LocalData.create(new ArrayList<>(), null, abc, null, fullyQualifiedNames, new HashSet<>(), ScriptExportMode.AS))).newLine(); + writer.appendNoHilight(i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(writer, LocalData.create(new ArrayList<>(), null, abc, null, fullyQualifiedNames, new HashSet<>(), ScriptExportMode.AS, -1))).newLine(); i++; } return writer; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index e27eb02f9..3b2670050 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -64,6 +64,8 @@ import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NextNameAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NextValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NullCoalesceAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; @@ -79,6 +81,8 @@ import com.jpexs.decompiler.flash.abc.avm2.model.clauses.FilterAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.EqAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.NeqAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.StrictEqAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.ABCException; @@ -115,6 +119,7 @@ import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.PushItem; import com.jpexs.decompiler.graph.model.SwitchItem; +import com.jpexs.decompiler.graph.model.TernarOpItem; import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.decompiler.graph.model.WhileItem; import com.jpexs.helpers.Reference; @@ -156,6 +161,7 @@ public class AVM2Graph extends Graph { * Method body */ private final MethodBody body; + private final int swfVersion; /** * ABC indexing @@ -200,6 +206,7 @@ public class AVM2Graph extends Graph { /** * Constructs AVM2 graph * + * @param swfVersion SWF version * @param abcIndex ABC indexing * @param code AVM2 code * @param abc ABC @@ -214,11 +221,12 @@ public class AVM2Graph extends Graph { * @param fullyQualifiedNames Fully qualified names * @param localRegAssignmentIps Local register assignment IPs */ - public AVM2Graph(AbcIndexing abcIndex, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, ScopeStack localScopeStack, HashMap localRegNames, List fullyQualifiedNames, HashMap localRegAssignmentIps) { + public AVM2Graph(int swfVersion, AbcIndexing abcIndex, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, ScopeStack localScopeStack, HashMap localRegNames, List fullyQualifiedNames, HashMap localRegAssignmentIps) { super(new AVM2GraphSource(code, isStatic, scriptIndex, classIndex, localRegs, abc, body, localRegNames, fullyQualifiedNames, localRegAssignmentIps), getExceptionEntries(body)); this.avm2code = code; this.abc = abc; this.body = body; + this.swfVersion = swfVersion; this.abcIndex = abcIndex; } @@ -725,6 +733,7 @@ public class AVM2Graph extends Graph { /** * Translates via Graph - decompiles. * + * @param swfVersion SWF version * @param secondPassData Second pass data * @param callStack Call stack * @param abcIndex ABC indexing @@ -746,9 +755,9 @@ public class AVM2Graph extends Graph { * @return List of graph target items * @throws InterruptedException On interrupt */ - public static List translateViaGraph(SecondPassData secondPassData, List callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, int staticOperation, HashMap localRegAssignmentIps, boolean thisHasDefaultToPrimitive) throws InterruptedException { + public static List translateViaGraph(int swfVersion, SecondPassData secondPassData, List callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, int staticOperation, HashMap localRegAssignmentIps, boolean thisHasDefaultToPrimitive) throws InterruptedException { ScopeStack localScopeStack = new ScopeStack(); - AVM2Graph g = new AVM2Graph(abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localScopeStack, localRegNames, fullyQualifiedNames, localRegAssignmentIps); + AVM2Graph g = new AVM2Graph(swfVersion, abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localScopeStack, localRegNames, fullyQualifiedNames, localRegAssignmentIps); AVM2LocalData localData = new AVM2LocalData(); localData.secondPassData = secondPassData; @@ -768,6 +777,7 @@ public class AVM2Graph extends Graph { localData.scriptIndex = scriptIndex; localData.ip = 0; localData.code = code; + localData.swfVersion = swfVersion; g.init(localData); Set allParts = new HashSet<>(); for (GraphPart head : g.heads) { @@ -3212,4 +3222,38 @@ public class AVM2Graph extends Graph { return result; } + + @Override + protected GraphTargetItem handleTernar(TernarOpItem ternar, BaseLocalData localData) { + if (localData.swfVersion < 50) { + return ternar; + } + + if (true) { //FIXME, WIP - implement compiler part + return ternar; + } + if (ternar.expression instanceof EqAVM2Item) { + EqAVM2Item eq = (EqAVM2Item) ternar.expression; + if (eq.rightSide instanceof NullAVM2Item) { + if (ternar.onFalse.getNotCoerced() instanceof GetPropertyAVM2Item) { + GetPropertyAVM2Item gp = (GetPropertyAVM2Item) ternar.onFalse.getNotCoerced(); + if (gp.object.valueEquals(eq.leftSide)) { + gp.nullCondition = true; + return gp; + } + } + } + } + + if (ternar.expression instanceof NeqAVM2Item) { + NeqAVM2Item neq = (NeqAVM2Item) ternar.expression; + if (neq.rightSide instanceof NullAVM2Item) { + if (ternar.onTrue.valueEquals(neq.leftSide)) { + return new NullCoalesceAVM2Item(ternar.getSrc(), ternar.getLineStartItem(), ternar.onTrue, ternar.onFalse); + } + } + } + + return ternar; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java index 5577166a8..8edc8308e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java @@ -203,7 +203,7 @@ public class AVM2GraphSource extends GraphSource { public List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException { List ret = new ArrayList<>(); Reference lineStartItem = new Reference<>(localData.lineStartInstruction); - ConvertOutput co = code.toSourceOutput(localData.allSwitchParts, ((AVM2LocalData) localData).callStack, ((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, ((AVM2LocalData) localData).scopeStack, ((AVM2LocalData) localData).localScopeStack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssignmentIps, ((AVM2LocalData) localData).bottomSetLocals); + ConvertOutput co = code.toSourceOutput(localData.swfVersion, localData.allSwitchParts, ((AVM2LocalData) localData).callStack, ((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, ((AVM2LocalData) localData).scopeStack, ((AVM2LocalData) localData).localScopeStack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssignmentIps, ((AVM2LocalData) localData).bottomSetLocals); localData.lineStartInstruction = lineStartItem.getVal(); ret.addAll(co.output); return ret; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index 0a74c4b41..39572db62 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -267,6 +267,7 @@ public abstract class InstructionDefinition implements Serializable { /** * Translates instruction to high level code. * + * @param swfVersion SWF version * @param switchParts Switch parts * @param callStack Call stack * @param abcIndex ABC indexing @@ -294,7 +295,7 @@ public abstract class InstructionDefinition implements Serializable { * @param bottomSetLocals Bottom set locals * @throws InterruptedException On interrupt */ - public void translate(Set switchParts, List callStack, AbcIndexing abcIndex, Map> setLocalPosToGetLocalPos, Reference lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, AVM2Instruction ins, List output, MethodBody body, ABC abc, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, AVM2Code code, boolean thisHasDefaultToPrimitive, LinkedIdentityHashSet bottomSetLocals) throws InterruptedException { + public void translate(int swfVersion, Set switchParts, List callStack, AbcIndexing abcIndex, Map> setLocalPosToGetLocalPos, Reference lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, AVM2Instruction ins, List output, MethodBody body, ABC abc, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, AVM2Code code, boolean thisHasDefaultToPrimitive, LinkedIdentityHashSet bottomSetLocals) throws InterruptedException { AVM2LocalData localData = new AVM2LocalData(); localData.allSwitchParts = switchParts; localData.isStatic = isStatic; @@ -317,6 +318,7 @@ public abstract class InstructionDefinition implements Serializable { localData.thisHasDefaultToPrimitive = thisHasDefaultToPrimitive; localData.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos; localData.bottomSetLocals = bottomSetLocals; + localData.swfVersion = swfVersion; translate(localData, stack, ins, output, path); lineStartItem.setVal(localData.lineStartInstruction); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java index 0dd2d897e..d49637093 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java @@ -49,7 +49,7 @@ public class NewClassIns extends InstructionDefinition { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) throws InterruptedException { int clsIndex = ins.operands[0]; HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - stack.pop().toString(writer, LocalData.create(localData.callStack /*??*/, localData.abcIndex, localData.abc, localData.localRegNames, localData.fullyQualifiedNames, new HashSet<>(), ScriptExportMode.AS)); + stack.pop().toString(writer, LocalData.create(localData.callStack /*??*/, localData.abcIndex, localData.abc, localData.localRegNames, localData.fullyQualifiedNames, new HashSet<>(), ScriptExportMode.AS, localData.swfVersion)); writer.finishHilights(); String baseType = writer.toString(); ABC abc = localData.abc; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java index d6c8eb641..25e1874f4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java @@ -107,10 +107,11 @@ public abstract class AVM2Item extends GraphTargetItem { * @param propertyName Property name * @param localData Local data * @param isStatic Is static + * @param nullCondition Null condition - ?. * @return Writer * @throws InterruptedException On interrupt */ - protected GraphTextWriter formatProperty(GraphTextWriter writer, GraphTargetItem object, GraphTargetItem propertyName, LocalData localData, boolean isStatic) throws InterruptedException { + protected GraphTextWriter formatProperty(GraphTextWriter writer, GraphTargetItem object, GraphTargetItem propertyName, LocalData localData, boolean isStatic, boolean nullCondition) throws InterruptedException { boolean empty = object.getThroughDuplicate() instanceof FindPropertyAVM2Item; if (object instanceof LocalRegAVM2Item) { if (((LocalRegAVM2Item) object).computedValue != null) { @@ -170,16 +171,16 @@ public abstract class AVM2Item extends GraphTargetItem { } data.namespaceIndex = namespaceIndex; data.isStatic = isStatic; - + + String operator = nullCondition ? "?." : "."; + if (((FullMultinameAVM2Item) propertyName).name != null) { if (((FullMultinameAVM2Item) propertyName).namespace != null) { - //writer.append("."); - writer.allowWrapHere().hilightSpecial(".", HighlightSpecialType.PROPERTY_TYPE, 0, data); + writer.allowWrapHere().hilightSpecial(operator, HighlightSpecialType.PROPERTY_TYPE, 0, data); } return propertyName.toString(writer, localData); } else { - writer.allowWrapHere().hilightSpecial(".", HighlightSpecialType.PROPERTY_TYPE, 0, data); - //writer.append("."); + writer.allowWrapHere().hilightSpecial(operator, HighlightSpecialType.PROPERTY_TYPE, 0, data); return propertyName.toString(writer, localData); } } else { 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 d44b2f8c2..226fa8056 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 @@ -97,7 +97,7 @@ public class CallPropertyAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - formatProperty(writer, receiver, propertyName, localData, isStatic); + formatProperty(writer, receiver, propertyName, localData, isStatic, false); writer.spaceBeforeCallParenthesis(arguments.size()); writer.append("("); for (int a = 0; a < arguments.size(); a++) { 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 e92da7493..746a101d8 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 @@ -86,7 +86,7 @@ public class ConstructPropAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.append("new "); - formatProperty(writer, object, propertyName, localData, isStatic); + formatProperty(writer, object, propertyName, localData, isStatic, false); writer.spaceBeforeCallParenthesis(args.size()); writer.append("("); for (int a = 0; a < args.size(); a++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java index a291dd300..cb1d5f2b8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java @@ -151,13 +151,13 @@ public class FullMultinameAVM2Item extends AVM2Item { public boolean isTopLevel(String tname, ABC abc, HashMap localRegNames, List fullyQualifiedNames, Set seenMethods) throws InterruptedException { String cname; if (name != null) { - cname = name.toString(LocalData.create(new ArrayList<>(), null, abc, localRegNames, fullyQualifiedNames, seenMethods, ScriptExportMode.AS)); + cname = name.toString(LocalData.create(new ArrayList<>(), null, abc, localRegNames, fullyQualifiedNames, seenMethods, ScriptExportMode.AS, -1)); } else { cname = (abc.constants.getMultiname(multinameIndex).getName(abc.constants, fullyQualifiedNames, true, true)); } String cns = ""; if (namespace != null) { - cns = namespace.toString(LocalData.create(new ArrayList<>(), null, abc, localRegNames, fullyQualifiedNames, seenMethods, ScriptExportMode.AS)); + cns = namespace.toString(LocalData.create(new ArrayList<>(), null, abc, localRegNames, fullyQualifiedNames, seenMethods, ScriptExportMode.AS, -1)); } else { Namespace ns = abc.constants.getMultiname(multinameIndex).getNamespace(abc.constants); if ((ns != null) && (ns.name_index != 0)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetPropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetPropertyAVM2Item.java index 4ada66681..f5c5d548d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetPropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetPropertyAVM2Item.java @@ -68,6 +68,11 @@ public class GetPropertyAVM2Item extends AVM2Item { * Is static */ public boolean isStatic; + + /** + * Is null condition - ?. + */ + public boolean nullCondition = false; @Override public void visit(GraphTargetVisitorInterface visitor) { @@ -171,7 +176,7 @@ public class GetPropertyAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return formatProperty(writer, object, propertyName, localData, isStatic); + return formatProperty(writer, object, propertyName, localData, isStatic, nullCondition); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitPropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitPropertyAVM2Item.java index ae281c8fc..27e64f28f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitPropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitPropertyAVM2Item.java @@ -113,7 +113,7 @@ public class InitPropertyAVM2Item extends AVM2Item implements SetTypeAVM2Item, A @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - formatProperty(writer, object, propertyName, localData, isStatic); + formatProperty(writer, object, propertyName, localData, isStatic, false); if (compoundOperator != null) { writer.append(" "); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java index dfe6b39ab..5039b318a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java @@ -130,8 +130,8 @@ public class NewFunctionAVM2Item extends AVM2Item { if (body != null) { List callStack = new ArrayList<>(localData.callStack); callStack.add(body); - body.convert(callStack, localData.abcIndex, new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, scopeStack, 0, new NulWriter(), localData.fullyQualifiedNames, null, false, new HashSet<>(localData.seenMethods)); - body.toString(callStack, localData.abcIndex, path + "/inner", ScriptExportMode.AS, abc, null, writer, localData.fullyQualifiedNames, new HashSet<>(localData.seenMethods)); + body.convert(localData.swfVersion, callStack, localData.abcIndex, new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, scopeStack, 0, new NulWriter(), localData.fullyQualifiedNames, null, false, new HashSet<>(localData.seenMethods)); + body.toString(localData.swfVersion, callStack, localData.abcIndex, path + "/inner", ScriptExportMode.AS, abc, null, writer, localData.fullyQualifiedNames, new HashSet<>(localData.seenMethods)); } writer.endBlock(); writer.endMethod(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NullCoalesceAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NullCoalesceAVM2Item.java new file mode 100644 index 000000000..7cc1d2d7c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NullCoalesceAVM2Item.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010-2024 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.model; + +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.model.BinaryOpItem; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class NullCoalesceAVM2Item extends BinaryOpItem { + + public NullCoalesceAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartItem, GraphTargetItem leftSide, GraphTargetItem rightSide) { + super(instruction, lineStartItem, PRECEDENCE_NULLCOALESCE, leftSide, rightSide, "??", null, null); + } + + @Override + public GraphTargetItem returnType() { + return leftSide.returnType(); + } + + @Override + public List getOperatorInstruction() { + return new ArrayList<>(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetPropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetPropertyAVM2Item.java index f7ba3f908..4eb7922b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetPropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetPropertyAVM2Item.java @@ -127,7 +127,7 @@ public class SetPropertyAVM2Item extends AVM2Item implements SetTypeAVM2Item, As @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - formatProperty(writer, object, propertyName, localData, isStatic); + formatProperty(writer, object, propertyName, localData, isStatic, false); if (compoundOperator != null) { writer.append(" "); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/TraitSlotConstAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/TraitSlotConstAVM2Item.java index 0fd06fd5a..c36bc41fd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/TraitSlotConstAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/TraitSlotConstAVM2Item.java @@ -93,6 +93,7 @@ public class TraitSlotConstAVM2Item extends AVM2Item { cd.assignedValues.put(trait, new AssignedValue(null, assignedValue, initializer, methodIndex)); boolean insideInterface = classIndex > -1 ? localData.abc.instance_info.get(classIndex).isInterface() : false; trait.toString( + localData.swfVersion, localData.abcIndex, DottedChain.EMPTY /*??*/, null, diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/DeletePropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/DeletePropertyAVM2Item.java index dfba2e330..2867aa273 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/DeletePropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/DeletePropertyAVM2Item.java @@ -98,7 +98,7 @@ public class DeletePropertyAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.append("delete "); - formatProperty(writer, object, propertyName, localData, isStatic); + formatProperty(writer, object, propertyName, localData, isStatic, false); return writer; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 665841d5e..95b39ac4f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -705,7 +705,7 @@ public class AVM2SourceGenerator implements SourceGenerator { List callStack = new ArrayList<>(); callStack.add(pcinit); try { - pcinit.convert(callStack, null, d, "-", ScriptExportMode.AS, true, mi, -1, ci.index, ci.abc, null, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, new NulWriter(), new ArrayList<>(), ci.abc.class_info.get(ci.index).static_traits, false, new HashSet<>()); + pcinit.convert(-1 /*FIXME??*/, callStack, null, d, "-", ScriptExportMode.AS, true, mi, -1, ci.index, ci.abc, null, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, new NulWriter(), new ArrayList<>(), ci.abc.class_info.get(ci.index).static_traits, false, new HashSet<>()); //FIXME! Add skinparts from _skinParts attribute of parent class!!! } catch (InterruptedException ex) { Logger.getLogger(AVM2SourceGenerator.class.getName()).log(Level.SEVERE, "Getting parent skinparts interrupted", ex); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index e3f7094b4..75ec974a7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -428,6 +428,7 @@ public final class MethodBody implements Cloneable { /** * Converts the method body. * + * @param swfVersion SWF version * @param callStack Call stack * @param abcIndex ABC indexing * @param convertData Convert data @@ -448,7 +449,7 @@ public final class MethodBody implements Cloneable { * @param seenMethods Seen methods * @throws InterruptedException On interrupt */ - public void convert(List callStack, AbcIndexing abcIndex, final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, Traits initTraits, boolean firstLevel, Set seenMethods) throws InterruptedException { + public void convert(int swfVersion, List callStack, AbcIndexing abcIndex, final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, Traits initTraits, boolean firstLevel, Set seenMethods) throws InterruptedException { seenMethods.add(this.method_info); if (debugMode) { System.err.println("Decompiling " + path); @@ -471,10 +472,10 @@ public final class MethodBody implements Cloneable { HashMap localRegNames = getLocalRegNames(abc); List convertedItems1; try (Statistics s = new Statistics("AVM2Code.toGraphTargetItems")) { - convertedItems1 = converted.getCode().toGraphTargetItems(callStack, abcIndex, convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, 0, new HashMap<>()); //converted.getCode().visitCode(converted) + convertedItems1 = converted.getCode().toGraphTargetItems(swfVersion, callStack, abcIndex, convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, 0, new HashMap<>()); //converted.getCode().visitCode(converted) } try (Statistics s = new Statistics("Graph.graphToString")) { - Graph.graphToString(convertedItems1, writer, LocalData.create(callStack, abcIndex, abc, localRegNames, fullyQualifiedNames, seenMethods, exportMode)); + Graph.graphToString(convertedItems1, writer, LocalData.create(callStack, abcIndex, abc, localRegNames, fullyQualifiedNames, seenMethods, exportMode, swfVersion)); } convertedItems = convertedItems1; } @@ -522,6 +523,7 @@ public final class MethodBody implements Cloneable { /** * Returns a string representation of this MethodBody. * + * @param swfVersion SWF version * @param callStack Call stack * @param abcIndex ABC indexing * @param path Path @@ -534,7 +536,7 @@ public final class MethodBody implements Cloneable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toString(List callStack, AbcIndexing abcIndex, final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List fullyQualifiedNames, Set seenMethods) throws InterruptedException { + public GraphTextWriter toString(int swfVersion, List callStack, AbcIndexing abcIndex, final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List fullyQualifiedNames, Set seenMethods) throws InterruptedException { seenMethods.add(method_info); if (exportMode != ScriptExportMode.AS) { @@ -565,7 +567,7 @@ public final class MethodBody implements Cloneable { fullyQualifiedNames2.remove(tname); } - Graph.graphToString(convertedItems, writer, LocalData.create(callStack, abcIndex, abc, localRegNames, fullyQualifiedNames2, seenMethods, exportMode)); + Graph.graphToString(convertedItems, writer, LocalData.create(callStack, abcIndex, abc, localRegNames, fullyQualifiedNames2, seenMethods, exportMode, swfVersion)); //writer.endMethod(); } else if (convertException instanceof TimeoutException) { // exception was logged in convert method @@ -647,20 +649,21 @@ public final class MethodBody implements Cloneable { /** * Converts the method body to high-level source code. * + * @param swfVersion SWF version * @param callStack Call stack * @param abcIndex ABC indexing * @param scriptIndex Script index * @param seenMethods Seen methods * @return High-level source code */ - public String toSource(List callStack, AbcIndexing abcIndex, int scriptIndex, Set seenMethods) { + public String toSource(int swfVersion, List callStack, AbcIndexing abcIndex, int scriptIndex, Set seenMethods) { ConvertData convertData = new ConvertData(); convertData.deobfuscationMode = 0; try { - convert(callStack, abcIndex, convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, seenMethods); + convert(swfVersion, callStack, abcIndex, convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, seenMethods); HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); writer.indent().indent().indent(); - toString(callStack, abcIndex, "", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), seenMethods); + toString(swfVersion, callStack, abcIndex, "", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), seenMethods); writer.unindent().unindent().unindent(); writer.finishHilights(); return writer.toString(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 32651b8e4..d3ac7ff56 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -712,6 +712,7 @@ public abstract class Trait implements Cloneable, Serializable { /** * To string. * + * @param swfVersion SWF version * @param abcIndex ABC indexing * @param packageName Package name * @param parent Parent trait @@ -729,7 +730,7 @@ public abstract class Trait implements Cloneable, Serializable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toString(AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { + public GraphTextWriter toString(int swfVersion, AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { writer.appendNoHilight(abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); return writer; } @@ -737,6 +738,7 @@ public abstract class Trait implements Cloneable, Serializable { /** * Converts trait. * + * @param swfVersion SWF version * @param abcIndex ABC indexing * @param parent Parent trait * @param convertData Convert data @@ -752,7 +754,7 @@ public abstract class Trait implements Cloneable, Serializable { * @param scopeStack Scope stack * @throws InterruptedException On interrupt */ - public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { + public void convert(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { } /** @@ -849,6 +851,7 @@ public abstract class Trait implements Cloneable, Serializable { /** * ToString conversion including package. * + * @param swfVersion SWF version * @param abcIndex ABC indexing * @param parent Parent trait * @param convertData Convert data @@ -865,7 +868,7 @@ public abstract class Trait implements Cloneable, Serializable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toStringPackaged(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { + public GraphTextWriter toStringPackaged(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { Multiname name = abc.constants.getMultiname(name_index); int nskind = name.getSimpleNamespaceKind(abc.constants); if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { @@ -878,7 +881,7 @@ public abstract class Trait implements Cloneable, Serializable { List traits = new ArrayList<>(); traits.add(this); writeImports(traits, -1, abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); - toString(abcIndex, name.getNameWithNamespace(abc.constants, true).getWithoutLast(), parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); + toString(swfVersion, abcIndex, name.getNameWithNamespace(abc.constants, true).getWithoutLast(), parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); writer.endBlock(); writer.newLine(); } @@ -888,6 +891,7 @@ public abstract class Trait implements Cloneable, Serializable { /** * Converts trait including package. * + * @param swfVersion * @param abcIndex ABC indexing * @param parent Parent trait * @param convertData Convert data @@ -903,18 +907,19 @@ public abstract class Trait implements Cloneable, Serializable { * @param scopeStack Scope stack * @throws InterruptedException On interrupt */ - public void convertPackaged(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { + public void convertPackaged(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { Multiname name = abc.constants.getMultiname(name_index); int nskind = name.getSimpleNamespaceKind(abc.constants); if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { String nsname = name.getSimpleNamespaceName(abc.constants).toPrintableString(true); - convert(abcIndex, parent, convertData, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, scopeStack); + convert(swfVersion, abcIndex, parent, convertData, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, scopeStack); } } /** * ToString of header. * + * @param swfVersion SWF version * @param parent Parent trait * @param packageName Package name * @param convertData Convert data @@ -931,14 +936,15 @@ public abstract class Trait implements Cloneable, Serializable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toStringHeader(Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { - toString(null, packageName, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); + public GraphTextWriter toStringHeader(int swfVersion, Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { + toString(swfVersion, null, packageName, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); return writer; } /** * Converts header. * + * @param swfVersion SWF version * @param parent Parent trait * @param convertData Convert data * @param path Path @@ -952,8 +958,8 @@ public abstract class Trait implements Cloneable, Serializable { * @param parallel Parallel * @throws InterruptedException On interrupt */ - public void convertHeader(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - convert(null, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, new ScopeStack()); + public void convertHeader(int swfVersion, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + convert(swfVersion, null, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, new ScopeStack()); } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 0ef514dc7..4bc15c7e4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -147,28 +147,13 @@ public class TraitClass extends Trait implements TraitWithSlot { } @Override - public GraphTextWriter toStringHeader(Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) { + public GraphTextWriter toStringHeader(int swfVersion, Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) { abc.instance_info.get(class_info).getClassHeaderStr(convertData.assetsDir, writer, abc, fullyQualifiedNames, false, false /*??*/); return writer; } - - /** - * Converts header. - * - * @param parent Parent trait - * @param convertData Convert data - * @param path Path - * @param abc ABC - * @param isStatic Is static - * @param exportMode Export mode - * @param scriptIndex Script index - * @param classIndex Class index - * @param writer Writer - * @param fullyQualifiedNames Fully qualified names - * @param parallel Parallel - */ + @Override - public void convertHeader(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { + public void convertHeader(int swfVersion, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } /** @@ -203,7 +188,7 @@ public class TraitClass extends Trait implements TraitWithSlot { * @throws InterruptedException On interrupt */ @Override - public GraphTextWriter toString(AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { + public GraphTextWriter toString(int swfVersion, AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { InstanceInfo instanceInfo = abc.instance_info.get(class_info); @@ -259,7 +244,7 @@ public class TraitClass extends Trait implements TraitWithSlot { //static variables & constants ClassInfo classInfo = abc.class_info.get(class_info); - classInfo.static_traits.toString(packageName, first, abcIndex, new Class[]{TraitSlotConst.class}, this, convertData, path + "/" + instanceInfoName, abc, true, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, new ArrayList<>(), isInterface); + classInfo.static_traits.toString(swfVersion, packageName, first, abcIndex, new Class[]{TraitSlotConst.class}, this, convertData, path + "/" + instanceInfoName, abc, true, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, new ArrayList<>(), isInterface); //static initializer int bodyIndex = abc.findBodyIndex(classInfo.cinit_index); @@ -275,7 +260,7 @@ public class TraitClass extends Trait implements TraitWithSlot { first.setVal(false); List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - abc.bodies.get(bodyIndex).toString(callStack, abcIndex, path + "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + abc.bodies.get(bodyIndex).toString(swfVersion, callStack, abcIndex, path + "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); //first.setVal(true); //writer.endBlock(); } else { @@ -294,7 +279,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } //instance variables - instanceInfo.instance_traits.toString(packageName, first, abcIndex, new Class[]{TraitSlotConst.class}, this, convertData, path + "/" + instanceInfoName, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, new ArrayList<>(), isInterface); + instanceInfo.instance_traits.toString(swfVersion, packageName, first, abcIndex, new Class[]{TraitSlotConst.class}, this, convertData, path + "/" + instanceInfoName, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, new ArrayList<>(), isInterface); //instance initializer - constructor if (!instanceInfo.isInterface()) { @@ -319,7 +304,7 @@ public class TraitClass extends Trait implements TraitWithSlot { if (body != null) { List callStack = new ArrayList<>(); callStack.add(body); - body.toString(callStack, abcIndex, path + "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + body.toString(swfVersion, callStack, abcIndex, path + "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); } } @@ -329,10 +314,10 @@ public class TraitClass extends Trait implements TraitWithSlot { } //static methods - classInfo.static_traits.toString(packageName, first, abcIndex, new Class[]{TraitClass.class, TraitFunction.class, TraitMethodGetterSetter.class}, this, convertData, path + "/" + instanceInfoName, abc, true, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, new ArrayList<>(), isInterface); + classInfo.static_traits.toString(swfVersion, packageName, first, abcIndex, new Class[]{TraitClass.class, TraitFunction.class, TraitMethodGetterSetter.class}, this, convertData, path + "/" + instanceInfoName, abc, true, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, new ArrayList<>(), isInterface); //instance methods - instanceInfo.instance_traits.toString(packageName, first, abcIndex, new Class[]{TraitClass.class, TraitFunction.class, TraitMethodGetterSetter.class}, this, convertData, path + "/" + instanceInfoName, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, convertData.ignoreFrameScripts ? frameTraitNames : new ArrayList<>(), isInterface); + instanceInfo.instance_traits.toString(swfVersion, packageName, first, abcIndex, new Class[]{TraitClass.class, TraitFunction.class, TraitMethodGetterSetter.class}, this, convertData, path + "/" + instanceInfoName, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, convertData.ignoreFrameScripts ? frameTraitNames : new ArrayList<>(), isInterface); if (first.getVal()) { writer.newLine(); @@ -342,27 +327,9 @@ public class TraitClass extends Trait implements TraitWithSlot { writer.newLine(); return writer; } - - /** - * Converts trait. - * - * @param abcIndex ABC indexing - * @param parent Parent trait - * @param convertData Convert data - * @param path Path - * @param abc ABC - * @param isStatic Is static - * @param exportMode Export mode - * @param scriptIndex Script index - * @param classIndex Class index - * @param writer Writer - * @param fullyQualifiedNames Fully qualified names - * @param parallel Parallel - * @param scopeStack Scope stack - * @throws InterruptedException On interrupt - */ + @Override - public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { + public void convert(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { fullyQualifiedNames = new ArrayList<>(); @@ -404,7 +371,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - abc.bodies.get(bodyIndex).convert(callStack, abcIndex, convertData, path + "/" + instanceInfoName + ".staticinitializer", exportMode, true, classInfo.cinit_index, scriptIndex, class_info, abc, this, newScopeStack, GraphTextWriter.TRAIT_CLASS_INITIALIZER, writer, fullyQualifiedNames, classInfo.static_traits, true, new HashSet<>()); + abc.bodies.get(bodyIndex).convert(swfVersion, callStack, abcIndex, convertData, path + "/" + instanceInfoName + ".staticinitializer", exportMode, true, classInfo.cinit_index, scriptIndex, class_info, abc, this, newScopeStack, GraphTextWriter.TRAIT_CLASS_INITIALIZER, writer, fullyQualifiedNames, classInfo.static_traits, true, new HashSet<>()); newScopeStack.push(new ClassAVM2Item(abc.instance_info.get(class_info).getName(abc.constants))); classInitializerIsEmpty = !writer.getMark(); @@ -417,7 +384,7 @@ public class TraitClass extends Trait implements TraitWithSlot { MethodBody constructorBody = abc.bodies.get(bodyIndex); List callStack = new ArrayList<>(); callStack.add(constructorBody); - constructorBody.convert(callStack, abcIndex, convertData, path + "/" + instanceInfoName + ".initializer", exportMode, false, instanceInfo.iinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, writer, fullyQualifiedNames, instanceInfo.instance_traits, true, new HashSet<>()); + constructorBody.convert(swfVersion, callStack, abcIndex, convertData, path + "/" + instanceInfoName + ".initializer", exportMode, false, instanceInfo.iinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, writer, fullyQualifiedNames, instanceInfo.instance_traits, true, new HashSet<>()); if (convertData.ignoreFrameScripts) { //find all addFrameScript(xx,this.method) in constructor @@ -472,9 +439,9 @@ public class TraitClass extends Trait implements TraitWithSlot { } //static variables,constants & methods - classInfo.static_traits.convert(abcIndex, this, convertData, path + "/" + instanceInfoName, abc, true, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, newScopeStack); + classInfo.static_traits.convert(swfVersion, abcIndex, this, convertData, path + "/" + instanceInfoName, abc, true, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, newScopeStack); - instanceInfo.instance_traits.convert(abcIndex, this, convertData, path + "/" + instanceInfoName, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, newScopeStack); + instanceInfo.instance_traits.convert(swfVersion, abcIndex, this, convertData, path + "/" + instanceInfoName, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, newScopeStack); } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index ec6e5bd23..84d84fd3f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -77,7 +77,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { } @Override - public GraphTextWriter toStringHeader(Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) { + public GraphTextWriter toStringHeader(int swfVersion, Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) { MethodBody body = abc.findBody(method_info); if (body == null) { writer.appendNoHilight("native "); @@ -91,24 +91,9 @@ public class TraitFunction extends Trait implements TraitWithSlot { abc.method_info.get(method_info).getReturnTypeStr(writer, abc.constants, fullyQualifiedNames); return writer; } - - /** - * Converts header. - * - * @param parent Parent trait - * @param convertData Convert data - * @param path Path - * @param abc ABC - * @param isStatic Is static - * @param exportMode Export mode - * @param scriptIndex Script index - * @param classIndex Class index - * @param writer Writer - * @param fullyQualifiedNames Fully qualified names - * @param parallel Parallel - */ + @Override - public void convertHeader(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { + public void convertHeader(int swfVersion, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } /** @@ -124,10 +109,10 @@ public class TraitFunction extends Trait implements TraitWithSlot { } @Override - public GraphTextWriter toString(AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { + public GraphTextWriter toString(int swfVersion, AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { getMetaData(this, convertData, abc, writer); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); - toStringHeader(parent, packageName, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); + toStringHeader(swfVersion, parent, packageName, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); writer.startBlock(); int bodyIndex = abc.findBodyIndex(method_info); @@ -135,7 +120,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { //writeUses(scriptIndex, classIndex, isStatic, abc, writer); List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - abc.bodies.get(bodyIndex).toString(callStack, abcIndex, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + abc.bodies.get(bodyIndex).toString(swfVersion, callStack, abcIndex, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); } writer.endBlock(); @@ -144,34 +129,17 @@ public class TraitFunction extends Trait implements TraitWithSlot { return writer; } - /** - * Converts trait. - * - * @param abcIndex ABC indexing - * @param parent Parent trait - * @param convertData Convert data - * @param path Path - * @param abc ABC - * @param isStatic Is static - * @param exportMode Export mode - * @param scriptIndex Script index - * @param classIndex Class index - * @param writer Writer - * @param fullyQualifiedNames Fully qualified names - * @param parallel Parallel - * @param scopeStack Scope stack - * @throws InterruptedException On interrupt - */ + @Override - public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { + public void convert(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { fullyQualifiedNames = new ArrayList<>(); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); - convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + convertHeader(swfVersion, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); if (bodyIndex != -1) { List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - abc.bodies.get(bodyIndex).convert(callStack, abcIndex, convertData, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, scopeStack, 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); + abc.bodies.get(bodyIndex).convert(swfVersion, callStack, abcIndex, convertData, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, scopeStack, 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); } writer.endMethod(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index 9836c06f8..b729c85d9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -69,24 +69,9 @@ public class TraitMethodGetterSetter extends Trait { abc.constants.getMultiname(name_index).deleted = d; abc.method_info.get(method_info).delete(abc, d); } - - /** - * Converts header. - * - * @param parent Parent trait - * @param convertData Convert data - * @param path Path - * @param abc ABC - * @param isStatic Is static - * @param exportMode Export mode - * @param scriptIndex Script index - * @param classIndex Class index - * @param writer Writer - * @param fullyQualifiedNames Fully qualified names - * @param parallel Parallel - */ + @Override - public void convertHeader(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { + public void convertHeader(int swfVersion, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } /** @@ -122,7 +107,7 @@ public class TraitMethodGetterSetter extends Trait { } @Override - public GraphTextWriter toStringHeader(Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) { + public GraphTextWriter toStringHeader(int swfVersion, Trait parent, DottedChain packageName, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) { String addKind = ""; if (kindType == TRAIT_GETTER) { addKind = "get "; @@ -146,38 +131,20 @@ public class TraitMethodGetterSetter extends Trait { abc.method_info.get(method_info).getReturnTypeStr(writer, abc.constants, fullyQualifiedNames); return writer; } - - /** - * Converts trait. - * - * @param abcIndex ABC indexing - * @param parent Parent trait - * @param convertData Convert data - * @param path Path - * @param abc ABC - * @param isStatic Is static - * @param exportMode Export mode - * @param scriptIndex Script index - * @param classIndex Class index - * @param writer Writer - * @param fullyQualifiedNames Fully qualified names - * @param parallel Parallel - * @param scopeStack Scope stack - * @throws InterruptedException On interrupt - */ + @Override - public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { + public void convert(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { int nsKind = getName(abc).getSimpleNamespaceKind(abc.constants); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false, true); - convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + convertHeader(swfVersion, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { if (!(classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1)) { if (bodyIndex != -1) { List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - abc.bodies.get(bodyIndex).convert(callStack, abcIndex, convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, scopeStack, 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); + abc.bodies.get(bodyIndex).convert(swfVersion, callStack, abcIndex, convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, scopeStack, 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); } } } @@ -197,11 +164,11 @@ public class TraitMethodGetterSetter extends Trait { } @Override - public GraphTextWriter toString(AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { + public GraphTextWriter toString(int swfVersion, AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { getMetaData(this, convertData, abc, writer); writer.startMethod(method_info, getName(abc).getName(abc.constants, new ArrayList<>(), true, false)); path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false, true); - toStringHeader(parent, packageName, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); + toStringHeader(swfVersion, parent, packageName, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); int bodyIndex = abc.findBodyIndex(method_info); if (classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1) { writer.appendNoHilight(";"); @@ -215,7 +182,7 @@ public class TraitMethodGetterSetter extends Trait { //writeUses(scriptIndex, classIndex, isStatic, abc, writer); List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - abc.bodies.get(bodyIndex).toString(callStack, abcIndex, path, exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + abc.bodies.get(bodyIndex).toString(swfVersion, callStack, abcIndex, path, exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); } } else { String retTypeRaw = abc.method_info.get(method_info).getReturnTypeRaw(abc.constants, fullyQualifiedNames); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index 719fb2de6..d08349dcf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -164,6 +164,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { /** * Gets value as string. * + * @param swfVersion SWF version * @param abcIndex ABC indexing * @param exportMode Export mode * @param convertData Convert data @@ -172,7 +173,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { * @param fullyQualifiedNames Fully qualified names * @throws InterruptedException On interrupt */ - public void getValueStr(AbcIndexing abcIndex, ScriptExportMode exportMode, ConvertData convertData, GraphTextWriter writer, ABC abc, List fullyQualifiedNames) throws InterruptedException { + public void getValueStr(int swfVersion, AbcIndexing abcIndex, ScriptExportMode exportMode, ConvertData convertData, GraphTextWriter writer, ABC abc, List fullyQualifiedNames) throws InterruptedException { if (convertData.assignedValues.containsKey(this)) { AssignedValue assignment = convertData.assignedValues.get(this); @@ -188,7 +189,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(abc.findBodyIndex(assignment.method))); - assignment.value.toString(writer, LocalData.create(callStack, abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>(), exportMode)); + assignment.value.toString(writer, LocalData.create(callStack, abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>(), exportMode, swfVersion)); } writer.endMethod(); writer.endTrait(); @@ -231,7 +232,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { } @Override - public GraphTextWriter toString(AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { + public GraphTextWriter toString(int swfVersion, AbcIndexing abcIndex, DottedChain packageName, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { getMetaData(this, convertData, abc, writer); Multiname n = getName(abc); boolean showModifier = true; @@ -252,40 +253,22 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { List callStack = new ArrayList<>(); AssignedValue assignment = convertData.assignedValues.get(this); callStack.add(abc.bodies.get(abc.findBodyIndex(assignment.method))); - return val.toString(writer, LocalData.create(callStack, abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>(), exportMode)); + return val.toString(writer, LocalData.create(callStack, abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>(), exportMode, swfVersion)); } } getNameStr(writer, abc, fullyQualifiedNames); if (hasValueStr(abc, convertData)) { writer.appendNoHilight(" = "); - getValueStr(abcIndex, exportMode, convertData, writer, abc, fullyQualifiedNames); + getValueStr(swfVersion, abcIndex, exportMode, convertData, writer, abc, fullyQualifiedNames); } return writer.appendNoHilight(";").newLine(); } - /** - * Converts trait. - * - * @param abcIndex ABC indexing - * @param parent Parent trait - * @param convertData Convert data - * @param path Path - * @param abc ABC - * @param isStatic Is static - * @param exportMode Export mode - * @param scriptIndex Script index - * @param classIndex Class index - * @param writer Writer - * @param fullyQualifiedNames Fully qualified names - * @param parallel Parallel - * @param scopeStack Scope stack - * @throws InterruptedException On interrupt - */ @Override - public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { + public void convert(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { getNameStr(writer, abc, fullyQualifiedNames); if (hasValueStr(abc, convertData)) { - getValueStr(abcIndex, exportMode, convertData, writer, abc, fullyQualifiedNames); + getValueStr(swfVersion, abcIndex, exportMode, convertData, writer, abc, fullyQualifiedNames); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index a532d63a8..24eb223f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -218,6 +218,7 @@ public class Traits implements Cloneable, Serializable { * Convert data */ ConvertData convertData; + private final int swfVersion; /** * ABC indexing @@ -232,6 +233,7 @@ public class Traits implements Cloneable, Serializable { /** * Constructs a new TraitConvertTask object. * + * @param swfVersion SWF version * @param abcIndex ABC indexing * @param trait Trait * @param parent Parent trait @@ -249,7 +251,7 @@ public class Traits implements Cloneable, Serializable { * @param parallel Parallel flag * @param scopeStack Scope stack */ - public TraitConvertTask(AbcIndexing abcIndex, Trait trait, Trait parent, ConvertData convertData, boolean makePackages, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, int traitIndex, boolean parallel, ScopeStack scopeStack) { + public TraitConvertTask(int swfVersion, AbcIndexing abcIndex, Trait trait, Trait parent, ConvertData convertData, boolean makePackages, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, int traitIndex, boolean parallel, ScopeStack scopeStack) { this.trait = trait; this.parent = parent; this.convertData = convertData; @@ -264,6 +266,7 @@ public class Traits implements Cloneable, Serializable { this.fullyQualifiedNames = fullyQualifiedNames; this.traitIndex = traitIndex; this.parallel = parallel; + this.swfVersion = swfVersion; this.abcIndex = abcIndex; this.scopeStack = scopeStack; } @@ -277,9 +280,9 @@ public class Traits implements Cloneable, Serializable { @Override public Void call() throws InterruptedException { if (makePackages) { - trait.convertPackaged(abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, scopeStack); + trait.convertPackaged(swfVersion, abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, scopeStack); } else { - trait.convert(abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, scopeStack); + trait.convert(swfVersion, abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, scopeStack); } return null; } @@ -288,6 +291,7 @@ public class Traits implements Cloneable, Serializable { /** * To string. * + * @param swfVersion SWF version * @param packageName Package name * @param first Whether to add newline * @param abcIndex ABC indexing @@ -309,7 +313,7 @@ public class Traits implements Cloneable, Serializable { * @return Writer * @throws InterruptedException On interrupt */ - public GraphTextWriter toString(DottedChain packageName, Reference first, AbcIndexing abcIndex, Class[] traitTypes, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, List ignoredTraitNames, boolean insideInterface) throws InterruptedException { + public GraphTextWriter toString(int swfVersion, DottedChain packageName, Reference first, AbcIndexing abcIndex, Class[] traitTypes, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, List ignoredTraitNames, boolean insideInterface) throws InterruptedException { List ordered = traits; for (Trait trait : ordered) { @@ -344,9 +348,9 @@ public class Traits implements Cloneable, Serializable { int h = abc.getGlobalTraitId(TraitType.METHOD , isStatic, classIndex, t); writer.startTrait(h); if (makePackages) { - trait.toStringPackaged(abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); + trait.toStringPackaged(swfVersion, abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); } else { - trait.toString(abcIndex, packageName, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); + trait.toString(swfVersion, abcIndex, packageName, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface); } writer.endTrait(); } @@ -356,6 +360,7 @@ public class Traits implements Cloneable, Serializable { /** * Converts traits. * + * @param swfVersion SWF version * @param abcIndex ABC indexing * @param parent Parent trait * @param convertData Convert data @@ -372,10 +377,10 @@ public class Traits implements Cloneable, Serializable { * @param scopeStack Scope stack * @throws InterruptedException On interrupt */ - public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { + public void convert(int swfVersion, AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { if (!parallel || traits.size() < 2) { for (int t = 0; t < traits.size(); t++) { - TraitConvertTask task = new TraitConvertTask(abcIndex, traits.get(t), parent, convertData, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, t, parallel, scopeStack); + TraitConvertTask task = new TraitConvertTask(swfVersion, abcIndex, traits.get(t), parent, convertData, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, t, parallel, scopeStack); task.call(); } } else { @@ -385,7 +390,7 @@ public class Traits implements Cloneable, Serializable { futureResults = new ArrayList<>(); for (int t = 0; t < traits.size(); t++) { // each convert task needs a separate NulWriter, because they are executed parallel - TraitConvertTask task = new TraitConvertTask(abcIndex, traits.get(t), parent, convertData, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, new NulWriter(), fullyQualifiedNames, t, parallel, scopeStack); + TraitConvertTask task = new TraitConvertTask(swfVersion, abcIndex, traits.get(t), parent, convertData, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, new NulWriter(), fullyQualifiedNames, t, parallel, scopeStack); Future future = executor.submit(task); futureResults.add(future); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/ConstVarMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/ConstVarMultinameUsage.java index 10ff35c50..4886028df 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/ConstVarMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/ConstVarMultinameUsage.java @@ -56,13 +56,13 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage { ConvertData convertData = new ConvertData(); if (parentTraitIndex > -1) { if (traitsType == TRAITS_TYPE_CLASS) { - ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).convertHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); + ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).convertHeader(-1, null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); } else if (traitsType == TRAITS_TYPE_INSTANCE) { - ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).convertHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); + ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).convertHeader(-1, null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); } } try { - ((TraitSlotConst) traits.traits.get(traitIndex)).convertHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS /*?? FIXME*/, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); + ((TraitSlotConst) traits.traits.get(traitIndex)).convertHeader(-1, null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS /*?? FIXME*/, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); } catch (InterruptedException ex) { // ignore } @@ -76,13 +76,13 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage { if (parentTraitIndex > -1) { if (traitsType == TRAITS_TYPE_CLASS) { - ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).toStringHeader(null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); + ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).toStringHeader(-1, null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); } else if (traitsType == TRAITS_TYPE_INSTANCE) { - ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).toStringHeader(null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); + ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).toStringHeader(-1, null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); } } try { - ((TraitSlotConst) traits.traits.get(traitIndex)).toStringHeader(null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); + ((TraitSlotConst) traits.traits.get(traitIndex)).toStringHeader(-1, null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); } catch (InterruptedException ex) { // ignore } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/MethodMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/MethodMultinameUsage.java index 3dd98b9ff..3992d24c5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/MethodMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/MethodMultinameUsage.java @@ -68,12 +68,12 @@ public abstract class MethodMultinameUsage extends TraitMultinameUsage { if (!isInitializer) { if (parentTraitIndex > -1) { if (traitsType == TRAITS_TYPE_CLASS) { - ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).convertHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); + ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).convertHeader(-1, null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); } else { - ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).convertHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); + ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).convertHeader(-1, null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); } } - ((TraitMethodGetterSetter) traits.traits.get(traitIndex)).convertHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); + ((TraitMethodGetterSetter) traits.traits.get(traitIndex)).convertHeader(-1, null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, nulWriter, new ArrayList<>(), false); } HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); @@ -100,13 +100,13 @@ public abstract class MethodMultinameUsage extends TraitMultinameUsage { } if (parentTraitIndex > -1) { if (traitsType == TRAITS_TYPE_CLASS) { - ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).toStringHeader(null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); + ((TraitMethodGetterSetter) abc.class_info.get(classIndex).static_traits.traits.get(parentTraitIndex)).toStringHeader(-1, null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); } else { - ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).toStringHeader(null, DottedChain.EMPTY /*??*/,convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); + ((TraitMethodGetterSetter) abc.instance_info.get(classIndex).instance_traits.traits.get(parentTraitIndex)).toStringHeader(-1, null, DottedChain.EMPTY /*??*/,convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); } writer.appendNoHilight(" "); } - ((TraitMethodGetterSetter) traits.traits.get(traitIndex)).toStringHeader(null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); + ((TraitMethodGetterSetter) traits.traits.get(traitIndex)).toStringHeader(-1, null, DottedChain.EMPTY /*??*/, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); } writer.finishHilights(); return writer.toString().trim(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java index 6d728bcc4..28a232074 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java @@ -135,13 +135,13 @@ public class AS3ScriptExporter { } - private String handleMxmlMethod(AbcIndexing abcIndex, Map namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) { + private String handleMxmlMethod(int swfVersion, AbcIndexing abcIndex, Map namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) { StringBuilder out = new StringBuilder(); int method = t.method_info; try { List callStack = new ArrayList<>(); callStack.add(pack.abc.findBody(method)); - pack.abc.findBody(method).convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + pack.abc.findBody(method).convert(swfVersion, callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); List ci = pack.abc.findBody(method).convertedItems; if (!ci.isEmpty()) { @@ -170,7 +170,7 @@ public class AS3ScriptExporter { int name2 = ((FullMultinameAVM2Item) cap.propertyName).multinameIndex; for (Trait ct : pack.abc.instance_info.get(cindex).instance_traits.traits) { if (ct.name_index == name2 && (ct instanceof TraitMethodGetterSetter)) { - tagContent.append(handleMxmlMethod(abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); + tagContent.append(handleMxmlMethod(swfVersion, abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); } } } @@ -210,13 +210,13 @@ public class AS3ScriptExporter { return out.toString(); } - private String handleMxmlArrMethod(AbcIndexing abcIndex, Map namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) { + private String handleMxmlArrMethod(int swfVersion, AbcIndexing abcIndex, Map namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) { StringBuilder out = new StringBuilder(); int method = t.method_info; try { List callStack = new ArrayList<>(); callStack.add(pack.abc.findBody(method)); - pack.abc.findBody(method).convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()/*??*/); + pack.abc.findBody(method).convert(swfVersion, callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()/*??*/); List ci = pack.abc.findBody(method).convertedItems; if (!ci.isEmpty() && (ci.get(0) instanceof DeclarationAVM2Item)) { @@ -232,7 +232,7 @@ public class AS3ScriptExporter { int name = ((FullMultinameAVM2Item) cp.propertyName).multinameIndex; for (Trait ct : pack.abc.instance_info.get(cindex).instance_traits.traits) { if (ct.name_index == name && (ct instanceof TraitMethodGetterSetter)) { - out.append(handleMxmlMethod(abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); + out.append(handleMxmlMethod(swfVersion, abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); } } } @@ -285,7 +285,7 @@ public class AS3ScriptExporter { return ns + ":" + parentName; } - private String generateMxml(AbcIndexing abcIndex, ScriptPack pack) { + private String generateMxml(int swfVersion, AbcIndexing abcIndex, ScriptPack pack) { StringBuilder out = new StringBuilder(); StringBuilder tagProp = new StringBuilder(); StringBuilder tagContent = new StringBuilder(); @@ -309,7 +309,7 @@ public class AS3ScriptExporter { try { List callStack = new ArrayList<>(); callStack.add(pack.abc.findBody(iinit)); - pack.abc.findBody(iinit).convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, iinit, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + pack.abc.findBody(iinit).convert(swfVersion, callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, iinit, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); List iinitBody = pack.abc.findBody(iinit).convertedItems; for (GraphTargetItem it : iinitBody) { if (it instanceof InitPropertyAVM2Item) { @@ -325,7 +325,7 @@ public class AS3ScriptExporter { int name = ((FullMultinameAVM2Item) cp.propertyName).multinameIndex; for (Trait ct : pack.abc.instance_info.get(cindex).instance_traits.traits) { if (ct.name_index == name && (ct instanceof TraitMethodGetterSetter)) { - tagContent.append(handleMxmlMethod(abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); + tagContent.append(handleMxmlMethod(swfVersion, abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); } } tagContent.append(""); @@ -343,7 +343,7 @@ public class AS3ScriptExporter { int name = ((FullMultinameAVM2Item) gp.propertyName).multinameIndex; for (Trait ct : pack.abc.instance_info.get(cindex).instance_traits.traits) { if (ct.name_index == name && (ct instanceof TraitMethodGetterSetter)) { - tagContent.append(handleMxmlArrMethod(abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); + tagContent.append(handleMxmlArrMethod(swfVersion, abcIndex, namespaces, pack, cindex, (TraitMethodGetterSetter) ct)); } } } @@ -471,7 +471,7 @@ public class AS3ScriptExporter { if (flexClass != null && item.getClassPath().toRawString().equals(flexClass)) { File file = item.getExportFile(outdir, ".mxml"); String filePath = file.getPath(); - String mxml = generateMxml(swf.getAbcIndex(), item); + String mxml = generateMxml(swf.version, swf.getAbcIndex(), item); if (mxml != null) { Helper.writeFile(filePath, Utf8Helper.getBytes(mxml)); files.add(filePath.toLowerCase()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java index 19bba73a5..2a2e21e39 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java @@ -101,7 +101,7 @@ public class PcodeGraphVizExporter { * @throws InterruptedException On interrupt */ public void exportAs3(AbcIndexing abcIndex, ABC abc, MethodBody body, GraphTextWriter writer) throws InterruptedException { - AVM2Graph gr = new AVM2Graph(abcIndex, body.getCode(), abc, body, false, -1, -1, new HashMap<>(), new ScopeStack(), new ScopeStack(), new HashMap<>(), new ArrayList<>(), new HashMap<>()); // body.getCode().visitCode(body)); + AVM2Graph gr = new AVM2Graph(-1, abcIndex, body.getCode(), abc, body, false, -1, -1, new HashMap<>(), new ScopeStack(), new ScopeStack(), new HashMap<>(), new ArrayList<>(), new HashMap<>()); // body.getCode().visitCode(body)); export(gr, writer); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 60511a3ea..54071fc8f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -2813,6 +2813,11 @@ public class XFLConverter { } private static Map getFrameScriptsFromPack(AbcIndexing abcIndex, ScriptPack pack) { + + int swfVersion = -1; + if (pack.getOpenable() instanceof SWF) { + swfVersion = ((SWF) pack.getOpenable()).version; + } Map ret = new HashMap<>(); int classIndex = getPackMainClassId(pack); if (classIndex > -1) { @@ -2823,7 +2828,7 @@ public class XFLConverter { try { List callStack = new ArrayList<>(); callStack.add(constructorBody); - constructorBody.convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + constructorBody.convert(swfVersion, callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); Map frameToTraitName = new HashMap<>(); @@ -2889,10 +2894,11 @@ public class XFLConverter { StringBuilder scriptBuilder = new StringBuilder(); callStack = new ArrayList<>(); - callStack.add(frameBody); - frameBody.convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, methodIndex, pack.scriptIndex, classIndex, abc, methodTrait, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + callStack.add(frameBody); + + frameBody.convert(swfVersion, callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, methodIndex, pack.scriptIndex, classIndex, abc, methodTrait, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); StringBuilderTextWriter writer = new StringBuilderTextWriter(Configuration.getCodeFormatting(), scriptBuilder); - frameBody.toString(callStack, abcIndex, "??", ScriptExportMode.AS, abc, methodTrait, writer, new ArrayList<>(), new HashSet<>()); + frameBody.toString(swfVersion, callStack, abcIndex, "??", ScriptExportMode.AS, abc, methodTrait, writer, new ArrayList<>(), new HashSet<>()); String script = scriptBuilder.toString(); ret.put(frame, script); 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 9d2096410..63cca1569 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -3352,7 +3352,8 @@ public class Graph { } else { ternarOnFalse = filteredOnFalse.get(0).value; } - stack.push(new TernarOpItem(null, localData.lineStartInstruction, expr.invert(null), ternarOnTrue, ternarOnFalse)); + TernarOpItem top = new TernarOpItem(null, localData.lineStartInstruction, expr.invert(null), ternarOnTrue, ternarOnFalse); + stack.push(handleTernar(top, localData)); } else { boolean isIf = true; //If the ontrue is empty, switch ontrue and onfalse @@ -4292,4 +4293,14 @@ public class Graph { protected boolean partIsSwitch(GraphPart part) { return false; } + + /** + * Replaces ternar with custom value + * @param ternar Ternar + * @param localData Local data + * @return Custom item + */ + protected GraphTargetItem handleTernar(TernarOpItem ternar, BaseLocalData localData) { + return ternar; + } } 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 a9ef460af..2cee054f7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -87,13 +87,15 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { public static final int PRECEDENCE_LOGICALOR = 12; - public static final int PRECEDENCE_CONDITIONAL = 13; + public static final int PRECEDENCE_NULLCOALESCE = 13; + + public static final int PRECEDENCE_CONDITIONAL = 14; - public static final int PRECEDENCE_ASSIGNMENT = 14; + public static final int PRECEDENCE_ASSIGNMENT = 15; - public static final int PRECEDENCE_COMMA = 15; + public static final int PRECEDENCE_COMMA = 16; - public static final int NOPRECEDENCE = 16; + public static final int NOPRECEDENCE = 17; /** * Source item diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java index 955000cd4..d934545bb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java @@ -85,6 +85,11 @@ public class LocalData { */ public ScriptExportMode exportMode; + /** + * SWF version + */ + public int swfVersion; + /** * Creates a new local data * @@ -105,10 +110,11 @@ public class LocalData { * @param localRegNames Local register names * @param fullyQualifiedNames Fully qualified names * @param seenMethods Seen methods - * @param exportMode + * @param exportMode Export mode + * @param swfVersion SWF version * @return Local data */ - public static LocalData create(List callStack, AbcIndexing abcIndex, ABC abc, HashMap localRegNames, List fullyQualifiedNames, Set seenMethods, ScriptExportMode exportMode) { + public static LocalData create(List callStack, AbcIndexing abcIndex, ABC abc, HashMap localRegNames, List fullyQualifiedNames, Set seenMethods, ScriptExportMode exportMode, int swfVersion) { LocalData localData = new LocalData(); localData.abc = abc; localData.constantsAvm2 = abc.constants; @@ -118,6 +124,7 @@ public class LocalData { localData.abcIndex = abcIndex; localData.callStack = callStack; localData.exportMode = exportMode; + localData.swfVersion = swfVersion; return localData; } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java index b5f7fd59c..fbbbfde1c 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java @@ -107,9 +107,9 @@ public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBas List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - abc.bodies.get(bodyIndex).convert(callStack, swf.getAbcIndex(), new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(clsIndex).instance_traits, true, new HashSet<>()); + abc.bodies.get(bodyIndex).convert(swf.version, callStack, swf.getAbcIndex(), new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(clsIndex).instance_traits, true, new HashSet<>()); writer = new HighlightedTextWriter(new CodeFormatting(), false); - abc.bodies.get(bodyIndex).toString(callStack, swf.getAbcIndex(), "run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), new HashSet<>()); + abc.bodies.get(bodyIndex).toString(swf.version, callStack, swf.getAbcIndex(), "run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), new HashSet<>()); } catch (InterruptedException ex) { fail(); return; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java index 0dffc827a..0cf73f548 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java @@ -159,8 +159,8 @@ public class AS3Generator { List callStack = new ArrayList<>(); callStack.add(b); - b.convert(callStack, swf.getAbcIndex(), new ConvertData(), "", ScriptExportMode.AS, false, ((TraitMethodGetterSetter) t).method_info, pack.scriptIndex, classId, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(classId).instance_traits, true, new HashSet<>()); - b.toString(callStack, swf.getAbcIndex(), "", ScriptExportMode.AS, abc, null, src, new ArrayList<>(), new HashSet<>()); + b.convert(swf.version, callStack, swf.getAbcIndex(), new ConvertData(), "", ScriptExportMode.AS, false, ((TraitMethodGetterSetter) t).method_info, pack.scriptIndex, classId, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(classId).instance_traits, true, new HashSet<>()); + b.toString(swf.version, callStack, swf.getAbcIndex(), "", ScriptExportMode.AS, abc, null, src, new ArrayList<>(), new HashSet<>()); src.finishHilights(); String[] srcs = src.toString().split("[\r\n]+"); for (int i = 0; i < srcs.length; i++) { diff --git a/libsrc/ffdec_lib/testdata/as3_harman/bin/harman.swf b/libsrc/ffdec_lib/testdata/as3_harman/bin/harman.swf index a5e868807..a88da8fee 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_harman/bin/harman.swf and b/libsrc/ffdec_lib/testdata/as3_harman/bin/harman.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_harman/bin/harman_encrypted.swf b/libsrc/ffdec_lib/testdata/as3_harman/bin/harman_encrypted.swf index 67d2580bc..82f5b563b 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_harman/bin/harman_encrypted.swf and b/libsrc/ffdec_lib/testdata/as3_harman/bin/harman_encrypted.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_harman/src/Main.as b/libsrc/ffdec_lib/testdata/as3_harman/src/Main.as index f9f7a0a8b..545dce930 100644 --- a/libsrc/ffdec_lib/testdata/as3_harman/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_harman/src/Main.as @@ -11,7 +11,9 @@ package import flash.system.ApplicationDomain; public class Main extends Sprite - { + { + + Operators; private var swfLoader: Loader; diff --git a/libsrc/ffdec_lib/testdata/as3_harman/src/Operators.as b/libsrc/ffdec_lib/testdata/as3_harman/src/Operators.as new file mode 100644 index 000000000..57330f7e4 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_harman/src/Operators.as @@ -0,0 +1,20 @@ +package +{ + public class Operators + { + private var a:Object = {x:1, y:2}; + private var b:String = null; + + public function testNullMember() : void { + var result:*; + + result = a?.z; + } + + public function testNullCoalesce() :void { + var result:String; + + result = b ?? "empty"; + } + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java index 43ec77936..de17a03b5 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java @@ -267,7 +267,7 @@ public class ASMSourceEditorPane extends DebuggableEditorPane implements CaretLi public void graph() { try { - AVM2Graph gr = new AVM2Graph(null /*?*/, abc.bodies.get(bodyIndex).getCode(), abc, abc.bodies.get(bodyIndex), false, -1, -1, new HashMap<>(), new ScopeStack(), new ScopeStack(), new HashMap<>(), new ArrayList<>(), new HashMap<>()); //, abc.bodies.get(bodyIndex).getCode().visitCode(abc.bodies.get(bodyIndex))); + AVM2Graph gr = new AVM2Graph(-1, null /*?*/, abc.bodies.get(bodyIndex).getCode(), abc, abc.bodies.get(bodyIndex), false, -1, -1, new HashMap<>(), new ScopeStack(), new ScopeStack(), new HashMap<>(), new ArrayList<>(), new HashMap<>()); //, abc.bodies.get(bodyIndex).getCode().visitCode(abc.bodies.get(bodyIndex))); (new GraphDialog(getAbcPanel().getMainPanel().getMainFrame().getWindow(), gr, name)).setVisible(true); } catch (InterruptedException ex) { Logger.getLogger(ASMSourceEditorPane.class.getName()).log(Level.SEVERE, null, ex); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java b/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java index f0e4e38c9..065df7541 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java @@ -105,13 +105,13 @@ public class TraitsListItem { return ""; } Trait trait = traits.get(index); - trait.convertHeader(null, convertData, "", abc, true, ScriptExportMode.AS, scriptIndex, classIndex, new NulWriter(), new ArrayList<>(), false); + trait.convertHeader(-1, null, convertData, "", abc, true, ScriptExportMode.AS, scriptIndex, classIndex, new NulWriter(), new ArrayList<>(), false); HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); boolean insideInterface = false; if (classIndex > -1) { insideInterface = abc.instance_info.get(classIndex).isInterface(); } - trait.toStringHeader(null, DottedChain.EMPTY /*??*/, convertData, "", abc, true, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<>(), false, insideInterface); + trait.toStringHeader(-1, null, DottedChain.EMPTY /*??*/, convertData, "", abc, true, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<>(), false, insideInterface); writer.finishHilights(); s = writer.toString(); } else { @@ -121,13 +121,13 @@ public class TraitsListItem { return ""; } Trait trait = traits.get(index); - trait.convertHeader(null, convertData, "", abc, false, ScriptExportMode.AS, scriptIndex, classIndex, new NulWriter(), new ArrayList<>(), false); + trait.convertHeader(-1, null, convertData, "", abc, false, ScriptExportMode.AS, scriptIndex, classIndex, new NulWriter(), new ArrayList<>(), false); HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); boolean insideInterface = false; if (classIndex > -1) { insideInterface = abc.instance_info.get(classIndex).isInterface(); } - trait.toStringHeader(null, DottedChain.EMPTY /*??*/, convertData, "", abc, false, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<>(), false, insideInterface); + trait.toStringHeader(-1, null, DottedChain.EMPTY /*??*/, convertData, "", abc, false, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<>(), false, insideInterface); writer.finishHilights(); s = writer.toString(); }