diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index d5bbfe1c7..034f30aac 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -37,6 +37,7 @@ import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.NamespaceSet; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; +import com.jpexs.decompiler.flash.abc.types.ValueKind; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; @@ -1451,4 +1452,51 @@ public class ABC { getSwf().clearScriptCache(); getMethodIndexing(); } + + public void mergeABC(ABC secondABC) { + Map namespaceMap = new HashMap<>(); + Map namespaceSetMap = new HashMap<>(); + Map multinameMap = new HashMap<>(); + Map methodInfoMap = new HashMap<>(); + + constants.merge(secondABC.constants, namespaceMap, namespaceSetMap, multinameMap); + for (int i = 0; i < secondABC.method_info.size(); i++) { + MethodInfo secondMethodInfo = secondABC.method_info.get(i); + int newParamTypes[] = new int[secondMethodInfo.param_types.length]; + int newParamNames[] = new int[secondMethodInfo.paramNames.length]; + int newRetType = multinameMap.get(secondMethodInfo.ret_type); + int newNameIndex = constants.getStringId(secondABC.constants.getString(secondMethodInfo.name_index), true); + ValueKind newOptional[] = new ValueKind[secondMethodInfo.optional.length]; + for (int k = 0; k < secondMethodInfo.optional.length; k++) { + int vkind = secondMethodInfo.optional[k].value_kind; + int newValueIndex; + switch (vkind) { + case ValueKind.CONSTANT_ExplicitNamespace: + case ValueKind.CONSTANT_Namespace: + case ValueKind.CONSTANT_PackageInternalNs: + case ValueKind.CONSTANT_PackageNamespace: + case ValueKind.CONSTANT_ProtectedNamespace: + case ValueKind.CONSTANT_PrivateNs: + case ValueKind.CONSTANT_StaticProtectedNs: + newValueIndex = namespaceMap.get(secondMethodInfo.optional[k].value_index); + break; + default: + newValueIndex = secondMethodInfo.optional[k].value_index; + } + newOptional[k] = new ValueKind(newValueIndex, vkind); + } + + MethodInfo newMethodInfo = new MethodInfo(newParamTypes, newRetType, newNameIndex, secondMethodInfo.flags, newOptional, newParamNames); + int newIndex = addMethodInfo(newMethodInfo); + methodInfoMap.put(i, newIndex); + } + for (MethodBody secondBody : secondABC.bodies) { + //TODO!!! + //MethodBody newBody = new MethodBody(this, mergeTraits(secondBody.traits), codeBytes, exceptions) + } + } + + private Traits mergeTraits(Traits secondTraits) { + return null; //TODO + } } 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 517152c1f..55317afe1 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 @@ -200,12 +200,14 @@ public class ScriptPack extends AS3ClassTreeItem { //TODO: handle this better in GUI(?) writer.startTrait(GraphTextWriter.TRAIT_SCRIPT_INITIALIZER); writer.startMethod(script_init); - if (!scriptInitializerIsEmpty) { - writer.startBlock(); - abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>()); - writer.endBlock(); - } else { - writer.append(" "); + if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { + if (!scriptInitializerIsEmpty) { + writer.startBlock(); + abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>()); + writer.endBlock(); + } else { + writer.append(" "); + } } writer.endMethod(); writer.endTrait(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java index 1303e51f5..50ad462fc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java @@ -377,6 +377,14 @@ public class AVM2ConstantPool implements Cloneable { return null; } + public int getDecimalId(Decimal val, boolean add) { + int id = getDecimalId(val); + if (add && id == -1) { + id = addDecimal(val); + } + return id; + } + public Float getFloat(int index) { try { return constant_float.get(index); @@ -514,6 +522,10 @@ public class AVM2ConstantPool implements Cloneable { return constant_float4.indexOf(value); } + private int getDecimalId(Decimal value) { + return constant_decimal.indexOf(value); + } + private int getStringId(String value) { return constant_string.indexOf(value); } @@ -755,4 +767,114 @@ public class AVM2ConstantPool implements Cloneable { } return null; } + + /** + * Merges second constantpool into this one + * + * @param secondPool + * @param namespaceMap Output map of merged namespaces. Index in second pool + * to index in this pool. + * @param namespaceSetMap Output map of merged namespace sets. Index in + * second pool to index in this pool. + * @param multinameMap Output map of merged multinames. Index in second pool + * to index in this pool. + */ + public void merge(AVM2ConstantPool secondPool, Map namespaceMap, Map namespaceSetMap, Map multinameMap) { + for (String val : secondPool.constant_string) { + getStringId(val, true); + } + for (Long val : secondPool.constant_int) { + getIntId(val, true); + } + for (Long val : secondPool.constant_uint) { + getUIntId(val, true); + } + for (Double val : secondPool.constant_double) { + getDoubleId(val, true); + } + for (Float val : secondPool.constant_float) { + getFloatId(val, true); + } + for (Float4 val : secondPool.constant_float4) { + getFloat4Id(val, true); + } + for (Decimal val : secondPool.constant_decimal) { + getDecimalId(val, true); + } + namespaceMap.put(0, 0); + for (int i = 1; i < secondPool.constant_namespace.size(); i++) { + Namespace secondNamespace = secondPool.getNamespace(i); + String secondNsNameStr = secondNamespace.name_index == 0 ? null : secondPool.getString(secondNamespace.name_index); + int mappedId; + if (secondNamespace.kind == Namespace.KIND_PRIVATE) {//always add, this does not exists in this ABC. Conflicting private namespaces can have same names. + mappedId = addNamespace(secondNamespace.kind, getStringId(secondNsNameStr, true)); + } else { + mappedId = getNamespaceId(secondNamespace.kind, secondNsNameStr, 0, true); + } + namespaceMap.put(i, mappedId); + } + namespaceSetMap.put(0, 0); + for (int i = 1; i < secondPool.constant_namespace_set.size(); i++) { + NamespaceSet secondNamespaceSet = secondPool.getNamespaceSet(i); + int mappedsNss[] = new int[secondNamespaceSet.namespaces.length]; + for (int n = 0; n < secondNamespaceSet.namespaces.length; n++) { + mappedsNss[n] = namespaceMap.get(secondNamespaceSet.namespaces[n]); + } + int mappedId = getNamespaceSetId(mappedsNss, true); + namespaceSetMap.put(i, mappedId); + } + multinameMap.put(0, 0); + for (int i = 1; i < secondPool.constant_multiname.size(); i++) { + Multiname secondMultiname = secondPool.getMultiname(i); + Multiname importedMultiname = null; + int newNameIndex = secondMultiname.name_index <= 0 ? secondMultiname.name_index : getStringId(secondPool.getString(secondMultiname.name_index), true); + int newNsIndex = secondMultiname.namespace_index <= 0 ? secondMultiname.namespace_index : namespaceMap.get(secondMultiname.namespace_index); + int newNssIndex = secondMultiname.namespace_set_index <= 0 ? secondMultiname.namespace_set_index : namespaceSetMap.get(secondMultiname.namespace_set_index); + + switch (secondMultiname.kind) { + case Multiname.MULTINAME: + importedMultiname = Multiname.createMultiname(false, newNameIndex, newNssIndex); + break; + case Multiname.MULTINAMEA: + importedMultiname = Multiname.createMultiname(true, newNameIndex, newNssIndex); + break; + case Multiname.MULTINAMEL: + importedMultiname = Multiname.createMultinameL(false, newNssIndex); + break; + case Multiname.MULTINAMELA: + importedMultiname = Multiname.createMultinameL(true, newNssIndex); + break; + case Multiname.QNAME: + importedMultiname = Multiname.createQName(false, newNameIndex, newNsIndex); + break; + case Multiname.QNAMEA: + importedMultiname = Multiname.createQName(true, newNameIndex, newNsIndex); + break; + case Multiname.RTQNAME: + importedMultiname = Multiname.createRTQName(false, newNameIndex); + break; + case Multiname.RTQNAMEA: + importedMultiname = Multiname.createRTQName(true, newNameIndex); + break; + case Multiname.RTQNAMEL: + importedMultiname = Multiname.createRTQNameL(false); + break; + case Multiname.RTQNAMELA: + importedMultiname = Multiname.createRTQNameL(true); + break; + case Multiname.TYPENAME: + int newQnameIndex = multinameMap.get(secondMultiname.qname_index); + int newParams[] = new int[secondMultiname.params.length]; + for (int p = 0; p < secondMultiname.params.length; p++) { + newParams[p] = multinameMap.get(secondMultiname.params[p]); + } + importedMultiname = Multiname.createTypeName(newQnameIndex, newParams); + break; + } + + int mappedId = getMultinameId(importedMultiname, true); + multinameMap.put(i, mappedId); + } + + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index 022b3dd2f..20f504f49 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -386,4 +386,17 @@ public class MethodInfo { } return writer.hilightSpecial(rname, HighlightSpecialType.RETURNS); } + + public String getReturnTypeRaw(AVM2ConstantPool constants, List fullyQualifiedNames) { + String rname = "*"; + if (ret_type > 0) { + Multiname multiname = constants.getMultiname(ret_type); + if (multiname.kind != Multiname.TYPENAME && multiname.name_index > 0 && constants.getString(multiname.name_index).equals("void")) { + rname = "void"; + } else { + rname = multiname.getName(constants, fullyQualifiedNames, false); + } + } + return rname; + } } 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 2eea9627c..f21028ecc 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 @@ -131,14 +131,16 @@ public class TraitClass extends Trait implements TraitWithSlot { if (bodyIndex != -1) { writer.startTrait(GraphTextWriter.TRAIT_CLASS_INITIALIZER); writer.startMethod(classInfo.cinit_index); - if (!classInitializerIsEmpty) { - writer.startBlock(); - abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames); - writer.endBlock(); - } else { - //Note: There must be trait/method highlight even if the initializer is empty to TraitList in GUI to work correctly - //TODO: handle this better in GUI(?) - writer.append(" ").newLine(); + if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { + if (!classInitializerIsEmpty) { + writer.startBlock(); + abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames); + writer.endBlock(); + } else { + //Note: There must be trait/method highlight even if the initializer is empty to TraitList in GUI to work correctly + //TODO: handle this better in GUI(?) + writer.append(" ").newLine(); + } } writer.endMethod(); writer.endTrait(); @@ -178,8 +180,10 @@ public class TraitClass extends Trait implements TraitWithSlot { MethodBody body = bodyIndex == -1 ? null : abc.bodies.get(bodyIndex); abc.method_info.get(instanceInfo.iinit_index).getParamStr(writer, abc.constants, body, abc, fullyQualifiedNames); writer.appendNoHilight(")").startBlock(); - if (body != null) { - body.toString(path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames); + if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { + if (body != null) { + body.toString(path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames); + } } writer.endBlock().newLine(); 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 8b24560a3..1ed3656a0 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 @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.exporters.script.Dependency; import com.jpexs.decompiler.flash.exporters.script.DependencyParser; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.ScopeStack; @@ -112,9 +113,11 @@ public class TraitMethodGetterSetter extends Trait { path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false); convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); - if (!(classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1)) { - if (bodyIndex != -1) { - abc.bodies.get(bodyIndex).convert(convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true); + if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { + if (!(classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1)) { + if (bodyIndex != -1) { + abc.bodies.get(bodyIndex).convert(convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true); + } } } writer.endMethod(); @@ -135,8 +138,30 @@ public class TraitMethodGetterSetter extends Trait { writer.appendNoHilight(";"); } else { writer.startBlock(); - if (bodyIndex != -1) { - abc.bodies.get(bodyIndex).toString(path, exportMode, abc, this, writer, fullyQualifiedNames); + if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { + if (bodyIndex != -1) { + abc.bodies.get(bodyIndex).toString(path, exportMode, abc, this, writer, fullyQualifiedNames); + } + } else { + String retTypeRaw = abc.method_info.get(method_info).getReturnTypeRaw(abc.constants, fullyQualifiedNames); + switch (retTypeRaw) { + case "void": + break; + case "int": + case "uint": + writer.append("return 0; //autogenerated").newLine(); + break; + case "double": + case "float": + writer.append("return 0.0; //autogenerated").newLine(); + break; + case "String": + writer.append("return \"\"; //autogenerated").newLine(); + break; + default: + writer.append("return null; //autogenerated").newLine(); + break; + } } writer.endBlock(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index 2ee16f80f..29337bd30 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -106,7 +106,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { return writer; } - public void getValueStr(Trait parent, ConvertData convertData, GraphTextWriter writer, ABC abc, List fullyQualifiedNames) throws InterruptedException { + public void getValueStr(ScriptExportMode exportMode, Trait parent, ConvertData convertData, GraphTextWriter writer, ABC abc, List fullyQualifiedNames) throws InterruptedException { if (convertData.assignedValues.containsKey(this)) { AssignedValue assignment = convertData.assignedValues.get(this); @@ -119,8 +119,9 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { writer.appendNoHilight(assignment.method); writer.newLine(); } - - assignment.value.toString(writer, LocalData.create(abc.constants, new HashMap<>(), fullyQualifiedNames)); + if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { + assignment.value.toString(writer, LocalData.create(abc.constants, new HashMap<>(), fullyQualifiedNames)); + } writer.endMethod(); writer.endTrait(); return; @@ -165,7 +166,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { getNameStr(writer, abc, fullyQualifiedNames); if (value_kind != 0 || convertData.assignedValues.containsKey(this)) { writer.appendNoHilight(" = "); - getValueStr(parent, convertData, writer, abc, fullyQualifiedNames); + getValueStr(exportMode, parent, convertData, writer, abc, fullyQualifiedNames); } return writer.appendNoHilight(";").newLine(); } @@ -174,7 +175,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { public void convert(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { getNameStr(writer, abc, fullyQualifiedNames); if (value_kind != 0 || convertData.assignedValues.containsKey(this)) { - getValueStr(parent, convertData, writer, abc, fullyQualifiedNames); + getValueStr(exportMode, parent, convertData, writer, abc, fullyQualifiedNames); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/modes/ScriptExportMode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/modes/ScriptExportMode.java index c89b0bc12..943310a33 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/modes/ScriptExportMode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/modes/ScriptExportMode.java @@ -22,5 +22,5 @@ package com.jpexs.decompiler.flash.exporters.modes; */ public enum ScriptExportMode { - AS, PCODE, PCODE_HEX, HEX, CONSTANTS; + AS, PCODE, PCODE_HEX, HEX, CONSTANTS, AS_METHOD_STUBS; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java index 3f2c8386b..d6f1b4aab 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ScriptExportSettings.java @@ -41,6 +41,7 @@ public class ScriptExportSettings { public String getFileExtension() { switch (mode) { case AS: + case AS_METHOD_STUBS: return ".as"; case PCODE: case PCODE_HEX: diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java index a786965da..809d8e96f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java @@ -6,7 +6,10 @@ import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.InstanceInfo; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter; import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter; +import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; import com.jpexs.decompiler.flash.exporters.swf.SwfToSwcExporter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; @@ -112,21 +115,38 @@ public class As3ScriptReplacer extends MxmlcRunner { } } - //remove all subclasses + List removedPacks = new ArrayList<>(); + + //remove all subclasses from the SWC for (ScriptPack sp : copyPacks) { DottedChain dc = sp.getPathPackage().add(sp.getPathScriptName()); if (isParentDeleted(sp.abc, sp.allABCs, dc)) { sp.abc.script_info.get(sp.scriptIndex).delete(sp.abc, true); modAbcs.add(sp.abc); + removedPacks.add(sp); } } + + //Export subclasses so they can be compiled by Flex, but ONLY STUBS. + //No method code to avoid code compilation problems. + //This compiled code won't be used at all in original SWF, + //it is used only by Flex to properly compile current script + AS3ScriptExporter ex = new AS3ScriptExporter(); + ex.exportActionScript3(swfCopy, null, tempDir.getAbsolutePath(), removedPacks, new ScriptExportSettings(ScriptExportMode.AS_METHOD_STUBS, false), false, null); + + //now really remove the classes from SWF copy for (ABC a : modAbcs) { a.pack(); } + //Generate SWC file from the modified SWF file. + //Flex then uses the code already present in the SWC, no need to decompile it (hurray!) SwfToSwcExporter swcExport = new SwfToSwcExporter(); swcExport.exportSwf(swfCopy, swcFile, true); + //Write new script Helper.writeFile(scriptFileToCompile.getAbsolutePath(), txt.getBytes("UTF-8")); + + //Compile it (and subclasses stubs) mxmlc("-include-inheritance-dependencies-only", "-warnings=false", "-library-path", swcFile.getAbsolutePath(), "-source-path", tempDir.getAbsolutePath(), "-output", compiledSwfFile.getAbsolutePath(), "-debug=true", scriptFileToCompile.getAbsolutePath()); try (FileInputStream fis = new FileInputStream(compiledSwfFile)) { @@ -146,6 +166,7 @@ public class As3ScriptReplacer extends MxmlcRunner { ABCContainerTag lastTag = newTags.get(newTags.size() - 1); ((Tag) lastTag).setSwf(swf); swf.addTag(oldTagIndex + 1, (Tag) lastTag); + //TODO: looks like ABCs need to be merged. Parent class needs to be defined earlier than used :-( ((Tag) lastTag).setModified(true); ((Tag) oldPack.abc.parentTag).setModified(true); } diff --git a/libsrc/ffdec_lib/testdata/as3/as3.swf b/libsrc/ffdec_lib/testdata/as3/as3.swf index 731abd8fd..3f191024a 100644 Binary files a/libsrc/ffdec_lib/testdata/as3/as3.swf and b/libsrc/ffdec_lib/testdata/as3/as3.swf differ diff --git a/libsrc/ffdec_lib/testdata/flexedit/Main.as b/libsrc/ffdec_lib/testdata/flexedit/Main.as new file mode 100644 index 000000000..ad4e8e444 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/flexedit/Main.as @@ -0,0 +1,24 @@ +package { + + import flash.display.MovieClip; + import flash.text.TextField; + import pkg.MyClass; + + + public class Main extends MovieClip { + + private var mc:MyClass; + + + public function Main() { + this.mc = new MyClass(5); + var display_txt:TextField = new TextField(); + display_txt.text = "Hello myclass: "+this.mc.getVal()+" char:"+this.mc.getAChar(); + display_txt.width = 300; + addChild(display_txt); + + + } + } + +} diff --git a/libsrc/ffdec_lib/testdata/flexedit/Main.fla b/libsrc/ffdec_lib/testdata/flexedit/Main.fla new file mode 100644 index 000000000..fe5d67f1e Binary files /dev/null and b/libsrc/ffdec_lib/testdata/flexedit/Main.fla differ diff --git a/libsrc/ffdec_lib/testdata/flexedit/Main.html b/libsrc/ffdec_lib/testdata/flexedit/Main.html new file mode 100644 index 000000000..31d8258de --- /dev/null +++ b/libsrc/ffdec_lib/testdata/flexedit/Main.html @@ -0,0 +1,49 @@ + + + + Main + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + Get Adobe Flash player + + + + + +
+ + diff --git a/libsrc/ffdec_lib/testdata/flexedit/Main.swf b/libsrc/ffdec_lib/testdata/flexedit/Main.swf new file mode 100644 index 000000000..d8f1d7414 Binary files /dev/null and b/libsrc/ffdec_lib/testdata/flexedit/Main.swf differ diff --git a/libsrc/ffdec_lib/testdata/flexedit/pkg/MyClass.as b/libsrc/ffdec_lib/testdata/flexedit/pkg/MyClass.as new file mode 100644 index 000000000..9a683daa3 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/flexedit/pkg/MyClass.as @@ -0,0 +1,17 @@ +package pkg { + + public class MyClass extends ParentClass { + + private var val:int; + + public function MyClass(val) { + this.val = val; + } + + public function getVal():int{ + return this.val; + } + + } + +} diff --git a/libsrc/ffdec_lib/testdata/flexedit/pkg/ParentClass.as b/libsrc/ffdec_lib/testdata/flexedit/pkg/ParentClass.as new file mode 100644 index 000000000..1dedf44d8 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/flexedit/pkg/ParentClass.as @@ -0,0 +1,11 @@ +package pkg { + + public class ParentClass extends ParentParentClass { + + public function ParentClass() { + // constructor code + } + + } + +} diff --git a/libsrc/ffdec_lib/testdata/flexedit/pkg/ParentParentClass.as b/libsrc/ffdec_lib/testdata/flexedit/pkg/ParentParentClass.as new file mode 100644 index 000000000..8325f3168 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/flexedit/pkg/ParentParentClass.as @@ -0,0 +1,22 @@ +package pkg { + + public class ParentParentClass { + + //Reference to subclass: (circular reference) + private var other:ParentClass; + + public function ParentParentClass() { + // constructor code + } + + public function setOther(other:ParentClass){ + this.other = other; + } + + public function getAChar():String{ + return "A"; + } + + } + +}