diff --git a/CHANGELOG.md b/CHANGELOG.md index be7fc7de6..fb29d3ffc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - [#2430] AS1/2/3 - Missing syntax hilighting of "new" keyword and few others - [#2428] Charset setting on FLA export in format MX and below - [#2428] Default charset for SWFS v5 and lower is WINDOWS-1252 +- [#2418] AS3 - initialization of class static vars in script initializer (Haxe) ## [22.0.2] - 2025-01-17 ### Added @@ -3707,6 +3708,7 @@ Major version of SWF to XML export changed to 2. [#2437]: https://www.free-decompiler.com/flash/issues/2437 [#2430]: https://www.free-decompiler.com/flash/issues/2430 [#2428]: https://www.free-decompiler.com/flash/issues/2428 +[#2418]: https://www.free-decompiler.com/flash/issues/2418 [#2375]: https://www.free-decompiler.com/flash/issues/2375 [#2374]: https://www.free-decompiler.com/flash/issues/2374 [#2389]: https://www.free-decompiler.com/flash/issues/2389 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 408043589..c8a180979 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -5921,7 +5921,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { 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<>()); + 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<>(), new ArrayList<>()); List infos = documentPack.abc.findBody(mi).convertedItems; if (!infos.isEmpty()) { if (infos.get(0) instanceof IfItem) { @@ -5999,7 +5999,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(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<>()); + 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<>(), new ArrayList<>()); List cinitBody = p.abc.findBody(cinit).convertedItems; for (GraphTargetItem cit : cinitBody) { if (cit instanceof SetPropertyAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 80a5f9f43..8ab3e7ae4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -265,16 +265,16 @@ public class ScriptPack extends AS3ClassTreeItem { int sinit_index = abc.script_info.get(scriptIndex).init_index; int sinit_bodyIndex = abc.findBodyIndex(sinit_index); if (sinit_bodyIndex != -1 && (isSimple || traitIndices.isEmpty())) { - //initialize all classes traits - /*for (Trait t : traits) { + List initClasses = new ArrayList<>(); + for (Trait t : traits) { if (t instanceof TraitClass) { - ts.add(abc.class_info.get(((TraitClass) t).class_info).static_traits); + initClasses.add(((TraitClass) t).class_info); } - }*/ + } writer.mark(); List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(sinit_bodyIndex)); - 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<>()); + 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<>(), initClasses); scriptInitializerIsEmpty = !writer.getMark(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index d68b8c2d9..d50f4193f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -2542,10 +2542,11 @@ public class AVM2Code implements Cloneable { * @param initTraits Initialized traits * @param staticOperation Static operation * @param localRegAssignmentIps Local register assignment IPs + * @param initTraitClasses Class ids which traits to init * @return List of GraphTargetItems * @throws InterruptedException On interrupt */ - public List toGraphTargetItems(int swfVersion, List callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssignmentIps) throws InterruptedException { + public List toGraphTargetItems(int swfVersion, List callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssignmentIps, List initTraitClasses) throws InterruptedException { initToSource(); List list; HashMap localRegs = new HashMap<>(); @@ -2564,7 +2565,18 @@ public class AVM2Code implements Cloneable { } catch (SecondPassException spe) { 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) { + if (initTraits != null) { + + + Map initClassMultinames = new LinkedHashMap<>(); + if (initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) { + for (int c : initTraitClasses) { + initClassMultinames.put(abc.instance_info.get(c).name_index, abc.class_info.get(c).static_traits); + } + } + initClassMultinames.put(-1, initTraits); + + loopi: for (int i = 0; i < list.size(); i++) { GraphTargetItem ti = list.get(i); @@ -2600,71 +2612,87 @@ public class AVM2Code implements Cloneable { if ((ti instanceof InitPropertyAVM2Item) || (ti instanceof SetPropertyAVM2Item)) { int multinameIndex = 0; GraphTargetItem value = null; - if (ti instanceof InitPropertyAVM2Item) { + GraphTargetItem obj = null; + if (ti instanceof InitPropertyAVM2Item) { multinameIndex = ((InitPropertyAVM2Item) ti).propertyName.multinameIndex; value = ((InitPropertyAVM2Item) ti).value; + obj = ((InitPropertyAVM2Item) ti).object; } if (ti instanceof SetPropertyAVM2Item) { multinameIndex = ((FullMultinameAVM2Item) ((SetPropertyAVM2Item) ti).propertyName).multinameIndex; value = ((SetPropertyAVM2Item) ti).value; + obj = ((SetPropertyAVM2Item) ti).object; } Multiname m = abc.constants.getMultiname(multinameIndex); - for (int j = 0; j < initTraits.traits.size(); j++) { - Trait t = initTraits.traits.get(j); - Multiname tm = abc.constants.getMultiname(t.name_index); - if (tm != null && tm.equals(m)) { - if ((t instanceof TraitSlotConst)) { - //if (((TraitSlotConst) t).isConst() || initializerType == GraphTextWriter.TRAIT_CLASS_INITIALIZER || initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) - { - TraitSlotConst tsc = (TraitSlotConst) t; - if (value != null && !convertData.assignedValues.containsKey(tsc)) { + + Multiname om = null; + if (obj instanceof GetPropertyAVM2Item) { + om = abc.constants.getMultiname(((FullMultinameAVM2Item) ((GetPropertyAVM2Item) obj).propertyName).multinameIndex); + } + if (obj instanceof GetLexAVM2Item) { + om = ((GetLexAVM2Item) obj).propertyName; + } + + for (int classMultiname : initClassMultinames.keySet()) { + Traits ts = initClassMultinames.get(classMultiname); + Multiname cm = classMultiname == -1 ? null : abc.constants.getMultiname(classMultiname); + for (int j = 0; j < ts.traits.size(); j++) { + Trait t = ts.traits.get(j); + Multiname tm = abc.constants.getMultiname(t.name_index); + if (tm != null && tm.equals(m) && (classMultiname == -1 || Objects.equals(om, cm))) { + if ((t instanceof TraitSlotConst)) { + //if (((TraitSlotConst) t).isConst() || initializerType == GraphTextWriter.TRAIT_CLASS_INITIALIZER || initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) + { + TraitSlotConst tsc = (TraitSlotConst) t; + if (value != null && !convertData.assignedValues.containsKey(tsc)) { - if (!isStatic) { - Set subItems = value.getAllSubItemsRecursively(); - subItems.add(value); - List laterMultinames = new ArrayList<>(); - for (int k = j + 1; k < initTraits.traits.size(); k++) { - int tMultinameIndex = initTraits.traits.get(k).name_index; - if (tMultinameIndex > 0) { - Multiname tMultiname = abc.constants.getMultiname(tMultinameIndex); - laterMultinames.add(tMultiname); + if (!isStatic) { + Set subItems = value.getAllSubItemsRecursively(); + subItems.add(value); + List laterMultinames = new ArrayList<>(); + for (int k = j + 1; k < initTraits.traits.size(); k++) { + int tMultinameIndex = initTraits.traits.get(k).name_index; + if (tMultinameIndex > 0) { + Multiname tMultiname = abc.constants.getMultiname(tMultinameIndex); + laterMultinames.add(tMultiname); + } } + for (GraphTargetItem item : subItems) { + + //if later slot is referenced, we must add it in constructor instead of direct assignment + if (item instanceof GetPropertyAVM2Item) { + Multiname multiName = abc.constants.getMultiname(((FullMultinameAVM2Item) ((GetPropertyAVM2Item) item).propertyName).multinameIndex); + if (laterMultinames.contains(multiName)) { + continue loopi; + } + } + if (item instanceof GetLexAVM2Item) { + Multiname multiName = ((GetLexAVM2Item) item).propertyName; + if (laterMultinames.contains(multiName)) { + continue loopi; + } + } + + if (item instanceof LocalRegAVM2Item) { //it is surely in constructor block, not in slot/const + continue loopi; + } + } } - for (GraphTargetItem item : subItems) { - - //if later slot is referenced, we must add it in constructor instead of direct assignment - if (item instanceof GetPropertyAVM2Item) { - Multiname multiName = abc.constants.getMultiname(((FullMultinameAVM2Item) ((GetPropertyAVM2Item) item).propertyName).multinameIndex); - if (laterMultinames.contains(multiName)) { - continue loopi; - } - } - if (item instanceof GetLexAVM2Item) { - Multiname multiName = ((GetLexAVM2Item) item).propertyName; - if (laterMultinames.contains(multiName)) { - continue loopi; - } - } - - if (item instanceof LocalRegAVM2Item) { //it is surely in constructor block, not in slot/const - continue loopi; - } - } + if (value instanceof NewFunctionAVM2Item) { + NewFunctionAVM2Item f = (NewFunctionAVM2Item) value; + f.functionName = tsc.getName(abc).getName(abc.constants, fullyQualifiedNames, true, true); + } + AssignedValue av = new AssignedValue(classMultiname == -1 ? ti : null, value, initializerType, methodIndex); + convertData.assignedValues.put(tsc, av); + if (!isStatic) { + list.remove(i); + i--; + } + continue loopi; } - if (value instanceof NewFunctionAVM2Item) { - NewFunctionAVM2Item f = (NewFunctionAVM2Item) value; - f.functionName = tsc.getName(abc).getName(abc.constants, fullyQualifiedNames, true, true); - } - AssignedValue av = new AssignedValue(ti, value, initializerType, methodIndex); - convertData.assignedValues.put(tsc, av); - if (!isStatic) { - list.remove(i); - i--; - } - continue loopi; } + break; } - break; } } } @@ -2700,14 +2728,34 @@ public class AVM2Code implements Cloneable { } } - + if (initializerType == GraphTextWriter.TRAIT_CLASS_INITIALIZER || initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) { Map commandToAssigned = new IdentityHashMap<>(); Map commandToTrait = new IdentityHashMap<>(); for (TraitSlotConst tsc : convertData.assignedValues.keySet()) { + //if on script, do not use traits that belong to class and vice-versa + if (initTraits != null && !initTraits.traits.contains(tsc)) { + continue; + } AssignedValue asv = convertData.assignedValues.get(tsc); - commandToAssigned.put(asv.command, asv); - commandToTrait.put(asv.command, tsc); + if (asv.command == null) { + TraitSlotConstAVM2Item item = new TraitSlotConstAVM2Item( + null, + null, + tsc, + asv.value, + true, + scriptIndex, + classIndex, + GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, + abc.script_info.get(scriptIndex).init_index, + initTraits.traits.indexOf(tsc) + ); + list.add(item); + } else { + commandToAssigned.put(asv.command, asv); + commandToTrait.put(asv.command, tsc); + } } for (int i = 0; i < list.size(); i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java index 5039b318a..39690a0ce 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java @@ -130,7 +130,7 @@ public class NewFunctionAVM2Item extends AVM2Item { if (body != null) { List callStack = new ArrayList<>(localData.callStack); callStack.add(body); - 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.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), new ArrayList<>()); body.toString(localData.swfVersion, callStack, localData.abcIndex, path + "/inner", ScriptExportMode.AS, abc, null, writer, localData.fullyQualifiedNames, new HashSet<>(localData.seenMethods)); } writer.endBlock(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 0f7a8a483..0ad419d71 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -706,7 +706,7 @@ public class AVM2SourceGenerator implements SourceGenerator { List callStack = new ArrayList<>(); callStack.add(pcinit); try { - 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<>()); + 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<>(), new ArrayList<>()); //FIXME! Add skinparts from _skinParts attribute of parent class!!! } catch (InterruptedException ex) { Logger.getLogger(AVM2SourceGenerator.class.getName()).log(Level.SEVERE, "Getting parent skinparts interrupted", ex); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java index 24680b195..856a31350 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.configuration.Configuration; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -30,7 +31,7 @@ public class ConvertData { public int deobfuscationMode; - public Map assignedValues = new HashMap<>(); + public Map assignedValues = new LinkedHashMap<>(); public boolean thisHasDefaultToPrimitive; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 75ec974a7..ffd1ce52f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -447,9 +447,10 @@ public final class MethodBody implements Cloneable { * @param initTraits Initial traits * @param firstLevel First level * @param seenMethods Seen methods + * @param initTraitClasses Class ids which traits to init * @throws InterruptedException On interrupt */ - public void convert(int swfVersion, List callStack, AbcIndexing abcIndex, final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, Traits initTraits, boolean firstLevel, Set seenMethods) throws InterruptedException { + public void convert(int swfVersion, List callStack, AbcIndexing abcIndex, final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, Traits initTraits, boolean firstLevel, Set seenMethods, List initTraitClasses) throws InterruptedException { seenMethods.add(this.method_info); if (debugMode) { System.err.println("Decompiling " + path); @@ -472,7 +473,7 @@ public final class MethodBody implements Cloneable { HashMap localRegNames = getLocalRegNames(abc); List convertedItems1; try (Statistics s = new Statistics("AVM2Code.toGraphTargetItems")) { - 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) + 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<>(), initTraitClasses); //converted.getCode().visitCode(converted) } try (Statistics s = new Statistics("Graph.graphToString")) { Graph.graphToString(convertedItems1, writer, LocalData.create(callStack, abcIndex, abc, localRegNames, fullyQualifiedNames, seenMethods, exportMode, swfVersion)); @@ -660,7 +661,7 @@ public final class MethodBody implements Cloneable { ConvertData convertData = new ConvertData(); convertData.deobfuscationMode = 0; try { - 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); + 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, new ArrayList<>()); HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); writer.indent().indent().indent(); toString(swfVersion, callStack, abcIndex, "", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), seenMethods); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index f16ce85ff..a5510c924 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -395,7 +395,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } } - 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<>()); + 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<>(), new ArrayList<>()); newScopeStack.push(new ClassAVM2Item(abc.instance_info.get(class_info).getName(abc.constants))); classInitializerIsEmpty = !writer.getMark(); @@ -408,7 +408,7 @@ public class TraitClass extends Trait implements TraitWithSlot { MethodBody constructorBody = abc.bodies.get(bodyIndex); List callStack = new ArrayList<>(); callStack.add(constructorBody); - 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<>()); + 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<>(), new ArrayList<>()); if (convertData.ignoreFrameScripts) { //find all addFrameScript(xx,this.method) in constructor diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index 84d84fd3f..e2f90c5fb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -139,7 +139,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { if (bodyIndex != -1) { List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - 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<>()); + 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<>(), new ArrayList<>()); } writer.endMethod(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index 340c0a01e..b7daed296 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -147,7 +147,7 @@ public class TraitMethodGetterSetter extends Trait { if (bodyIndex != -1) { List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - 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<>()); + 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<>(), new ArrayList<>()); } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java index 28a232074..aead23a64 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java @@ -141,7 +141,7 @@ public class AS3ScriptExporter { try { List callStack = new ArrayList<>(); callStack.add(pack.abc.findBody(method)); - 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<>()); + 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<>(), new ArrayList<>()); List ci = pack.abc.findBody(method).convertedItems; if (!ci.isEmpty()) { @@ -216,7 +216,7 @@ public class AS3ScriptExporter { try { List callStack = new ArrayList<>(); callStack.add(pack.abc.findBody(method)); - 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<>()/*??*/); + 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<>()/*??*/, new ArrayList<>()); List ci = pack.abc.findBody(method).convertedItems; if (!ci.isEmpty() && (ci.get(0) instanceof DeclarationAVM2Item)) { @@ -309,7 +309,7 @@ public class AS3ScriptExporter { try { List callStack = new ArrayList<>(); callStack.add(pack.abc.findBody(iinit)); - 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<>()); + 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<>(), new ArrayList<>()); List iinitBody = pack.abc.findBody(iinit).convertedItems; for (GraphTargetItem it : iinitBody) { if (it instanceof InitPropertyAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 78aa1d5f0..e7aa8df19 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -2845,7 +2845,7 @@ public class XFLConverter { try { List callStack = new ArrayList<>(); callStack.add(constructorBody); - 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<>()); + 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<>(), new ArrayList<>()); if (constructorBody.convertedItems != null) { for (int j = 0; j < constructorBody.convertedItems.size(); j++) { GraphTargetItem ti = constructorBody.convertedItems.get(j); @@ -3039,7 +3039,7 @@ public class XFLConverter { try { List callStack = new ArrayList<>(); callStack.add(constructorBody); - 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<>()); + 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<>(), new ArrayList<>()); List allFramesAccessibilityTraitNames = new ArrayList<>(); List frameTraitNames = new ArrayList<>(); if (constructorBody.convertedItems != null) { @@ -3093,7 +3093,7 @@ public class XFLConverter { MethodBody traitBody = abc.findBody(tm.method_info); List traitCallStack = new ArrayList<>(); traitCallStack.add(traitBody); - traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>(), new ArrayList<>()); if (traitBody.convertedItems == null) { continue; } @@ -3120,7 +3120,7 @@ public class XFLConverter { MethodBody traitBody = abc.findBody(tm.method_info); List traitCallStack = new ArrayList<>(); traitCallStack.add(traitBody); - traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>(), new ArrayList<>()); if (traitBody.convertedItems != null) { for (int j = 0; j < traitBody.convertedItems.size(); j++) { GraphTargetItem ti = traitBody.convertedItems.get(j); @@ -3150,7 +3150,7 @@ public class XFLConverter { MethodBody traitBody = abc.findBody(tm.method_info); List traitCallStack = new ArrayList<>(); traitCallStack.add(traitBody); - traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>(), new ArrayList<>()); if (traitBody.convertedItems != null) { if (!traitBody.convertedItems.isEmpty()) { if (traitBody.convertedItems.get(0) instanceof IfItem) { @@ -3252,7 +3252,7 @@ public class XFLConverter { MethodBody traitBody = abc.findBody(tm.method_info); List traitCallStack = new ArrayList<>(); traitCallStack.add(traitBody); - traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>(), new ArrayList<>()); if (traitBody.convertedItems != null) { if (!traitBody.convertedItems.isEmpty()) { if (traitBody.convertedItems.get(0) instanceof IfItem) { @@ -3373,7 +3373,7 @@ public class XFLConverter { MethodBody traitBody = abc.findBody(tm.method_info); List traitCallStack = new ArrayList<>(); traitCallStack.add(traitBody); - traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>()); + traitBody.convert(swfVersion, traitCallStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new Traits(), true, new HashSet<>(), new ArrayList<>()); if (traitBody.convertedItems != null) { for (int j = 0; j < traitBody.convertedItems.size(); j++) { GraphTargetItem ti = traitBody.convertedItems.get(j); @@ -3479,7 +3479,7 @@ public class XFLConverter { try { List callStack = new ArrayList<>(); callStack.add(constructorBody); - 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<>()); + 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<>(), new ArrayList<>()); Map frameToTraitName = new HashMap<>(); @@ -3547,7 +3547,7 @@ public class XFLConverter { callStack = new ArrayList<>(); 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<>()); + 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<>(), new ArrayList<>()); if (frameBody.convertedItems != null) { for (int i = 0; i < frameBody.convertedItems.size(); i++) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java index fbbbfde1c..3f4bcf804 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java @@ -107,7 +107,7 @@ public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBas List callStack = new ArrayList<>(); callStack.add(abc.bodies.get(bodyIndex)); - abc.bodies.get(bodyIndex).convert(swf.version, callStack, swf.getAbcIndex(), new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(clsIndex).instance_traits, true, new HashSet<>()); + abc.bodies.get(bodyIndex).convert(swf.version, callStack, swf.getAbcIndex(), new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(clsIndex).instance_traits, true, new HashSet<>(), new ArrayList<>()); writer = new HighlightedTextWriter(new CodeFormatting(), false); abc.bodies.get(bodyIndex).toString(swf.version, callStack, swf.getAbcIndex(), "run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), new HashSet<>()); } catch (InterruptedException ex) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java index 13997b67d..61153f57e 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java @@ -45,6 +45,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase { addSwf("standard", "testdata/as3_new/bin/as3_new.flex.swf"); addSwf("assembled", "testdata/as3_assembled/bin/as3_assembled.swf"); addSwf("getouterscope", "testdata/getouterscope/getouterscope.swf"); + addSwf("haxe", "testdata/haxe/output.swf"); } private void decompileScriptPack(String swfId, String path, String expectedResult) { @@ -720,4 +721,31 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase { + "TestHello;\n" ); } + + @Test + public void testHaxeStaticVars() { + /* + Static vars in Haxe are initialized in script initializer (normal flash uses class initializer) + */ + decompileScriptPack("haxe", "tests_classes.TestStaticVars", "package tests_classes\n" + + "{\n" + + " public class TestStaticVars\n" + + " {\n" + + " public static var sa:int = 1001;\n" + + " \n" + + " public static var sb:int = 1002;\n" + + " \n" + + " public var b:int;\n" + + " \n" + + " public var a:int;\n" + + " \n" + + " public function TestStaticVars(param1:int, param2:int)\n" + + " {\n" + + " a = param1;\n" + + " b = param2;\n" + + " }\n" + + " }\n" + + "}\n" + ); + } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java index 0cf73f548..92acd86d7 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java @@ -159,7 +159,7 @@ public class AS3Generator { List callStack = new ArrayList<>(); callStack.add(b); - b.convert(swf.version, callStack, swf.getAbcIndex(), new ConvertData(), "", ScriptExportMode.AS, false, ((TraitMethodGetterSetter) t).method_info, pack.scriptIndex, classId, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(classId).instance_traits, true, new HashSet<>()); + b.convert(swf.version, callStack, swf.getAbcIndex(), new ConvertData(), "", ScriptExportMode.AS, false, ((TraitMethodGetterSetter) t).method_info, pack.scriptIndex, classId, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(classId).instance_traits, true, new HashSet<>(), new ArrayList<>()); b.toString(swf.version, callStack, swf.getAbcIndex(), "", ScriptExportMode.AS, abc, null, src, new ArrayList<>(), new HashSet<>()); src.finishHilights(); String[] srcs = src.toString().split("[\r\n]+"); diff --git a/libsrc/ffdec_lib/testdata/haxe/build.bat b/libsrc/ffdec_lib/testdata/haxe/build.bat new file mode 100644 index 000000000..7aaaa8d0a --- /dev/null +++ b/libsrc/ffdec_lib/testdata/haxe/build.bat @@ -0,0 +1,3 @@ +@echo off +c:\HaxeToolkit\haxe\haxe.exe build.hxml +pause \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/haxe/build.hxml b/libsrc/ffdec_lib/testdata/haxe/build.hxml new file mode 100644 index 000000000..357bde274 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/haxe/build.hxml @@ -0,0 +1,4 @@ +-cp src +-main Main +-swf output.swf +-swf-version 11 \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/haxe/output.swf b/libsrc/ffdec_lib/testdata/haxe/output.swf new file mode 100644 index 000000000..783f55a72 Binary files /dev/null and b/libsrc/ffdec_lib/testdata/haxe/output.swf differ diff --git a/libsrc/ffdec_lib/testdata/haxe/src/Main.hx b/libsrc/ffdec_lib/testdata/haxe/src/Main.hx new file mode 100644 index 000000000..2f5b716f3 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/haxe/src/Main.hx @@ -0,0 +1,9 @@ +import flash.display.Sprite; +import flash.Lib; +import tests_classes.TestStaticVars; + +class Main extends Sprite { + public static function main() { + var obj = new TestStaticVars(10, 20); + } +} diff --git a/libsrc/ffdec_lib/testdata/haxe/src/tests_classes/TestStaticVars.hx b/libsrc/ffdec_lib/testdata/haxe/src/tests_classes/TestStaticVars.hx new file mode 100644 index 000000000..8a3351432 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/haxe/src/tests_classes/TestStaticVars.hx @@ -0,0 +1,14 @@ +package tests_classes; + +class TestStaticVars { + public var a:Int; + public var b:Int; + + public static var sa:Int = 1001; + public static var sb:Int = 1002; + + public function new(a:Int, b:Int) { + this.a = a; + this.b = b; + } +}