Harman air - Null coalesce and nullish member access operators - WIP

This commit is contained in:
Jindra Petřík
2024-11-20 17:05:37 +01:00
parent 26cfb56291
commit f73f2669c0
45 changed files with 341 additions and 273 deletions
@@ -43,6 +43,11 @@ public abstract class BaseLocalData {
* Second pass data
*/
public SecondPassData secondPassData = null;
/**
* SWF version
*/
public int swfVersion = -1;
/**
* Constructor.
@@ -5916,7 +5916,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
try {
List<MethodBody> 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<GraphTargetItem> 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<GraphTargetItem> cinitBody = p.abc.findBody(cinit).convertedItems;
for (GraphTargetItem cit : cinitBody) {
if (cit instanceof SetPropertyAVM2Item) {
@@ -296,6 +296,7 @@ public class AVM2LocalData extends BaseLocalData {
finallyKinds = localData.finallyKinds;
seenMethods = localData.seenMethods;
bottomSetLocals = localData.bottomSetLocals;
swfVersion = localData.swfVersion;
}
/**
@@ -257,6 +257,11 @@ public class ScriptPack extends AS3ClassTreeItem {
*/
public void convert(AbcIndexing abcIndex, final NulWriter writer, final List<Trait> 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<MethodBody> 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<Trait> 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
@@ -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<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssignmentIps, LinkedIdentityHashSet<SetLocalAVM2Item> bottomStackSetLocals) throws ConvertException, InterruptedException {
public ConvertOutput toSourceOutput(int swfVersion, Set<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssignmentIps, LinkedIdentityHashSet<SetLocalAVM2Item> 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<GraphTargetItem> toGraphTargetItems(List<MethodBody> callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap<Integer, String> localRegNames, ScopeStack scopeStack, int initializerType, List<DottedChain> fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap<Integer, Integer> localRegAssignmentIps) throws InterruptedException {
public List<GraphTargetItem> toGraphTargetItems(int swfVersion, List<MethodBody> callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap<Integer, String> localRegNames, ScopeStack scopeStack, int initializerType, List<DottedChain> fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap<Integer, Integer> localRegAssignmentIps) throws InterruptedException {
initToSource();
List<GraphTargetItem> list;
HashMap<Integer, GraphTargetItem> 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:
@@ -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;
@@ -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<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, ScopeStack localScopeStack, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, HashMap<Integer, Integer> localRegAssignmentIps) {
public AVM2Graph(int swfVersion, AbcIndexing abcIndex, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, ScopeStack localScopeStack, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, HashMap<Integer, Integer> 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<GraphTargetItem> translateViaGraph(SecondPassData secondPassData, List<MethodBody> callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssignmentIps, boolean thisHasDefaultToPrimitive) throws InterruptedException {
public static List<GraphTargetItem> translateViaGraph(int swfVersion, SecondPassData secondPassData, List<MethodBody> callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> 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<GraphPart> 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;
}
}
@@ -203,7 +203,7 @@ public class AVM2GraphSource extends GraphSource {
public List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
List<GraphTargetItem> ret = new ArrayList<>();
Reference<GraphSourceItem> 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;
@@ -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<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, AVM2Code code, boolean thisHasDefaultToPrimitive, LinkedIdentityHashSet<SetLocalAVM2Item> bottomSetLocals) throws InterruptedException {
public void translate(int swfVersion, Set<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, AVM2Code code, boolean thisHasDefaultToPrimitive, LinkedIdentityHashSet<SetLocalAVM2Item> 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);
}
@@ -49,7 +49,7 @@ public class NewClassIns extends InstructionDefinition {
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> 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;
@@ -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 {
@@ -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++) {
@@ -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++) {
@@ -151,13 +151,13 @@ public class FullMultinameAVM2Item extends AVM2Item {
public boolean isTopLevel(String tname, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, Set<Integer> 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)) {
@@ -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
@@ -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(" ");
@@ -130,8 +130,8 @@ public class NewFunctionAVM2Item extends AVM2Item {
if (body != null) {
List<MethodBody> 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();
@@ -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<GraphSourceItem> getOperatorInstruction() {
return new ArrayList<>();
}
}
@@ -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(" ");
@@ -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,
@@ -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;
}
@@ -705,7 +705,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
List<MethodBody> 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);
@@ -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<MethodBody> 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<DottedChain> fullyQualifiedNames, Traits initTraits, boolean firstLevel, Set<Integer> seenMethods) throws InterruptedException {
public void convert(int swfVersion, List<MethodBody> 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<DottedChain> fullyQualifiedNames, Traits initTraits, boolean firstLevel, Set<Integer> 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<Integer, String> localRegNames = getLocalRegNames(abc);
List<GraphTargetItem> 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<MethodBody> callStack, AbcIndexing abcIndex, final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List<DottedChain> fullyQualifiedNames, Set<Integer> seenMethods) throws InterruptedException {
public GraphTextWriter toString(int swfVersion, List<MethodBody> callStack, AbcIndexing abcIndex, final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List<DottedChain> fullyQualifiedNames, Set<Integer> 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<MethodBody> callStack, AbcIndexing abcIndex, int scriptIndex, Set<Integer> seenMethods) {
public String toSource(int swfVersion, List<MethodBody> callStack, AbcIndexing abcIndex, int scriptIndex, Set<Integer> 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();
@@ -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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<Trait> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> fullyQualifiedNames, boolean parallel) throws InterruptedException {
convert(swfVersion, null, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, new ScopeStack());
}
/**
@@ -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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<MethodBody> 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<MethodBody> 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<DottedChain> 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<DottedChain> 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<MethodBody> 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);
}
/**
@@ -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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<MethodBody> 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<DottedChain> 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<DottedChain> 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<MethodBody> 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();
}
@@ -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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<DottedChain> 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<MethodBody> 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<DottedChain> 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<DottedChain> 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<MethodBody> 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);
@@ -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<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getValueStr(int swfVersion, AbcIndexing abcIndex, ScriptExportMode exportMode, ConvertData convertData, GraphTextWriter writer, ABC abc, List<DottedChain> 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<MethodBody> 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<DottedChain> 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<DottedChain> 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<MethodBody> 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<DottedChain> 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<DottedChain> 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);
}
}
@@ -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<DottedChain> 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<DottedChain> 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<Boolean> 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<DottedChain> fullyQualifiedNames, boolean parallel, List<String> ignoredTraitNames, boolean insideInterface) throws InterruptedException {
public GraphTextWriter toString(int swfVersion, DottedChain packageName, Reference<Boolean> 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<DottedChain> fullyQualifiedNames, boolean parallel, List<String> ignoredTraitNames, boolean insideInterface) throws InterruptedException {
List<Trait> 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<DottedChain> 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<DottedChain> 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<Void> future = executor.submit(task);
futureResults.add(future);
}
@@ -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
}
@@ -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();
@@ -135,13 +135,13 @@ public class AS3ScriptExporter {
}
private String handleMxmlMethod(AbcIndexing abcIndex, Map<String, String> namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) {
private String handleMxmlMethod(int swfVersion, AbcIndexing abcIndex, Map<String, String> namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) {
StringBuilder out = new StringBuilder();
int method = t.method_info;
try {
List<MethodBody> 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<GraphTargetItem> 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<String, String> namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) {
private String handleMxmlArrMethod(int swfVersion, AbcIndexing abcIndex, Map<String, String> namespaces, ScriptPack pack, int cindex, TraitMethodGetterSetter t) {
StringBuilder out = new StringBuilder();
int method = t.method_info;
try {
List<MethodBody> 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<GraphTargetItem> 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<MethodBody> 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<GraphTargetItem> 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("</").append(subtagName).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());
@@ -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);
}
@@ -2813,6 +2813,11 @@ public class XFLConverter {
}
private static Map<Integer, String> getFrameScriptsFromPack(AbcIndexing abcIndex, ScriptPack pack) {
int swfVersion = -1;
if (pack.getOpenable() instanceof SWF) {
swfVersion = ((SWF) pack.getOpenable()).version;
}
Map<Integer, String> ret = new HashMap<>();
int classIndex = getPackMainClassId(pack);
if (classIndex > -1) {
@@ -2823,7 +2828,7 @@ public class XFLConverter {
try {
List<MethodBody> 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<Integer, String> 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);
@@ -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;
}
}
@@ -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
@@ -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<MethodBody> callStack, AbcIndexing abcIndex, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, Set<Integer> seenMethods, ScriptExportMode exportMode) {
public static LocalData create(List<MethodBody> callStack, AbcIndexing abcIndex, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, Set<Integer> 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;
}
}