diff --git a/lib/flashdebugger.jar b/lib/flashdebugger.jar index 7c5425670..84b21f3d5 100644 Binary files a/lib/flashdebugger.jar and b/lib/flashdebugger.jar differ diff --git a/lib/jsyntaxpane-0.9.5.jar b/lib/jsyntaxpane-0.9.5.jar index dfec0b488..0d0dca890 100644 Binary files a/lib/jsyntaxpane-0.9.5.jar and b/lib/jsyntaxpane-0.9.5.jar differ 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 af233e6df..073326e86 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 @@ -35,7 +35,9 @@ import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.GetDescendantsAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair; import com.jpexs.decompiler.flash.abc.avm2.model.NanAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; @@ -49,8 +51,10 @@ 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.IfCondition; import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing.ClassIndex; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.ClassInfo; +import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.InstanceInfo; import com.jpexs.decompiler.flash.abc.types.MetadataInfo; import com.jpexs.decompiler.flash.abc.types.MethodBody; @@ -66,12 +70,16 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.Loop; +import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.AndItem; @@ -1166,6 +1174,122 @@ public class AVM2SourceGenerator implements SourceGenerator { } ParsedSymbol s = null; + if (Configuration.handleSkinPartsAutomatically.get()) { + + Map skinParts = new HashMap<>(); + for (GraphTargetItem t : traitItems) { + String tname = null; + List>> tmetadata = null; + if (t instanceof MethodAVM2Item) { + tname = ((MethodAVM2Item) t).functionName; + tmetadata = ((MethodAVM2Item) t).metadata; + } else if (t instanceof SlotAVM2Item) { + tname = ((SlotAVM2Item) t).var; + tmetadata = ((SlotAVM2Item) t).metadata; + } else if (t instanceof ConstAVM2Item) { + tname = ((ConstAVM2Item) t).var; + tmetadata = ((ConstAVM2Item) t).metadata; + } + if (tname != null && tmetadata != null) { + for (Map.Entry> en : tmetadata) { + if ("SkinPart".equals(en.getKey())) { + boolean req = false; + if (en.getValue().containsKey("required")) { + if ("true".equals(en.getValue().get("required"))) { + req = true; + } + } + skinParts.put(tname, req); + } + } + } + } + if (!skinParts.isEmpty()) { + + //Merge parts from _skinParts attribute of parent class + GraphTargetItem parent = extendsVal; + if (parent instanceof UnresolvedAVM2Item) { + parent = ((UnresolvedAVM2Item) parent).resolved; + } + if (parent instanceof TypeItem) { + ClassIndex ci = abcIndex.findClass(parent); + if (ci != null) { + int mi = ci.abc.class_info.get(ci.index).cinit_index; + MethodBody pcinit = ci.abc.findBody(mi); + ConvertData d = new ConvertData(); + + List initt = new ArrayList<>(); + initt.add(ci.abc.class_info.get(ci.index).static_traits); + + try { + pcinit.convert(d, "-", ScriptExportMode.AS, true, mi, -1, ci.index, ci.abc, null, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, new NulWriter(), new ArrayList<>(), initt, false); + //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); + } + for (Trait t : ci.abc.class_info.get(ci.index).static_traits.traits) { + if (t instanceof TraitSlotConst) { + TraitSlotConst tsc = (TraitSlotConst) t; + if (tsc.kindType == Trait.TRAIT_SLOT) { + if ("_skinParts".equals(tsc.getName(ci.abc).getName(ci.abc.constants, new ArrayList<>(), true))) { + if (d.assignedValues.containsKey(tsc)) { + if (d.assignedValues.get(tsc).value instanceof NewObjectAVM2Item) { + NewObjectAVM2Item no = (NewObjectAVM2Item) d.assignedValues.get(tsc).value; + for (NameValuePair nvp : no.pairs) { + skinParts.put(EcmaScript.toString(nvp.name.getResult()), EcmaScript.toBoolean(nvp.value.getResult())); + } + } + + } + } + } + } + } + + } + } + + /* + Add + override protected function get skinParts() : Object + { + return _skinParts; + } + */ + List getterBody = new ArrayList<>(); + UnresolvedAVM2Item sp = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, TypeItem.UNBOUNDED, 0, new DottedChain("_skinParts"), + null, openedNamespaces); + getterBody.add(new ReturnValueAVM2Item(null, null, sp)); + List subvars = new ArrayList<>(); + subvars.add(sp); + List> allopns = new ArrayList<>(); + allopns.add(openedNamespaces); + + GetterAVM2Item getter = new GetterAVM2Item(allopns, false, false, new ArrayList<>(), new NamespaceItem(pkg.toRawString() + ":" + name, Namespace.KIND_PROTECTED), isInterface, null, false, false, 0, + true, false, false, "skinParts", new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), + getterBody, subvars, new TypeItem("Object")); + + /* + Add + private static var _skinParts = {attr1:false, attr2:true}; + */ + List pairs = new ArrayList<>(); + for (String tname : skinParts.keySet()) { + pairs.add(new NameValuePair(new StringAVM2Item(null, null, tname), skinParts.get(tname) ? new TrueItem(null, null) : new FalseItem(null, null))); + } + + NewObjectAVM2Item sltVal = new NewObjectAVM2Item(null, null, pairs); + + SlotAVM2Item slt = new SlotAVM2Item( + new ArrayList<>(), new NamespaceItem(pkg.toRawString() + ":" + name, Namespace.KIND_PRIVATE), + null, true, "_skinParts", new TypeItem("Object"), sltVal, 0); + + traitItems.add(0, slt); + traitItems.add(getter); + + } + } + Trait[] it = generateTraitsPhase1(importedClasses, openedNamespaces, name, superName, false, localData, traitItems, instanceInfo.instance_traits, class_index); Trait[] st = generateTraitsPhase1(importedClasses, openedNamespaces, name, superName, true, localData, traitItems, classInfo.static_traits, class_index); generateTraitsPhase2(importedClasses, pkg, traitItems, it, openedNamespaces, localData); @@ -1244,6 +1368,7 @@ public class AVM2SourceGenerator implements SourceGenerator { for (int i = 0; i < implementsStr.size(); i++) { instanceInfo.interfaces[i] = superIntName(localData, implementsStr.get(i)); } + } @Override @@ -1534,12 +1659,10 @@ public class AVM2SourceGenerator implements SourceGenerator { n.setSlotNumber(slotNames.indexOf(variableName)); n.setSlotScope(slotScope); } + } else if (isThisOrSuper) { + n.setRegNumber(0); } else { - if (isThisOrSuper) { - n.setRegNumber(0); - } else { - n.setRegNumber(registerNames.indexOf(variableName)); - } + n.setRegNumber(registerNames.indexOf(variableName)); } } } @@ -1560,10 +1683,8 @@ public class AVM2SourceGenerator implements SourceGenerator { if (needsActivation) { if (n.getSlotScope() != slotScope) { continue; - } else { - if (n.getSlotNumber() < paramRegCount) { - continue; - } + } else if (n.getSlotNumber() < paramRegCount) { + continue; } } for (NameAVM2Item d : declarations) { @@ -1968,15 +2089,23 @@ public class AVM2SourceGenerator implements SourceGenerator { n.resolveCustomNs(abcIndex, importedClasses, localData.pkg, ln, localData); } } - ((TraitMethodGetterSetter) traits[k]).method_info = method(mai.isStatic(), methodName(mai.outsidePackage, localData.pkg, mai.functionName, mai.pkg, className, mai.customNamespace), false, isInterface, new ArrayList<>(), localData.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType); + String suffix = null; + if (item instanceof GetterAVM2Item) { + suffix = "get"; + } + if (item instanceof SetterAVM2Item) { + suffix = "set"; + } + + ((TraitMethodGetterSetter) traits[k]).method_info = method(mai.isStatic(), methodName(mai.outsidePackage, localData.pkg, mai.functionName, mai.pkg, className, mai.customNamespace, suffix), false, isInterface, new ArrayList<>(), localData.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType); } else if (item instanceof FunctionAVM2Item) { FunctionAVM2Item fai = (FunctionAVM2Item) item; - ((TraitFunction) traits[k]).method_info = method(false, methodName(false/*?*/, localData.pkg, fai.functionName, fai.pkg, null, null), false, isInterface, new ArrayList<>(), localData.pkg, fai.needsActivation, fai.subvariables, methodInitScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType); + ((TraitFunction) traits[k]).method_info = method(false, methodName(false/*?*/, localData.pkg, fai.functionName, fai.pkg, null, null, ""), false, isInterface, new ArrayList<>(), localData.pkg, fai.needsActivation, fai.subvariables, methodInitScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType); } } } - private int methodName(boolean outsidePkg, DottedChain pkg, String methodName, NamespaceItem ns, String className, String customNs) { + private int methodName(boolean outsidePkg, DottedChain pkg, String methodName, NamespaceItem ns, String className, String customNs, String typeSuffix) { StringBuilder sb = new StringBuilder(); /*if (ns != null) { sb.append(ns.name.toRawString()); @@ -2009,6 +2138,10 @@ public class AVM2SourceGenerator implements SourceGenerator { } sb.append(":"); sb.append(methodName); + if (typeSuffix != null && !typeSuffix.isEmpty()) { + sb.append("/"); + sb.append(typeSuffix); + } return abcIndex.getSelectedAbc().constants.getStringId(sb.toString(), true); } @@ -2132,7 +2265,8 @@ public class AVM2SourceGenerator implements SourceGenerator { traits[k] = tmgs; traits[k].metadata = generateMetadata(((MethodAVM2Item) item).metadata); - } /*else if (item instanceof FunctionAVM2Item) { + } + /*else if (item instanceof FunctionAVM2Item) { TraitFunction tf = new TraitFunction(); tf.slot_id = slot_id++; tf.kindType = Trait.TRAIT_FUNCTION; @@ -2206,7 +2340,9 @@ public class AVM2SourceGenerator implements SourceGenerator { traitScope++; } //direct parent class to new_class instruction - mbCode.add(ins(AVM2Instructions.GetLex, parents.get(0))); + if (!parents.isEmpty()) { //NON EXISTING PARENT CLASS - TODO: handle as error! + mbCode.add(ins(AVM2Instructions.GetLex, parents.get(0))); + } } mbCode.add(ins(AVM2Instructions.NewClass, tc.class_info)); for (int i = 0; i < parents.size(); i++) { @@ -2366,7 +2502,7 @@ public class AVM2SourceGenerator implements SourceGenerator { /* public void calcRegisters(Reference activationReg, SourceGeneratorLocalData localData, boolean needsActivation, List funParamNames,List funSubVariables,List funBody, Reference hasArguments) throws ParseException { }*/ - /*public int resolveType(String objType) { + /*public int resolveType(String objType) { if (objType.equals("*")) { return 0; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 29ebe176e..c161303b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -30,6 +30,9 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair; +import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.MethodBody; @@ -37,6 +40,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.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; @@ -97,7 +101,7 @@ public abstract class Trait implements Cloneable, Serializable { public abstract void delete(ABC abc, boolean d); - public final List>> getMetaDataTable(ABC abc) { + public final List>> getMetaDataTable(Trait parent, ConvertData convertData, ABC abc) { List>> ret = new ArrayList<>(); for (int m : metadata) { if (m >= 0 && m < abc.metadata_info.size()) { @@ -110,6 +114,58 @@ public abstract class Trait implements Cloneable, Serializable { ret.add(new SimpleEntry<>(name, data)); } } + if (Configuration.handleSkinPartsAutomatically.get()) { + /* + private static var _skinParts:Object = {"attr":false,"attr2":true}; + => + [SkinPart required="false"] + public var attr; + [SkinPart required="true"] + public var attr2; + */ + if (parent instanceof TraitClass) { + String thisName = getName(abc).getName(abc.constants, new ArrayList<>(), true); + List classTraits = abc.class_info.get(((TraitClass) parent).class_info).static_traits.traits; + for (Trait t : classTraits) { + if (t.kindType == Trait.TRAIT_SLOT) { + if ("_skinParts".equals(t.getName(abc).getName(abc.constants, new ArrayList<>(), true))) { + if (t.getName(abc).getNamespace(abc.constants).kind == Namespace.KIND_PRIVATE) { + if (convertData.assignedValues.containsKey(t)) { + if (convertData.assignedValues.get(t).value instanceof NewObjectAVM2Item) { + NewObjectAVM2Item no = (NewObjectAVM2Item) convertData.assignedValues.get(t).value; + for (NameValuePair nvp : no.pairs) { + if (nvp.name instanceof StringAVM2Item) { + if (thisName.equals(((StringAVM2Item) nvp.name).getValue())) { + String newReq = "" + nvp.value.getResult(); + boolean found = false; + //if already has SkinPart metadata, change required value only + for (int i = 0; i < ret.size(); i++) { + Entry> e = ret.get(i); + if ("SkinPart".equals(e.getKey())) { + e.getValue().put("required", newReq); + found = true; + break; + } + } + + //add new metadata if not found + if (!found) { + Map data = new HashMap<>(); + data.put("required", newReq); + + ret.add(new SimpleEntry<>("SkinPart", data)); + } + } + } + } + } + } + } + } + } + } + } + } return ret; } @@ -377,8 +433,8 @@ public abstract class Trait implements Cloneable, Serializable { } } - public final GraphTextWriter getMetaData(ABC abc, GraphTextWriter writer) { - List>> md = getMetaDataTable(abc); + public final GraphTextWriter getMetaData(Trait parent, ConvertData convertData, ABC abc, GraphTextWriter writer) { + List>> md = getMetaDataTable(parent, convertData, abc); for (Entry> en : md) { String name = en.getKey(); if (METADATA_DEFINITION.equals(name) || METADATA_CTOR_DEFINITION.equals(name)) { @@ -549,4 +605,8 @@ public abstract class Trait implements Cloneable, Serializable { throw new RuntimeException(); } } + + public boolean isVisible(boolean isStatic, ABC abc) { + return true; + } } 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 410509c81..75d4e11b8 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 @@ -128,7 +128,7 @@ public class TraitClass extends Trait implements TraitWithSlot { writer.startClass(class_info); - getMetaData(abc, writer); + getMetaData(parent, convertData, abc, writer); //class header instanceInfo.getClassHeaderStr(writer, abc, fullyQualifiedNames, false); writer.startBlock(); 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 bfa7a39b3..887971236 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 @@ -78,7 +78,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { @Override public GraphTextWriter toString(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { writeImportsUsages(abc, writer, getPackage(abc), fullyQualifiedNames); - getMetaData(abc, writer); + getMetaData(parent, convertData, abc, writer); writer.startMethod(method_info); toStringHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); 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 ca3f87cfd..cc836a0ae 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 @@ -19,7 +19,9 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; @@ -122,7 +124,7 @@ public class TraitMethodGetterSetter extends Trait { if (classIndex < 0) { writeImportsUsages(abc, writer, getPackage(abc), fullyQualifiedNames); } - getMetaData(abc, writer); + getMetaData(parent, convertData, abc, writer); writer.startMethod(method_info); path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false); toStringHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); @@ -155,4 +157,23 @@ public class TraitMethodGetterSetter extends Trait { TraitMethodGetterSetter ret = (TraitMethodGetterSetter) super.clone(); return ret; } + + @Override + public boolean isVisible(boolean isStatic, ABC abc) { + if (Configuration.handleSkinPartsAutomatically.get()) { + if ("skinParts".equals(getName(abc).getName(abc.constants, new ArrayList<>(), true))) { + if (kindType == TRAIT_GETTER) { + MethodInfo mi = abc.method_info.get(method_info); + if (mi.param_types.length == 0 && "Object".equals(abc.constants.getMultiname(mi.ret_type).getNameWithNamespace(abc.constants).toRawString())) { + if (abc.constants.getNamespace(abc.constants.getMultiname(name_index).namespace_index).kind == Namespace.KIND_PROTECTED) { + return false; + } + } + } + } + + } + return true; + } + } 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 e752b0aaa..922aa5b88 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 @@ -21,9 +21,11 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; import com.jpexs.decompiler.flash.abc.types.AssignedValue; import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ValueKind; +import static com.jpexs.decompiler.flash.abc.types.traits.Trait.TRAIT_GETTER; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; @@ -33,6 +35,7 @@ import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Helper; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -138,17 +141,15 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { @Override public GraphTextWriter toString(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - getMetaData(abc, writer); + getMetaData(parent, convertData, abc, writer); Multiname n = getName(abc); boolean showModifier = true; if ((classIndex == -1) && (n != null)) { Namespace ns = n.getNamespace(abc.constants); if (ns == null) { showModifier = false; - } else { - if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { - showModifier = false; - } + } else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { + showModifier = false; } } if (showModifier) { @@ -204,4 +205,26 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames); parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames); } + + @Override + public boolean isVisible(boolean isStatic, ABC abc) { + + if (Configuration.handleSkinPartsAutomatically.get()) { + /* + Hide: private static var _skinParts + (part of [SkinPart] compilations) + */ + if (isStatic && "_skinParts".equals(getName(abc).getName(abc.constants, new ArrayList<>(), true))) { + if (kindType == Trait.TRAIT_SLOT) { + if ("_skinParts".equals(getName(abc).getName(abc.constants, new ArrayList<>(), true))) { + if (getName(abc).getNamespace(abc.constants).kind == Namespace.KIND_PRIVATE) { + return false; + } + } + } + } + } + return true; + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 5d4788448..ad3ed16dc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -165,6 +165,9 @@ public class Traits implements Cloneable, Serializable { continue; } } + if (!trait.isVisible(isStatic, abc)) { + continue; + } writer.newLine(); int h = t; if (classIndex != -1) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 70da2c458..6e664b970 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -561,6 +561,10 @@ public class Configuration { @ConfigurationCategory("script") public static final ConfigurationItem useRegExprLiteral = null; + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem handleSkinPartsAutomatically = null; + private enum OSId { WINDOWS, OSX, UNIX diff --git a/libsrc/ffdec_lib/testdata/flex/TestFlex.as b/libsrc/ffdec_lib/testdata/flex/TestFlex.as index 1fab6ed25..9206a87d4 100644 --- a/libsrc/ffdec_lib/testdata/flex/TestFlex.as +++ b/libsrc/ffdec_lib/testdata/flex/TestFlex.as @@ -14,6 +14,7 @@ package private var e:TestDefaultProperty; private var f:TestDeprecated; private var g:TestEffect_Event; + private var h:TestSkinParts; diff --git a/libsrc/ffdec_lib/testdata/flex/TestFlex.swf b/libsrc/ffdec_lib/testdata/flex/TestFlex.swf index 74956305e..9ea66243d 100644 Binary files a/libsrc/ffdec_lib/testdata/flex/TestFlex.swf and b/libsrc/ffdec_lib/testdata/flex/TestFlex.swf differ diff --git a/libsrc/ffdec_lib/testdata/flex/build.bat b/libsrc/ffdec_lib/testdata/flex/build.bat index 5f137b726..052620c0f 100644 --- a/libsrc/ffdec_lib/testdata/flex/build.bat +++ b/libsrc/ffdec_lib/testdata/flex/build.bat @@ -6,8 +6,8 @@ goto block2 set ISDEBUG=true :block2 set COMPILERPATH=mxmlc.exe -if not exist %COMPILERPATH% goto notex -%COMPILERPATH% -warnings=false -debug=%ISDEBUG% TestFlex.as>out.txt +rem if not exist %COMPILERPATH% goto notex +%COMPILERPATH% -warnings=false -debug=%ISDEBUG% -static-link-runtime-shared-libraries TestFlex.as>out.txt start notepad out.txt if errorlevel==1 goto failed goto end diff --git a/libsrc/ffdec_lib/testdata/flex/classes/TestSkinParts.as b/libsrc/ffdec_lib/testdata/flex/classes/TestSkinParts.as new file mode 100644 index 000000000..50a97a118 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/flex/classes/TestSkinParts.as @@ -0,0 +1,24 @@ +package classes +{ + import spark.components.Panel; + import spark.components.Button; + + public class TestSkinParts extends Panel + { + // declare the skin parts - only close is required + [SkinPart(required="true")] + public var closeIcon:Button; + [SkinPart(required="false")] + public var minimizeIcon:Button; + [SkinPart(required="false")] + public var resizeGripper:Button; + + [SkinPart(required="false")] + public static var neco:Button; + + [SkinPart(required="false")] + public function test(){ + } + + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/abc/TraitsListModel.java b/src/com/jpexs/decompiler/flash/gui/abc/TraitsListModel.java index c777a875c..f5a49cbfa 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/TraitsListModel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/TraitsListModel.java @@ -56,10 +56,14 @@ public final class TraitsListModel implements ListModel { items = new ArrayList<>(); if (classIndex > -1) { for (int t = 0; t < abc.class_info.get(classIndex).static_traits.traits.size(); t++) { - items.add(new TraitsListItem(TraitsListItem.Type.getTypeForTrait(abc.class_info.get(classIndex).static_traits.traits.get(t)), t, true, abc, classIndex, scriptIndex)); + if (abc.class_info.get(classIndex).static_traits.traits.get(t).isVisible(true, abc)) { + items.add(new TraitsListItem(TraitsListItem.Type.getTypeForTrait(abc.class_info.get(classIndex).static_traits.traits.get(t)), t, true, abc, classIndex, scriptIndex)); + } } for (int t = 0; t < abc.instance_info.get(classIndex).instance_traits.traits.size(); t++) { - items.add(new TraitsListItem(TraitsListItem.Type.getTypeForTrait(abc.instance_info.get(classIndex).instance_traits.traits.get(t)), t, false, abc, classIndex, scriptIndex)); + if (abc.instance_info.get(classIndex).instance_traits.traits.get(t).isVisible(false, abc)) { + items.add(new TraitsListItem(TraitsListItem.Type.getTypeForTrait(abc.instance_info.get(classIndex).instance_traits.traits.get(t)), t, false, abc, classIndex, scriptIndex)); + } } items.add(new TraitsListItem(TraitsListItem.Type.INITIALIZER, 0, false, abc, classIndex, scriptIndex)); items.add(new TraitsListItem(TraitsListItem.Type.INITIALIZER, 0, true, abc, classIndex, scriptIndex)); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index 1c196d425..b751ddc3f 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -422,4 +422,7 @@ config.name.displayDupInstructions = Show \u00a7\u00a7dup instructions config.description.displayDupInstructions = Display \u00a7\u00a7dup instructions in the code. Without them, the code can be easily compiled but some dupped code with sideeffects could be executed twice. config.name.useRegExprLiteral = Decompile RegExp as /pattern/mod literal. -config.description.useRegExprLiteral = Use /pattern/mod syntax when decompiling regular expressions. new RegExp("pat","mod") is used otherwise \ No newline at end of file +config.description.useRegExprLiteral = Use /pattern/mod syntax when decompiling regular expressions. new RegExp("pat","mod") is used otherwise + +config.name.handleSkinPartsAutomatically = Handle [SkinPart] metadata automatically +config.description.handleSkinPartsAutomatically = Decompiles and direct edits [SkinPart] metadata automatically. When turned off, _skinParts attribute and its getter method is visible and manually editable. \ No newline at end of file