diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e219c595..b91d9ece9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Fixed +- [#1888] Casts for missing types, cast handling for script local classes ## [17.0.3] - 2022-11-30 ### Added 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 afc22356a..7dcb0ddf5 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 @@ -1977,7 +1977,7 @@ public class AVM2Code implements Cloneable { if (!beginDeclaredSlotsNames.contains(traitName)) { Slot sl = new Slot(new NewActivationAVM2Item(null, null), abc.constants.getMultiname(traits.get(traitName).name_index)); TraitSlotConst tsc = (TraitSlotConst) traits.get(traitName); - GraphTargetItem type = PropertyAVM2Item.multinameToType(tsc.type_index, abc.constants); + GraphTargetItem type = AbcIndexing.multinameToType(tsc.type_index, abc.constants); DeclarationAVM2Item d = new DeclarationAVM2Item(new GetLexAVM2Item(null, null, sl.multiname, abc.constants, type, TypeItem.UNBOUNDED /*?*/, false), type); declaredSlotsDec.add(d); declaredSlots.add(sl); @@ -2044,7 +2044,7 @@ public class AVM2Code implements Cloneable { if (!declaredProperties.contains(propName.resolvedMultinameName)) { if (traits.containsKey(propName.resolvedMultinameName)) { TraitSlotConst tsc = traits.get(propName.resolvedMultinameName); - GraphTargetItem type = PropertyAVM2Item.multinameToType(tsc.type_index, abc.constants); + GraphTargetItem type = AbcIndexing.multinameToType(tsc.type_index, abc.constants); DeclarationAVM2Item d = new DeclarationAVM2Item(subItem, type); sp.setDeclaration(d); declaredPropsDec.add(d); @@ -2081,7 +2081,7 @@ public class AVM2Code implements Cloneable { if (index == -1) { GraphTargetItem type = TypeItem.UNBOUNDED; if (traits.containsKey(slotPropertyName)) { - type = PropertyAVM2Item.multinameToType(traits.get(slotPropertyName).type_index, abc.constants); + type = AbcIndexing.multinameToType(traits.get(slotPropertyName).type_index, abc.constants); } DeclarationAVM2Item d = new DeclarationAVM2Item(subItem, type); ssti.setDeclaration(d); @@ -2147,7 +2147,7 @@ public class AVM2Code implements Cloneable { } HashMap localRegTypes = new HashMap<>(); for (int i = 0; i < abc.method_info.get(methodIndex).param_types.length; i++) { - localRegTypes.put(i + 1, PropertyAVM2Item.multinameToType(abc.method_info.get(methodIndex).param_types[i], abc.constants)); + localRegTypes.put(i + 1, AbcIndexing.multinameToType(abc.method_info.get(methodIndex).param_types[i], abc.constants)); } //try { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java index 487cdcf31..fb500c55d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java @@ -60,7 +60,7 @@ public interface SetTypeIns { result.value = value; output.add(result); for (int i = 0; i < numDups; i++) { - stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value, localData.localRegTypes.containsKey(regId) ? localData.localRegTypes.get(regId) : TypeItem.UNBOUNDED)); + stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value, localData.localRegTypes.containsKey(regId) ? localData.localRegTypes.get(regId) : value.returnType())); } return; } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java index a57b42e3b..eb6ebd803 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.model.ConstructPropAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; @@ -31,6 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.XMLAVM2Item; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.helpers.Reference; import java.util.ArrayList; import java.util.List; @@ -70,9 +72,7 @@ public class ConstructPropIns extends InstructionDefinition { } FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); GraphTargetItem obj = stack.pop(); - if (obj instanceof FindPropertyAVM2Item) { - multiname.property = false; //can be type - } + if (multiname.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods)) { if (args.size() == 1) { @@ -97,8 +97,16 @@ public class ConstructPropIns extends InstructionDefinition { stack.push(new RegExpAvm2Item(pattern, modifiers, ins, localData.lineStartInstruction)); return; } + + Reference isStatic = new Reference<>(false); + Reference type = new Reference<>(null); + Reference callType = new Reference<>(null); + GetPropertyIns.resolvePropertyType(localData, obj, multiname, isStatic, type, callType); - stack.push(new ConstructPropAVM2Item(ins, localData.lineStartInstruction, obj, multiname, args)); + if (obj instanceof FindPropertyAVM2Item) { + multiname.property = false; //can be type + } + stack.push(new ConstructPropAVM2Item(ins, localData.lineStartInstruction, obj, multiname, args, type.getVal())); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetGlobalSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetGlobalSlotIns.java index c4b76bb1c..8dc2a718b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetGlobalSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetGlobalSlotIns.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.model.GetSlotAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -56,7 +57,7 @@ public class GetGlobalSlotIns extends InstructionDefinition { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst)t; if (tsc.slot_id == slotIndex) { - slotType = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); + slotType = AbcIndexing.multinameToType(tsc.type_index, localData.abc.constants); break; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java index ef5864cce..04632288c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java @@ -55,8 +55,8 @@ public class GetLexIns extends InstructionDefinition { GraphTargetItem obj, int multinameIndex, Reference isStatic, Reference type, Reference callType) { - type.setVal(TypeItem.UNBOUNDED); - callType.setVal(TypeItem.UNBOUNDED); + type.setVal(TypeItem.UNKNOWN); + callType.setVal(TypeItem.UNKNOWN); String multinameStr = localData.abc.constants.getMultiname(multinameIndex).getName(localData.abc.constants, new ArrayList<>(), true, true); for (int b = localData.callStack.size() - 1; b >= 0; b--) { MethodBody body = localData.callStack.get(b); @@ -67,7 +67,7 @@ public class GetLexIns extends InstructionDefinition { tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), multinameStr )) { - GraphTargetItem ty = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); + GraphTargetItem ty = AbcIndexing.multinameToType(tsc.type_index, localData.abc.constants); type.setVal(ty); callType.setVal(ty); return; @@ -82,9 +82,10 @@ public class GetLexIns extends InstructionDefinition { localData.abcIndex.findPropertyTypeOrCallType(localData.abc, new TypeItem(currentClassName), multinameStr, localData.abc.constants.getMultiname(multinameIndex).namespace_index, true, true, true, type, callType); } - if (type.getVal().equals(TypeItem.UNBOUNDED)) { - TypeItem ti = new TypeItem(localData.abc.constants.getMultiname(multinameIndex).getNameWithNamespace(localData.abc.constants, true)); - if (localData.abcIndex.findClass(ti) != null) { + if (type.getVal().equals(TypeItem.UNKNOWN)) { + //TypeItem ti = new TypeItem(localData.abc.constants.getMultiname(multinameIndex).getNameWithNamespace(localData.abc.constants, true)); + GraphTargetItem ti = AbcIndexing.multinameToType(multinameIndex, localData.abc.constants); + if (localData.abcIndex.findClass(ti, localData.abc, localData.scriptIndex) != null) { type.setVal(ti); callType.setVal(TypeItem.UNBOUNDED); isStatic.setVal(true); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java index b3235f8bc..8aa87504d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java @@ -147,8 +147,8 @@ public class GetPropertyIns extends InstructionDefinition { GraphTargetItem obj, FullMultinameAVM2Item multiname, Reference isStatic, Reference type, Reference callType) { - type.setVal(TypeItem.UNBOUNDED); - callType.setVal(TypeItem.UNBOUNDED); + type.setVal(TypeItem.UNKNOWN); + callType.setVal(TypeItem.UNKNOWN); String multinameStr = localData.abc.constants.getMultiname(multiname.multinameIndex).getName(localData.abc.constants, new ArrayList<>(), true, true); if (obj instanceof FindPropertyAVM2Item) { FindPropertyAVM2Item fprop = (FindPropertyAVM2Item) obj; @@ -162,7 +162,7 @@ public class GetPropertyIns extends InstructionDefinition { tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), multinameStr )) { - GraphTargetItem ty = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); + GraphTargetItem ty = AbcIndexing.multinameToType(tsc.type_index, localData.abc.constants); type.setVal(ty); callType.setVal(ty); return; @@ -171,16 +171,15 @@ public class GetPropertyIns extends InstructionDefinition { } } - if (type.getVal().equals(TypeItem.UNBOUNDED)) { + if (type.getVal().equals(TypeItem.UNKNOWN)) { if (localData.abcIndex != null) { String currentClassName = localData.classIndex == -1 ? null : localData.abc.instance_info.get(localData.classIndex).getName(localData.abc.constants).getNameWithNamespace(localData.abc.constants, true).toRawString(); - GraphTargetItem thisPropType = TypeItem.UNBOUNDED; if (currentClassName != null) { localData.abcIndex.findPropertyTypeOrCallType(localData.abc, new TypeItem(currentClassName), multinameStr, localData.abc.constants.getMultiname(multiname.multinameIndex).namespace_index, true, true, true, type, callType); } - if (type.getVal().equals(TypeItem.UNBOUNDED)) { - TypeItem ti = new TypeItem(localData.abc.constants.getMultiname(multiname.multinameIndex).getNameWithNamespace(localData.abc.constants, true)); - if (localData.abcIndex.findClass(ti) != null) { + if (type.getVal().equals(TypeItem.UNKNOWN)) { + GraphTargetItem ti = AbcIndexing.multinameToType(multiname.multinameIndex, localData.abc.constants);//new TypeItem(localData.abc.constants.getMultiname(multiname.multinameIndex).getNameWithNamespace(localData.abc.constants, true)); + if (localData.abcIndex.findClass(ti, localData.abc, localData.scriptIndex) != null) { type.setVal(ti); callType.setVal(TypeItem.UNBOUNDED); isStatic.setVal(true); @@ -205,7 +204,7 @@ public class GetPropertyIns extends InstructionDefinition { } else { if (localData.abcIndex != null) { GraphTargetItem receiverType = obj.returnType(); - if (!receiverType.equals(TypeItem.UNBOUNDED)) { + if (!receiverType.equals(TypeItem.UNBOUNDED) && !receiverType.equals(TypeItem.UNKNOWN)) { boolean parentStatic = false; if (obj instanceof GetLexAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSlotIns.java index dcf8a7ddb..b34d48245 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSlotIns.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.model.GetSlotAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -59,7 +60,7 @@ public class GetSlotIns extends InstructionDefinition { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst)t; if (tsc.slot_id == slotIndex) { - slotType = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); + slotType = AbcIndexing.multinameToType(tsc.type_index, localData.abc.constants); break; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java index 646884851..e3b54513c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java @@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetSlotAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -146,7 +147,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst)t; if (tsc.slot_id == slotIndex) { - slotType = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); + slotType = AbcIndexing.multinameToType(tsc.type_index, localData.abc.constants); break; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/CoerceIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/CoerceIns.java index 3a07437f2..d13c3d0ff 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/CoerceIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/CoerceIns.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2TypeErrorException; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.ecma.EcmaScript; @@ -80,7 +81,7 @@ public class CoerceIns extends InstructionDefinition implements CoerceOrConvertT @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int multinameIndex = ins.operands[0]; - stack.push(new CoerceAVM2Item(ins, localData.lineStartInstruction, stack.pop(), PropertyAVM2Item.multinameToType(multinameIndex, localData.getConstants()))); + stack.push(new CoerceAVM2Item(ins, localData.lineStartInstruction, stack.pop(), AbcIndexing.multinameToType(multinameIndex, localData.getConstants()))); } @Override @@ -96,6 +97,6 @@ public class CoerceIns extends InstructionDefinition implements CoerceOrConvertT @Override public GraphTargetItem getTargetType(AVM2ConstantPool constants, AVM2Instruction ins) { int multinameIndex = ins.operands[0]; - return PropertyAVM2Item.multinameToType(multinameIndex, constants); + return AbcIndexing.multinameToType(multinameIndex, constants); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CoerceAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CoerceAVM2Item.java index 70515998a..999c127ce 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CoerceAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CoerceAVM2Item.java @@ -108,6 +108,9 @@ public class CoerceAVM2Item extends AVM2Item { if (typeObj instanceof ApplyTypeAVM2Item) { return typeObj; } + if (typeObj instanceof TypeItem) { + return typeObj; + } return new TypeItem(typeObj.toString()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java index 8d31294f9..00869c12e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java @@ -36,12 +36,15 @@ public class ConstructPropAVM2Item extends AVM2Item { public GraphTargetItem propertyName; public List args; + + public GraphTargetItem type; - public ConstructPropAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object, GraphTargetItem propertyName, List args) { + public ConstructPropAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object, GraphTargetItem propertyName, List args, GraphTargetItem type) { super(instruction, lineStartIns, PRECEDENCE_PRIMARY); this.object = object; this.propertyName = propertyName; this.args = args; + this.type = type; } @Override @@ -71,8 +74,8 @@ public class ConstructPropAVM2Item extends AVM2Item { } @Override - public GraphTargetItem returnType() { - return TypeItem.UNBOUNDED; + public GraphTargetItem returnType() { + return type; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java index 95844d39e..4b72ddc78 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java @@ -56,6 +56,9 @@ public class FullMultinameAVM2Item extends AVM2Item { this.namespace = null; this.property = property; this.resolvedMultinameName = resolvedMultinameName; + if (property == false) { + System.err.println("xxx"); + } } public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex, String resolvedMultinameName) { @@ -65,6 +68,9 @@ public class FullMultinameAVM2Item extends AVM2Item { this.name = null; this.namespace = null; this.property = property; + if (property == false) { + System.err.println("xxx"); + } } public FullMultinameAVM2Item(boolean property, GraphSourceItem instruction, GraphSourceItem lineStartIns, int multinameIndex, String resolvedMultinameName, GraphTargetItem name, GraphTargetItem namespace) { @@ -74,6 +80,9 @@ public class FullMultinameAVM2Item extends AVM2Item { this.namespace = namespace; this.property = property; this.resolvedMultinameName = resolvedMultinameName; + if (property == false) { + System.err.println("xxx"); + } } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreDecrementAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreDecrementAVM2Item.java index f02e017e1..d95dc6250 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreDecrementAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreDecrementAVM2Item.java @@ -34,7 +34,7 @@ import java.util.List; public class PreDecrementAVM2Item extends UnaryOpItem implements AssignmentAVM2Item { public PreDecrementAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object) { - super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "--", "Number"); + super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "--", "" /*"Number" Causes unneccessary ++Number(xx) when xx not number*/); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreIncrementAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreIncrementAVM2Item.java index 88744a0f5..86def3d7f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreIncrementAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/PreIncrementAVM2Item.java @@ -33,7 +33,7 @@ import java.util.List; public class PreIncrementAVM2Item extends UnaryOpItem { public PreIncrementAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object) { - super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "++", "Number"); + super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "++", "" /*"Number" Causes unneccessary ++Number(xx) when xx not number*/); } @Override 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 d4ef4ab75..a2161a24b 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 @@ -1304,7 +1304,7 @@ public class AVM2SourceGenerator implements SourceGenerator { parent = ((UnresolvedAVM2Item) parent).resolved; } if (parent instanceof TypeItem) { - ClassIndex ci = abcIndex.findClass(parent); + ClassIndex ci = abcIndex.findClass(parent, null, null/*FIXME?*/); if (ci != null) { int mi = ci.abc.class_info.get(ci.index).cinit_index; MethodBody pcinit = ci.abc.findBody(mi); @@ -1971,7 +1971,7 @@ public class AVM2SourceGenerator implements SourceGenerator { */ int parentConstMinAC = 0; - AbcIndexing.ClassIndex ci = abcIndex.findClass(new TypeItem(superType)); + AbcIndexing.ClassIndex ci = abcIndex.findClass(new TypeItem(superType), null, null/*FIXME?*/); if (ci != null) { MethodInfo pmi = ci.abc.method_info.get(ci.abc.instance_info.get(ci.index).iinit_index); @@ -2483,7 +2483,7 @@ public class AVM2SourceGenerator implements SourceGenerator { mbCode.add(ins(AVM2Instructions.PushNull)); } else { - AbcIndexing.ClassIndex ci = abcIndex.findClass(AbcIndexing.multinameToType(abc.instance_info.get(tc.class_info).name_index, constants)); + AbcIndexing.ClassIndex ci = abcIndex.findClass(AbcIndexing.multinameToType(abc.instance_info.get(tc.class_info).name_index, constants), null, null/*FIXME?*/); while (ci != null && ci.parent != null) { ci = ci.parent; Multiname origM = ci.abc.constants.getMultiname(ci.abc.instance_info.get(ci.index).name_index); @@ -2589,16 +2589,16 @@ public class AVM2SourceGenerator implements SourceGenerator { if (tsc.type_index == 0) { return TypeItem.UNBOUNDED; } - return PropertyAVM2Item.multinameToType(tsc.type_index, abc.getSelectedAbc().constants); + return AbcIndexing.multinameToType(tsc.type_index, abc.getSelectedAbc().constants); } if (t instanceof TraitMethodGetterSetter) { TraitMethodGetterSetter tmgs = (TraitMethodGetterSetter) t; if (tmgs.kindType == Trait.TRAIT_GETTER) { - return PropertyAVM2Item.multinameToType(abc.getSelectedAbc().method_info.get(tmgs.method_info).ret_type, abc.getSelectedAbc().constants); + return AbcIndexing.multinameToType(abc.getSelectedAbc().method_info.get(tmgs.method_info).ret_type, abc.getSelectedAbc().constants); } if (tmgs.kindType == Trait.TRAIT_SETTER) { if (abc.getSelectedAbc().method_info.get(tmgs.method_info).param_types.length > 0) { - return PropertyAVM2Item.multinameToType(abc.getSelectedAbc().method_info.get(tmgs.method_info).param_types[0], abc.getSelectedAbc().constants); + return AbcIndexing.multinameToType(abc.getSelectedAbc().method_info.get(tmgs.method_info).param_types[0], abc.getSelectedAbc().constants); } else { return TypeItem.UNBOUNDED; } @@ -2662,7 +2662,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } public static void parentNames(AbcIndexing abc, int name_index, List indices, List names, List namespaces, List outABCs) { - AbcIndexing.ClassIndex ci = abc.findClass(new TypeItem(abc.getSelectedAbc().constants.getMultiname(name_index).getNameWithNamespace(abc.getSelectedAbc().constants, true /*FIXME!!*/))); + AbcIndexing.ClassIndex ci = abc.findClass(new TypeItem(abc.getSelectedAbc().constants.getMultiname(name_index).getNameWithNamespace(abc.getSelectedAbc().constants, true /*FIXME!!*/)), null, null/*FIXME?*/); while (ci != null) { int ni = ci.abc.instance_info.get(ci.index).name_index; indices.add(ni); @@ -2761,7 +2761,7 @@ public class AVM2SourceGenerator implements SourceGenerator { }*/ ABC abc = abcIndex.getSelectedAbc(); AVM2ConstantPool constants = abc.constants; - AbcIndexing.ClassIndex ci = abcIndex.findClass(new TypeItem(dname)); + AbcIndexing.ClassIndex ci = abcIndex.findClass(new TypeItem(dname), null, null/*FIXME?*/); if (ci != null) { Multiname m = ci.abc.instance_info.get(ci.index).getName(ci.abc.constants); if (m != null) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java index 6e9f172eb..8de221710 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java @@ -20,12 +20,14 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.model.ApplyTypeAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.types.ClassInfo; import com.jpexs.decompiler.flash.abc.types.InstanceInfo; 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 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; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; @@ -43,6 +45,8 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Indexing of ABCs for faster access. Indexes ABC classes for faster class and @@ -311,6 +315,52 @@ public final class AbcIndexing { this.value = value; this.objType = objType; } + } + + private static class ClassDef { + public GraphTargetItem type; + public DottedChain pkg; + + public ClassDef(GraphTargetItem type, ABC abc, Integer scriptIndex) { + this.type = type; + if (scriptIndex != null) { + for (Trait t : abc.script_info.get(scriptIndex).traits.traits) { + Namespace ns = t.getName(abc).getNamespace(abc.constants); + if (ns.kind == Namespace.KIND_PACKAGE) { + pkg = ns.getName(abc.constants); + } + } + } + } + + @Override + public int hashCode() { + int hash = 3; + hash = 17 * hash + Objects.hashCode(this.type); + hash = 17 * hash + Objects.hashCode(this.pkg); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ClassDef other = (ClassDef) obj; + if (!Objects.equals(this.type, other.type)) { + return false; + } + return Objects.equals(this.pkg, other.pkg); + } + + + } public static class ClassIndex { @@ -320,20 +370,57 @@ public final class AbcIndexing { public ABC abc; public ClassIndex parent; + + public Integer scriptIndex; @Override public String toString() { return abc.constants.getMultiname(abc.instance_info.get(index).name_index).getNameWithNamespace(abc.constants, true).toPrintableString(true); } - public ClassIndex(int index, ABC abc, ClassIndex parent) { + public ClassIndex(int index, ABC abc, ClassIndex parent, Integer scriptIndex) { this.index = index; this.abc = abc; this.parent = parent; + this.scriptIndex = scriptIndex; } + + @Override + public int hashCode() { + int hash = 5; + hash = 37 * hash + this.index; + hash = 37 * hash + System.identityHashCode(this.abc); + hash = 37 * hash + Objects.hashCode(this.parent); + hash = 37 * hash + Objects.hashCode(this.scriptIndex); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ClassIndex other = (ClassIndex) obj; + if (this.index != other.index) { + return false; + } + if (this.abc != other.abc) { + return false; + } + if (!Objects.equals(this.parent, other.parent)) { + return false; + } + return Objects.equals(this.scriptIndex, other.scriptIndex); + } } - private final Map classes = new HashMap<>(); + private final Map classes = new HashMap<>(); private final Map instanceProperties = new HashMap<>(); @@ -343,23 +430,30 @@ public final class AbcIndexing { private final Map classNsProperties = new HashMap<>(); - private final Map scriptProperties = new HashMap<>(); - - public ClassIndex findClass(GraphTargetItem cls) { - if (!classes.containsKey(cls)) { - if (parent == null) { - return null; - } - return parent.findClass(cls); + private final Map scriptProperties = new HashMap<>(); + + public ClassIndex findClass(GraphTargetItem cls, ABC abc, Integer scriptIndex) { + ClassDef keyWithScriptIndex = new ClassDef(cls, abc, scriptIndex); + if (classes.containsKey(keyWithScriptIndex)) { + return classes.get(keyWithScriptIndex); } - return classes.get(cls); + + ClassDef keyWithNoScriptIndex = new ClassDef(cls, abc, null); + if (classes.containsKey(keyWithNoScriptIndex)) { + return classes.get(keyWithNoScriptIndex); + } + + if (parent == null) { + return null; + } + return parent.findClass(cls, abc, scriptIndex); } public void findPropertyTypeOrCallType(ABC abc, GraphTargetItem cls, String propName, int ns, boolean findStatic, boolean findInstance, boolean findProtected, Reference type, Reference callType) { TraitIndex traitIndex = findProperty(new PropertyDef(propName, cls, abc, ns), findStatic, findInstance, findProtected); if (traitIndex == null) { - type.setVal(TypeItem.UNBOUNDED); - callType.setVal(TypeItem.UNBOUNDED); + type.setVal(TypeItem.UNKNOWN); + callType.setVal(TypeItem.UNKNOWN); } else { type.setVal(traitIndex.returnType); callType.setVal(traitIndex.callReturnType); @@ -465,7 +559,7 @@ public final class AbcIndexing { } //now search parent class - AbcIndexing.ClassIndex ci = findClass(prop.parent); + AbcIndexing.ClassIndex ci = findClass(prop.parent, prop.abc, null); if (ci != null && ci.parent != null && (prop.abc == null || prop.propNsIndex == 0)) { AbcIndexing.ClassIndex ciParent = ci.parent; DottedChain parentClass = ciParent.abc.instance_info.get(ciParent.index).getName(ciParent.abc.constants).getNameWithNamespace(ciParent.abc.constants, true); @@ -495,23 +589,45 @@ public final class AbcIndexing { return null; } - public static GraphTargetItem multinameToType(int m_index, AVM2ConstantPool constants) { + private static GraphTargetItem multinameToType(Set visited, int m_index, AVM2ConstantPool constants) { + if (visited.contains(m_index)) { + Logger.getLogger(AbcIndexing.class.getName()).log(Level.WARNING, "Recursive typename detected"); + return null; + } if (m_index == 0) { return TypeItem.UNBOUNDED; } Multiname m = constants.getMultiname(m_index); if (m.kind == Multiname.TYPENAME) { - GraphTargetItem obj = multinameToType(m.qname_index, constants); + visited.add(m_index); + GraphTargetItem obj = multinameToType(visited, m.qname_index, constants); + if (obj == null) { + return null; + } List params = new ArrayList<>(); for (int pm : m.params) { - params.add(multinameToType(pm, constants)); + GraphTargetItem r = multinameToType(visited, pm, constants); + if (r == null) { + return null; + } + if (pm == 0) { + r = new NullAVM2Item(null, null); + } + params.add(r); } return new ApplyTypeAVM2Item(null, null, obj, params); } else { + if (m.namespace_index != 0 && m.getNamespace(constants).kind == Namespace.KIND_PRIVATE) { + return new TypeItem(m.getName(constants, new ArrayList<>(), true, true), "ns:"+m.namespace_index); + } return new TypeItem(m.getNameWithNamespace(constants, true)); } } + public static GraphTargetItem multinameToType(int m_index, AVM2ConstantPool constants) { + return multinameToType(new HashSet<>(), m_index, constants); + } + private static GraphTargetItem getTraitCallReturnType(ABC abc, Trait t) { if (t instanceof TraitSlotConst) { return TypeItem.UNBOUNDED; @@ -524,12 +640,12 @@ public final class AbcIndexing { if (tmgs.kindType == Trait.TRAIT_SETTER) { return TypeItem.UNBOUNDED; } - return PropertyAVM2Item.multinameToType(abc.method_info.get(tmgs.method_info).ret_type, abc.constants); + return multinameToType(abc.method_info.get(tmgs.method_info).ret_type, abc.constants); } if (t instanceof TraitFunction) { TraitFunction tf = (TraitFunction) t; - return PropertyAVM2Item.multinameToType(abc.method_info.get(tf.method_info).ret_type, abc.constants); + return multinameToType(abc.method_info.get(tf.method_info).ret_type, abc.constants); } return TypeItem.UNBOUNDED; @@ -541,16 +657,16 @@ public final class AbcIndexing { if (tsc.type_index == 0) { return TypeItem.UNBOUNDED; } - return PropertyAVM2Item.multinameToType(tsc.type_index, abc.constants); + return multinameToType(tsc.type_index, abc.constants); } if (t instanceof TraitMethodGetterSetter) { TraitMethodGetterSetter tmgs = (TraitMethodGetterSetter) t; if (tmgs.kindType == Trait.TRAIT_GETTER) { - return PropertyAVM2Item.multinameToType(abc.method_info.get(tmgs.method_info).ret_type, abc.constants); + return multinameToType(abc.method_info.get(tmgs.method_info).ret_type, abc.constants); } if (tmgs.kindType == Trait.TRAIT_SETTER) { if (abc.method_info.get(tmgs.method_info).param_types.length > 0) { - return PropertyAVM2Item.multinameToType(abc.method_info.get(tmgs.method_info).param_types[0], abc.constants); + return multinameToType(abc.method_info.get(tmgs.method_info).param_types[0], abc.constants); } else { return TypeItem.UNBOUNDED; } @@ -601,8 +717,8 @@ public final class AbcIndexing { public void removeAbc(ABC abc) { abcs.remove(abc); - Set gti_keys = new HashSet<>(classes.keySet()); - for (GraphTargetItem key : gti_keys) { + Set gti_keys = new HashSet<>(classes.keySet()); + for (ClassDef key : gti_keys) { if (classes.get(key).abc == abc) { classes.remove(key); } @@ -650,29 +766,39 @@ public final class AbcIndexing { return; } List addedClasses = new ArrayList<>(); + for (int i = 0; i < abc.instance_info.size(); i++) { - InstanceInfo ii = abc.instance_info.get(i); - if (ii.deleted) { - continue; - } - ClassInfo ci = abc.class_info.get(i); - ClassIndex cindex = new ClassIndex(i, abc, null); - addedClasses.add(cindex); - GraphTargetItem cname = multinameToType(ii.name_index, abc.constants); - classes.put(cname, cindex); - - indexTraits(abc, ii.name_index, ii.instance_traits, instanceProperties, instanceNsProperties); - indexTraits(abc, ii.name_index, ci.static_traits, classProperties, classNsProperties); + } - for (int i = 0; i < abc.script_info.size(); i++) { + for (int i = 0; i < abc.script_info.size(); i++) { indexTraits(abc, 0, abc.script_info.get(i).traits, null, scriptProperties); + for (int t = 0; t < abc.script_info.get(i).traits.traits.size(); t++) { + Trait tr = abc.script_info.get(i).traits.traits.get(t); + if (tr instanceof TraitClass) { + TraitClass tc = (TraitClass)tr; + InstanceInfo ii = abc.instance_info.get(tc.class_info); + if (ii.deleted) { + continue; + } + ClassInfo ci = abc.class_info.get(tc.class_info); + int nsKind = abc.constants.getMultiname(tc.name_index).getNamespace(abc.constants).kind; + Integer classScriptIndex = nsKind == Namespace.KIND_PACKAGE ? null : i; + ClassIndex cindex = new ClassIndex(tc.class_info, abc, null, classScriptIndex); + addedClasses.add(cindex); + GraphTargetItem cname = multinameToType(ii.name_index, abc.constants); + classes.put(new ClassDef(cname, abc, classScriptIndex), cindex); + + indexTraits(abc, ii.name_index, ii.instance_traits, instanceProperties, instanceNsProperties); + indexTraits(abc, ii.name_index, ci.static_traits, classProperties, classNsProperties); + } + } } for (ClassIndex cindex : addedClasses) { int parentClassName = abc.instance_info.get(cindex.index).super_index; if (parentClassName > 0) { TypeItem parentClass = new TypeItem(abc.constants.getMultiname(parentClassName).getNameWithNamespace(abc.constants, true)); - ClassIndex parentClassIndex = findClass(parentClass); + ClassIndex parentClassIndex = findClass(parentClass, abc, null); if (parentClassIndex == null) { //Parent class can be deleted, do not check. TODO: handle this better //throw new RuntimeException("Parent class " + parentClass + " definition not found!"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index 8d23c9e74..b9b3758bc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -104,41 +104,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { return abc.getSelectedAbc().constants.getNamespaceSetId(nssa, true); } - private static GraphTargetItem multinameToType(Set visited, int m_index, AVM2ConstantPool constants) { - if (visited.contains(m_index)) { - Logger.getLogger(PropertyAVM2Item.class.getName()).log(Level.WARNING, "Recursive typename detected"); - return null; - } - if (m_index == 0) { - return TypeItem.UNBOUNDED; - } - Multiname m = constants.getMultiname(m_index); - if (m.kind == Multiname.TYPENAME) { - visited.add(m_index); - GraphTargetItem obj = multinameToType(visited, m.qname_index, constants); - if (obj == null) { - return null; - } - List params = new ArrayList<>(); - for (int pm : m.params) { - GraphTargetItem r = multinameToType(visited, pm, constants); - if (r == null) { - return null; - } - if (pm == 0) { - r = new NullAVM2Item(null, null); - } - params.add(r); - } - return new ApplyTypeAVM2Item(null, null, obj, params); - } else { - return new TypeItem(m.getNameWithNamespace(constants, true)); - } - } - - public static GraphTargetItem multinameToType(int m_index, AVM2ConstantPool constants) { - return multinameToType(new HashSet<>(), m_index, constants); - } + public void resolve(boolean mustExist, SourceGeneratorLocalData localData, Reference isType, Reference objectType, Reference propertyType, Reference propertyIndex, Reference propertyValue, Reference propertyValueABC) throws CompilationException { Integer namespaceSuffixInt = null; @@ -217,7 +183,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { // super is special cause its static type is the super class, but it still allows access to protected members // so for super to work we need to also allow the protected namespace of the super class // however this namespace is in the ABC of the super class and not in abcIndex.getSelectedAbc() - AbcIndexing.ClassIndex ci = abcIndex.findClass(objType); + AbcIndexing.ClassIndex ci = abcIndex.findClass(objType, null, null/*FIXME?*/); int superProtectedNs = ci.abc.instance_info.get(ci.index).protectedNS; AbcIndexing.TraitIndex sp = abcIndex.findProperty(new AbcIndexing.PropertyDef(propertyName, objType, ci.abc, superProtectedNs), false, true, true); if (sp != null) { @@ -252,7 +218,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { if (t instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) t; objType = new TypeItem(DottedChain.FUNCTION); - propType = multinameToType(tsc.type_index, constants); + propType = AbcIndexing.multinameToType(tsc.type_index, constants); propIndex = tsc.name_index; if (!localData.traitUsages.containsKey(b)) { localData.traitUsages.put(b, new ArrayList<>()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index b5e0690b2..d84c0f52a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -363,7 +363,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { DottedChain pkg = classChain.getWithoutLast(); TypeItem ti = new TypeItem(pkg.addWithSuffix(name.get(0))); - AbcIndexing.ClassIndex ci = abc.findClass(ti); + AbcIndexing.ClassIndex ci = abc.findClass(ti, null, null/*FIXME?*/); if (ci != null) { resolved = ti; @@ -412,7 +412,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { if (!isProperty) { for (int i = 0; i < name.size(); i++) { DottedChain fname = name.subChain(i + 1); - AbcIndexing.ClassIndex ci = abc.findClass(new TypeItem(fname)); + AbcIndexing.ClassIndex ci = abc.findClass(new TypeItem(fname), null, null/*FIXME?*/); if (ci != null) { if (!subtypes.isEmpty() && name.size() > i + 1) { continue; @@ -441,7 +441,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { n.resolveCustomNs(abcIndex, importedClasses, pkg, openedNamespaces, localData); Namespace ons = abc.getSelectedAbc().constants.getNamespace(n.getCpoolIndex(abc)); TypeItem ti = new TypeItem(ons.getName(abc.getSelectedAbc().constants).addWithSuffix(name.get(0))); - AbcIndexing.ClassIndex ci = abc.findClass(ti); + AbcIndexing.ClassIndex ci = abc.findClass(ti, null, null/*FIXME?*/); if (ci != null) { if (!subtypes.isEmpty() && name.size() > 1) { continue; @@ -471,7 +471,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { boolean isSuper = name.get(0).equals("super"); GraphTargetItem ntype = thisType; if (isSuper) { - AbcIndexing.ClassIndex ci = abc.findClass(thisType); + AbcIndexing.ClassIndex ci = abc.findClass(thisType, null, null/*FIXME?*/); if (ci == null) { throw new CompilationException("This class not found", line); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java index 681c7bba8..056c08902 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java @@ -45,7 +45,7 @@ import java.util.List; public class PreDecrementActionItem extends UnaryOpItem { public PreDecrementActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object) { - super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "--", "Number"); + super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "--", "" /*"Number" Causes unneccessary ++Number(xx) when xx not number*/); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java index 28d5f8d36..951eba49b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java @@ -45,7 +45,7 @@ import java.util.List; public class PreIncrementActionItem extends UnaryOpItem { public PreIncrementActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object) { - super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "++", "Number"); + super(instruction, lineStartIns, PRECEDENCE_UNARY, object, "++", "" /*"Number" Causes unneccessary ++Number(xx) when xx not number*/); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java index f8d923edb..43bb5ad70 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java @@ -53,29 +53,42 @@ public class TypeItem extends GraphTargetItem { public final DottedChain fullTypeName; public boolean printRaw = false; + + public String ns; public TypeItem(String s) { - this(s == null ? new DottedChain(new String[]{}, new String[]{""}) : DottedChain.parseWithSuffix(s)); + this(s, null); + } + public TypeItem(String s, String ns) { + this(s == null ? new DottedChain(new String[]{}, new String[]{""}) : DottedChain.parseWithSuffix(s), ns); } public TypeItem(DottedChain fullTypeName) { - this(fullTypeName, new ArrayList<>()); - } + this(fullTypeName, (String)null); + } + public TypeItem(DottedChain fullTypeName, String ns) { + this(fullTypeName, new ArrayList<>(), ns); + } - public TypeItem(DottedChain fullTypeName, List subtypes) { + public TypeItem(DottedChain fullTypeName, List subtypes, String ns) { super(null, null, NOPRECEDENCE); this.fullTypeName = fullTypeName; + this.ns = ns; } @Override public int hashCode() { - int hash = 7; - hash = 83 * hash + Objects.hashCode(fullTypeName); + int hash = 5; + hash = 17 * hash + Objects.hashCode(this.fullTypeName); + hash = 17 * hash + Objects.hashCode(this.ns); return hash; } @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj == null) { return false; } @@ -83,9 +96,14 @@ public class TypeItem extends GraphTargetItem { return false; } final TypeItem other = (TypeItem) obj; - return Objects.equals(fullTypeName, other.fullTypeName); + if (!Objects.equals(this.ns, other.ns)) { + return false; + } + return Objects.equals(this.fullTypeName, other.fullTypeName); } + + @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { boolean as3 = localData.constantsAvm2 != null; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java index c9f795375..172ea0c2b 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java @@ -172,7 +172,7 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testSwitch() { - decompileMethod("assembled", "testSwitch", "switch(somevar)\r\n" + decompileMethod("assembled", "testSwitch", "switch(int(somevar))\r\n" + "{\r\n" + "case 0:\r\n" + "var _loc2_:String = \"X\";\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java index a4a14f8d4..1fde6259a 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java @@ -264,7 +264,10 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile + "trace(\"b\");\r\n" + "i = int(xlist[i].@id);\r\n" + "trace(\"c\");\r\n" - + "i = int(x.item[i].@id);\r\n", + + "i = int(x.item[i].@id);\r\n" + + "var lc:LocalClass;\r\n" + + "i = (lc = new LocalClass()).attr;\r\n" + + "s = String(lc.attr);\r\n", false); } @@ -1390,7 +1393,7 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile @Test public void testProperty() { - decompileMethod("classic_air", "testProperty", "var d:* = new TestClass1();\r\n" + decompileMethod("classic_air", "testProperty", "var d:TestClass1 = new TestClass1();\r\n" + "var k:int = 15;\r\n" + "if(k == 15)\r\n" + "{\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java index a4c86a589..98d1c496b 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java @@ -141,9 +141,9 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes + "trace(\"arr[2] += 5\");\r\n" + "b[2] += 5;\r\n" + "trace(\"arr[call()] /= 5\");\r\n" - + "b[this.calc()] = b[this.calc()] / 5;\r\n" + + "b[this.calc()] = Number(b[this.calc()]) / 5;\r\n" + "trace(\"arr[call()][call()] &= 10;\");\r\n" - + "b[this.calc()][this.calc()] = b[this.calc()][this.calc()] & 10;\r\n" + + "b[this.calc()][this.calc()] = Number(b[this.calc()][this.calc()]) & 10;\r\n" + "try\r\n" + "{\r\n" + "trace(\"in try\");\r\n" @@ -263,7 +263,10 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes + "trace(\"b\");\r\n" + "i = int(xlist[i].@id);\r\n" + "trace(\"c\");\r\n" - + "i = int(x.item[i].@id);\r\n", + + "i = int(x.item[i].@id);\r\n" + + "var lc:LocalClass = new LocalClass();\r\n" + + "i = lc.attr;\r\n" + + "s = String(lc.attr);\r\n", false); } @@ -1385,7 +1388,7 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes @Test public void testProperty() { - decompileMethod("classic", "testProperty", "var d:* = new TestClass1();\r\n" + decompileMethod("classic", "testProperty", "var d:TestClass1 = new TestClass1();\r\n" + "var k:* = 7 + 8;\r\n" + "if(k == 15)\r\n" + "{\r\n" diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf index e4c35de59..e1f309e02 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf index 73a199820..2037716d6 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestConvert.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestConvert.as index 28bea5543..b6e0dbc2a 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestConvert.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestConvert.as @@ -66,7 +66,14 @@ package tests i = int(xlist[i].@id); trace("c"); i = int(x.item[i].@id); - + + var lc:LocalClass = new LocalClass(); + i = lc.attr; + s = String(lc.attr); } } } + +class LocalClass{ + public var attr:int = 5; +} \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestProperty.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestProperty.as index 5cd36f06c..210d9a7b5 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestProperty.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestProperty.as @@ -5,7 +5,7 @@ package tests { public function run():* { - var d:* = new TestClass1(); + var d:TestClass1 = new TestClass1(); var k:* = 7 + 8; if (k == 15) {